diff --git a/README.md b/README.md index 5e63e3e..7e20007 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,8 @@ doxygen doc/Doxyfile 上述命令执行完毕后,将在doxygen/html下找到生成的代码文档。 +该版本还未实现数组初始化定义等功能 + ## 实验3:从SysY IR 生成ARMv7汇编代码 ### 后端相关源码 diff --git a/doc/markdowns/IR.md b/doc/markdowns/IR.md new file mode 100644 index 0000000..412cde3 --- /dev/null +++ b/doc/markdowns/IR.md @@ -0,0 +1,169 @@ +这个头文件定义了一个用于生成中间表示(IR)的数据结构,主要用于编译器前端将抽象语法树(AST)转换为中间代码。以下是文件中定义的主要类和功能的整理和解释: + +--- + +### **1. 类型系统(Type System)** +#### **1.1 `Type` 类** +- **作用**:表示所有基本标量类型(如 `int`、`float`、`void` 等)以及指针类型和函数类型。 +- **成员**: + - `Kind` 枚举:表示类型的种类(如 `kInt`、`kFloat`、`kPointer` 等)。 + - `kind`:当前类型的种类。 + - 构造函数:`Type(Kind kind)`,用于初始化类型。 + - 静态方法:如 `getIntType()`、`getFloatType()` 等,用于获取特定类型的单例对象。 + - 类型检查方法:如 `isInt()`、`isFloat()` 等,用于检查当前类型是否为某种类型。 + - `getSize()`:获取类型的大小。 + - `as()`:将当前类型动态转换为派生类(如 `PointerType` 或 `FunctionType`)。 + +#### **1.2 `PointerType` 类** +- **作用**:表示指针类型,派生自 `Type`。 +- **成员**: + - `baseType`:指针指向的基础类型。 + - 静态方法:`get(Type *baseType)`,用于获取指向 `baseType` 的指针类型。 + - `getBaseType()`:获取指针指向的基础类型。 + +#### **1.3 `FunctionType` 类** +- **作用**:表示函数类型,派生自 `Type`。 +- **成员**: + - `returnType`:函数的返回类型。 + - `paramTypes`:函数的参数类型列表。 + - 静态方法:`get(Type *returnType, const std::vector ¶mTypes)`,用于获取函数类型。 + - `getReturnType()`:获取函数的返回类型。 + - `getParamTypes()`:获取函数的参数类型列表。 + +--- + +### **2. 中间表示(IR)** +#### **2.1 `Value` 类** +- **作用**:表示 IR 中的所有值(如指令、常量、参数等)。 +- **成员**: + - `Kind` 枚举:表示值的种类(如 `kAdd`、`kSub`、`kConstant` 等)。 + - `kind`:当前值的种类。 + - `type`:值的类型。 + - `name`:值的名称。 + - `uses`:值的用途列表(表示哪些指令使用了该值)。 + - 构造函数:`Value(Kind kind, Type *type, const std::string &name)`。 + - 类型检查方法:如 `isInt()`、`isFloat()` 等。 + - `getUses()`:获取值的用途列表。 + - `replaceAllUsesWith(Value *value)`:将该值的所有用途替换为另一个值。 + - `print(std::ostream &os)`:打印值的表示。 + +#### **2.2 `ConstantValue` 类** +- **作用**:表示编译时常量(如整数常量、浮点数常量)。 +- **成员**: + - `iScalar` 和 `fScalar`:分别存储整数和浮点数常量的值。 + - 静态方法:`get(int value)` 和 `get(float value)`,用于获取常量值。 + - `getInt()` 和 `getFloat()`:获取常量的值。 + +#### **2.3 `Argument` 类** +- **作用**:表示函数或基本块的参数。 +- **成员**: + - `block`:参数所属的基本块。 + - `index`:参数的索引。 + - 构造函数:`Argument(Type *type, BasicBlock *block, int index, const std::string &name)`。 + - `getParent()`:获取参数所属的基本块。 + - `getIndex()`:获取参数的索引。 + +#### **2.4 `BasicBlock` 类** +- **作用**:表示基本块,包含一系列指令。 +- **成员**: + - `parent`:基本块所属的函数。 + - `instructions`:基本块中的指令列表。 + - `arguments`:基本块的参数列表。 + - `successors` 和 `predecessors`:基本块的后继和前驱列表。 + - 构造函数:`BasicBlock(Function *parent, const std::string &name)`。 + - `getParent()`:获取基本块所属的函数。 + - `getInstructions()`:获取基本块中的指令列表。 + - `createArgument()`:为基本块创建一个参数。 + +#### **2.5 `Instruction` 类** +- **作用**:表示 IR 中的指令,派生自 `User`。 +- **成员**: + - `Kind` 枚举:表示指令的种类(如 `kAdd`、`kSub`、`kLoad` 等)。 + - `kind`:当前指令的种类。 + - `parent`:指令所属的基本块。 + - 构造函数:`Instruction(Kind kind, Type *type, BasicBlock *parent, const std::string &name)`。 + - `getParent()`:获取指令所属的基本块。 + - `getFunction()`:获取指令所属的函数。 + - 指令分类方法:如 `isBinary()`、`isUnary()`、`isMemory()` 等。 + +#### **2.6 `User` 类** +- **作用**:表示使用其他值的指令或全局值,派生自 `Value`。 +- **成员**: + - `operands`:指令的操作数列表。 + - 构造函数:`User(Kind kind, Type *type, const std::string &name)`。 + - `getOperand(int index)`:获取指定索引的操作数。 + - `addOperand(Value *value)`:添加一个操作数。 + - `replaceOperand(int index, Value *value)`:替换指定索引的操作数。 + +#### **2.7 具体指令类** +- **`CallInst`**:表示函数调用指令。 +- **`UnaryInst`**:表示一元操作指令(如取反、类型转换)。 +- **`BinaryInst`**:表示二元操作指令(如加法、减法)。 +- **`ReturnInst`**:表示返回指令。 +- **`UncondBrInst`**:表示无条件跳转指令。 +- **`CondBrInst`**:表示条件跳转指令。 +- **`AllocaInst`**:表示栈内存分配指令。 +- **`LoadInst`**:表示从内存加载值的指令。 +- **`StoreInst`**:表示将值存储到内存的指令。 + +--- + +### **3. 模块和函数** +#### **3.1 `Function` 类** +- **作用**:表示函数,包含多个基本块。 +- **成员**: + - `parent`:函数所属的模块。 + - `blocks`:函数中的基本块列表。 + - 构造函数:`Function(Module *parent, Type *type, const std::string &name)`。 + - `getReturnType()`:获取函数的返回类型。 + - `getParamTypes()`:获取函数的参数类型列表。 + - `addBasicBlock()`:为函数添加一个基本块。 + +#### **3.2 `GlobalValue` 类** +- **作用**:表示全局变量或常量。 +- **成员**: + - `parent`:全局值所属的模块。 + - `hasInit`:是否有初始化值。 + - `isConst`:是否是常量。 + - 构造函数:`GlobalValue(Module *parent, Type *type, const std::string &name, const std::vector &dims, Value *init)`。 + - `init()`:获取全局值的初始化值。 + +#### **3.3 `Module` 类** +- **作用**:表示整个编译单元(如一个源文件)。 +- **成员**: + - `children`:模块中的所有值(如函数、全局变量)。 + - `functions`:模块中的函数列表。 + - `globals`:模块中的全局变量列表。 + - `createFunction()`:创建一个函数。 + - `createGlobalValue()`:创建一个全局变量。 + - `getFunction()`:获取指定名称的函数。 + - `getGlobalValue()`:获取指定名称的全局变量。 + +--- + +### **4. 工具类** +#### **4.1 `Use` 类** +- **作用**:表示值与其使用者之间的关系。 +- **成员**: + - `index`:值在使用者操作数列表中的索引。 + - `user`:使用者。 + - `value`:被使用的值。 + - 构造函数:`Use(int index, User *user, Value *value)`。 + - `getValue()`:获取被使用的值。 + +#### **4.2 `range` 类** +- **作用**:封装迭代器对 `[begin, end)`,用于遍历容器。 +- **成员**: + - `begin()` 和 `end()`:返回范围的起始和结束迭代器。 + - `size()`:返回范围的大小。 + - `empty()`:判断范围是否为空。 + +--- + +### **5. 总结** +- **类型系统**:`Type`、`PointerType`、`FunctionType` 用于表示 IR 中的类型。 +- **中间表示**:`Value`、`ConstantValue`、`Instruction` 等用于表示 IR 中的值和指令。 +- **模块和函数**:`Module`、`Function`、`GlobalValue` 用于组织 IR 的结构。 +- **工具类**:`Use` 和 `range` 用于辅助实现 IR 的数据结构和遍历。 + +这个头文件定义了一个完整的 IR 数据结构,适用于编译器前端将 AST 转换为中间代码,并支持后续的优化和目标代码生成。 \ No newline at end of file diff --git a/doc/markdowns/IRbuilder.md b/doc/markdowns/IRbuilder.md new file mode 100644 index 0000000..40b5e4b --- /dev/null +++ b/doc/markdowns/IRbuilder.md @@ -0,0 +1,156 @@ +`IRBuilder.h` 文件定义了一个 `IRBuilder` 类,用于简化中间表示(IR)的构建过程。`IRBuilder` 提供了创建各种 IR 指令的便捷方法,并将这些指令插入到指定的基本块中。以下是对文件中主要内容的整理和解释: + +--- + +### **1. `IRBuilder` 类的作用** +`IRBuilder` 是一个工具类,用于在生成中间表示(IR)时简化指令的创建和插入操作。它的主要功能包括: +- 提供创建各种 IR 指令的工厂方法。 +- 将创建的指令插入到指定的基本块中。 +- 支持在基本块的任意位置插入指令。 + +--- + +### **2. 主要成员** + +#### **2.1 成员变量** +- **`block`**:当前操作的基本块。 +- **`position`**:当前操作的插入位置(基本块中的迭代器)。 + +#### **2.2 构造函数** +- **默认构造函数**:`IRBuilder()`。 +- **带参数的构造函数**: + - `IRBuilder(BasicBlock *block)`:初始化 `IRBuilder`,并设置当前基本块和插入位置(默认在基本块末尾)。 + - `IRBuilder(BasicBlock *block, BasicBlock::iterator position)`:初始化 `IRBuilder`,并设置当前基本块和插入位置。 + +#### **2.3 设置方法** +- **`setPosition(BasicBlock *block, BasicBlock::iterator position)`**:设置当前基本块和插入位置。 +- **`setPosition(BasicBlock::iterator position)`**:设置当前插入位置。 + +#### **2.4 获取方法** +- **`getBasicBlock()`**:获取当前基本块。 +- **`getPosition()`**:获取当前插入位置。 + +--- + +### **3. 指令创建方法** +`IRBuilder` 提供了多种工厂方法,用于创建不同类型的 IR 指令。这些方法会将创建的指令插入到当前基本块的指定位置。 + +#### **3.1 函数调用指令** +- **`createCallInst(Function *callee, const std::vector &args, const std::string &name)`**: + - 创建一个函数调用指令。 + - 参数: + - `callee`:被调用的函数。 + - `args`:函数参数列表。 + - `name`:指令的名称(可选)。 + - 返回:`CallInst*`。 + +#### **3.2 一元操作指令** +- **`createUnaryInst(Instruction::Kind kind, Type *type, Value *operand, const std::string &name)`**: + - 创建一个一元操作指令(如取反、类型转换)。 + - 参数: + - `kind`:指令的类型(如 `kNeg`、`kFtoI` 等)。 + - `type`:指令的结果类型。 + - `operand`:操作数。 + - `name`:指令的名称(可选)。 + - 返回:`UnaryInst*`。 + +- **具体一元操作指令**: + - `createNegInst(Value *operand, const std::string &name)`:创建整数取反指令。 + - `createNotInst(Value *operand, const std::string &name)`:创建逻辑取反指令。 + - `createFtoIInst(Value *operand, const std::string &name)`:创建浮点数转整数指令。 + - `createFNegInst(Value *operand, const std::string &name)`:创建浮点数取反指令。 + - `createIToFInst(Value *operand, const std::string &name)`:创建整数转浮点数指令。 + +#### **3.3 二元操作指令** +- **`createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs, Value *rhs, const std::string &name)`**: + - 创建一个二元操作指令(如加法、减法)。 + - 参数: + - `kind`:指令的类型(如 `kAdd`、`kSub` 等)。 + - `type`:指令的结果类型。 + - `lhs` 和 `rhs`:左操作数和右操作数。 + - `name`:指令的名称(可选)。 + - 返回:`BinaryInst*`。 + +- **具体二元操作指令**: + - 整数运算: + - `createAddInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数加法指令。 + - `createSubInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数减法指令。 + - `createMulInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数乘法指令。 + - `createDivInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数除法指令。 + - `createRemInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数取余指令。 + - 整数比较: + - `createICmpEQInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数相等比较指令。 + - `createICmpNEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数不等比较指令。 + - `createICmpLTInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数小于比较指令。 + - `createICmpLEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数小于等于比较指令。 + - `createICmpGTInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数大于比较指令。 + - `createICmpGEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数大于等于比较指令。 + - 浮点数运算: + - `createFAddInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数加法指令。 + - `createFSubInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数减法指令。 + - `createFMulInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数乘法指令。 + - `createFDivInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数除法指令。 + - `createFRemInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数取余指令。 + - 浮点数比较: + - `createFCmpEQInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数相等比较指令。 + - `createFCmpNEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数不等比较指令。 + - `createFCmpLTInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数小于比较指令。 + - `createFCmpLEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数小于等于比较指令。 + - `createFCmpGTInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数大于比较指令。 + - `createFCmpGEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数大于等于比较指令。 + +#### **3.4 控制流指令** +- **`createReturnInst(Value *value)`**: + - 创建返回指令。 + - 参数: + - `value`:返回值(可选)。 + - 返回:`ReturnInst*`。 + +- **`createUncondBrInst(BasicBlock *block, std::vector args)`**: + - 创建无条件跳转指令。 + - 参数: + - `block`:目标基本块。 + - `args`:跳转参数(可选)。 + - 返回:`UncondBrInst*`。 + +- **`createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, const std::vector &thenArgs, const std::vector &elseArgs)`**: + - 创建条件跳转指令。 + - 参数: + - `condition`:跳转条件。 + - `thenBlock`:条件为真时的目标基本块。 + - `elseBlock`:条件为假时的目标基本块。 + - `thenArgs` 和 `elseArgs`:跳转参数(可选)。 + - 返回:`CondBrInst*`。 + +#### **3.5 内存操作指令** +- **`createAllocaInst(Type *type, const std::vector &dims, const std::string &name)`**: + - 创建栈内存分配指令。 + - 参数: + - `type`:分配的类型。 + - `dims`:数组维度(可选)。 + - `name`:指令的名称(可选)。 + - 返回:`AllocaInst*`。 + +- **`createLoadInst(Value *pointer, const std::vector &indices, const std::string &name)`**: + - 创建加载指令。 + - 参数: + - `pointer`:指针值。 + - `indices`:数组索引(可选)。 + - `name`:指令的名称(可选)。 + - 返回:`LoadInst*`。 + +- **`createStoreInst(Value *value, Value *pointer, const std::vector &indices, const std::string &name)`**: + - 创建存储指令。 + - 参数: + - `value`:要存储的值。 + - `pointer`:指针值。 + - `indices`:数组索引(可选)。 + - `name`:指令的名称(可选)。 + - 返回:`StoreInst*`。 + +--- + +### **4. 总结** +- `IRBuilder` 是一个用于简化 IR 构建的工具类,提供了创建各种 IR 指令的工厂方法。 +- 通过 `IRBuilder`,可以方便地在指定基本块的任意位置插入指令。 +- 该类的设计使得 IR 的生成更加模块化和易于维护。 \ No newline at end of file diff --git a/doc/markdowns/IRcpp.md b/doc/markdowns/IRcpp.md new file mode 100644 index 0000000..91cd1bb --- /dev/null +++ b/doc/markdowns/IRcpp.md @@ -0,0 +1,121 @@ +这个 `IR.cpp` 文件实现了 `IR.h` 中定义的中间表示(IR)数据结构的功能。它包含了类型系统、值、指令、基本块、函数和模块的具体实现,以及一些辅助函数用于打印 IR 的内容。以下是对文件中主要内容的整理和解释: + +--- + +### **1. 辅助函数** +#### **1.1 `interleave` 函数** +- **作用**:用于在输出流中插入分隔符(如逗号)来打印容器中的元素。 +- **示例**: + ```cpp + interleave(os, container, ", "); + ``` + +#### **1.2 打印函数** +- **`printVarName`**:打印变量名,全局变量以 `@` 开头,局部变量以 `%` 开头。 +- **`printBlockName`**:打印基本块名,以 `^` 开头。 +- **`printFunctionName`**:打印函数名,以 `@` 开头。 +- **`printOperand`**:打印操作数,如果是常量则直接打印值,否则打印变量名。 + +--- + +### **2. 类型系统** +#### **2.1 `Type` 类的实现** +- **静态方法**: + - `getIntType()`、`getFloatType()`、`getVoidType()`、`getLabelType()`:返回对应类型的单例对象。 + - `getPointerType(Type *baseType)`:返回指向 `baseType` 的指针类型。 + - `getFunctionType(Type *returnType, const vector ¶mTypes)`:返回函数类型。 +- **`getSize()`**:返回类型的大小(如 `int` 和 `float` 为 4 字节,指针为 8 字节)。 +- **`print()`**:打印类型的表示。 + +#### **2.2 `PointerType` 类的实现** +- **静态方法**: + - `get(Type *baseType)`:返回指向 `baseType` 的指针类型,使用 `std::map` 缓存已创建的指针类型。 +- **`getBaseType()`**:返回指针指向的基础类型。 + +#### **2.3 `FunctionType` 类的实现** +- **静态方法**: + - `get(Type *returnType, const vector ¶mTypes)`:返回函数类型,使用 `std::set` 缓存已创建的函数类型。 +- **`getReturnType()`** 和 `getParamTypes()`:分别返回函数的返回类型和参数类型列表。 + +--- + +### **3. 值(Value)** +#### **3.1 `Value` 类的实现** +- **`replaceAllUsesWith(Value *value)`**:将该值的所有用途替换为另一个值。 +- **`isConstant()`**:判断值是否为常量(包括常量值、全局值和函数)。 + +#### **3.2 `ConstantValue` 类的实现** +- **静态方法**: + - `get(int value)` 和 `get(float value)`:返回整数或浮点数常量,使用 `std::map` 缓存已创建的常量。 +- **`getInt()` 和 `getFloat()`**:返回常量的值。 +- **`print()`**:打印常量的值。 + +#### **3.3 `Argument` 类的实现** +- **构造函数**:初始化参数的类型、所属基本块和索引。 +- **`print()`**:打印参数的表示。 + +--- + +### **4. 基本块(BasicBlock)** +#### **4.1 `BasicBlock` 类的实现** +- **构造函数**:初始化基本块的名称和所属函数。 +- **`print()`**:打印基本块的表示,包括参数和指令。 + +--- + +### **5. 指令(Instruction)** +#### **5.1 `Instruction` 类的实现** +- **构造函数**:初始化指令的类型、所属基本块和名称。 +- **`print()`**:由具体指令类实现。 + +#### **5.2 具体指令类的实现** +- **`CallInst`**:表示函数调用指令。 + - **`print()`**:打印函数调用的表示。 +- **`UnaryInst`**:表示一元操作指令(如取反、类型转换)。 + - **`print()`**:打印一元操作的表示。 +- **`BinaryInst`**:表示二元操作指令(如加法、减法)。 + - **`print()`**:打印二元操作的表示。 +- **`ReturnInst`**:表示返回指令。 + - **`print()`**:打印返回指令的表示。 +- **`UncondBrInst`**:表示无条件跳转指令。 + - **`print()`**:打印无条件跳转的表示。 +- **`CondBrInst`**:表示条件跳转指令。 + - **`print()`**:打印条件跳转的表示。 +- **`AllocaInst`**:表示栈内存分配指令。 + - **`print()`**:打印内存分配的表示。 +- **`LoadInst`**:表示从内存加载值的指令。 + - **`print()`**:打印加载指令的表示。 +- **`StoreInst`**:表示将值存储到内存的指令。 + - **`print()`**:打印存储指令的表示。 + +--- + +### **6. 函数(Function)** +#### **6.1 `Function` 类的实现** +- **构造函数**:初始化函数的名称、返回类型和参数类型。 +- **`print()`**:打印函数的表示,包括基本块和指令。 + +--- + +### **7. 模块(Module)** +#### **7.1 `Module` 类的实现** +- **`print()`**:打印模块的表示,包括所有函数和全局变量。 + +--- + +### **8. 用户(User)** +#### **8.1 `User` 类的实现** +- **`setOperand(int index, Value *value)`**:设置指定索引的操作数。 +- **`replaceOperand(int index, Value *value)`**:替换指定索引的操作数,并更新用途列表。 + +--- + +### **9. 总结** +- **类型系统**:实现了 `Type`、`PointerType` 和 `FunctionType`,用于表示 IR 中的类型。 +- **值**:实现了 `Value`、`ConstantValue` 和 `Argument`,用于表示 IR 中的值和参数。 +- **基本块**:实现了 `BasicBlock`,用于组织指令。 +- **指令**:实现了多种具体指令类(如 `CallInst`、`BinaryInst` 等),用于表示 IR 中的操作。 +- **函数和模块**:实现了 `Function` 和 `Module`,用于组织 IR 的结构。 +- **打印功能**:通过 `print()` 方法,可以将 IR 的内容输出为可读的文本格式。 + +这个文件是编译器中间表示的核心实现,能够将抽象语法树(AST)转换为中间代码,并支持后续的优化和目标代码生成。 \ No newline at end of file diff --git a/src/ASTPrinter.cpp b/src/ASTPrinter.cpp index 1b05d6c..d283c7c 100644 --- a/src/ASTPrinter.cpp +++ b/src/ASTPrinter.cpp @@ -133,69 +133,58 @@ std::any ASTPrinter::visitBlockStmt(SysYParser::BlockStmtContext *ctx){ } // std::any ASTPrinter::visitBlockItem(SysYParser::BlockItemContext *ctx); -std::any ASTPrinter::visitStmt(SysYParser::StmtContext *ctx){ - if(ctx->lValue()&& ctx->exp()) { - cout << getIndent(); - ctx->lValue()->accept(this); - cout << ' ' << ctx->ASSIGN()->getText() <<' '; +std::any ASTPrinter::visitAssignStmt(SysYParser::AssignStmtContext *ctx){ + ctx->lValue()->accept(this); + cout << ' ' << ctx->ASSIGN()->getText() << ' '; + ctx->exp()->accept(this); + cout << ctx->SEMICOLON()->getText() << '\n'; + return nullptr; +} + +std::any ASTPrinter::visitExpStmt(SysYParser::ExpStmtContext *ctx){ + if (ctx->exp()) { ctx->exp()->accept(this); - cout << ctx->SEMICOLON()->getText() << endl; } - else if(ctx->blockStmt()){ - ctx->blockStmt()->accept(this); + cout << ctx->SEMICOLON()->getText() << '\n'; + return nullptr; +} + +std::any ASTPrinter::visitIfStmt(SysYParser::IfStmtContext *ctx){ + cout << getIndent() << ctx->IF()->getText() << ' ' << ctx->LPAREN()->getText(); + ctx->cond()->accept(this); + cout << ctx->RPAREN()->getText() << ' '; + ctx->stmt(0)->accept(this); + if (ctx->ELSE()) { + cout << getIndent() << ctx->ELSE()->getText() << ' '; + ctx->stmt(1)->accept(this); } - else if(ctx->IF()){ - cout << getIndent() << "if ("; - ctx->cond()->accept(this); - cout << ")"; - // visit ctx->stmt(0) to judge if it is a blockStmt or a Lvale=exp - if(ctx->stmt(0)->blockStmt())ctx->stmt(0)->accept(this); - else{ - cout << " {"<< endl; - indentLevel++; - ctx->stmt(0)->accept(this); - indentLevel--; - cout << getIndent() << "}" << endl; - } - if (ctx->stmt().size() > 1) { - cout << getIndent() << "else"; - if(ctx->stmt(1)->blockStmt())ctx->stmt(1)->accept(this); - else{ - cout << " {"<< endl; - indentLevel++; - ctx->stmt(1)->accept(this); - indentLevel--; - cout << getIndent() << "}" << endl; - } - } - } - else if(ctx->WHILE()){ - cout << getIndent() << "while ("; - ctx->cond()->accept(this); - cout << ")"; - if(ctx->stmt(0)->blockStmt())ctx->stmt(0)->accept(this); - else{ - cout << " {"<< endl; - indentLevel++; - ctx->stmt(0)->accept(this); - indentLevel--; - cout << getIndent() << "}" << endl; - } - } - else if(ctx->BREAK()){ - cout << getIndent() << "break;" << endl; - } - else if(ctx->CONTINUE()){ - cout << getIndent() << "continue;" << endl; - } - else if(ctx->RETURN()){ - cout << getIndent() << "return"; - if(ctx->exp()){ - cout << ' '; - ctx->exp()->accept(this); - } - cout << ctx->SEMICOLON()->getText() << endl; + return nullptr; +} + +std::any ASTPrinter::visitWhileStmt(SysYParser::WhileStmtContext *ctx){ + cout << getIndent() << ctx->WHILE()->getText() << ' ' << ctx->LPAREN()->getText(); + ctx->cond()->accept(this); + cout << ctx->RPAREN()->getText() << ' '; + ctx->stmt()->accept(this); + return nullptr; +} + +std::any ASTPrinter::visitBreakStmt(SysYParser::BreakStmtContext *ctx){ + cout << getIndent() << ctx->BREAK()->getText() << ctx->SEMICOLON()->getText() << '\n'; + return nullptr; +} + +std::any ASTPrinter::visitContinueStmt(SysYParser::ContinueStmtContext *ctx){ + cout << getIndent() << ctx->CONTINUE()->getText() << ctx->SEMICOLON()->getText() << '\n'; + return nullptr; +} + +std::any ASTPrinter::visitReturnStmt(SysYParser::ReturnStmtContext *ctx){ + cout << getIndent() << ctx->RETURN()->getText() << ' '; + if (ctx->exp()) { + ctx->exp()->accept(this); } + cout << ctx->SEMICOLON()->getText() << '\n'; return nullptr; } @@ -211,6 +200,12 @@ std::any ASTPrinter::visitLValue(SysYParser::LValueContext *ctx){ return nullptr; } // std::any ASTPrinter::visitPrimaryExp(SysYParser::PrimaryExpContext *ctx); +std::any ASTPrinter::visitParenExp(SysYParser::ParenExpContext *ctx){ + cout << ctx->LPAREN()->getText(); + ctx->exp()->accept(this); + cout << ctx->RPAREN()->getText(); + return nullptr; +} std::any ASTPrinter::visitNumber(SysYParser::NumberContext *ctx) { if(ctx->ILITERAL())cout << ctx->ILITERAL()->getText(); @@ -222,28 +217,15 @@ std::any ASTPrinter::visitString(SysYParser::StringContext *ctx) { cout << ctx->STRING()->getText(); return nullptr; } - -std::any ASTPrinter::visitUnaryExp(SysYParser::UnaryExpContext *ctx){ - if(ctx->primaryExp()) - ctx->primaryExp()->accept(this); - else if(ctx->Ident()){ - cout << ctx->Ident()->getText() << ctx->LPAREN()->getText(); - if(ctx->funcRParams()) - ctx->funcRParams()->accept(this); - if (ctx->RPAREN()) - cout << ctx->RPAREN()->getText(); - else - cout << ""; - } - else if(ctx->unaryExp()){ - cout << ctx->unaryOp()->getText(); - ctx->unaryExp()->accept(this); - } - else - ctx->accept(this); +// std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx); +// std::any ASTPrinter::visitUnaryOp(SysYParser::UnaryOpContext *ctx); +std::any ASTPrinter::visitCall(SysYParser::CallContext *ctx){ + cout << ctx->Ident()->getText() << ctx->LPAREN()->getText(); + if(ctx->funcRParams()) + ctx->funcRParams()->accept(this); + cout << ctx->RPAREN()->getText(); return nullptr; } -// std::any ASTPrinter::visitUnaryOp(SysYParser::UnaryOpContext *ctx); any ASTPrinter::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) { if (ctx->exp().empty()) diff --git a/src/ASTPrinter.h b/src/ASTPrinter.h index 8c55383..31b4863 100644 --- a/src/ASTPrinter.h +++ b/src/ASTPrinter.h @@ -26,23 +26,27 @@ public: std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override; std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override; - // std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override; - // std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override; - // std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override; - // std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override; - // std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override; - // std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override; - // std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override; - // std::any visitBlockItem(SysYParser::BlockItemContext *ctx) override; - std::any visitStmt(SysYParser::StmtContext *ctx) override; + // std::any visitStmt(SysYParser::StmtContext *ctx) override; + + std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override; + std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override; + std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override; + std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override; + std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override; + std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override; + std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override; + // std::any visitExp(SysYParser::ExpContext *ctx) override; // std::any visitCond(SysYParser::CondContext *ctx) override; std::any visitLValue(SysYParser::LValueContext *ctx) override; // std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override; + std::any visitParenExp(SysYParser::ParenExpContext *ctx) override; std::any visitNumber(SysYParser::NumberContext *ctx) override; std::any visitString(SysYParser::StringContext *ctx) override; - std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override; + // std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override; + std::any visitCall(SysYParser::CallContext *ctx) override; + // std::any visitUnExpOp(SysYParser::UnExpContext *ctx) override; // std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override; std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override; std::any visitMulExp(SysYParser::MulExpContext *ctx) override; diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index b0419a6..fb1ef33 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -77,7 +77,9 @@ private: std::unique_ptr module; IRBuilder builder; SymbolTable symbols_table; - //array init use variables + + static Type current_type; + int d = 0, n = 0; vector path; bool isalloca; @@ -94,39 +96,42 @@ public: public: std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override; - std::any visitDecl(SysYParser::DeclContext *ctx) override; - std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override; - std::any visitBType(SysYParser::BTypeContext *ctx) override; - std::any visitConstDef(SysYParser::ConstDefContext *ctx) override; - std::any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override; - std::any visitFuncType(SysYParser::FuncTypeContext* ctx) override; - std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override; - - std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override; - - std::any visitVarDef(SysYParser::VarDefContext *ctx, Type* btype); - + // std::any visitVarDef(SysYParser::VarDefContext *ctx) override; + std::any visitInitVal(SysYParser::InitValContext *ctx) override; std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override; - std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override; - std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override; - - std::any visitStmt(SysYParser::StmtContext *ctx) override; - - std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override; - + // std::any visitStmt(SysYParser::StmtContext *ctx) override; + std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override; + std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override; + std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override; + std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override; + std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override; + std::any visitExp(SysYParser::ExpContext *ctx) override; + std::any visitLValue(SysYParser::LValueContext *ctx) override; + // std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override; + std::any visitParenExp(SysYParser::ParenExpContext *ctx) override; std::any visitNumber(SysYParser::NumberContext *ctx) override; - std::any visitString(SysYParser::StringContext *ctx) override; + std::any visitCall(SysYParser::CallContext *ctx) override; + // std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override; + std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override; + std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override; + std::any visitMulExp(SysYParser::MulExpContext *ctx) override; + std::any visitAddExp(SysYParser::AddExpContext *ctx) override; + std::any visitRelExp(SysYParser::RelExpContext *ctx) override; + std::any visitEqExp(SysYParser::EqExpContext *ctx) override; + std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override; + std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override; + std::any visitConstExp(SysYParser::ConstExpContext *ctx) override; private: std::any visitConstGlobalDecl(SysYParser::ConstDeclContext *ctx, Type* type);