使用 LLVM 链接器生成 C 代码

Posted

技术标签:

【中文标题】使用 LLVM 链接器生成 C 代码【英文标题】:Using the LLVM linker to produce C code 【发布时间】:2015-08-12 08:48:04 【问题描述】:

我尝试使用以下命令从llvm-g++ 编译的 C++ 代码生成 C 代码:

llvm-g++ -emit-llvm -c ./example.cpp -o example.o
llc -march=c example.o

我在运行 Ubuntu (Linux 3.16.0-45-generic) 的机器上尝试了这些命令。

但是,LLVM 静态链接器没有将 C 代码写入标准输出,而是报告编译的文件无效:error: expected top-level entity

如何?

【问题讨论】:

【参考方案1】:

原来的 C 后端 (llvm-cbe) 在 3.1 (release notes) 中被删除,但是有这个 Julia 项目,resurrected LLVM "C Backend", with improvements,它复活了它。

【讨论】:

【参考方案2】:

不幸的是,在 Ubuntu 系统上发出 LLVM 位码可能会有点痛苦,因为它们将 DragonEgg 作为默认前端 - 请参阅 this question 和 this bugreport。

如果您对上面生成的文件执行file example.o,您会发现它实际上不是 LLVM IR 位码(它解释了错误):

$ file example.o
example.o: ELF 64-bit LSB  relocatable, x86-64, version 1 (SYSV), not stripped

在 Ubuntu 系统上获取 LLVM IR 位码的最简单方法是使用 clang:

$ clang -emit-llvm -c example.cpp -o example.o
$ file example.o
example.o: LLVM IR bitcode

也就是说,在 LLVM 3.1 中删除了 C 后端(请参阅 release notes 和 this question)。正如您从 llc -version 的输出中看到的那样,它没有被列出,并且尝试使用它会在我的 Ubuntu 14.04 系统上出现以下错误:

llc-3.4: error: invalid target 'c'.

【讨论】:

【参考方案3】:

正如手册页所说:

The llc command compiles LLVM source inputs
into assembly language for a specified architecture.

它不会对目标文件进行逆向工程以生成 C 文件(这是您想要实现的),这对我来说毫无意义。

要了解支持哪些架构(大致意思是可以使用哪个 CPU):

 llc -version

(您会注意到“C”不是架构)。

如果您尝试将一段 C++ 代码重写为 C,最好的办法是手动完成。您需要在 C 中重写所有 C++ 特定的东西(类、异常、模板等),这将花费或多或少的时间,具体取决于 C++ 代码的复杂性。

【讨论】:

OP 想要将 LLVM IR 位码转换为 C(注意 -emit-llvm 选项,它应该生成位码而不是目标文件)。它在早期版本中受支持(例如,参见this FAQ),但在 3.1 中删除了 C 后端 (release notes)。

以上是关于使用 LLVM 链接器生成 C 代码的主要内容,如果未能解决你的问题,请参考以下文章

重新排序 gnu autotools 链接器标志

Xcode - 链接器命令失败,退出代码为 1

C编译器链接器加载器详解

链接器可以内联函数吗?

链接器错误 2019 C++,VS2008

指定要生成的备用编译器和链接器