2012-06-03 123 views
11

如何在LLVM中聲明stdinstoutstderr(最好是C版本)?我正在嘗試使用我創建的玩具語言中的某些stdio函數。一個這樣的功能是fgetsLLVM stdin/stdout/stderr

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中編寫什麼來聲明stdinstoutstderr,像fgets這樣的函數,就像玩具語言編譯器一樣?

+0

你可以在C中編寫幫助函數,它將返回stdin/stdout/stderr並將它們與你的程序連接起來。 –

+0

我會盡力,儘管如果可以的話,我寧願使用LLVM API給我們做的事情。 – tophat

回答

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

它是平臺特定的。有時stdin是宏的不同的符號名稱。

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

對於Microsoft Visual C++,標準輸入是#define stdin (&__iob_func()[0])

所以,你真的需要看看你的平臺stdio.h頭找出答案。

+0

那麼,那麼我需要在LLVM API中編寫什麼來聲明stdin,例如,在玩具語言編譯器中? – tophat

+0

你需要查看你的platfrom'stdio.h'頭文件來找出用於stdio的符號/聲明,因此它與您將使用的C運行時庫正確鏈接。 –

5

如果您使用的功能,如putcharprintfgetsstrtolputs,fflush你將不需要0​​和stdout。我編寫了一個玩具編譯器,這些足夠I/O字符串和整數。 fflush被調用爲空,並且stdout被刷新。

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