• llvm常见问题 (FAQ)


    llvm常见问题 (FAQ)

    License

    可以修改 LLVM 源代码并重新分发修改后的源代码吗?

    可以修改 LLVM 源代码并重新分发基于二进制文件或其它工具,而无需重新分发源代码吗?

    源代码

    LLVM 是用什么语言编写的?

    LLVM 源代码的可移植性如何?

    使用什么 API,将值存储到 LLVM IR 的 SSA 表示中的一个虚拟寄存器?

    源语言

    支持哪些源语言?

    想编写一个自托管的 LLVM 编译器。应该如何与 LLVM 中端优化器和后端代码生成器交互?

    对用于构建编译器的更高级别的源语言结构有什么支持?

    不明白GetElementPtr指令。帮助!

    使用 C 和 C++ 前端

    可以将 C 或 C++ 代码编译为独立于平台的 LLVM bitcode位码吗?

    关于demo页面生成代码的问题

    当#include <iostream>发生的事情?llvm.global_ctors以及_GLOBAL__I_a...是什么 ?

    出现在代码中的这个“undef ”是什么?

    “Go“代码在哪里使用?

    为什么 instcombine +simplifiedcfg对不匹配的函数的调用变成“无法访问”?为什么不让验证者拒绝?

    许可证license

    可以修改 LLVM 源代码,重新分发修改后的源代码吗?

    是的。修改后的源代码分发必须保留版权声明并遵循Apache License v2.0 with LLVM Exceptions 中列出的条件。

    可以修改 LLVM 源代码,重新分发二进制文件或工具,而无需重新分发源代码吗?

    是的。在比 GPL 限制更少的许可下分发 LLVM,如上面的第一个问题所述。

    源代码

    LLVM 是用什么语言编写的?

    所有 LLVM 工具和库都是用 C++ 编写的,并广泛使用了 STL。

    LLVM 源代码的可移植性如何?

    LLVM 源代码应该可以移植到大多数modern Unix-like操作系统。LLVM 对 Windows 系统也有很好的支持。大多数代码是用标准 C++ 编写的,操作系统服务抽象支持库。构建和测试 LLVM 所需的工具已移植到大平台。

    使用什么 API,将值存储到 LLVM IR 的 SSA 表示中的一个虚拟寄存器?

    简而言之:不能。一旦理解了正在发生的事情,这实际上是一个愚蠢的问题。基本上,在代码中:

    %result = add i32 %foo, %bar

    %result只是给予一个add 指令Value。换句话说,%result 就是添加指令。“赋值”没有明确地将任何东西“存储”到任何“虚拟寄存器”;“ =”更像是数学意义上的相等。

    详细解释:为了生成 IR 的文本表示,必须为每条指令指定某种名称,以便其它指令可以在文本上引用。但是,从 C++ 操作的同构内存中表示没有这样的限制,指令可以简单地保留指向Value引用的任何指针。事实上,虚拟编号临时变量的名称,如%1,根本没有在内存中明确表示(参见资料 Value::getName())。

    源语言

    支持哪些源语言?

    LLVM 目前通过Clang完全支持 C 和 C++ 源语言。许多其它语言前端是使用 LLVM 编写的,在使用 LLVM 的项目中提供了一个不完整的列表 。

    编写一个自托管的 LLVM 编译器。应该如何与 LLVM 中端优化器和后端代码生成器交互?

    编译器前端将通过以 LLVM 中间表示 (IR) 格式,创建模块来与 LLVM 通信。用语言(不是 C++)编写编译器,有 3 种主要方法可以从前端生成 LLVM IR:

    使用语言的 FFI(外部函数接口)调用 LLVM 库代码。

    for:最佳跟踪对 LLVM IR、.ll 语法和 .bc 格式的更改

    for:启用运行 LLVM 优化过程,无需发出/解析开销

    for:很好地适应 JIT 上下文

    against:要写很多丑陋的胶水代码

    从编译器的本地语言发出 LLVM 汇编程序集。

    for:非常容易上手

    against:当连接到中间端时,.ll 解析器比bitcode位码读取器慢

    against:跟踪 IR 的变化可能更难

    从编译器的本地语言发出 LLVM 位码。

    for:在与中端接口时,可以使用更高效的bitcode位码reader

    against:必须用语言重新设计 LLVM IR 对象模型和位码编写器

    against:跟踪 IR 的变化可能更难

    如果选择第一个选项,include/llvm-c 中的 C 绑定应该会有很大帮助,因为大多数语言都强烈支持与 C 的接口。从托管代码调用 C 的最常见障碍,与垃圾收集器的接口。C 接口设计只需要很少的内存管理,在这方面很简单。

    对用于构建编译器的更高级别的源语言结构,有什么支持?

    目前,没有太多。LLVM 支持对代码有用的中间表示,但不支持大多数编译器所需的高级(抽象语法树)表示。没有用于词法或语义分析的工具。

    不明白GetElementPtr指令。帮助!

    请参阅 The Often Misunderstood GEP Instruction

    使用 C 和 C++ 前端

    可以将 C 或 C++ 代码编译为独立于平台的 LLVM 位码吗?

    不,C 和 C++ 本质上是依赖于平台的语言。最明显的例子是预处理器。使 C 代码具有可移植性的非常常见方法,使用预处理器来包含特定于平台的代码。实际上,预处理后,平台的信息会丢失,结果本质上取决于预处理所针对的平台。

    另一个例子是sizeof。sizeof(long)在平台之间变化是很常见的。在大多数 C 前端,sizeof立即扩展为常量,从而硬连接特定于平台的细节。

    此外,由于许多平台根据 C 定义它们的 ABI,并且由于 LLVM 比 C 级别低,因此前端当前必须发出platform-specific的 IR,以使结果符合平台 ABI。

    关于demo页面生成代码的问题

    当#include <iostream>发生的事情,llvm.global_ctors以及_GLOBAL__I_a...是什么?

    如果#include的<iostream>header换成C ++翻译单元,该文件可能会使用std::cin/ std::cout/ ...全局对象。但是,C++ 不保证不同翻译单元中静态对象之间的初始化顺序,静态std::cout,例如,如果使用了 .cpp 文件中的静态 ctor/dtor ,该对象不一定会在使用自动初始化。

    为了让std::cout和friends 在这些场景中正常工作,使用的 STL 声明了一个静态对象,该对象在包含<iostream>。该对象具有静态构造函数和析构函数,用于在全局 iostream 对象,可能在文件中使用之前初始化和销毁。在.ll文件中看到的代码,对应于构造函数和析构函数的注册代码。

    如果希望更容易理解演示页面中编译器生成的 LLVM 代码,请参考使用printf()代替 iostreams 来打印信息。

    所有的代码都去哪儿了?

    如果正在使用 LLVM 演示页面,了解输入的所有代码发生了什么。请记住,演示脚本是通过 LLVM 优化器运行代码的,如果代码实际上没有做任何有用的事情,可能会全部删除。

    为了防止这种情况,确保确实需要该代码。例如,如果正在计算某个表达式,则从函数返回值,而不是将其留在局部变量中。如果真的想约束优化器,可以读取和分配volatile全局变量。

    出现在代码中的这个“undef ”是什么?

    undef是表示未定义值的 LLVM 方式。如果在使用变量之前未初始化变量,则可以获得这些。例如,C 函数:

    int X() { int i; return i; }

    编译为“ret i32 undef”,因为“i ”从未为其指定值。

    为什么 instcombine +simplifiedcfg 将对调用约定不匹配的函数的调用变成“无法访问”?为什么不让验证者拒绝?

    这是使用自定义调用约定的前端作者遇到的一个常见问题:

    需要确保在函数和每次调用函数时,都设置正确的调用约定。例如,这段代码:

    define fastcc void @foo() {

        ret void

    }

    define void @bar() {

        call void @foo()

        ret void

    }

    优化为:

    define fastcc void @foo() {

        ret void

    }

    define void @bar() {

        unreachable

    }

    ……用“opt -instcombine -simplifycfg”。这通常会bites people难受,因为“他们所有的代码都消失了”。间接调用需要在调用者和被调用者上设置调用约定,所以人们经常问为什么不让验证者拒绝这种事情。

    答案是这段代码有未定义的行为,但并不违法。如果将其设为非法,那么每个可能会创建的转换都必须确保不会发生,并且存在可以创建此类构造的有效代码(在死代码中)。可能导致这种情况发生的事情是相当contrived的,但仍然需要接受。下面是一个例子:

    define fastcc void @foo() {

        ret void

    }

    define internal void @bar(void()* %FP, i1 %cond) {

        br i1 %cond, label %T, label %F

    T:

        call void %FP()

        ret void

    F:

        call fastcc void %FP()

        ret void

    }

    define void @test() {

        %X = or i1 false, false

        call void @bar(void()* @foo, i1 %X)

        ret void

    }

    在这个例子中,“test”总是传递@foo/ falseinto bar,确保conv 正确的动态调用(因此,代码定义得很好)。如果通过内联程序运行,会得到这个(明确的“或”是存在的,这样内联程序就不会死代码,消除一堆东西):

    define fastcc void @foo() {

        ret void

    }

    define void @test() {

        %X = or i1 false, false

        br i1 %X, label %T.i, label %F.i

    T.i:

        call void @foo()

        br label %bar.exit

    F.i:

        call fastcc void @foo()

        br label %bar.exit

    bar.exit:

        ret void

    }

    可以看到内联传递@foo,使用错误的调用约定进行了未定义的调用。真的不想让内联程序知道这种事情,需要是有效的代码。在这种情况下,死代码消除可以轻松删除未定义的代码。但是,如果%X是 @test输入参数,内联程序将生成以下内容:

    define fastcc void @foo() {

        ret void

    }

    define void @test(i1 %X) {

        br i1 %X, label %T.i, label %F.i

    T.i:

        call void @foo()

        br label %bar.exit

    F.i:

        call fastcc void @foo()

        br label %bar.exit

    bar.exit:

        ret void

    }

    这一点的有趣之处在于,对于定义良好的代码来说,%X 必须为 false,但没有多少死代码能够删除无法访问的损坏调用。由于 instcombine/simplifycfg将 undefined 调用变为 unreachable,最终得到了一个条件为 unreachable 的分支:

    unreachable 的分支永远不会发生,所以“-inline -instcombine -simplifycfg”能够产生:

    define fastcc void @foo() {

       ret void

    }

    define void @test(i1 %X) {

    F.i:

       call fastcc void @foo()

       ret void

    }

    参考链接:Frequently Asked Questions (FAQ

    人工智能芯片与自动驾驶
  • 相关阅读:
    mysql常用命令
    使用MyBatis Generator自动创建代码(dao,mapping,poji)
    基于SSH框架的学生公寓管理系统的质量属性
    对于SSH框架的选择
    Hibernate的查询方式总结
    关于C/S模式开发的学习笔记
    window10系统安装SQL数据库和小蝴蝶的问题
    基于框架的图书管理系统开发的质量属性
    实验一 框架的选择及其原因
    软件体系架构的认识
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/14968187.html
Copyright © 2020-2023  润新知