llvm使用心得
常用llvm命令
# 将.c编译为bitcode
clang -emit-llvm -c test.c# 将bitcode反汇编为ir
llvm-dis test.bc# 将ir转成bitcode
llvm-as test.ll# 用lli执行bitcode或ir
lli test.bc
lli test.ll# llc将bitcode或ir转成目标汇编
llc test.bc
llc test.ll# as将汇编转成目标文件
as -o test.o test.s# ld将目标文件链接成可执行文件
ld test.o -lc -o test_exe
定义字符串
llvm里,字符串有个类似字符串常量池的东西,里面定义了代表字符串内容的global var:
@".str0" = private unnamed_addr constant [2 x i8] c"a\00", align 1
使用字符串的时候,用getelementptr命令引用:
define i8* @"run"()
{
entry:%"__t0" = getelementptr [2 x i8], [2 x i8]* @".str0", i32 0, i32 0ret i8* %"__t0"
}
注意后面2个indice=0的参数,第一个0表示,getelementptr从[2 x i8]*里取得第一个也是唯一一个元素(索引为0),其类型是[2 x i8],第二个0表示再取这个char array的第一个元素的地址,相当于C里的&arr[0],返回的自然是i8*。
可见,getelementptr是很强大的,它可以取得一个嵌套结构里的任意成员。
basic block
llvm ir的构建,基于的是basic block,指令是放在basic block里。basic block正是编译原理里的概念:除了最后一条指令外,不包含条件或无条件跳转的指令集合。
经验总结
- 使用IR构建DSL的过程,就像用汇编开发程序的过程
- 如果不清楚IR如何表达,可用C写一段简单代码,再用clang -emit-llvm -S转成ir后看一下人家怎么翻译的。