对于编写编译器,将LLVM IR与C用于目标语言的优缺点是什么?我知道两者都被使用,我想如果我使用 clang 来编译 C,最终的机器代码会相似。那么还有什么需要考虑的呢?
我已经将LLVM IR用于一些编译器后端,并使用了使用C作为后端的编译器。我发现给LLVM IR带来优势的一件事是它是类型的。很难在不从 LLVM 库获得错误的情况下制作完全格式错误的输出。
在我看来,在源代码和 IR 之间保持密切关联以进行调试也更容易。
此外,您还可以获得所有很酷的LLVM命令行工具来分析和处理前端发出的IR。
LLVM的优势:
- JIT - 可以动态编译和运行代码。当然,C也可以这样做(例如,使用嵌入式
tcc
),但它是一个不那么健壮和可移植的选项。 - 您可以在生成的 IR 上运行自己的优化传递。
- 免费反射 - 使用 LLVM 检查生成的代码要容易得多。
- LLVM库没有大多数C编译器那么大(当然,不包括
tcc
)。
LLVM 的缺点:
- 代码是不可移植的,您必须根据目标稍微更改它。LLVM有一个可移植的子集,但它仍然是一个狡猾的做法。
- 运行时对C++库的依赖性可能是一个问题。
我怀疑在面向 C 时能否为您的语言实现正确的调试支持。
没有CLANG或处于实验状态的体系结构和操作系统。
C 语言被广泛接受,但 LLVM IR 允许您为 LLVM 引擎提供勺子。并非所有通往 IR 的路径都是相同的。
我将使用LLVM来引用框架,并使用LLVM IR来引用目标语言。
C 优势
- 跨平台
- 调试(请阅读下文。它部分与第 4 点有关。
- 互操作性
- 易于使用
LLVM IR 优势
- 性能
- 自定义选项
- 内存占用
- 强打字/安全
C
-
存在用于各种嵌入式系统的C编译器,尽管LLVM最近获得了更多的目标。可以说,在这个类别中,C比LLVM IR(中间表示)略有优势。
-
针对 C 而不是 LLVM 的主要优点是,与 LLVM 相比,生成的代码处于更高的级别。使用标准化调试器(如 GDB),可以说更容易推理生成的代码的行为。使用调试器(如 GDB)为编译为 C 的语言构造调试器也更容易。
-
第三点。互操作性更挑剔。但是,C 具有标准化的应用程序二进制接口。因此,编写库并将这些库与用 C 和/或 C+ 编写的其他程序接口更容易。尽管如此,许多语言,如Java,都为C提供了标准化的接口。
-
可以说,通过针对 C 更容易入门并让某些东西工作
LLVM
-
C 是一种相当高级的语言,如果不按习惯编写,性能可能会下降(取决于目标编译器以及编译器所做的假设)。有一些论文,例如GHC的llVM后端这说明了 C 语言的一些缺点以及 LLVM IR 作为目标语言的优点。
-
由于 LLVM(框架)是作为可重用单元的集合构建的,因此很容易为特定目标语言编写特定于目标语言的传递。编写自定义 GC 也更容易(截至 2020 年,对此有一些支持)。在C的情况下,这也是可能的,并且有一些垃圾收集器,例如Boehm GC。但是,C 不是作为中间语言设计的。
-
内存占用。与 LLVM 位码相比,生成的 C 代码具有更大的内存占用。如果您正在编译和链接一个大型系统,您可能会获得针对LLVM的编译时间优势。
-
而 C 是弱类型语言。LLVM IR 是一个强类型。因此,可以说以LLVM IR为目标更安全。