-
Notifications
You must be signed in to change notification settings - Fork 0
Documentation of Orz IR
This is a brief guide of Orz IR.
整体 IR 的设计参考了之前 syc 以及 koopa 中的设计,同样都使用了组合而非继承进行抽象,将 IR 中的组件的数据和引用值(ID)分开来操作。
更多的细节可以参考生成的文档。具体的构建一个 IR 并且输出的例子目前在 main.rs
中。
Orz IR 中为了实现内存安全使用了一个基于 HashMap
的(伪)链表实现了程序布局(Layout)的存储。所有的指令、常量或者基本块的数据全部通过 Value
这个类型进行索引,Value
和 Block
以及 Function
在语义上是不同的,但是其内部的编号使用同一个计数器进行分配(usize
应该用不完),Value
可以转换为 Inst
,这个转换只是为了让程序的语义更清楚,因为 Value
还包含了常量值而不只是指令。注意 Block
类型没有实现和 Value
的相互转换,二者可以完全独立,但是目前实现中内部的计数器仍然使用了同一个。
用于分配内部编号的结构为 ir::module::IdAllocator
,此外还实现了一个分配器 ir::module::NameAllocator
用于管理和分配变量/中间结果的名称。实际上内部就是简单的计数器。
数据流图是存储函数中局部数据关系的结构。其中主要存储了 values
和 blocks
这两个表,用于通过 Value
/Block
查找对应的数据。另外内部还有对整个模块的一些数据的引用。
数据流图只存储了数据之间的依赖关系(或者说操作关系),程序的局部布局使用 ir::layout::Layout
进行存储,全局变量、自定义类型(结构体)以及函数的布局(事实上只是个顺序)在 Module
中直接使用 Vec
存储。
Layout 和 Dfg 均存储在对应函数的 ir::entities::FunctionData
中。
构建指令时应当使用 builder()
函数获得对应的构造器从而进行构建,具体的接口直接参考代码或者 Cargo 生成的文档。构造器会返回一个 Value
/Block
/Function
,之后可以将这些引用值添加到 Layout 中得到程序布局。注意函数在创建时已经自动添加。
对 IR 构建之后的操作使用 Pass 来完成。如何实现一个 Pass 可以参考目前 Printer 的实现。