Compare commits

...

7 Commits

529 changed files with 658 additions and 707072 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 KiB

View File

@ -1,169 +0,0 @@
这个头文件定义了一个用于生成中间表示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<T>()`:将当前类型动态转换为派生类(如 `PointerType``FunctionType`)。
#### **1.2 `PointerType` 类**
- **作用**:表示指针类型,派生自 `Type`
- **成员**
- `baseType`:指针指向的基础类型。
- 静态方法:`get(Type *baseType)`,用于获取指向 `baseType` 的指针类型。
- `getBaseType()`:获取指针指向的基础类型。
#### **1.3 `FunctionType` 类**
- **作用**:表示函数类型,派生自 `Type`
- **成员**
- `returnType`:函数的返回类型。
- `paramTypes`:函数的参数类型列表。
- 静态方法:`get(Type *returnType, const std::vector<Type *> &paramTypes)`,用于获取函数类型。
- `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<Value *> &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 转换为中间代码,并支持后续的优化和目标代码生成。

View File

@ -1,156 +0,0 @@
`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<Value *> &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<Value *> args)`**
- 创建无条件跳转指令。
- 参数:
- `block`:目标基本块。
- `args`:跳转参数(可选)。
- 返回:`UncondBrInst*`
- **`createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs)`**
- 创建条件跳转指令。
- 参数:
- `condition`:跳转条件。
- `thenBlock`:条件为真时的目标基本块。
- `elseBlock`:条件为假时的目标基本块。
- `thenArgs``elseArgs`:跳转参数(可选)。
- 返回:`CondBrInst*`
#### **3.5 内存操作指令**
- **`createAllocaInst(Type *type, const std::vector<Value *> &dims, const std::string &name)`**
- 创建栈内存分配指令。
- 参数:
- `type`:分配的类型。
- `dims`:数组维度(可选)。
- `name`:指令的名称(可选)。
- 返回:`AllocaInst*`
- **`createLoadInst(Value *pointer, const std::vector<Value *> &indices, const std::string &name)`**
- 创建加载指令。
- 参数:
- `pointer`:指针值。
- `indices`:数组索引(可选)。
- `name`:指令的名称(可选)。
- 返回:`LoadInst*`
- **`createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices, const std::string &name)`**
- 创建存储指令。
- 参数:
- `value`:要存储的值。
- `pointer`:指针值。
- `indices`:数组索引(可选)。
- `name`:指令的名称(可选)。
- 返回:`StoreInst*`
---
### **4. 总结**
- `IRBuilder` 是一个用于简化 IR 构建的工具类,提供了创建各种 IR 指令的工厂方法。
- 通过 `IRBuilder`,可以方便地在指定基本块的任意位置插入指令。
- 该类的设计使得 IR 的生成更加模块化和易于维护。

View File

@ -1,121 +0,0 @@
这个 `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<Type *> &paramTypes)`:返回函数类型。
- **`getSize()`**:返回类型的大小(如 `int` 和 `float` 为 4 字节,指针为 8 字节)。
- **`print()`**:打印类型的表示。
#### **2.2 `PointerType` 类的实现**
- **静态方法**
- `get(Type *baseType)`:返回指向 `baseType` 的指针类型,使用 `std::map` 缓存已创建的指针类型。
- **`getBaseType()`**:返回指针指向的基础类型。
#### **2.3 `FunctionType` 类的实现**
- **静态方法**
- `get(Type *returnType, const vector<Type *> &paramTypes)`:返回函数类型,使用 `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转换为中间代码并支持后续的优化和目标代码生成。

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,7 @@ add_library(riscv64_backend_lib STATIC
RISCv64ISel.cpp RISCv64ISel.cpp
RISCv64LLIR.cpp RISCv64LLIR.cpp
RISCv64RegAlloc.cpp RISCv64RegAlloc.cpp
RISCv64LinearScan.cpp
Handler/CalleeSavedHandler.cpp Handler/CalleeSavedHandler.cpp
Handler/LegalizeImmediates.cpp Handler/LegalizeImmediates.cpp
Handler/PrologueEpilogueInsertion.cpp Handler/PrologueEpilogueInsertion.cpp

View File

@ -82,7 +82,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break; case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break;
case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break; case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break;
case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break; case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break;
case RVOpcodes::FSD: *OS << "fsd "; break; case RVOpcodes::FSD: *OS << "fsd "; break;
case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break; case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break;
case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break; case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break;
case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break; case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break;
@ -102,6 +102,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::FLE_S: *OS << "fle.s "; break; case RVOpcodes::FLE_S: *OS << "fle.s "; break;
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break; case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break; case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
case RVOpcodes::FCVT_W_S_RTZ: *OS << "fcvt.w.s "; break;
case RVOpcodes::FMV_S: *OS << "fmv.s "; break; case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break; case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break; case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;

View File

@ -1,10 +1,13 @@
#include "RISCv64Backend.h" #include "RISCv64Backend.h"
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h" #include "RISCv64RegAlloc.h"
#include "RISCv64LinearScan.h" // <--- 新增此行
#include "RISCv64AsmPrinter.h" #include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h" #include "RISCv64Passes.h"
#include <sstream> #include <sstream>
#include <future> // <--- 新增此行
#include <chrono> // <--- 新增此行
#include <iostream> // <--- 新增此行,用于打印超时警告
namespace sysy { namespace sysy {
// 顶层入口 // 顶层入口
@ -196,9 +199,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 === // === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) // 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
DEEPDEBUG = 0;
RISCv64ISel isel; RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func); std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
@ -206,9 +206,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
std::stringstream ss_after_isel; std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get()); RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true); printer_isel.run(ss_after_isel, true);
if (DEBUG) {
std::cout << ss_after_isel.str();
}
if (DEBUG) { if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str(); << ss_after_isel.str();
@ -228,13 +226,13 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
<< ss_after_eli.str(); << ss_after_eli.str();
} }
// 阶段 2: 除法强度削弱优化 (Division Strength Reduction) // // 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
DivStrengthReduction div_strength_reduction; // DivStrengthReduction div_strength_reduction;
div_strength_reduction.runOnMachineFunction(mfunc.get()); // div_strength_reduction.runOnMachineFunction(mfunc.get());
// 阶段 2.1: 指令调度 (Instruction Scheduling) // // 阶段 2.1: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler; // PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get()); // scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation) // 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get()); RISCv64RegAlloc reg_alloc(mfunc.get());
@ -254,9 +252,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
mfunc->dumpStackFrameInfo(std::cerr); mfunc->dumpStackFrameInfo(std::cerr);
} }
// 阶段 4: 窥孔优化 (Peephole Optimization) // // 阶段 4: 窥孔优化 (Peephole Optimization)
PeepholeOptimizer peephole; // PeepholeOptimizer peephole;
peephole.runOnMachineFunction(mfunc.get()); // peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling) // 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler; PostRA_Scheduler local_scheduler;
@ -276,7 +274,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
printer.run(ss); printer.run(ss);
return ss.str(); return ss.str();
} }
} // namespace sysy } // namespace sysy

View File

@ -745,83 +745,12 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case Instruction::kFtoI: { // 浮点 to 整数 (带向下取整) case Instruction::kFtoI: { // 浮点 to 整数 (使用硬件指令进行向零截断)
// 目标:实现 floor(x) 的效果, C/C++中浮点转整数是截断(truncate) // 直接生成一条带有 rtz 舍入模式的转换指令
// 对于正数floor(x) == truncate(x) auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S_RTZ);
// RISC-V的 fcvt.w.s 默认是“四舍五入到偶数” instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
// 我们需要手动实现截断逻辑 instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
// 逻辑: CurMBB->addInstruction(std::move(instr));
// temp_i = fcvt.w.s(x) // 四舍五入
// temp_f = fcvt.s.w(temp_i) // 转回浮点
// if (x < temp_f) { // 如果原数更小,说明被“五入”了
// result = temp_i - 1
// } else {
// result = temp_i
// }
auto temp_i_vreg = getNewVReg(Type::getIntType());
auto temp_f_vreg = getNewVReg(Type::getFloatType());
auto cmp_vreg = getNewVReg(Type::getIntType());
// 1. fcvt.w.s temp_i_vreg, src_vreg
auto fcvt_w = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
fcvt_w->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
fcvt_w->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(fcvt_w));
// 2. fcvt.s.w temp_f_vreg, temp_i_vreg
auto fcvt_s = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
CurMBB->addInstruction(std::move(fcvt_s));
// 3. flt.s cmp_vreg, src_vreg, temp_f_vreg
auto flt = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
flt->addOperand(std::make_unique<RegOperand>(cmp_vreg));
flt->addOperand(std::make_unique<RegOperand>(src_vreg));
flt->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
CurMBB->addInstruction(std::move(flt));
// 创建标签
int unique_id = this->local_label_counter++;
std::string rounded_up_label = MFunc->getName() + "_ftoi_rounded_up_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_ftoi_done_" + std::to_string(unique_id);
// 4. bne cmp_vreg, x0, rounded_up_label
auto bne = std::make_unique<MachineInstr>(RVOpcodes::BNE);
bne->addOperand(std::make_unique<RegOperand>(cmp_vreg));
bne->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
bne->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
CurMBB->addInstruction(std::move(bne));
// 5. else 分支: mv dest_vreg, temp_i_vreg
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(dest_vreg));
mv->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
CurMBB->addInstruction(std::move(mv));
// 6. j done_label
auto j = std::make_unique<MachineInstr>(RVOpcodes::J);
j->addOperand(std::make_unique<LabelOperand>(done_label));
CurMBB->addInstruction(std::move(j));
// 7. rounded_up_label:
auto label_up = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
label_up->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
CurMBB->addInstruction(std::move(label_up));
// 8. addiw dest_vreg, temp_i_vreg, -1
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
addi->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
addi->addOperand(std::make_unique<ImmOperand>(-1));
CurMBB->addInstruction(std::move(addi));
// 9. done_label:
auto label_done = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
label_done->addOperand(std::make_unique<LabelOperand>(done_label));
CurMBB->addInstruction(std::move(label_done));
break; break;
} }
case Instruction::kFNeg: { // 浮点取负 case Instruction::kFNeg: { // 浮点取负
@ -1202,10 +1131,11 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto r_value_byte = getVReg(memset->getValue()); auto r_value_byte = getVReg(memset->getValue());
// 为memset内部逻辑创建新的临时虚拟寄存器 // 为memset内部逻辑创建新的临时虚拟寄存器
auto r_counter = getNewVReg(); Type* ptr_type = Type::getPointerType(Type::getIntType());
auto r_end_addr = getNewVReg(); auto r_counter = getNewVReg(ptr_type);
auto r_current_addr = getNewVReg(); auto r_end_addr = getNewVReg(ptr_type);
auto r_temp_val = getNewVReg(); auto r_current_addr = getNewVReg(ptr_type);
auto r_temp_val = getNewVReg(Type::getIntType());
// 定义一系列lambda表达式来简化指令创建 // 定义一系列lambda表达式来简化指令创建
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) { auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
@ -1296,7 +1226,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) --- // --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
auto base_ptr_node = node->operands[0]; auto base_ptr_node = node->operands[0];
auto current_addr_vreg = getNewVReg(); auto current_addr_vreg = getNewVReg(gep->getType());
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) { if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) {
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR); auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
@ -1338,13 +1268,13 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// 如果步长为0例如对一个void类型或空结构体索引则不产生任何偏移 // 如果步长为0例如对一个void类型或空结构体索引则不产生任何偏移
if (stride != 0) { if (stride != 0) {
// --- 为当前索引和步长生成偏移计算指令 --- // --- 为当前索引和步长生成偏移计算指令 ---
auto offset_vreg = getNewVReg(); auto offset_vreg = getNewVReg(Type::getIntType());
// 处理索引 - 区分常量与动态值 // 处理索引 - 区分常量与动态值
unsigned index_vreg; unsigned index_vreg;
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) { if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
// 对于常量索引,直接创建新的虚拟寄存器 // 对于常量索引,直接创建新的虚拟寄存器
index_vreg = getNewVReg(); index_vreg = getNewVReg(Type::getIntType());
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(index_vreg)); li->addOperand(std::make_unique<RegOperand>(index_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt())); li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
@ -1362,7 +1292,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv)); CurMBB->addInstruction(std::move(mv));
} else { } else {
// 步长不为1需要生成乘法指令 // 步长不为1需要生成乘法指令
auto size_vreg = getNewVReg(); auto size_vreg = getNewVReg(Type::getIntType());
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_size->addOperand(std::make_unique<RegOperand>(size_vreg)); li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
li_size->addOperand(std::make_unique<ImmOperand>(stride)); li_size->addOperand(std::make_unique<ImmOperand>(stride));

View File

@ -0,0 +1,517 @@
#include "RISCv64LinearScan.h"
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h"
#include <iostream>
#include <set>
extern int DEBUG;
namespace sysy {
RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc)
: MFunc(mfunc),
ISel(mfunc->getISel()),
vreg_type_map(ISel->getVRegTypeMap()) {
// 初始化可用的物理寄存器池,与图着色版本保持一致
// 整数寄存器
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, /*T5保留作为大立即数加载寄存器*/ PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
// 浮点寄存器
allocable_fp_regs = {
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17,
PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21, PhysicalReg::F22,
PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25, PhysicalReg::F26, PhysicalReg::F27,
PhysicalReg::F28, PhysicalReg::F29, PhysicalReg::F30, PhysicalReg::F31,
};
// 新增识别所有通过寄存器传递的参数并建立vreg到物理寄存器(preg)的映射
// 这等同于图着色算法中的“预着色”步骤。
if (MFunc->getFunc()) {
int int_arg_idx = 0;
int fp_arg_idx = 0;
for (Argument* arg : MFunc->getFunc()->getArguments()) {
unsigned arg_vreg = ISel->getVReg(arg);
if (arg->getType()->isFloat()) {
if (fp_arg_idx < 8) { // fa0-fa7
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_arg_idx);
abi_vreg_map[arg_vreg] = preg;
fp_arg_idx++;
}
} else { // 整数或指针
if (int_arg_idx < 8) { // a0-a7
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx);
abi_vreg_map[arg_vreg] = preg;
int_arg_idx++;
}
}
}
}
}
void RISCv64LinearScan::run() {
if (DEBUG) std::cerr << "===== Running Linear Scan Register Allocation for function: " << MFunc->getName() << " =====\n";
bool changed = true;
while(changed) {
// 1. 准备阶段
linearizeBlocks();
computeLiveIntervals();
// 2. 执行线性扫描
changed = linearScan();
// 3. 如果有溢出,重写代码,然后下一轮重新开始
if (changed) {
rewriteProgram();
if (DEBUG) std::cerr << "--- Spilling detected, re-running linear scan ---\n";
}
}
// 4. 将最终分配结果应用到机器指令
applyAllocation();
// 5. 收集用到的被调用者保存寄存器
MFunc->getFrameInfo().vreg_to_preg_map = this->vreg_to_preg_map;
collectUsedCalleeSavedRegs();
if (DEBUG) std::cerr << "===== Finished Linear Scan Register Allocation =====\n\n";
}
// 步骤 1.1: 对基本块进行线性化,这里我们简单地按现有顺序排列
void RISCv64LinearScan::linearizeBlocks() {
linear_order_blocks.clear();
for (auto& mbb : MFunc->getBlocks()) {
linear_order_blocks.push_back(mbb.get());
}
}
// RISCv64LinearScan.cpp
void RISCv64LinearScan::computeLiveIntervals() {
instr_numbering.clear();
live_intervals.clear();
unhandled.clear();
// a. 对所有指令进行线性编号并记录CALL指令的位置
int num = 0;
std::set<int> call_locations;
for (auto* mbb : linear_order_blocks) {
for (auto& instr : mbb->getInstructions()) {
instr_numbering[instr.get()] = num;
if (instr->getOpcode() == RVOpcodes::CALL) {
call_locations.insert(num);
}
num += 2; // 指令编号间隔为2方便在溢出重写时插入指令
}
}
// b. 遍历所有指令记录每个vreg首次和末次出现的位置
std::map<unsigned, std::pair<int, int>> vreg_ranges; // vreg -> {first_instr_num, last_instr_num}
for (auto* mbb : linear_order_blocks) {
for (auto& instr_ptr : mbb->getInstructions()) {
const MachineInstr* instr = instr_ptr.get();
int instr_num = instr_numbering.at(instr);
std::set<unsigned> use, def;
getInstrUseDef(instr, use, def);
auto all_vregs = use;
all_vregs.insert(def.begin(), def.end());
for (unsigned vreg : all_vregs) {
if (vreg_ranges.find(vreg) == vreg_ranges.end()) {
vreg_ranges[vreg] = {instr_num, instr_num};
} else {
vreg_ranges[vreg].second = std::max(vreg_ranges[vreg].second, instr_num);
}
}
}
}
// c. 根据记录的边界创建LiveInterval对象并检查是否跨越CALL
for (auto const& [vreg, range] : vreg_ranges) {
live_intervals.emplace(vreg, LiveInterval(vreg));
auto& interval = live_intervals.at(vreg);
interval.start = range.first;
interval.end = range.second;
// 检查此区间是否跨越了任何CALL指令
auto it = call_locations.lower_bound(interval.start);
if (it != call_locations.end() && *it < interval.end) {
interval.crosses_call = true;
}
}
// d. 将所有计算出的活跃区间放入 unhandled 列表
for (auto& pair : live_intervals) {
unhandled.push_back(&pair.second);
}
std::sort(unhandled.begin(), unhandled.end(), [](const LiveInterval* a, const LiveInterval* b){
return a->start < b->start;
});
}
// RISCv64LinearScan.cpp
// 在类的定义中添加一个辅助函数来判断寄存器类型
bool isCalleeSaved(PhysicalReg preg) {
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) return true;
if (preg == PhysicalReg::S0) return true; // s0 通常也作为被调用者保存
// 浮点寄存器
if (preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) return true;
if (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27) return true;
return false;
}
// 线性扫描主算法
bool RISCv64LinearScan::linearScan() {
active.clear();
spilled_vregs.clear();
vreg_to_preg_map.clear();
// 将寄存器池分为调用者保存和被调用者保存两类
std::set<PhysicalReg> free_caller_int_regs, free_callee_int_regs;
std::set<PhysicalReg> free_caller_fp_regs, free_callee_fp_regs;
for (auto preg : allocable_int_regs) {
if (isCalleeSaved(preg)) free_callee_int_regs.insert(preg);
else free_caller_int_regs.insert(preg);
}
for (auto preg : allocable_fp_regs) {
if (isCalleeSaved(preg)) free_callee_fp_regs.insert(preg);
else free_caller_fp_regs.insert(preg);
}
// 预处理ABI参数寄存器
vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end());
std::vector<LiveInterval*> normal_unhandled;
for(LiveInterval* interval : unhandled) {
if(abi_vreg_map.count(interval->vreg)) {
active.push_back(interval);
PhysicalReg preg = abi_vreg_map.at(interval->vreg);
if (isFPVReg(interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.erase(preg); else free_caller_fp_regs.erase(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.erase(preg); else free_caller_int_regs.erase(preg);
}
} else {
normal_unhandled.push_back(interval);
}
}
unhandled = normal_unhandled;
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
// 主循环
for (LiveInterval* current : unhandled) {
// a. 释放active列表中已结束的区间
std::vector<LiveInterval*> new_active;
for (LiveInterval* active_interval : active) {
if (active_interval->end < current->start) {
PhysicalReg preg = vreg_to_preg_map.at(active_interval->vreg);
if (isFPVReg(active_interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg);
}
} else {
new_active.push_back(active_interval);
}
}
active = new_active;
// b. 约束化地为当前区间分配寄存器
bool is_fp = isFPVReg(current->vreg);
auto& free_caller = is_fp ? free_caller_fp_regs : free_caller_int_regs;
auto& free_callee = is_fp ? free_callee_fp_regs : free_callee_int_regs;
PhysicalReg allocated_preg = PhysicalReg::INVALID;
if (current->crosses_call) {
// 跨调用区间:必须使用被调用者保存寄存器
if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
} else {
// 非跨调用区间:优先使用调用者保存寄存器
if (!free_caller.empty()) {
allocated_preg = *free_caller.begin();
free_caller.erase(allocated_preg);
} else if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
}
if (allocated_preg != PhysicalReg::INVALID) {
vreg_to_preg_map[current->vreg] = allocated_preg;
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
} else {
// c. 没有可用寄存器,需要溢出
spillAtInterval(current);
}
}
return !spilled_vregs.empty();
}
void RISCv64LinearScan::chooseRegForInterval(LiveInterval* current) {
bool is_fp = isFPVReg(current->vreg);
auto& free_regs = is_fp ? free_fp_regs : free_int_regs;
if (!free_regs.empty()) {
// 有可用寄存器
PhysicalReg preg = *free_regs.begin();
free_regs.erase(free_regs.begin());
vreg_to_preg_map[current->vreg] = preg;
active.push_back(current);
// 保持 active 列表按结束点排序
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){
return a->end < b->end;
});
} else {
// 没有可用寄存器,需要溢出
spillAtInterval(current);
}
}
void RISCv64LinearScan::spillAtInterval(LiveInterval* current) {
LiveInterval* spill_candidate = nullptr;
// 启发式溢出:
// 如果current需要callee-saved则从active中找一个占用callee-saved且结束最晚的区间比较
// 否则找active中结束最晚的区间
// 这里简化处理总是找active中结束最晚的区间
auto last_active = active.back();
if (last_active->end > current->end) {
// 溢出active中的区间
spill_candidate = last_active;
PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg);
vreg_to_preg_map[current->vreg] = preg; // 把换出的寄存器给current
// 更新active列表
active.pop_back();
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
spilled_vregs.insert(spill_candidate->vreg);
} else {
// 溢出当前区间
spilled_vregs.insert(current->vreg);
}
}
// 步骤 3: 重写程序,插入溢出代码
void RISCv64LinearScan::rewriteProgram() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int spill_offset = frame_info.locals_size; // 溢出区域接在局部变量之后
for (unsigned vreg : spilled_vregs) {
if (frame_info.spill_offsets.count(vreg)) continue; // 避免重复分配
int size = isFPVReg(vreg) ? 4 : (vreg_type_map.at(vreg)->isPointer() ? 8 : 4);
spill_offset += size;
spill_offset = (spill_offset + 7) & ~7; // 8字节对齐
frame_info.spill_offsets[vreg] = -(16 + spill_offset);
}
frame_info.spill_size = spill_offset - frame_info.locals_size;
for (auto& mbb : MFunc->getBlocks()) {
auto& instrs = mbb->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> new_instrs;
for (auto it = instrs.begin(); it != instrs.end(); ++it) {
auto& instr = *it;
std::set<unsigned> use_vregs, def_vregs;
getInstrUseDef(instr.get(), use_vregs, def_vregs);
// 建立溢出vreg到新临时vreg的映射
std::map<unsigned, unsigned> use_remap;
std::map<unsigned, unsigned> def_remap;
// 1. 为所有溢出的USE创建LOAD指令和映射
for (unsigned old_vreg : use_vregs) {
if (spilled_vregs.count(old_vreg) && use_remap.find(old_vreg) == use_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
use_remap[old_vreg] = new_temp_vreg;
RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
));
new_instrs.push_back(std::move(load));
}
}
// 2. 为所有溢出的DEF创建映射
for (unsigned old_vreg : def_vregs) {
if (spilled_vregs.count(old_vreg) && def_remap.find(old_vreg) == def_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
def_remap[old_vreg] = new_temp_vreg;
}
}
// 3. 基于角色精确地替换原指令中的操作数
auto opcode = instr->getOpcode();
auto& operands = instr->getOperands();
auto replace_reg_op = [](RegOperand* reg_op, const std::map<unsigned, unsigned>& remap) {
if (reg_op->isVirtual() && remap.count(reg_op->getVRegNum())) {
reg_op->setVRegNum(remap.at(reg_op->getVRegNum()));
}
};
if (op_info.count(opcode)) {
const auto& info = op_info.at(opcode);
// 替换 Defs
for (int idx : info.first) {
if (idx < operands.size() && operands[idx]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), def_remap);
}
}
// 替换 Uses
for (int idx : info.second) {
if (idx < operands.size()) {
if (operands[idx]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), use_remap);
} else if (operands[idx]->getKind() == MachineOperand::KIND_MEM) {
replace_reg_op(static_cast<MemOperand*>(operands[idx].get())->getBase(), use_remap);
}
}
}
} else if (opcode == RVOpcodes::CALL) {
// 特殊处理 CALL 指令
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[0].get()), def_remap);
}
for (size_t i = 1; i < operands.size(); ++i) {
if (operands[i]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[i].get()), use_remap);
}
}
}
// 4. 将修改后的指令放入新列表
new_instrs.push_back(std::move(instr));
// 5. 为所有溢出的DEF创建STORE指令
for(const auto& pair : def_remap) {
unsigned old_vreg = pair.first;
unsigned new_temp_vreg = pair.second;
Type* type = vreg_type_map.at(old_vreg);
RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
));
new_instrs.push_back(std::move(store));
}
}
instrs = std::move(new_instrs);
}
}
// 步骤 4: 应用最终分配结果
void RISCv64LinearScan::applyAllocation() {
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
if (op_ptr->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op_ptr.get());
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
// 如果一个vreg最终没有颜色这通常意味着它是一个短生命周期的临时变量
// 在溢出重写中产生,但在下一轮分配前就被优化掉了。
// 或者是一个从未被使用的定义。
// 给他一个临时寄存器以防万一。
reg_op->setPReg(PhysicalReg::T5);
}
}
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
auto reg_op = mem_op->getBase();
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
reg_op->setPReg(PhysicalReg::T5);
}
}
}
}
}
}
}
void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
// 这个函数与图着色版本中的 getInstrUseDef 逻辑完全相同,此处直接复用
auto opcode = instr->getOpcode();
const auto& operands = instr->getOperands();
// op_info 的定义已被移到函数外部的命名空间中
auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<const RegOperand*>(op);
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<const MemOperand*>(op);
auto reg_op = mem_op->getBase();
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
}
};
if (op_info.count(opcode)) {
const auto& info = op_info.at(opcode);
for (int idx : info.first) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), def);
for (int idx : info.second) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), use);
// MemOperand 的基址寄存器总是一个 use
for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use);
} else if (opcode == RVOpcodes::CALL) {
// CALL指令的特殊处理
// 第一个操作数如果有是def返回值
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def);
// 后续的寄存器操作数是use参数
for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[i].get(), use);
}
}
// 辅助函数: 判断是否为浮点vreg
bool RISCv64LinearScan::isFPVReg(unsigned vreg) const {
return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat();
}
// 辅助函数: 收集被使用的被调用者保存寄存器
void RISCv64LinearScan::collectUsedCalleeSavedRegs() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
frame_info.used_callee_saved_regs.clear();
const auto& callee_saved_int = getCalleeSavedIntRegs();
const auto& callee_saved_fp = getCalleeSavedFpRegs();
std::set<PhysicalReg> callee_saved_set(callee_saved_int.begin(), callee_saved_int.end());
callee_saved_set.insert(callee_saved_fp.begin(), callee_saved_fp.end());
callee_saved_set.insert(PhysicalReg::S0); // s0总是被用作帧指针
for(const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second;
if(callee_saved_set.count(preg)) {
frame_info.used_callee_saved_regs.insert(preg);
}
}
}
} // namespace sysy

View File

@ -55,41 +55,12 @@ void RISCv64RegAlloc::run() {
if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n"; if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n";
const int MAX_ITERATIONS = 50; while (true) {
int iteration = 0;
while (iteration++ < MAX_ITERATIONS) {
if (doAllocation()) { if (doAllocation()) {
break; break;
} else { } else {
rewriteProgram(); rewriteProgram();
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n"; if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation ---\n";
if (iteration >= MAX_ITERATIONS) {
std::cerr << "ERROR: Register allocation failed to converge after " << MAX_ITERATIONS << " iterations\n";
std::cerr << " Spill worklist size: " << spillWorklist.size() << "\n";
std::cerr << " Total nodes: " << (initial.size() + coloredNodes.size()) << "\n";
// Emergency spill remaining nodes to break the loop
std::cerr << " Emergency spilling remaining spill worklist nodes...\n";
for (unsigned node : spillWorklist) {
spilledNodes.insert(node);
}
// Also spill any nodes that didn't get colors
std::set<unsigned> uncolored;
for (unsigned node : initial) {
if (color_map.find(node) == color_map.end()) {
uncolored.insert(node);
}
}
for (unsigned node : uncolored) {
spilledNodes.insert(node);
}
// Force completion
break;
}
} }
} }

View File

@ -22,7 +22,6 @@ public:
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg // 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val); unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; }
unsigned getNewVReg(Type* type); unsigned getNewVReg(Type* type);
unsigned getVRegCounter() const; unsigned getVRegCounter() const;
// 获取 vreg_map 的公共接口 // 获取 vreg_map 的公共接口

View File

@ -41,6 +41,8 @@ enum class PhysicalReg {
// 假设 vreg_counter 不会达到这么大的值 // 假设 vreg_counter 不会达到这么大的值
PHYS_REG_START_ID = 1000000, PHYS_REG_START_ID = 1000000,
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间 PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
INVALID, ///< 无效寄存器标记
}; };
// RISC-V 指令操作码枚举 // RISC-V 指令操作码枚举
@ -86,6 +88,7 @@ enum class RVOpcodes {
// 浮点转换 // 浮点转换
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点) FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数) FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
FCVT_W_S_RTZ, // fcvt.w.s rd, rs1, rtz (使用向零截断模式)
// 浮点传送/移动 // 浮点传送/移动
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间) FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)

View File

@ -0,0 +1,104 @@
#ifndef RISCV64_LINEARSCAN_H
#define RISCV64_LINEARSCAN_H
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h"
#include <vector>
#include <map>
#include <set>
#include <algorithm>
namespace sysy {
// 前向声明
class MachineBasicBlock;
class MachineFunction;
class RISCv64ISel;
/**
* @brief 表示一个虚拟寄存器的活跃区间。
* 包含起始和结束指令编号。为了简化,我们不处理有“洞”的区间。
*/
struct LiveInterval {
unsigned vreg = 0;
int start = -1;
int end = -1;
bool crosses_call = false;
LiveInterval(unsigned vreg) : vreg(vreg) {}
// 用于排序,按起始点从小到大
bool operator<(const LiveInterval& other) const {
return start < other.start;
}
};
class RISCv64LinearScan {
public:
RISCv64LinearScan(MachineFunction* mfunc);
void run();
private:
// --- 核心算法流程 ---
void linearizeBlocks();
void computeLiveIntervals();
bool linearScan();
void rewriteProgram();
void applyAllocation();
void chooseRegForInterval(LiveInterval* current);
void spillAtInterval(LiveInterval* current);
// --- 辅助函数 ---
void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def);
bool isFPVReg(unsigned vreg) const;
void collectUsedCalleeSavedRegs();
MachineFunction* MFunc;
RISCv64ISel* ISel;
// --- 线性扫描数据结构 ---
std::vector<MachineBasicBlock*> linear_order_blocks;
std::map<const MachineInstr*, int> instr_numbering;
std::map<unsigned, LiveInterval> live_intervals;
std::vector<LiveInterval*> unhandled;
std::vector<LiveInterval*> active; // 活跃且已分配物理寄存器的区间
std::set<unsigned> spilled_vregs; // 记录在本轮被决定溢出的vreg
// --- 寄存器池和分配结果 ---
std::vector<PhysicalReg> allocable_int_regs;
std::vector<PhysicalReg> allocable_fp_regs;
std::set<PhysicalReg> free_int_regs;
std::set<PhysicalReg> free_fp_regs;
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
std::map<unsigned, PhysicalReg> abi_vreg_map;
const std::map<unsigned, Type*>& vreg_type_map;
};
static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = {
{RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}},
{RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}},
{RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}},
{RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}},
{RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}},
{RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}},
{RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}},
{RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
{RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}},
{RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
{RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}},
{RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}},
{RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}},
{RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}},
{RVOpcodes::RET, {{}, {}}}, {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}},
{RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}},
{RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}},
{RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}},
{RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}}
};
} // namespace sysy
#endif // RISCV64_LINEARSCAN_H

View File

@ -1 +0,0 @@
3

View File

@ -1,3 +0,0 @@
int main(){
return 3;
}

View File

@ -1 +0,0 @@
10

View File

@ -1,8 +0,0 @@
//test domain of global var define and local define
int a = 3;
int b = 5;
int main(){
int a = 5;
return a + b;
}

View File

@ -1 +0,0 @@
5

View File

@ -1,8 +0,0 @@
//test local var define
int main(){
int a, b0, _c;
a = 1;
b0 = 2;
_c = 3;
return b0 + _c;
}

View File

@ -1 +0,0 @@
0

View File

@ -1,4 +0,0 @@
int a[10][10];
int main(){
return 0;
}

View File

@ -1 +0,0 @@
14

View File

@ -1,9 +0,0 @@
//test array define
int main(){
int a[4][2] = {};
int b[4][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int c[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
int d[4][2] = {1, 2, {3}, {5}, 7 , 8};
int e[4][2] = {{d[2][1], c[2][1]}, {3, 4}, {5, 6}, {7, 8}};
return e[3][1] + e[0][0] + e[0][1] + a[2][0];
}

View File

@ -1 +0,0 @@
21

View File

@ -1,9 +0,0 @@
int main(){
const int a[4][2] = {{1, 2}, {3, 4}, {}, 7};
int b[4][2] = {};
int c[4][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int d[3 + 1][2] = {1, 2, {3}, {5}, a[3][0], 8};
int e[4][2][1] = {{d[2][1], {c[2][1]}}, {3, 4}, {5, 6}, {7, 8}};
return e[3][1][0] + e[0][0][0] + e[0][1][0] + d[3][0];
}

View File

@ -1 +0,0 @@
5

View File

@ -1,6 +0,0 @@
//test const gloal var define
const int a = 10, b = 5;
int main(){
return b;
}

View File

@ -1 +0,0 @@
5

View File

@ -1,5 +0,0 @@
//test const local var define
int main(){
const int a = 10, b = 5;
return b;
}

View File

@ -1 +0,0 @@
4

View File

@ -1,5 +0,0 @@
const int a[5]={0,1,2,3,4};
int main(){
return a[4];
}

View File

@ -1 +0,0 @@
9

View File

@ -1,11 +0,0 @@
int a;
int func(int p){
p = p - 1;
return p;
}
int main(){
int b;
a = 10;
b = func(a);
return b;
}

View File

@ -1 +0,0 @@
4

View File

@ -1,8 +0,0 @@
int defn(){
return 4;
}
int main(){
int a=defn();
return a;
}

View File

@ -1 +0,0 @@
9

View File

@ -1,7 +0,0 @@
//test add
int main(){
int a, b;
a = 10;
b = -1;
return a + b;
}

View File

@ -1 +0,0 @@
15

View File

@ -1,5 +0,0 @@
//test addc
const int a = 10;
int main(){
return a + 5;
}

View File

@ -1 +0,0 @@
248

View File

@ -1,7 +0,0 @@
//test sub
const int a = 10;
int main(){
int b;
b = 2;
return b - a;
}

View File

@ -1 +0,0 @@
8

View File

@ -1,6 +0,0 @@
//test subc
int main(){
int a;
a = 10;
return a - 2;
}

View File

@ -1 +0,0 @@
50

View File

@ -1,7 +0,0 @@
//test mul
int main(){
int a, b;
a = 10;
b = 5;
return a * b;
}

View File

@ -1 +0,0 @@
25

View File

@ -1,5 +0,0 @@
//test mulc
const int a = 5;
int main(){
return a * 5;
}

View File

@ -1 +0,0 @@
2

View File

@ -1,7 +0,0 @@
//test div
int main(){
int a, b;
a = 10;
b = 5;
return a / b;
}

View File

@ -1 +0,0 @@
2

View File

@ -1,5 +0,0 @@
//test divc
const int a = 10;
int main(){
return a / 5;
}

View File

@ -1 +0,0 @@
3

View File

@ -1,6 +0,0 @@
//test mod
int main(){
int a;
a = 10;
return a / 3;
}

View File

@ -1 +0,0 @@
1

View File

@ -1,6 +0,0 @@
//test rem
int main(){
int a;
a = 10;
return a % 3;
}

View File

@ -1,2 +0,0 @@
-5
0

View File

@ -1,25 +0,0 @@
// test if-else-if
int ifElseIf() {
int a;
a = 5;
int b;
b = 10;
if(a == 6 || b == 0xb) {
return a;
}
else {
if (b == 10 && a == 1)
a = 25;
else if (b == 10 && a == -5)
a = a + 15;
else
a = -+a;
}
return a;
}
int main(){
putint(ifElseIf());
return 0;
}

View File

@ -1 +0,0 @@
25

View File

@ -1,18 +0,0 @@
// test if-if-else
int ififElse() {
int a;
a = 5;
int b;
b = 10;
if(a == 5)
if (b == 10)
a = 25;
else
a = a + 15;
return (a);
}
int main(){
return (ififElse());
}

View File

@ -1 +0,0 @@
25

View File

@ -1,18 +0,0 @@
// test if-{if-else}
int if_ifElse_() {
int a;
a = 5;
int b;
b = 10;
if(a == 5){
if (b == 10)
a = 25;
else
a = a + 15;
}
return (a);
}
int main(){
return (if_ifElse_());
}

View File

@ -1 +0,0 @@
25

View File

@ -1,18 +0,0 @@
// test if-{if}-else
int if_if_Else() {
int a;
a = 5;
int b;
b = 10;
if(a == 5){
if (b == 10)
a = 25;
}
else
a = a + 15;
return (a);
}
int main(){
return (if_if_Else());
}

View File

@ -1,2 +0,0 @@
88
0

View File

@ -1,31 +0,0 @@
int get_one(int a) {
return 1;
}
int deepWhileBr(int a, int b) {
int c;
c = a + b;
while (c < 75) {
int d;
d = 42;
if (c < 100) {
c = c + d;
if (c > 99) {
int e;
e = d * 2;
if (get_one(0) == 1) {
c = e * 2;
}
}
}
}
return (c);
}
int main() {
int p;
p = 2;
p = deepWhileBr(p, p);
putint(p);
return 0;
}

View File

@ -1 +0,0 @@
3

View File

@ -1,18 +0,0 @@
int doubleWhile() {
int i;
i = 5;
int j;
j = 7;
while (i < 100) {
i = i + 30;
while(j < 100){
j = j + 6;
}
j = j - 100;
}
return (j);
}
int main() {
return doubleWhile();
}

View File

@ -1 +0,0 @@
54

View File

@ -1,31 +0,0 @@
int FourWhile() {
int a;
a = 5;
int b;
int c;
b = 6;
c = 7;
int d;
d = 10;
while (a < 20) {
a = a + 3;
while(b < 10){
b = b + 1;
while(c == 7){
c = c - 1;
while(d < 20){
d = d + 3;
}
d = d - 1;
}
c = c + 1;
}
b = b - 2;
}
return (a + (b + d) + c);
}
int main() {
return FourWhile();
}

View File

@ -1 +0,0 @@
23

View File

@ -1,55 +0,0 @@
int g;
int h;
int f;
int e;
int EightWhile() {
int a;
a = 5;
int b;
int c;
b = 6;
c = 7;
int d;
d = 10;
while (a < 20) {
a = a + 3;
while(b < 10){
b = b + 1;
while(c == 7){
c = c - 1;
while(d < 20){
d = d + 3;
while(e > 1){
e = e-1;
while(f > 2){
f = f -2;
while(g < 3){
g = g +10;
while(h < 10){
h = h + 8;
}
h = h-1;
}
g = g- 8;
}
f = f + 1;
}
e = e + 1;
}
d = d - 1;
}
c = c + 1;
}
b = b - 2;
}
return (a + (b + d) + c)-(e + d - g + h);
}
int main() {
g = 1;
h = 2;
e = 4;
f = 6;
return EightWhile();
}

View File

@ -1 +0,0 @@
201

View File

@ -1,15 +0,0 @@
//test break
int main(){
int i;
i = 0;
int sum;
sum = 0;
while(i < 100){
if(i == 50){
break;
}
sum = sum + i;
i = i + 1;
}
return sum;
}

View File

@ -1 +0,0 @@
36

View File

@ -1,16 +0,0 @@
//test continue
int main(){
int i;
i = 0;
int sum;
sum = 0;
while(i < 100){
if(i == 50){
i = i + 1;
continue;
}
sum = sum + i;
i = i + 1;
}
return sum;
}

View File

@ -1 +0,0 @@
198

View File

@ -1,25 +0,0 @@
// test while-if
int whileIf() {
int a;
a = 0;
int b;
b = 0;
while (a < 100) {
if (a == 5) {
b = 25;
}
else if (a == 10) {
b = 42;
}
else {
b = a * 2;
}
a = a + 1;
}
return (b);
}
int main(){
return (whileIf());
}

View File

@ -1 +0,0 @@
96

View File

@ -1,23 +0,0 @@
int ifWhile() {
int a;
a = 0;
int b;
b = 3;
if (a == 5) {
while(b == 2){
b = b + 2;
}
b = b + 25;
}
else
while (a < 5) {
b = b * 2;
a = a + 1;
}
return (b);
}
int main(){
return (ifWhile());
}

View File

@ -1 +0,0 @@
88

View File

@ -1,25 +0,0 @@
int deepWhileBr(int a, int b) {
int c;
c = a + b;
while (c < 75) {
int d;
d = 42;
if (c < 100) {
c = c + d;
if (c > 99) {
int e;
e = d * 2;
if (1 == 1) {
c = e * 2;
}
}
}
}
return (c);
}
int main() {
int p;
p = 2;
return deepWhileBr(p, p);
}

Some files were not shown because too many files have changed in this diff Show More