[DragonEgg] Strange call to @"\01__isoc99_fscanf"

Dear all,

First of all, Merry Christmas! :slight_smile:

While testing a File I/O sample program, I’ve encountered a link failure due to missing implementation of β€œ\01__isoc99_fscanf” function. I think this function should be named β€œ__isoc99_fscanf” instead. Please see the program code and LLVM IR generated by DragonEgg and clang below. It shows that clang generates β€œ__isoc99_fscanf”, while DragonEgg gives β€œ\01__isoc99_fscanf”. We generally use DragonEgg as our compiler frontend, so it is more important. What could be the reason of β€œ\01” issue?

Thanks,

  • Dima.

marcusmae@M17xR4:~/forge/kernelgen/tests/behavior/fileio$ cat fileio.c
#include <inttypes.h>
#include <stdio.h>

const char* filename = β€œfileio.txt”;

int main(int argc, char* argv[])
{
if (argc != 2)
{
printf(β€œTest KernelGen support for File I/O\n”);
printf(β€œUsage: %s \n”, argv[0]);
return 0;
}

size_t szarray = (size_t)strtoumax(argv[1], NULL, 0);

// Write data to file.
FILE* wfile = fopen(filename, β€œw”);
if (!wfile)
{
fprintf(stderr, β€œCannot open output file %s\n”, filename);
return 1;
}
for (int i = 0; i < szarray; i++)
fprintf(wfile, "%d ", i);
fclose(wfile);

// Read data from file.
FILE* rfile = fopen(filename, β€œr”);
if (!rfile)
{
fprintf(stderr, β€œCannot open input file %s\n”, filename);
return 1;
}
for (int i = 0; i < szarray; i++)
{
int val;
fscanf(rfile, β€œ%d”, &val);
printf("%d β€œ, val);
}
printf(”\n");
fclose(rfile);

return 0;
}

marcusmae@M17xR4:~/forge/kernelgen/tests/behavior/fileio$ kernelgen-dragonegg -v -std=c99 fileio.c -o-
Using built-in specs.
COLLECT_GCC=kernelgen-gfortran
COLLECT_LTO_WRAPPER=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/libexec/gcc/x86_64-unknown-linux-gnu/4.6.4/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: …/configure --prefix=/home/marcusmae/rpmbuild/BUILDROOT/opt/kernelgen --program-prefix=kernelgen- --enable-languages=fortran,c++ --with-mpfr-include=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/include/ --with-mpfr-lib=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/lib --with-gmp-include=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/include/ --with-gmp-lib=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/lib --with-mpc-include=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/include/ --with-mpc-lib=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/lib --enable-plugin --enable-gold=default --disable-ld --with-ld=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/kernelgen-ld --disable-bootstrap
Thread model: posix
gcc version 4.6.4 20120720 (prerelease) (GCC)
COLLECT_GCC_OPTIONS=’-fplugin=dragonegg.so’ β€˜-fplugin-arg-dragonegg-emit-ir’ β€˜-fplugin-arg-dragonegg-llvm-ir-optimize=0’ β€˜-S’ β€˜-v’ β€˜-std=c99’ β€˜-o’ β€˜-’ β€˜-mtune=generic’ β€˜-march=x86-64’
/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/libexec/gcc/x86_64-unknown-linux-gnu/4.6.4/cc1 -quiet -v -imultilib . -imultiarch x86_64-linux-gnu -iprefix /home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/ -iplugindir=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/plugin fileio.c -iplugindir=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/plugin -quiet -dumpbase fileio.c -mtune=generic -march=x86-64 -auxbase-strip - -std=c99 -version -fplugin=dragonegg.so -fplugin-arg-dragonegg-emit-ir -fplugin-arg-dragonegg-llvm-ir-optimize=0 -o -
GNU C (GCC) version 4.6.4 20120720 (prerelease) (x86_64-unknown-linux-gnu)
compiled by GNU C version 4.6.4 20120720 (prerelease), GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Versions of loaded plugins:
dragonegg: 3.2svn
ignoring nonexistent directory β€œ/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/…/…/…/…/x86_64-unknown-linux-gnu/include”
ignoring duplicate directory β€œ/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/…/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/include”
ignoring nonexistent directory β€œ/usr/local/include/x86_64-linux-gnu”
ignoring duplicate directory β€œ/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/…/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/include-fixed”
ignoring nonexistent directory β€œ/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/…/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/…/…/…/…/x86_64-unknown-linux-gnu/include”
#include β€œβ€¦β€ search starts here:
#include <…> search starts here:
/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/include
/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/include-fixed
/usr/local/include
/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/…/…/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
GNU C (GCC) version 4.6.4 20120720 (prerelease) (x86_64-unknown-linux-gnu)
compiled by GNU C version 4.6.4 20120720 (prerelease), GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Versions of loaded plugins:
dragonegg: 3.2svn
Compiler executable checksum: 64cde6062a88e8edfe37057c679689e2
; ModuleID = β€˜fileio.c’
target datalayout = β€œe-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64”
target triple = β€œx86_64-unknown-linux-gnu”

%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32, [4 x i8] }

@filename = unnamed_addr global i8* getelementptr inbounds ([11 x i8]* @.cst, i64 0, i64 0)
@.cst = linker_private constant [11 x i8] c"fileio.txt\00", align 8
@.cst1 = linker_private constant [36 x i8] c"Test KernelGen support for File I/O\00", align 64
@.cst2 = linker_private constant [21 x i8] c"Usage: %s \0A\00", align 8
@.cst3 = linker_private constant [2 x i8] c"w\00", align 8
@.cst4 = linker_private constant [28 x i8] c"Cannot open output file %s\0A\00", align 8
@stderr = external global %struct._IO_FILE*
@.cst5 = linker_private constant [4 x i8] c"%d \00", align 8
@.cst6 = linker_private constant [2 x i8] c"r\00", align 8
@.cst7 = linker_private constant [27 x i8] c"Cannot open input file %s\0A\00", align 8
@.cst8 = linker_private constant [3 x i8] c"%d\00", align 8

define i32 @main(i32 %argc, i8** %argv) nounwind uwtable {
entry:
%argc_addr = alloca i32, align 4
%argv_addr = alloca i8**, align 8
%szarray = alloca i64
%wfile = alloca %struct._IO_FILE*
%rfile = alloca %struct._IO_FILE*
%i = alloca i32
%i1 = alloca i32
%val = alloca i32
%"" = alloca i32
%β€œalloca point” = bitcast i32 0 to i32
store i32 %argc, i32* %argc_addr
store i8** %argv, i8*** %argv_addr
%0 = load i32* %argc_addr, align 32
%1 = load i8*** %argv_addr, align 64
%β€œssa point” = bitcast i32 0 to i32
br label %β€œ2”

β€œ2”: ; preds = %entry
%2 = icmp ne i32 %0, 2
br i1 %2, label %β€œ3”, label %β€œ4”

β€œ3”: ; preds = %β€œ2”
%3 = call i32 @puts(i8* getelementptr inbounds ([36 x i8]* @.cst1, i64 0, i64 0)) nounwind
%4 = load i8** %1, align 8
%5 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([21 x i8]* @.cst2, i64 0, i64 0), i8* %4) nounwind
br label %β€œ15”

β€œ4”: ; preds = %β€œ2”
%6 = bitcast i8** %1 to i8*
%7 = getelementptr i8* %6, i64 8
%8 = bitcast i8* %7 to i8**
%9 = load i8** %8, align 8
%10 = call i64 @strtoumax(i8* noalias %9, i8** noalias null, i32 0) nounwind
%11 = load i8** @filename, align 8
%12 = call %struct._IO_FILE* @fopen(i8* noalias %11, i8* noalias getelementptr inbounds ([2 x i8]* @.cst3, i64 0, i64 0)) nounwind
%13 = icmp eq %struct._IO_FILE* %12, null
br i1 %13, label %β€œ5”, label %β€œ6”

β€œ5”: ; preds = %β€œ4”
%14 = load i8** @filename, align 8
%15 = load %struct._IO_FILE** @stderr, align 8
%16 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* noalias %15, i8* noalias getelementptr inbounds ([28 x i8]* @.cst4, i64 0, i64 0), i8* %14) nounwind
br label %β€œ15”

β€œ6”: ; preds = %β€œ4”
br label %β€œ8”

β€œ7”: ; preds = %β€œ8”
%17 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* noalias %12, i8* noalias getelementptr inbounds ([4 x i8]* @.cst5, i64 0, i64 0), i32 %19) nounwind
%18 = add i32 %19, 1
br label %β€œ8”

β€œ8”: ; preds = %β€œ7”, %β€œ6”
%19 = phi i32 [ %18, %β€œ7” ], [ 0, %β€œ6” ]
%20 = sext i32 %19 to i64
%21 = icmp ult i64 %20, %10
br i1 %21, label %β€œ7”, label %β€œ9”

β€œ9”: ; preds = %β€œ8”
%22 = call i32 @fclose(%struct._IO_FILE* %12) nounwind
%23 = load i8** @filename, align 8
%24 = call %struct._IO_FILE* @fopen(i8* noalias %23, i8* noalias getelementptr inbounds ([2 x i8]* @.cst6, i64 0, i64 0)) nounwind
%25 = icmp eq %struct._IO_FILE* %24, null
br i1 %25, label %β€œ10”, label %β€œ11”

β€œ10”: ; preds = %β€œ9”
%26 = load i8** @filename, align 8
%27 = load %struct._IO_FILE** @stderr, align 8
%28 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* noalias %27, i8* noalias getelementptr inbounds ([27 x i8]* @.cst7, i64 0, i64 0), i8* %26) nounwind
br label %β€œ15”

β€œ11”: ; preds = %β€œ9”
br label %β€œ13”

β€œ12”: ; preds = %β€œ13”
%29 = call i32 (%struct._IO_FILE*, i8*, …)* @"\01__isoc99_fscanf"(%struct._IO_FILE* noalias %24, i8* noalias getelementptr inbounds ([3 x i8]* @.cst8, i64 0, i64 0), i32* %val) nounwind
%30 = load i32* %val, align 4
%31 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([4 x i8]* @.cst5, i64 0, i64 0), i32 %30) nounwind
%32 = add i32 %33, 1
br label %β€œ13”

β€œ13”: ; preds = %β€œ12”, %β€œ11”
%33 = phi i32 [ %32, %β€œ12” ], [ 0, %β€œ11” ]
%34 = sext i32 %33 to i64
%35 = icmp ult i64 %34, %10
br i1 %35, label %β€œ12”, label %β€œ14”

β€œ14”: ; preds = %β€œ13”
%36 = call i32 @putchar(i32 10) nounwind
%37 = call i32 @fclose(%struct._IO_FILE* %24) nounwind
br label %β€œ15”

β€œ15”: ; preds = %β€œ14”, %β€œ10”, %β€œ5”, %β€œ3”
%38 = phi i32 [ 0, %β€œ14” ], [ 1, %β€œ10” ], [ 1, %β€œ5” ], [ 0, %β€œ3” ]
store i32 %38, i32* %"", align 1
br label %return

return: ; preds = %β€œ15”
%retval = load i32* %""
ret i32 %retval
}

declare i32 @puts(i8*)

declare i32 @printf(i8*, …)

declare i64 @strtoumax(i8* noalias, i8** noalias, i32) nounwind

declare %struct._IO_FILE* @fopen(i8* noalias, i8* noalias)

declare i32 @fprintf(%struct._IO_FILE* noalias, i8* noalias, …)

declare i32 @fclose(%struct._IO_FILE*)

declare i32 @"\01__isoc99_fscanf"(%struct._IO_FILE* noalias, i8* noalias, …)

declare i32 @putchar(i32)
COMPILER_PATH=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/libexec/gcc/x86_64-unknown-linux-gnu/4.6.4/:/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/libexec/gcc/:/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/…/…/…/…/x86_64-unknown-linux-gnu/bin/
LIBRARY_PATH=/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/:/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/:/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/…/…/…/…/lib64/:/lib/x86_64-linux-gnu/:/lib/…/lib64/:/usr/lib/x86_64-linux-gnu/:/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/…/…/…/:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS=’-fplugin=dragonegg.so’ β€˜-fplugin-arg-dragonegg-emit-ir’ β€˜-fplugin-arg-dragonegg-llvm-ir-optimize=0’ β€˜-S’ β€˜-v’ β€˜-std=c99’ β€˜-o’ β€˜-’ β€˜-mtune=generic’ β€˜-march=x86-64’

marcusmae@M17xR4:~/forge/kernelgen/tests/behavior/fileio$ clang -cc1 -I/usr/include -I/home/marcusmae/rpmbuild/CHROOT/opt/kernelgen/bin/…/lib/gcc/x86_64-unknown-linux-gnu/4.6.4/include -emit-llvm -std=c99 fileio.c -o-
; ModuleID = β€˜fileio.c’
target datalayout = β€œe-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128”
target triple = β€œx86_64-unknown-linux-gnu”

%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }

@.str = private unnamed_addr constant [11 x i8] c"fileio.txt\00", align 1
@filename = global i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), align 8
@.str1 = private unnamed_addr constant [37 x i8] c"Test KernelGen support for File I/O\0A\00", align 1
@.str2 = private unnamed_addr constant [21 x i8] c"Usage: %s \0A\00", align 1
@.str3 = private unnamed_addr constant [2 x i8] c"w\00", align 1
@stderr = external global %struct._IO_FILE*
@.str4 = private unnamed_addr constant [28 x i8] c"Cannot open output file %s\0A\00", align 1
@.str5 = private unnamed_addr constant [4 x i8] c"%d \00", align 1
@.str6 = private unnamed_addr constant [2 x i8] c"r\00", align 1
@.str7 = private unnamed_addr constant [27 x i8] c"Cannot open input file %s\0A\00", align 1
@.str8 = private unnamed_addr constant [3 x i8] c"%d\00", align 1
@.str9 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1

define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
%retval = alloca i32, align 4
%argc.addr = alloca i32, align 4
%argv.addr = alloca i8**, align 8
%szarray = alloca i64, align 8
%wfile = alloca %struct._IO_FILE*, align 8
%i = alloca i32, align 4
%rfile = alloca %struct._IO_FILE*, align 8
%i17 = alloca i32, align 4
%val = alloca i32, align 4
store i32 0, i32* %retval
store i32 %argc, i32* %argc.addr, align 4
store i8** %argv, i8*** %argv.addr, align 8
%0 = load i32* %argc.addr, align 4
%cmp = icmp ne i32 %0, 2
br i1 %cmp, label %if.then, label %if.end

if.then: ; preds = %entry
%call = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([37 x i8]* @.str1, i32 0, i32 0))
%1 = load i8*** %argv.addr, align 8
%arrayidx = getelementptr inbounds i8** %1, i64 0
%2 = load i8** %arrayidx, align 8
%call1 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([21 x i8]* @.str2, i32 0, i32 0), i8* %2)
store i32 0, i32* %retval
br label %return

if.end: ; preds = %entry
%3 = load i8*** %argv.addr, align 8
%arrayidx2 = getelementptr inbounds i8** %3, i64 1
%4 = load i8** %arrayidx2, align 8
%call3 = call i64 @strtoumax(i8* %4, i8** null, i32 0) nounwind
store i64 %call3, i64* %szarray, align 8
%5 = load i8** @filename, align 8
%call4 = call %struct._IO_FILE* @fopen(i8* %5, i8* getelementptr inbounds ([2 x i8]* @.str3, i32 0, i32 0))
store %struct._IO_FILE* %call4, %struct._IO_FILE** %wfile, align 8
%6 = load %struct._IO_FILE** %wfile, align 8
%tobool = icmp ne %struct._IO_FILE* %6, null
br i1 %tobool, label %if.end7, label %if.then5

if.then5: ; preds = %if.end
%7 = load %struct._IO_FILE** @stderr, align 8
%8 = load i8** @filename, align 8
%call6 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* %7, i8* getelementptr inbounds ([28 x i8]* @.str4, i32 0, i32 0), i8* %8)
store i32 1, i32* %retval
br label %return

if.end7: ; preds = %if.end
store i32 0, i32* %i, align 4
br label %for.cond

for.cond: ; preds = %for.inc, %if.end7
%9 = load i32* %i, align 4
%conv = sext i32 %9 to i64
%10 = load i64* %szarray, align 8
%cmp8 = icmp ult i64 %conv, %10
br i1 %cmp8, label %for.body, label %for.end

for.body: ; preds = %for.cond
%11 = load %struct._IO_FILE** %wfile, align 8
%12 = load i32* %i, align 4
%call10 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* %11, i8* getelementptr inbounds ([4 x i8]* @.str5, i32 0, i32 0), i32 %12)
br label %for.inc

for.inc: ; preds = %for.body
%13 = load i32* %i, align 4
%inc = add nsw i32 %13, 1
store i32 %inc, i32* %i, align 4
br label %for.cond

for.end: ; preds = %for.cond
%14 = load %struct._IO_FILE** %wfile, align 8
%call11 = call i32 @fclose(%struct._IO_FILE* %14)
%15 = load i8** @filename, align 8
%call12 = call %struct._IO_FILE* @fopen(i8* %15, i8* getelementptr inbounds ([2 x i8]* @.str6, i32 0, i32 0))
store %struct._IO_FILE* %call12, %struct._IO_FILE** %rfile, align 8
%16 = load %struct._IO_FILE** %rfile, align 8
%tobool13 = icmp ne %struct._IO_FILE* %16, null
br i1 %tobool13, label %if.end16, label %if.then14

if.then14: ; preds = %for.end
%17 = load %struct._IO_FILE** @stderr, align 8
%18 = load i8** @filename, align 8
%call15 = call i32 (%struct._IO_FILE*, i8*, …)* @fprintf(%struct._IO_FILE* %17, i8* getelementptr inbounds ([27 x i8]* @.str7, i32 0, i32 0), i8* %18)
store i32 1, i32* %retval
br label %return

if.end16: ; preds = %for.end
store i32 0, i32* %i17, align 4
br label %for.cond18

for.cond18: ; preds = %for.inc25, %if.end16
%19 = load i32* %i17, align 4
%conv19 = sext i32 %19 to i64
%20 = load i64* %szarray, align 8
%cmp20 = icmp ult i64 %conv19, %20
br i1 %cmp20, label %for.body22, label %for.end27

for.body22: ; preds = %for.cond18
%21 = load %struct._IO_FILE** %rfile, align 8
%call23 = call i32 (%struct._IO_FILE*, i8*, …)* @__isoc99_fscanf(%struct._IO_FILE* %21, i8* getelementptr inbounds ([3 x i8]* @.str8, i32 0, i32 0), i32* %val)
%22 = load i32* %val, align 4
%call24 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str5, i32 0, i32 0), i32 %22)
br label %for.inc25

for.inc25: ; preds = %for.body22
%23 = load i32* %i17, align 4
%inc26 = add nsw i32 %23, 1
store i32 %inc26, i32* %i17, align 4
br label %for.cond18

for.end27: ; preds = %for.cond18
%call28 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([2 x i8]* @.str9, i32 0, i32 0))
%24 = load %struct._IO_FILE** %rfile, align 8
%call29 = call i32 @fclose(%struct._IO_FILE* %24)
store i32 0, i32* %retval
br label %return

return: ; preds = %for.end27, %if.then14, %if.then5, %if.then
%25 = load i32* %retval
ret i32 %25
}

declare i32 @printf(i8*, …)

declare i64 @strtoumax(i8*, i8**, i32) nounwind

declare %struct._IO_FILE* @fopen(i8*, i8*)

declare i32 @fprintf(%struct._IO_FILE*, i8*, …)

declare i32 @fclose(%struct._IO_FILE*)

declare i32 @__isoc99_fscanf(%struct._IO_FILE*, i8*, …)

While testing a File I/O sample program, I've encountered a link failure due
to missing implementation of "\01__isoc99_fscanf" function. I think this
function should be named "__isoc99_fscanf" instead. Please see the program
code and LLVM IR generated by DragonEgg and clang below. It shows that clang
generates "__isoc99_fscanf", while DragonEgg gives "\01__isoc99_fscanf". We
generally use DragonEgg as our compiler frontend, so it is more important.
What could be the reason of "\01" issue?

\01 is the magic prefix from asm("") thing in C sources. Basically
this is the instruction to mangler not to change the name in any way,
so, it should be emitted to assembler / binary code as
"__isoc99_fscanf".

How does .s / .o look like?

Hi Anton!

Thanks for the hint! You’re right: it is β€œcallq __isoc99_fscanf” in .s file. My mistake is that I’m taking a function name directly from CallInst and trying to dlsym it from the running executable. Now I’m using mangler.getNameWithPrefix method to get the actual name, and it works.

Best regards,

  • D.

2012/12/25 Anton Korobeynikov <anton@korobeynikov.info>