如何将 clang 编译成 llvm IR

我想叮当编译我的 C/C + + 代码到 LLVM 位代码,而不是一个二进制可执行文件。我怎么才能做到呢?

如果我有 LLVM 位代码,我如何进一步编译它到一个二进制可执行文件?

在编译成二进制可执行文件之前,我想在 LLVM 位代码中加入一些我自己的代码。

130232 次浏览

你读过 clang文档吗? 你可能在找 -emit-llvm

给定一些 C/C + + 文件 foo.c:

> clang -S -emit-llvm foo.c

生成一个 LLVM IR 文件 foo.ll

-emit-llvm选项也可以直接传递给编译器前端,而不是通过 -cc1传递给驱动程序:

> clang -cc1 foo.c -emit-llvm

使用 IR 生产 foo.ll-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

如果您有多个源文件,您可能实际上想要使用链接时间优化来为整个程序输出一个位码文件。给出的其他答案将导致您最终为每个源文件提供一个位码文件。

相反,您希望使用链接时间优化进行编译

clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o

对于最后一个链接步骤,添加参数 -Wl,-plugin-opt = also-sent-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,但您可以使用任何其他版本) :

  1. 生成所有 .ll文件

    clang-3.8 -S -emit-llvm *.c
    
  2. link them into a single one

    llvm-link-3.8 -S -v -o single.ll *.ll
    
  3. (Optional) Optimise your code (maybe some alias analysis)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
    
  4. Generate assembly (generates a optimised.s file)

    llc-3.8 optimised.ll
    
  5. Create executable (named a.out)

    clang-3.8 optimised.s