【问题标题】:The perks and the pipeline for an LLVM based compilation基于 LLVM 的编译的特权和管道
【发布时间】:2013-12-23 09:15:00
【问题描述】:

我看到越来越多的人转向 LLVM,尤其是有 C 或 C++ 背景的人,所以有一种模式,其中有一种人正在接近这个编译器,令我惊讶的是高度异构的技术集LLVM 可以管理,我不知道这个虚拟机遵循什么管道以及由此产生的好处。

我想强调一个事实,我专注于 LLVM,而不是真正的 clang。

百万分之一的例子是this one ( Youtube Video ),其中管道对我来说并不明显,或者this other one,但显然有很多完全不同的解决方案,例如,LLVM 与JIT 解决方案。

简而言之,我看到了不同的语法和语义,人们使用 LLVM 来生成 GPU 着色器或二进制对象,但我看不到共同点。

“基于LLVM的编译”是什么意思,把LLVM看成一个黑盒子,输入输出是什么样的,中间的业务逻辑是什么?

【问题讨论】:

    标签: llvm


    【解决方案1】:

    我看不到共同点。

    共同点是将一种语言的代码转换为另一种语言的代码。这正是编译器所做的。所以如果你想把一段“源语言”的代码转换成一个“目标语言”的代码,你需要做的是:

    1. 编写一个“前端” - 一个将源语言转换为 LLVM 期望输入的组件。该语言是一种特定于 LLVM 的语言,称为“LLVM Bitcode”或“LLVM IR”。
      • 或者,重用现有前端 - 例如 Clang。
    2. 编写“后端” - 一个将 LLVM 发出的内容转换为目标语言的组件。
      • 或者使用现有的后端,例如 LLVM 的 x86 后端。

    就是这样。现在您可以享受 LLVM 在其输入和输出之间对其代码执行的优化、将代码“降低”为更接近机器代码的通用框架等内容。

    GCC 的行为是一样的,顺便说一下,只是 LLVM 在某些方面被许多人认为是优越的,特别是许可和易于修改。

    【讨论】:

    • 好的,但是,以 GLSL 为例,LLVM 并不真正了解 GLSL 作为一种语言,所以我为它编写了一个前端,但如果 LLVM 一开始并不真正了解 GLSL地方,它如何优化我的源代码?这些东西有一个指南,所以我可以阅读一些关于它的东西?
    • @user2485710 LLVM 也不知道 C,但它仍然可以优化它。关键是它真的只知道一种语言——它的 IR(中间表示)——但它可以很好地优化它,所以你需要做的就是转换为那个 IR。大多数(如果不是全部)优化编译器都以这种方式工作 - 作为另一个示例,JVM 完全不了解 Java(语言) - 它只知道运行 Java 字节码,这也是一种中间表示形式。
    • 我认为这就是为什么例如Android下的Dalvik可以同时用于Java和C/C++/native代码的原因?您能推荐一些关于使用 LLVM 创建前端或后端的内容吗?
    • @user2485710 编译是一个广泛的领域,如果您真的感兴趣,我建议您阅读course on compilation 或阅读一些good basic book on the topic。不过,如果您想直接加入,请查看this LLVM tutorial。有关后端设计的一些信息,请查看this backend-writing guide,但请记住它专注于基于寄存器的机器代码生成。
    【解决方案2】:

    LLVM 相对于其他可用源代码的编译器的优势在于它被设计为一组可重用的库。这意味着在某种程度上,您可以选择要包含在您的工具中的内容。不是每个语言工具都需要优化,也不是每个语言工具都需要代码生成。 LLVM 是一个非常灵活的语言处理系统。

    通常当人们说“基于 LLVM 的编译”时,他们的意思是使用一个或多个 LLVM 库来实现他们的工具。他们可以利用 LLVM 的所有工作来理解其 IR 并为多个目标生成代码。

    LLVM IR 是大多数 LLVM 库使用的通用表示。这是您需要写入的接口。对于机器代码等低级内容,您将需要处理一些其他 LLVM 表示(MachineInstr、MC 等)。

    至于编写前端来生成 LLVM IR,棘手的部分是确保从源语言到 LLVM IR 的翻译保留源语言的语义。 LLVM IR 对每条指令都有一套定义良好但低级的语义。如果您的源语言具有更高级别的语义,您将不得不将它们降低为 LLVM IR 指令序列来实现它。例如,没有处理 C 样式位域访问的 LLVM 指令,因此 C 语言前端必须使用一系列 LLVM 指令来实现功能(通常是移位和按位运算)。

    只要您在 LLVM IR 中正确实现源语言的语义,LLVM 库执行正确的代码转换就不会出现问题。如果某些所需的转换需要比 LLVM IR 提供的更高级别的语义信息,则您必须在转换为 LLVM IR 之前的某个阶段进行转换(因此您将获得可用的高级信息),或者您可以传递属性信息在 LLVM IR 中传达高级语义并编写自定义 LLVM pass 来实现转换。前者通常比后者干净得多。

    【讨论】:

      猜你喜欢
      • 2012-07-14
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多