我希望使用 clang 将我的 C/C++ 代码编译为 LLVM 比特码,而不是二进制可执行文件。我该如何实现?
如果我已经有了 LLVM 比特码,如何将其进一步编译为二进制可执行文件?
我想在将 LLVM 比特码编译为二进制可执行文件之前添加一些自己的代码。
给定一个 C/C++ 文件 foo.c
:
> clang -S -emit-llvm foo.c
生成一个LLVM IR文件 foo.ll
。
可以通过直接向编译器前端传递 -emit-llvm
选项,而不是通过 -cc1
驱动程序来传递。
> clang -cc1 foo.c -emit-llvm
使用 -cc1
可以生成带有IR的foo.ll
文件。同时,-cc1
还提供了一些很酷的选项,如-ast-print
。想了解更多细节,请查看-cc1 --help
。
要将LLVM IR进一步编译为汇编,请使用llc
工具:
> llc foo.ll
使用llc
工具生成汇编文件 foo.s
,默认为您运行它的机器体系结构。 llc
是LLVM工具之一 - 这里是其文档。
如果您有多个源文件,您可能确实想要使用链接时优化来输出整个程序的一个位码文件。其他提供的答案将导致您最终针对每个源文件都有一个位码文件。
相反,您需要使用链接时优化编译。
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
请注意,在这一步中,您需要包括任何必要的链接器标志(用于外部库等)。
请注意,您需要使用gold链接器才能使此操作起作用。如果您想强制clang使用特定的链接器,请在计算机上的一个名为“fakebin”的特殊目录中创建指向该链接器的符号链接,并添加选项。
-B/home/jeremy/fakebin
到任何上面的链接步骤。
also-emit-llvm
已被移除。 - Heath Mitchell如果您有多个文件,不想一个一个地输入每个文件名,我建议您按照以下简单步骤操作(我使用的是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
-basicaaa
是错误的标志,应该使用-basicaa
代替。 - anton_rh使用
clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
.bc
,clang前端实际上会做正确的事情;另外,请记住,llvm-ld
可以作为系统工具链的前端,即我之前使用llvm-ld -native
的答案应该按预期工作.... - Christophfoo.bc
是一个LLVM位码文件。 - Christophclang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode
. - ntc2