2012-02-05 90 views
104

我想铛编译我C/C++代码LLVM字节码而不是二进制可执行文件。我怎样才能做到这一点?如果我得到LLVM字节码,我该如何将它进一步编译为二进制可执行文件。如何使铛编译成LLVM IR

基本上我想编译成二进制可执行文件之前添加一些我自己的代码到LLVM字节码。

回答

143

鉴于一些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工具之一 - here is its documentation

+3

什么-S在这里做? – meawoppl 2014-02-27 16:17:53

+8

@meawoppl:-S像gcc中说的那样发出文本汇编而不是汇编二进制 – 2014-02-28 16:53:26

+0

Ahha。我很难在关于它的文档中找到任何内容。可以肯定的是,铿锵声中的许多标志镜像gcc标志结构? – meawoppl 2014-02-28 17:35:25

16

使用

clang -emit-llvm -o foo.bc -c foo.c 
clang -o foo foo.bc 
+6

我建议保持扩展的含义不变。 IOW中,'.o'应该指向二进制目标文件,将'.s'指定为汇编文件,以及其他指令(按照惯例'.ll')指向LLVM IR文件。否则很容易混淆。 Clang/LLVM现在没有自己的二进制对象链接器(尽管其中一个正在工作中)。 LLVM链接器'llvm-ld'只是将几个IR文件合并到一个文件夹中: – 2012-02-05 13:06:51

+1

@EliBendersky:在涉及文件扩展名的地方你是正确的 - 如果使用'.bc',clang前端实际上做得正确;另外,请记住,'llvm-ld'可以作为系统工具链的前端,也就是说,我以前使用'llvm-ld -native'的答案应该按预期工作.... – Christoph 2012-02-05 13:13:10

+0

不起作用。 foo.bc是一个对象文件。 – rickfoosusa 2014-09-25 21:15:04

17

如果你有多个源文件,你可能真的想使用链接时优化输出一个位码文件的整个程序。给出的其他答案会导致您最终得到每个源文件的位码文件。

相反,你想链接时优化

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

和最终链接步骤来编译,添加参数轮候册,-plugin-OPT =也-发出-LLVM

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program 

这给你已编译的程序和与之对应(program.bc)的位码。然后,您可以修改program.bc在任何你喜欢的方式,这样做

clang program.bc -o program 

在任何时候重新编译修改的程序,虽然知道你需要包括任何必要的连接标志(外部库等)在这一步再次。

请注意,您需要使用金连接器这个工作。如果要强制铛使用特定的连接,创建一个符号连接到连接在叫你的计算机上的“fakebin”的地方一个特殊的目录名为“LD”,并添加选项

-B/home/jeremy/fakebin 

到任何连接步骤以上。

+1

这非常有帮助,谢谢! – baibo 2015-01-29 23:18:08

5

如果你有多个文件,你不希望有键入每个文件,我建议你遵循这些简单的步骤(我用clang-3.8但你可以使用任何其他版本):

  1. 生成所有.ll文件

    clang-3.8 -S -emit-llvm *.c 
    
  2. 它们链接到一个单一的一个

    llvm-link-3.8 -S -v -o single.ll *.ll 
    
  3. (可选)优化你的代码(也许有些别名分析)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll 
    
  4. 生成汇编(生成optimised.s文件)

    llc-3.8 optimised.ll 
    
  5. 创建可执行文件(命名为a.out

    clang-3.8 optimised.s 
    
+0

您的解决方案非常独特:您使用“-S”而不是将其作为二进制输出。有“-S”和没有“-S”有没有区别? – 2017-09-24 01:46:55

+0

@PeterTeoh我使用'-S'选项(在步骤2中),我指定我想在LLVM IR中生成输出。基本上,所有的* .ll文件放在一个单一的。我这样做是为了检查优化是否真的改变了代码,即'single.ll'和'optimised.ll'现在应该看起来不同(代码方式),并且您还可以显示报告以查看是否存在任何差异。 – 2017-10-16 07:39:16