LLVM stdin / stdout / stderr

时间:2012-06-03 02:04:44

标签: llvm

如何在LLVM中声明stdinstoutstderr(最好是C版本)?我试图在我正在创建的玩具语言中使用一些stdio函数。其中一个功能是fgets

char * fgets ( char * str, int num, FILE * stream );

为了使用我需要的stdin。所以我编写了一些LLVM API代码来生成我找到的FILE定义,并将stdin声明为外部全局。代码生成了这个:

%file = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %marker*, %file*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
%marker = type { %marker*, %file*, i32 }

@stdin = external global %file*

但是,当我运行生成的模块时,它给了我这个错误:

Undefined symbols for architecture x86_64:
"_stdin", referenced from:
    _main in cc9A5m3z.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

显然,我写的不起作用。所以我的问题是我必须在LLVM API中编写什么来为像玩具语言编译器之类的函数stdin这样的函数声明stoutstderrfgets

3 个答案:

答案 0 :(得分:6)

如果有人有兴趣,我找到了我的问题的答案。经过一番激烈的搜索后,我找到了一种方法来获取stdin流而无需进行C扩展:fdopen并使FILE成为不透明的结构。

FILE* fdopen (int fildes, const char *mode)

当fdopen为文件描述符(fildes)传递0时,它返回stdin流。使用LLVM API,我生成了以下LLVM程序集:

%FILE = type opaque
declare %FILE* @fdopen(i32, i8*)
@r = constant [2 x i8] c"r\00"

然后我能够使用此调用语句检索stdin

%stdin = call %FILE* @fdopen(i32 0, i8* getelementptr inbounds ([2 x i8]* @r, i32 0, i32 0))

答案 1 :(得分:5)

如果您使用putcharprintfgetsstrtolputsfflush这样的功能,您将不再需要stdinstdout。我写了一个玩具编译器,这对于带有字符串和整数的I / O来说已经足够了。 <{1}}被调用为null,fflush被刷新。

stdout

答案 2 :(得分:1)

这是特定于平台的。有时stdin是不同符号名称的宏。

在Android上,例如,stdin是#define stdin (&__sF[0])

对于Microsoft Visual C ++,stdin为#define stdin (&__iob_func()[0])

所以你真的需要调查你的平台stdio.h标题来解决这个问题。