Answers:
给定一些C / C ++文件foo.c
:
> clang -S -emit-llvm foo.c
产生foo.ll
哪个是LLVM IR文件。
该-emit-llvm
选项也可以直接传递给编译器前端,而不是通过以下方式传递给驱动程序-cc1
:
> clang -cc1 foo.c -emit-llvm
foo.ll
用IR 产生。-cc1
添加了一些很酷的选项,例如-ast-print
。查看-cc1 --help
更多详细信息。
要在组装时进一步编译LLVM IR,请使用以下llc
工具:
> llc foo.ll
产生foo.s
装配体(默认为您在其上运行的机器体系结构)。llc
是LLVM工具之一- 这是其文档。
用
clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
.o
应该引用二进制目标文件,.s
程序集文件,以及其他(按约定.ll
)到LLVM IR文件。否则很容易混淆。Clang / LLVM现在没有自己的二进制对象链接器(尽管有一个链接正在编写中)。LLVM的链接llvm-ld
只是加入一些IR文件合并成一个
.bc
使用clang前端实际上会做正确的事;还有,请记住,llvm-ld
可以作为前端的系统工具链行事,即我以前的答案使用llvm-ld -native
应该按预期工作....
foo.bc
是LLVM位代码文件
clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode
。
如果您有多个源文件,则实际上可能要使用链接时间优化来为整个程序输出一个位代码文件。给出的其他答案将导致您最终为每个源文件得到一个位码文件。
相反,您想使用链接时间优化进行编译
clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o
在最后的链接步骤中,添加参数-Wl,-plugin-opt = also-emit-llvm
clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program
这样既可以提供已编译的程序,也可以提供与之相对应的位代码(program.bc)。然后,您可以按照自己喜欢的任何方式修改program.bc,并通过以下方式随时重新编译修改后的程序
clang program.bc -o program
尽管请注意,您需要在此步骤中再次包括任何必要的链接器标志(用于外部库等)。
请注意,您需要使用黄金链接器才能正常工作。如果要强制clang使用特定的链接程序,请在计算机上某个特殊目录“ fakebin”中创建指向该链接程序“ ld”的符号链接,并添加选项
-B/home/jeremy/fakebin
到上述任何链接步骤。
如果您有多个文件,并且不想键入每个文件,我建议您按照以下简单步骤操作(我正在使用,clang-3.8
但可以使用任何其他版本):
生成所有.ll
文件
clang-3.8 -S -emit-llvm *.c
将它们链接到一个
llvm-link-3.8 -S -v -o single.ll *.ll
(可选)优化代码(可能是一些别名分析)
opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
生成程序集(生成optimised.s
文件)
llc-3.8 optimised.ll
创建可执行文件(名为a.out
)
clang-3.8 optimised.s
-S
选项(在第2步中),我指定要在LLVM IR中生成输出。基本上,将所有* .ll文件放入一个文件中。我这样做是为了检查最佳化真正改变的代码,即single.ll
而optimised.ll
现在看起来应该不同(代码明智),你也可以显示报告,看看是否有在所有任何区别。
-basicaaa
是错误的标志,-basicaa
必须改用。