2009-09-13 154 views
10

我正在爲語言Timber編寫LLVM代碼生成器,當前編譯器會發出C代碼。我的問題是我需要從生成的LLVM文件調用C函數,例如編譯器有一個實時垃圾回收器,我需要調用函數來通知何時在堆上分配新對象。我不知道如何將這些函數與我生成的LLVM文件鏈接起來。LLVM - 鏈接問題

代碼生成是由生成.ll文件,然後手動編譯這些。

我想從LLVM調用一個外部函數,但我沒有運氣。在我已經發現的例子中,只發現了像「puts」和「printf」這樣的C標準函數,但我想調用一個自制函數。我卡住了。

+0

您的意思是說您要直接在LLVM IR中編寫代碼,而您無法撥打電話,或者您正在使用LLVM編譯代碼並遇到問題? – 2009-09-13 23:56:54

回答

5

與LLVM,因爲通常編譯您的LLVM彙編文件:

llvm-as *.ll 

編譯位碼文件.S彙編語言文件:

llc *.bc 

GCC它們在運行時庫:

gcc *.s runtime.c -o executable 

如果需要,在真正的makefile,共享庫等中替換。你明白了。

12

我假設你正在編寫一個LLVM轉換,並且你想將外部函數的調用添加到轉換後的代碼中。如果情況並非如此,請編輯您的問題並提供更多信息。

在您可以從LLVM代碼調用外部函數之前,您需要爲其插入一個聲明。例如:

virtual bool runOnModule(Module &m) { 
    Constant *log_func = m.getOrInsertFunction("log_func", 
               Type::VoidTy, 
               PointerType::getUnqual(Type::Int8Ty), 
               Type::Int32Ty, 
               Type::Int32Ty, 
               NULL); 
    ... 
} 

上面的代碼聲明的函數log_func返回空隙和三個參數:一個字節的指針(字符串),和兩個32位的整數。 getOrInsertFunctionModule的一種方法。

要真正調用函數,您必須插入一個CallInst。有幾個靜態的Create方法。

+0

這就是我正在試圖找出llvm所做的,謝謝! – Dan 2009-11-28 23:29:40

3

我把你的問題解釋爲「如何在C或C++中爲編譯爲LLVM的語言實現運行時庫?」

由Jonathan Tang詳細介紹的一種方法是將編譯器的輸出從LLVM IR轉換爲位編碼,然後將程序集與運行時源(或對象文件)相鏈接。

另一種可能更靈活的方法是使用llvm-gcc將運行時本身編譯爲LLVM位代碼,然後使用llvm-ld將編譯器的位代碼與運行時的位代碼鏈接起來。然後這個位代碼可以用opt重新優化,通過llvm-dis轉換回IR,直接用lli解釋(這樣做,afaik,只有在LLVM是根據libffi構建的情況下才能工作),或者編譯爲與llc(然後是本機二進制與香草gcc)。