2017-04-15 51 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

相关问题