编译为LLVM的问题

时间:2009-04-09 06:46:25

标签: c compiler-construction llvm backend

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

然而,我的想法被界面的复杂程度所困扰。

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

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

要使其输出LLVM IR,需要 61行代码 !!!

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

这是编译器后端的标准吗? 到目前为止,似乎更容易进行汇编或C后端。

4 个答案:

答案 0 :(得分:17)

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

使用专为元编程设计的语言,如OCaml,您的编译器将会小得多。例如,this OCaml Journal article describes an 87-line LLVM-based Brainfuck compilerthis mailing list post describes complete programming language implementation including parser可以编译Fibonacci函数(在其他程序中),整个编译器使用LLVM和HLVM is a high-level virtual machine with multicore-capable garbage collection in under 2,000 lines of OCaml code using LLVM在100行OCaml代码下。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

与非虚拟汇编程序相比,中间表示可能有点冗长。我学会了看.NET IL,虽然我从来没有比看起来更进一步。我对LLVM并不熟悉,但我想这也是同样的问题。

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

.NET和LLVM之类的中间表示关心确保单独编译的组件可以一起工作 - 甚至是用不同语言编写并由不同编译器前端编译的组件。这意味着需要元数据来描述比更高级别更高级别的内容。可能是参数处理的任意推送,弹出和加载,但可能只是任何事情。收益很大,但要付出代价。

还有其他问题。中间表示并不真正意味着由人类编写,但它意味着可读。此外,它的通用性足以在没有完全不兼容的从头开始重新设计的情况下存活多个版本。

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