Skip to content

Documentation of Orz IR

Junyi Mei edited this page Feb 17, 2024 · 5 revisions

This is a brief guide of Orz IR.

整体 IR 的设计参考了之前 syc 以及 koopa 中的设计,同样都使用了组合而非继承进行抽象,将 IR 中的组件的数据和引用值(ID)分开来操作。

更多的细节可以参考生成的文档。具体的构建一个 IR 并且输出的例子目前在 main.rs 中。

Value, Block, Function and Inst

Orz IR 中为了实现内存安全使用了一个基于 HashMap 的(伪)链表实现了程序布局(Layout)的存储。所有的指令、常量或者基本块的数据全部通过 Value 这个类型进行索引,ValueBlock 以及 Function 在语义上是不同的,但是其内部的编号使用同一个计数器进行分配(usize 应该用不完),Value 可以转换为 Inst,这个转换只是为了让程序的语义更清楚,因为 Value 还包含了常量值而不只是指令。注意 Block 类型没有实现和 Value 的相互转换,二者可以完全独立,但是目前实现中内部的计数器仍然使用了同一个。

用于分配内部编号的结构为 ir::module::IdAllocator,此外还实现了一个分配器 ir::module::NameAllocator 用于管理和分配变量/中间结果的名称。实际上内部就是简单的计数器。

Data Flow Graph 数据流图

数据流图是存储函数中局部数据关系的结构。其中主要存储了 valuesblocks 这两个表,用于通过 Value/Block 查找对应的数据。另外内部还有对整个模块的一些数据的引用。

Layout 布局

数据流图只存储了数据之间的依赖关系(或者说操作关系),程序的局部布局使用 ir::layout::Layout 进行存储,全局变量、自定义类型(结构体)以及函数的布局(事实上只是个顺序)在 Module 中直接使用 Vec 存储。

Layout 和 Dfg 均存储在对应函数的 ir::entities::FunctionData 中。

Builder 构造器

构建指令时应当使用 builder() 函数获得对应的构造器从而进行构建,具体的接口直接参考代码或者 Cargo 生成的文档。构造器会返回一个 Value/Block/Function,之后可以将这些引用值添加到 Layout 中得到程序布局。注意函数在创建时已经自动添加。

Pass

对 IR 构建之后的操作使用 Pass 来完成。如何实现一个 Pass 可以参考目前 Printer 的实现。

Clone this wiki locally