LLVM 基础设施和 Rust - Beka


LLVM 是许多编程语言背后的引擎。它被 C、C++、Rust、Go、Swift 等使用。这篇日志是关于 LLVM 的,我将探讨以下主题:


 
什么是 LLVM 基础架构
LLVM 基础设施是模块化和可重用的编译器和工具链技术的集合。LLVM 伞包含几个子项目,如 Clang、C/C++/Objective-C 编译器、Debugger LLDB、libc++ 等。数十年的研究和改进创造了一个用于构建语言和编译器的惊人工具,一些现代技术正在利用这些工具。
LLVM 项目于 2000 年由 Vikram Adve 和 Chris Lattner 在伊利诺伊大学厄巴纳-香槟分校启动。LLVM 的名称最初是Low-Level Virtual Machine的首字母缩写词。尽管现代 LLVM 基础架构与虚拟机无关,但名称保持不变。但缩写本身后来被删除,LLVM 成为该项目的全名。
LLVM 项目是在开源许可下发布的。后来 Lattner 被 Apple 聘用,整个团队被分配到 LLVM 系统上工作,用于 Apple 产品中的多种用途。LLVM 开始扩展其功能并成长为一个综合项目,该项目结合了 LLVM IR、LLVM 调试器和 LLVM API C++ 库。
LLVM Compiler Framework 是一个模块化和可重用的编译器框架,它使用 LLVM 基础设施来提供端到端的代码编译。它用于构建、优化、清理和生成中间代码 (IR) 或二进制(机器)代码 (BC)。LLVM 允许将编程语言代码转换为中间表示 (IR),中间表示 (IR) 可以转换为任何给定硬件架构的二进制代码 (BC)。IR 语言独立于源语言和目标语言。
LLVM 有多种使用方式。它的主要用途是作为编译器框架。在这里,您提供所谓的前端后端,或机器代码,它会生成 IR。该 IR 可以转换为二进制代码,并链接到目标平台的依赖于机器的汇编语言。
LLVM 的中间表示(IR)是一种类似于汇编的低级编程语言。但是除了汇编之外,它还提供了更好的类型注释和人性化的语法。此外,IR 使用无限组注册而不是预定义数量的寄存器。我们将在后面的部分探讨 IR 的内部运作。
 
.....
 
LLVM 的程序结构
LLVM IR,就像任何其他系统一样,有它的程序结构,顶层容器是一个Module,对应前端编译器的每个翻译单元。模块可以由一个或多个功能组成。每个函数都有一个或多个基本块,里面有指令。指令是一行,IR 语言中有多个指令可用。
LLVM IR 中的实际程序结构由分层容器组成。在顶层,您有模块。它对应前端编译器的每个翻译单元。模块可以与合并函数定义的 LLVM 链接器结合使用。函数是下一级容器,包括函数签名及其基本块。基本块是一组按顺序执行的指令。基本块有一个入口和一个出口。第一个块称为入口块。最后,IR 有指示。指令是单行可执行文件(图 2-a)。

在IR文件中你会遇到两种变量,局部变量,用%符号表示,全局变量,用@符号表示。LLVM IR 可以使用无限数量的临时寄存器,而不是像本地汇编程序那样使用预定义数量的寄存器。
LLVM IR 的另一个优点是它利用了所谓的静态单一分配 (SSA) 形式。这允许对代码进行各种优化。SSA 变量只能分配一次,而不是可以多次重新分配的常规变量。这允许编译器进行更有效的寄存器分配,因为很容易在任何给定点逼近许多活动变量。它可以检测未使用的变量并防止程序进行不必要的指针分配。
....
  
LLVM 和 Rustc
Rustc 开发的官方指南列出了他们使用 LLVM 的所有原因,我直接引用:

  • 我们不必编写整个编译器后端。这减少了实施和维护负担。
  • 我们受益于 LLVM 项目一直在收集的大量高级优化。
  • 我们可以自动将 Rust 编译到 LLVM 支持的任何平台。例如,一旦 LLVM 添加了对 wasm 的支持,瞧!rustc、clang 和许多其他语言都能够编译为 wasm!(好吧,还有一些额外的事情要做,但无论如何我们已经完成了 90%)。
  • 我们和其他编译器项目相互受益。例如,当发现 Spectre 和 Meltdown 安全漏洞时,只需要修补 LLVM。

现在,当我们熟悉了 LLVM IR 是什么、id 的作用以及为什么有这么多编译器基于它构建时,是时候动手并使用一个名为 的简单 Rust 程序探索 IR 的内部结构了simple1.rs:
...
点击标题见原文