我正在学习通过尝试重现hello world示例来编写LLVM传递。通过hello.cpp
看起来像:
#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
如下所示:
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
使用以下命令行编译程序:clang world.c -c -emit-llvm -O3 -o world.bc
llvm-dis
生成的bitcode看起来像:
; 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)"}
当我在bitcode上运行传递时:opt -load hello/libhello.so -hello src/world.bc > /dev/null
,输出为:
Hello: main
但是,tutorial声称输出应该是:
Hello: __main
Hello: puts
Hello: main
为什么前两个函数没有触发我的传球?
答案 0 :(得分:1)
我已阅读该教程,但我从未见过任何名为__main
的符号。
我一直认为它曾经是旧版LLVM / Clang的某种遗物,插入并用作可执行文件的入口点。
无论如何,bitcode文件中没有任何具有此类名称的函数的定义或声明。
此外,我认为输出的puts
函数是教程中的错误。函数传递应该在函数的 body 上执行分析/转换。对puts
的引用只是一个声明,因为它是在C
标准库中定义的外部符号,它将在链接期间解析。它没有在bitcode文件中定义的主体。
如果您还需要完成功能声明,则需要创建Module
通行证并使用isDeclaration()
function来区分它们。