diff --git a/docs/images/impl-value-instruction.svg b/docs/images/impl-value-instruction.svg index af053d9..5f77f6e 100644 --- a/docs/images/impl-value-instruction.svg +++ b/docs/images/impl-value-instruction.svg @@ -1,4 +1,4 @@ - + @@ -18,4 +18,4 @@ - BinaryOps (Value Binding): Add/Sub/Mul/..MemoryOps (Value Binding): Alloca/Load/Store/OffsetOtherOps (Value Binding): CallTerminatorOps (Terminator): Jmp/Ret/BrInstructionConstantValueConstantIntConstantUnit \ No newline at end of file + ValueConstantInstructionBinaryOps: Add/Sub/...MemoryOps: Load/Store/Alloca/OffsetOtherOps: CallTerminatorOps: Ret/Jump/BrConstantIntConstantUnitGlobalVariableArgument \ No newline at end of file diff --git a/docs/middle-ir-gen.md b/docs/middle-ir-gen.md index 13168a5..2c185e6 100644 --- a/docs/middle-ir-gen.md +++ b/docs/middle-ir-gen.md @@ -904,6 +904,10 @@ class="sourceCode c"> 4`. + 这引起的结果是 Expr 也可能产生控制流转移,为了方便起见,我们不会测试此类短路情况,但是你有兴趣可以实现. + ## 解释器 为了检测生成的中间代码生成正确性和评测,我们为大家提供了一个该中间表示的解释器。 @@ -956,6 +960,94 @@ $ accipit examples/factorial.acc ## C++ 模板代码说明 -出于实现上的方便,方便维护 use-def chain,类继承关系如下图所示: +请从 [ZJU Git](https://git.zju.edu.cn/accsys/accsys-cmake-template) 处获取模板代码,并阅读相关说明. +模板代码已经实现了 IR 的构造和输出到字符串文本格式的接口,你只需关心翻译到 IR 的过程即可. + +### Utils + +在 `utils` 下,我们实现了侵入式链表 `List`(位于 [list.h](https://git.zju.edu.cn/accsys/accsys-cmake-template/-/blob/master/accsys/include/utils/list.h?ref_type=heads))和前述基于模板的 RTTI (位于 [casting.h](https://git.zju.edu.cn/accsys/accsys-cmake-template/-/blob/master/accsys/include/utils/casting.h?ref_type=heads)) + +对于 `List` 你通常不会直接使用到,一般只作为底层存放 IR 的数据结构. + +对于 RTTI,我们实现了 `isa()` `dyn_cast()` 和 `cast()` 三个函数: + +- `isa(Val)`:返回 `Val` 是否为 To 类型 +- `dyn_cast(Val)`:如果 `Val` 为 To 类型,则进行 cast,否则返回 nullptr +- `cast(Val)`: 如果 `Val` 为 To 类型,则进行 cast,否则报错 + +上述三个函数使用模板并进行了偏特化,因此相比上述的 `is` 和 `as` 适用性更好,能够处理 `From &Val`、`From *Val`、`const From *Val` 和 `const From *const Val` 等情况,并算出合适的返回类型,模板类型参数 To 不必须是指针类型 + +### Type 类 + +表示 Accipit IR 中的各类 Type,包括基类 `Type` 、派生类 `PointerType` 和 `FunctionType`. +定义于 [type.h](https://git.zju.edu.cn/accsys/accsys-cmake-template/-/blob/master/accsys/include/ir/type.h?ref_type=heads) + +你只能使用静态成员函数获得 `Type *` 类型的值: + +```cpp title="type.h" +class Type { + //... + static Type *getPrimitiveTy(unsigned tid); + static Type *getIntegerTy(); + static Type *getUnitTy(); +}; + +class PointerType { + //... + static PointerType *get(Type *ElementType); +}; + +class FunctionType { + //... + static FunctionType *get(Type *Result, const std::vector &Params); + //... + static FunctionType *get(Type *Result); +}; +``` + +我们对除 `FunctionType` 以外的类进行了缓存,因此你在大部分情况下可以以指针比较的方式比较两个 `Type` 是否相同: + +```cpp +assert(Type::getUnitTy() == Type::getUnitTy() && "Type * should be the same") +``` + +### Value 类 + +`Value` 类定义于 [ir.h](https://git.zju.edu.cn/accsys/accsys-cmake-template/-/blob/master/accsys/include/ir/ir.h?ref_type=heads). +类继承关系如下图所示: + +![impl-value-instruction](images/impl-value-instruction.svg) + + +正如我们之前所述,`Value` 类包含符号和常数,具体来说,涉及: + +- 常数的基类 `Constant` 以及派生类 `ConstantInt` 与 `ConstantUnit` +- 指令基类 `Instruction`,每种指令都有其对应的派生类,例如 `BinaryInst` 和 `AllocaInst`. +- 全局变量 `GlobalVariable` 和函数参数 `Argument` + +几乎所有的 `Value` 都实现了静态成员函数 `Create` 并返回一个 `Value *` 类型的值. +`Value` 类构造函数都是私有的,你不允许直接调用它们,只能使用 Create 接口,因为 IR 内部有自己的内存管理方式. + +出于实现上的方便,并维护 `use-def chain`,terminator 类型的指令也是 `Value` 的子类 + + +### IR Structures + +`Instruction` 类,使用 `Instruction` 子类的 Create 接口构造,有以下重要的通用接口: + +- `getOpcode()` 获取指令的操作码,所有操作码是枚举 `BinaryOps`、`MemoryOps`、`OtherOps` 和 `TerminatorOps` 的其中一种. +- `getOperand()` 获取指令使用的 Value(操作数). +注意,根据定义,Function 和 BasicBlock 等均不是 Value. +- 各类 insert 接口,将这条“游离”的指令插入到某个基本块中(`insertInto`),或插入某条指令之前(`insertBefore`)或之后(`insertAfter`). + +`BasicBlock` 类,基本块,通过 Create 接口构造,通过 `insertInto` 接口插入到某个函数中. + +`Function` 类,函数类,通过 Create 接口构造,需要指定其所在的 Module + +`GlobalVariable` 类,全局变量类,通过 Create 接口构造,需要指定其所在的 Module + +`Module` 类,编译单元,实现了 print 接口,打印 IR + +### 使用示例和单元测试 -![impl-value-instruction](images/impl-value-instruction.svg) \ No newline at end of file +IR 相关的部分编写了一些单元测试,位于 [test](https://git.zju.edu.cn/accsys/accsys-cmake-template/-/tree/master/accsys/test?ref_type=heads) 子文件夹中,你可以运行这些测试,并参考我们提供的接口的使用方式 \ No newline at end of file