10

我一直在玩LLVM ,希望学习如何使用它。

然而,界面的复杂程度让我大吃一惊。

以他们的斐波那契函数为例

int fib(int x) {
    if(x<=2) 
        return 1;
    return fib(x-1) + fib(x-2);
   }

要让它输出 LLVM IR,需要61 行代码!!!

它们还包括以拥有最小编译器(200 字节)而闻名的 BrainFuck。不幸的是,使用 LLVM,它超过600 行(18 kb)。

这是编译器后端的规范吗?到目前为止,执行汇编或 C 后端似乎要容易得多。

4

4 回答 4

18

问题在于 C++ 而不是 LLVM。

使用专为元编程设计的语言,如OCaml,您的编译器将大大缩小。例如,这篇 OCaml Journal 文章描述了一个 87 行的基于 LLVM 的 Brainfuck 编译器这篇邮件列表文章描述了完整的编程语言实现,包括可以编译 Fibonacci 函数(以及其他程序)的解析器,整个编译器不到 100 行 OCaml代码使用 LLVM,而HLVM 是一个高级虚拟机,使用 LLVM 在 2,000 行以下 OCaml 代码中具有多核垃圾收集功能

于 2009-05-12T18:54:33.983 回答
1

LLVM 是否不会根据后端实现的特定架构来优化 IR?IR 代码不会直接 ​​1:1 转换成最终的二进制文件。据我了解,这就是它的工作原理。但是,我才刚刚开始使用后端(我将其移植到自定义处理器上)。

于 2009-04-09T07:58:09.020 回答
1

LLVM 确实需要一些样板代码,但是一旦你理解了它,它真的很简单。尝试寻找一个简单的 GCC 前端,你就会意识到 LLVM 是多么的干净。我肯定会推荐 LLVM 而不是 C 或 ASM。ASM 根本不可移植,生成源代码通常是一件坏事,因为它会使编译速度变慢。

于 2009-04-09T14:46:36.073 回答
1

与非虚拟汇编器相比,中间表示可能有点冗长。我了解到查看 .NET IL,尽管我从来没有比查看更进一步。我对 LLVM 不是很熟悉,但我想这是同一个问题。

但是,当您考虑它时,它是有道理的。一个很大的区别是 IR 必须处理大量元数据。在汇编器中几乎没有 - 处理器隐含地定义了很多,而函数调用之类的约定留给程序员/编译器来定义。这很方便,但会带来很大的可移植性和互操作问题。

.NET 和 LLVM 等中间表示关心确保单独编译的组件可以一起工作——即使是用不同语言编写并由不同编译器前端编译的组件。这意味着需要元数据来描述在更高级别上发生的事情,例如,可能是参数处理的任意推送、弹出和加载,但可能只是任何事情。回报是相当大的,但要付出代价。

还有其他问题。中间表示并不是真的要由人类编写,但它应该是可读的。此外,它的通用性足以在多个版本中生存,而无需完全不兼容的从头重新设计。

基本上,在这种情况下,显式几乎总是比隐式好,因此很难避免冗长。

于 2009-10-09T01:48:07.853 回答