2017-04-15 49 views
2

我正在學習編寫LLVM傳遞,試圖重現hello world示例。通hello.cpp看起來像:爲什麼基於FunctionPass的LLVM通過某些函數不會被觸發?

#include "llvm/Pass.h" 
#include "llvm/IR/Function.h" 
#include "llvm/Support/raw_ostream.h" 

using namespace llvm; 

namespace { 
    struct Hello : public FunctionPass { 
    static char ID; 
    Hello() : FunctionPass(ID) {} 

    bool runOnFunction(Function &F) override { 
     errs() << "Hello: "; 
     errs().write_escaped(F.getName()) << '\n'; 
     return false; 
    } 
    }; 
} 

char Hello::ID = 0;9 
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false); 

示例程序world.c看起來像:clang world.c -c -emit-llvm -O3 -o world.bc

通過llvm-dis產生的位碼是這樣的:

#include <stdio.h> 

int main() { 
    printf("Hello World\n"); 
    return 0; 
} 

該程序是使用下面的命令行編譯的:

; ModuleID = 'src/hello.bc' 
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-unknown-linux-gnu" 

@str = private unnamed_addr constant [12 x i8] c"Hello World\00" 

; Function Attrs: nounwind uwtable 
define i32 @main() #0 { 
    %puts = tail call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @str, i64 0, i64 0)) 
    ret i32 0 
} 

; Function Attrs: nounwind 
declare i32 @puts(i8* nocapture) #1 

attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } 
attributes #1 = { nounwind } 

!llvm.ident = !{!0} 

!0 = !{!"clang version 3.8.0 (tags/RELEASE_380/final)"} 

當我運行在位碼通:opt -load hello/libhello.so -hello src/world.bc > /dev/null,輸出爲:

Hello: main 

然而,tutorial聲稱,輸出應該是:

Hello: __main 
Hello: puts 
Hello: main 

爲什麼我的傳球沒有得到觸發前兩個功能?

回答

1

我讀過那篇教程,但是我從未見過名爲__main的任何符號。 我一直認爲它曾經是LLVM/Clang舊版本中的某種遺留物,插入並用作可執行文件的入口點。

無論如何,您的位代碼文件中沒有任何具有此類名稱的函數的定義或聲明。

此外,我認爲正在輸出的puts函數在本教程中是一個錯誤。函數通過應該對函數的主體執行分析/轉換。對puts的引用僅僅是一個聲明,因爲它是在C標準庫中定義的外部符號,它將在鏈接期間解析。它沒有在位碼文件中定義的主體。

如果您還需要通過函數聲明,那麼您需要創建一個Module通行證並使用isDeclaration()function調用來區分它們。

+0

你說的話很有道理。但是,我想知道他們是如何提出上面列出的輸出的。我的意思是,如果官方文件是如此虛假,我感到很驚訝。 –

+0

@ Holmes.Sherlock我認爲這只是疏忽。這個例子的目標更多地是建立和運行機器;除此之外,還有doxygen生成的doc和源代碼本身。該文件是在svn回購下,所以我想任何人都可以修改它。 – compor

相關問題