问题 LLVM stdin / stdout / stderr


如何宣布 stdinstout,和 stderr LLVM中的(最好是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中编写什么来声明 stdinstout,和 stderr 对于像 fgets 像玩具语言编译器?


9876
2018-06-03 02:04


起源

您可以在C中编写辅助函数,它将返回stdin / stdout / stderr并将它们与您的程序链接。 - Piotr Praszmo
我会试试,虽然我更愿意只使用LLVM API为我们做的事情,如果可以的话。 - tophat


答案:


如果有人有兴趣,我找到了我的问题的答案。经过一番激烈的搜索,我找到了一种方法来获得 stdin 流而不必进行C扩展: fdopen 和制作 FILE 一个不透明的结构。

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

当fdopen为文件描述符传递0时(fildes)它返回 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))

6
2018-06-03 17:54





如果你使用像 putcharprintfgetsstrtolputsfflush 你不需要 stdin 和 stdout。我写了一个玩具编译器,这对于带有字符串和整数的I / O来说已经足够了。 fflush 用null调用 stdout 脸红了。

%struct._IO_FILE = type opaque
declare i32 @fflush(%struct._IO_FILE*)
...
call i32 @fflush(%struct._IO_FILE* null)
...

5
2017-10-18 11:54





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

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

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

所以你真的需要调查你的平台 stdio.h 标题来说明这一点。


1
2018-06-03 04:23



那么,我需要在LLVM API中编写什么来声明stdin,例如玩具语言编译器? - tophat
你需要调查你的平台 stdio.h 标头用于确定用于stdio的符号/声明,因此它将与您将使用的C运行时库正确链接。 - Mārtiņš Možeiko