Compare commits

..

40 Commits

Author SHA1 Message Date
rain2133
88604c1f94 [IR]消除Falltrhough现象
[IR]优化生成Ret指令逻辑
[README]添加TODO表
2025-07-20 18:23:48 +08:00
rain2133
de696b2b53 [IR]重构数组地址相关指令
增加GEP指令以及相关方法
新增数组Array Type
删除无用指令(GetSubArray,LA)
删除冗余类定义(Lval)
修复中间代码生成逻辑
测试通过所以test目录下的文件
TODO:后端展开数组计算地址仅需要针对GEP指令展开
2025-07-20 15:33:58 +08:00
rain2133
18e7cbd413 Merge branch 'backend' into SCCP 2025-07-20 13:00:15 +08:00
rain2133
20cd16bf52 暂存2 2025-07-20 12:54:19 +08:00
Lixuanwang
80dee78f04 [backend]引入后端pass管理器 2025-07-20 12:45:52 +08:00
Lixuanwang
d7fb017550 Merge branch 'backend-llir' into backend 2025-07-19 18:00:42 +08:00
Lixuanwang
c4b18a70db [backend]准备合并backend-llir 2025-07-19 17:59:45 +08:00
Lixuanwang
9528335a04 [backend-llir]修复了许多重构的bug 2025-07-19 17:50:14 +08:00
rain2133
0d5748e9c5 [IR]修复初始化数组指令的逻辑,更新IR常量定义。 2025-07-19 16:18:05 +08:00
Lixuanwang
d4a6996d74 [backend]重构了后端 2025-07-19 16:06:35 +08:00
rain2133
36cfd2f64d 先将SCCP中重构IR的部分移植到backend 2025-07-19 15:00:04 +08:00
Lixuanwang
75e61bf274 [backend-llir]引入了LLIR定义 2025-07-19 14:29:57 +08:00
rain2133
8f1e477e73 暂存 2025-07-19 14:23:57 +08:00
Lixuanwang
c8308047df [backend]引入了Memset指令在后端的展开 2025-07-19 13:52:09 +08:00
Lixuanwang
86d1de6696 [backend]向脚本添加了打印不通过测例的功能 2025-07-19 12:00:02 +08:00
Lixuanwang
69d27f058d [backend]将testdata/下的测例替换为了赛方测试用例,更新了测试脚本 2025-07-19 01:44:37 +08:00
Lixuanwang
6335abe806 [backend]修复了引入常量重质化后全局常量加载指令的缺失问题 2025-07-19 00:46:46 +08:00
Lixuanwang
6ed5965b29 [backend]数组访存问题基本修复 2025-07-19 00:32:47 +08:00
Lixuanwang
0f26be3586 [backend]添加了对主函数中新引入的调试信息打印的控制,修改了测试脚本为云平台测试的参数,调整了73_int_io测例的输入文件的格式 2025-07-18 22:50:06 +08:00
Lixuanwang
d38ec13cbd [backend]修复了函数调用参数为常数时,参数传递有误的bug 2025-07-18 21:54:24 +08:00
rain2133
10b011a1de [fix]修复部分常量构建,[Pass]建立Pass基类和管理器,预重构优化遍结构 2025-07-18 21:28:36 +08:00
Lixuanwang
e8660120cc [backend]删除了后端对数组访存的地址展开,因为已经在IR中实现 2025-07-18 20:48:59 +08:00
Lixuanwang
3657c08644 [backend]引入新的活跃性分析 2025-07-18 20:24:47 +08:00
Lixuanwang
1bcb5eba2a [backend]去除了错误的寄存器分配机制 2025-07-18 18:50:21 +08:00
Lixuanwang
fc62446b40 Merge branch 'backend' of gitee.com:lixuanwang/mysysy into backend 2025-07-18 18:48:44 +08:00
Lixuanwang
fedb4b0a9f [backend]修复了栈分配空间大小不考虑数组的错误 2025-07-18 18:48:38 +08:00
Lixuanwang
4bf4c98787 [backend]修复了栈分配空间大小不考虑数组的错误 2025-07-18 18:44:13 +08:00
rain2133
34b5a93aaf [Mem2Reg]重构SSA提升 2025-07-18 18:17:45 +08:00
rain2133
a5d97185e1 [IR]修复IR报错,调整结构。 2025-07-18 18:17:22 +08:00
rain2133
fdc946c1b5 [IR]重构常量定义,引入undefvalue定义,修改常量方法使用尽量适配旧版 2025-07-18 16:40:16 +08:00
Lixuanwang
198c1974e3 [backend] 新pass ACE修改完毕 2025-07-18 13:04:02 +08:00
Lixuanwang
b90e4faa6a [backend] 删除了部分错误代码 2025-07-18 01:37:29 +08:00
Lixuanwang
be8ca144d0 [backend]引入了新的pass,负责消除数组复杂地址访问 2025-07-18 00:10:10 +08:00
rain2133
725da2858d [IR]指令构造器更新 2025-07-17 21:34:19 +08:00
rain2133
631ef80de2 [IR]phi指令重构,将block信息加入并提供新方法,后续需更改phi相关指令构建逻辑 2025-07-17 19:01:02 +08:00
rain2133
77fae4d662 [CFG]增加分支优化,为SCCP调用做铺垫,预备修改phi定义 2025-07-17 16:50:09 +08:00
rain2133
009f54863e [CFG]CFG优化方法转换为静态方法,方便其他优化遍调用,TODO:简化条件分支 2025-07-17 15:54:37 +08:00
rain2133
f7e318e623 [SCCP]初步构建SCCP,.cpp仍不完善暂不commit 2025-07-16 22:01:37 +08:00
rain2133
00348c1931 修改CFG优化的文件名,修改phidel标签 2025-07-16 22:01:37 +08:00
rain2133
5a6cfbee1e [SysYIROptUtils]增加通用优化工具类,修改相关代码 2025-07-16 22:01:37 +08:00
370 changed files with 49470 additions and 6135 deletions

2
.gitignore vendored
View File

@@ -36,7 +36,7 @@
doxygen doxygen
!/testdata/functional/*.out !/testdata/functional/*.out
!/testdata/performance/*.out !/testdata/h_functional/*.out
build/ build/
.antlr .antlr
.vscode/ .vscode/

View File

@@ -38,3 +38,12 @@ mysysy/ $ bash setup.sh
### 配套脚本 ### 配套脚本
TODO: 需要完善) TODO: 需要完善)
### TODO_list:
除开注释中的TODO后续时间充足可以考虑的TODO:
- store load指令由于gep指令的引入, 维度信息的记录是非必须的, 考虑删除
- use def关系经过mem2reg和phi函数明确转换为ssa形式, 以及函数参数通过value数组明确定义, 使得基本块的args参数信息记录非必须, 考虑删除

View File

@@ -0,0 +1,160 @@
#include "AddressCalculationExpansion.h"
#include <iostream>
#include <vector>
#include "IR.h"
#include "IRBuilder.h"
extern int DEBUG;
namespace sysy {
bool AddressCalculationExpansion::run() {
bool changed = false;
for (auto& funcPair : pModule->getFunctions()) {
Function* func = funcPair.second.get();
for (auto& bb_ptr : func->getBasicBlocks()) {
BasicBlock* bb = bb_ptr.get();
for (auto it = bb->getInstructions().begin(); it != bb->getInstructions().end(); ) {
Instruction* inst = it->get();
Value* basePointer = nullptr;
Value* valueToStore = nullptr;
size_t firstIndexOperandIdx = 0;
size_t numBaseOperands = 0;
if (inst->isLoad()) {
numBaseOperands = 1;
basePointer = inst->getOperand(0);
firstIndexOperandIdx = 1;
} else if (inst->isStore()) {
numBaseOperands = 2;
valueToStore = inst->getOperand(0);
basePointer = inst->getOperand(1);
firstIndexOperandIdx = 2;
} else {
++it;
continue;
}
if (inst->getNumOperands() <= numBaseOperands) {
++it;
continue;
}
std::vector<int> dims;
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
for (const auto& use_ptr : allocaInst->getDims()) {
Value* dimValue = use_ptr->getValue();
if (ConstantValue* constVal = dynamic_cast<ConstantValue*>(dimValue)) {
dims.push_back(constVal->getInt());
} else {
std::cerr << "Warning: AllocaInst dimension is not a constant integer. Skipping GEP expansion for: ";
SysYPrinter::printValue(allocaInst);
std::cerr << "\n";
dims.clear();
break;
}
}
} else if (GlobalValue* globalValue = dynamic_cast<GlobalValue*>(basePointer)) {
std::cerr << "Warning: GlobalValue dimension handling needs explicit implementation for GEP expansion. Skipping GEP for: ";
SysYPrinter::printValue(globalValue);
std::cerr << "\n";
++it;
continue;
} else {
std::cerr << "Warning: Base pointer is not AllocaInst/GlobalValue or its array dimensions cannot be determined for GEP expansion. Skipping GEP for: ";
SysYPrinter::printValue(basePointer);
std::cerr << " in instruction ";
SysYPrinter::printInst(inst);
std::cerr << "\n";
++it;
continue;
}
if (dims.empty() && (inst->getNumOperands() > numBaseOperands)) {
if (DEBUG) {
std::cerr << "ACE Warning: Could not get valid array dimensions for ";
SysYPrinter::printValue(basePointer);
std::cerr << " in instruction ";
SysYPrinter::printInst(inst);
std::cerr << " (expected dimensions for indices, but got none).\n";
}
++it;
continue;
}
std::vector<Value*> indexOperands;
for (size_t i = firstIndexOperandIdx; i < inst->getNumOperands(); ++i) {
indexOperands.push_back(inst->getOperand(i));
}
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
if (allocaInst->getNumDims() != indexOperands.size()) {
if (DEBUG) {
std::cerr << "ACE Warning: Index count (" << indexOperands.size() << ") does not match AllocaInst dimensions (" << allocaInst->getNumDims() << ") for instruction ";
SysYPrinter::printInst(inst);
std::cerr << "\n";
}
++it;
continue;
}
}
Value* totalOffset = ConstantInteger::get(0);
pBuilder->setPosition(bb, it);
for (size_t i = 0; i < indexOperands.size(); ++i) {
Value* index = indexOperands[i];
int stride = calculateStride(dims, i);
Value* strideConst = ConstantInteger::get(stride);
Type* intType = Type::getIntType();
BinaryInst* currentDimOffsetInst = pBuilder->createBinaryInst(Instruction::kMul, intType, index, strideConst);
BinaryInst* newTotalOffsetInst = pBuilder->createBinaryInst(Instruction::kAdd, intType, totalOffset, currentDimOffsetInst);
totalOffset = newTotalOffsetInst;
}
// 计算有效地址effective_address = basePointer + totalOffset
Value* effective_address = pBuilder->createBinaryInst(Instruction::kAdd, basePointer->getType(), basePointer, totalOffset);
// 创建新的 LoadInst 或 StoreInstindices 为空
Instruction* newInst = nullptr;
if (inst->isLoad()) {
newInst = pBuilder->createLoadInst(effective_address, {});
inst->replaceAllUsesWith(newInst);
} else { // StoreInst
newInst = pBuilder->createStoreInst(valueToStore, effective_address, {});
}
Instruction* oldInst = it->get();
++it;
for (size_t i = 0; i < oldInst->getNumOperands(); ++i) {
Value* operandValue = oldInst->getOperand(i);
if (operandValue) {
for (auto use_it = operandValue->getUses().begin(); use_it != operandValue->getUses().end(); ++use_it) {
if ((*use_it)->getUser() == oldInst && (*use_it)->getIndex() == i) {
operandValue->removeUse(*use_it);
break;
}
}
}
}
bb->getInstructions().erase(std::prev(it));
changed = true;
if (DEBUG) {
std::cerr << "ACE: Computed effective address:\n";
SysYPrinter::printInst(dynamic_cast<Instruction*>(effective_address));
std::cerr << "ACE: New Load/Store instruction:\n";
SysYPrinter::printInst(newInst);
std::cerr << "--------------------------------\n";
}
}
}
}
return changed;
}
} // namespace sysy

View File

@@ -21,12 +21,17 @@ add_executable(sysyc
IR.cpp IR.cpp
SysYIRGenerator.cpp SysYIRGenerator.cpp
SysYIRPrinter.cpp SysYIRPrinter.cpp
SysYIROptPre.cpp SysYIRCFGOpt.cpp
SysYIRAnalyser.cpp # SysYIRAnalyser.cpp
DeadCodeElimination.cpp # DeadCodeElimination.cpp
Mem2Reg.cpp AddressCalculationExpansion.cpp
Reg2Mem.cpp # Mem2Reg.cpp
# Reg2Mem.cpp
RISCv64Backend.cpp RISCv64Backend.cpp
RISCv64ISel.cpp
RISCv64RegAlloc.cpp
RISCv64AsmPrinter.cpp
RISCv64Passes.cpp
) )
# 设置 include 路径,包含 ANTLR 运行时库和项目头文件 # 设置 include 路径,包含 ANTLR 运行时库和项目头文件

View File

@@ -37,7 +37,7 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
auto storeInst = dynamic_cast<StoreInst*>(inst); auto storeInst = dynamic_cast<StoreInst*>(inst);
auto pointer = storeInst->getPointer(); auto pointer = storeInst->getPointer();
// 如果是全局变量或者是函数的数组参数 // 如果是全局变量或者是函数的数组参数
if (isGlobal(pointer) || (isArr(pointer) && if (SysYIROptUtils::isGlobal(pointer) || (SysYIROptUtils::isArr(pointer) &&
std::find(func->getEntryBlock()->getArguments().begin(), std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(), func->getEntryBlock()->getArguments().end(),
pointer) != func->getEntryBlock()->getArguments().end())) { pointer) != func->getEntryBlock()->getArguments().end())) {
@@ -63,7 +63,7 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
std::cout << "=== Dead Store Found ===\n"; std::cout << "=== Dead Store Found ===\n";
SysYPrinter::printInst(storeInst); SysYPrinter::printInst(storeInst);
} }
usedelete(storeInst); SysYIROptUtils::usedelete(storeInst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
} else { } else {
++iter; ++iter;
@@ -85,7 +85,7 @@ void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) {
std::cout << "=== Dead Load Binary Unary Found ===\n"; std::cout << "=== Dead Load Binary Unary Found ===\n";
SysYPrinter::printInst(inst); SysYPrinter::printInst(inst);
} }
usedelete(inst); SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
continue; continue;
} }
@@ -114,7 +114,7 @@ void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
std::cout << "=== Dead Alloca Found ===\n"; std::cout << "=== Dead Alloca Found ===\n";
SysYPrinter::printInst(inst); SysYPrinter::printInst(inst);
} }
usedelete(inst); SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
continue; continue;
} }
@@ -183,7 +183,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
/// 如果 pointer 仅被该 phi 使用,可以删除 ph /// 如果 pointer 仅被该 phi 使用,可以删除 ph
if (tag) { if (tag) {
changed = true; changed = true;
usedelete(inst); SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
continue; continue;
} }
@@ -193,7 +193,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
auto pointer = memsetInst->getPointer(); auto pointer = memsetInst->getPointer();
if (pointer->getUses().empty()) { if (pointer->getUses().empty()) {
changed = true; changed = true;
usedelete(inst); SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
continue; continue;
} }
@@ -234,7 +234,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
SysYPrinter::printInst(loadInst); SysYPrinter::printInst(loadInst);
SysYPrinter::printInst(nextStore); SysYPrinter::printInst(nextStore);
} }
usedelete(loadInst); SysYIROptUtils::usedelete(loadInst);
iter = instrs.erase(iter); iter = instrs.erase(iter);
// 删除 prevStore 这里是不是可以留给删除无用store处理 // 删除 prevStore 这里是不是可以留给删除无用store处理
// if (prevStore->getUses().empty()) { // if (prevStore->getUses().empty()) {
@@ -256,21 +256,4 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
} }
bool DeadCodeElimination::isGlobal(Value *val){
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
bool DeadCodeElimination::isArr(Value *val){
auto aval = dynamic_cast<AllocaInst *>(val);
return aval != nullptr && aval->getNumDims() != 0;
}
void DeadCodeElimination::usedelete(Instruction *instr){
for (auto &use1 : instr->getOperands()) {
auto val1 = use1->getValue();
val1->removeUse(use1);
}
}
} // namespace sysy } // namespace sysy

View File

@@ -49,6 +49,11 @@ auto Type::getFunctionType(Type *returnType, const std::vector<Type *> &paramTyp
return FunctionType::get(returnType, paramTypes); return FunctionType::get(returnType, paramTypes);
} }
auto Type::getArrayType(Type *elementType, unsigned numElements) -> Type * {
// forward to ArrayType
return ArrayType::get(elementType, numElements);
}
auto Type::getSize() const -> unsigned { auto Type::getSize() const -> unsigned {
switch (kind) { switch (kind) {
case kInt: case kInt:
@@ -58,6 +63,10 @@ auto Type::getSize() const -> unsigned {
case kPointer: case kPointer:
case kFunction: case kFunction:
return 8; return 8;
case Kind::kArray: {
const ArrayType* arrType = static_cast<const ArrayType*>(this);
return arrType->getElementType()->getSize() * arrType->getNumElements();
}
case kVoid: case kVoid:
return 0; return 0;
} }
@@ -95,6 +104,11 @@ FunctionType*FunctionType::get(Type *returnType, const std::vector<Type *> &para
return result.first->get(); return result.first->get();
} }
ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
// TODO:可以考虑在这里添加缓存,避免重复创建相同的数组类型
return new ArrayType(elementType, numElements);
}
void Value::replaceAllUsesWith(Value *value) { void Value::replaceAllUsesWith(Value *value) {
for (auto &use : uses) { for (auto &use : uses) {
use->getUser()->setOperand(use->getIndex(), value); use->getUser()->setOperand(use->getIndex(), value);
@@ -102,30 +116,54 @@ void Value::replaceAllUsesWith(Value *value) {
uses.clear(); uses.clear();
} }
ConstantValue* ConstantValue::get(int value) {
static std::map<int, std::unique_ptr<ConstantValue>> intConstants; // Implementations for static members
auto iter = intConstants.find(value);
if (iter != intConstants.end()) { std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> ConstantValue::mConstantPool;
return iter->second.get(); std::unordered_map<Type*, UndefinedValue*> UndefinedValue::UndefValues;
ConstantValue* ConstantValue::get(Type* type, ConstantValVariant val) {
ConstantValueKey key = {type, val};
auto it = mConstantPool.find(key);
if (it != mConstantPool.end()) {
return it->second;
} }
auto inst = new ConstantValue(value);
assert(inst); ConstantValue* newConstant = nullptr;
auto result = intConstants.emplace(value, inst); if (std::holds_alternative<int>(val)) {
return result.first->second.get(); newConstant = new ConstantInteger(type, std::get<int>(val));
} else if (std::holds_alternative<float>(val)) {
newConstant = new ConstantFloating(type, std::get<float>(val));
} else {
assert(false && "Unsupported ConstantValVariant type");
}
mConstantPool[key] = newConstant;
return newConstant;
} }
ConstantValue* ConstantValue::get(float value) { ConstantInteger* ConstantInteger::get(Type* type, int val) {
static std::map<float, std::unique_ptr<ConstantValue>> floatConstants; return dynamic_cast<ConstantInteger*>(ConstantValue::get(type, val));
auto iter = floatConstants.find(value);
if (iter != floatConstants.end()) {
return iter->second.get();
}
auto inst = new ConstantValue(value);
assert(inst);
auto result = floatConstants.emplace(value, inst);
return result.first->second.get();
} }
ConstantFloating* ConstantFloating::get(Type* type, float val) {
return dynamic_cast<ConstantFloating*>(ConstantValue::get(type, val));
}
UndefinedValue* UndefinedValue::get(Type* type) {
assert(!type->isVoid() && "Cannot get UndefinedValue of void type!");
auto it = UndefValues.find(type);
if (it != UndefValues.end()) {
return it->second;
}
UndefinedValue* newUndef = new UndefinedValue(type);
UndefValues[type] = newUndef;
return newUndef;
}
auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> { auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
std::set<Function *> result; std::set<Function *> result;
for (auto callee : callees) { for (auto callee : callees) {
@@ -441,44 +479,7 @@ Function * Function::clone(const std::string &suffix) const {
break; break;
} }
case Instruction::kLa: { // TODO复制GEP指令
auto oldLaInst = dynamic_cast<LaInst *>(inst);
auto oldPointer = oldLaInst->getPointer();
Value *newPointer;
std::vector<Value *> newIndices;
newPointer = oldNewValueMap.at(oldPointer);
for (const auto &index : oldLaInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
ss << oldLaInst->getName() << suffix;
auto newLaInst = new LaInst(newPointer, newIndices, oldNewBlockMap.at(oldLaInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldLaInst, newLaInst);
break;
}
case Instruction::kGetSubArray: {
auto oldGetSubArrayInst = dynamic_cast<GetSubArrayInst *>(inst);
auto oldFather = oldGetSubArrayInst->getFatherArray();
auto oldChild = oldGetSubArrayInst->getChildArray();
Value *newFather;
Value *newChild;
std::vector<Value *> newIndices;
newFather = oldNewValueMap.at(oldFather);
newChild = oldNewValueMap.at(oldChild);
for (const auto &index : oldGetSubArrayInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
ss << oldGetSubArrayInst->getName() << suffix;
auto newGetSubArrayInst =
new GetSubArrayInst(dynamic_cast<LVal *>(newFather), dynamic_cast<LVal *>(newChild), newIndices,
oldNewBlockMap.at(oldGetSubArrayInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldGetSubArrayInst, newGetSubArrayInst);
break;
}
case Instruction::kMemset: { case Instruction::kMemset: {
auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst); auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst);
@@ -545,6 +546,83 @@ void User::replaceOperand(unsigned index, Value *value) {
value->addUse(use); value->addUse(use);
} }
/**
* phi相关函数
*/
Value* PhiInst::getvalfromBlk(BasicBlock* blk){
refreshB2VMap();
if( blk2val.find(blk) != blk2val.end()) {
return blk2val.at(blk);
}
return nullptr;
}
BasicBlock* PhiInst::getBlkfromVal(Value* val){
// 返回第一个值对应的基本块
for(unsigned i = 0; i < vsize; i++) {
if(getValue(i) == val) {
return getBlock(i);
}
}
return nullptr;
}
void PhiInst::delValue(Value* val){
//根据value删除对应的基本块和值
unsigned i = 0;
BasicBlock* blk = getBlkfromVal(val);
for(i = 0; i < vsize; i++) {
if(getValue(i) == val) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::delBlk(BasicBlock* blk){
//根据Blk删除对应的基本块和值
unsigned i = 0;
Value* val = getvalfromBlk(blk);
for(i = 0; i < vsize; i++) {
if(getBlock(i) == blk) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
refreshB2VMap();
Value* val = blk2val.at(getBlock(k));
// 替换基本块
setOperand(2 * k + 1, newBlk);
// 替换blk2val映射
blk2val.erase(getBlock(k));
blk2val.emplace(newBlk, val);
}
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
refreshB2VMap();
Value* val = blk2val.at(oldBlk);
// 替换基本块
delBlk(oldBlk);
addIncoming(val, newBlk);
}
void PhiInst::refreshB2VMap(){
blk2val.clear();
for(unsigned i = 0; i < vsize; i++) {
blk2val.emplace(getBlock(i), getValue(i));
}
}
CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name) CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)
: Instruction(kCall, callee->getReturnType(), parent, name) { : Instruction(kCall, callee->getReturnType(), parent, name) {
addOperand(callee); addOperand(callee);

File diff suppressed because it is too large Load Diff

225
src/RISCv64AsmPrinter.cpp Normal file
View File

@@ -0,0 +1,225 @@
#include "RISCv64AsmPrinter.h"
#include "RISCv64ISel.h"
#include <stdexcept>
namespace sysy {
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
bool isMemoryOp(RVOpcodes opcode) {
switch (opcode) {
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
return true;
default:
return false;
}
}
RISCv64AsmPrinter::RISCv64AsmPrinter(MachineFunction* mfunc) : MFunc(mfunc) {}
void RISCv64AsmPrinter::run(std::ostream& os) {
OS = &os;
*OS << ".globl " << MFunc->getName() << "\n";
*OS << MFunc->getName() << ":\n";
printPrologue();
for (auto& mbb : MFunc->getBlocks()) {
printBasicBlock(mbb.get());
}
}
void RISCv64AsmPrinter::printPrologue() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
// 序言需要为保存ra和s0预留16字节
int total_stack_size = frame_info.locals_size + frame_info.spill_size + 16;
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size;
if (aligned_stack_size > 0) {
*OS << " addi sp, sp, -" << aligned_stack_size << "\n";
*OS << " sd ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " sd s0, " << (aligned_stack_size - 16) << "(sp)\n";
*OS << " mv s0, sp\n";
}
// 忠实还原保存函数入口参数的逻辑
Function* F = MFunc->getFunc();
if (F && F->getEntryBlock()) {
int arg_idx = 0;
RISCv64ISel* isel = MFunc->getISel();
for (AllocaInst* alloca_for_param : F->getEntryBlock()->getArguments()) {
if (arg_idx >= 8) break;
unsigned vreg = isel->getVReg(alloca_for_param);
if (frame_info.alloca_offsets.count(vreg)) {
int offset = frame_info.alloca_offsets.at(vreg);
auto arg_reg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + arg_idx);
*OS << " sw " << regToString(arg_reg) << ", " << offset << "(s0)\n";
}
arg_idx++;
}
}
}
void RISCv64AsmPrinter::printEpilogue() {
int aligned_stack_size = MFunc->getFrameInfo().total_size;
if (aligned_stack_size > 0) {
*OS << " ld ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " ld s0, " << (aligned_stack_size - 16) << "(sp)\n";
*OS << " addi sp, sp, " << aligned_stack_size << "\n";
}
}
void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb) {
if (!mbb->getName().empty()) {
*OS << mbb->getName() << ":\n";
}
for (auto& instr : mbb->getInstructions()) {
printInstruction(instr.get());
}
}
void RISCv64AsmPrinter::printInstruction(MachineInstr* instr) {
auto opcode = instr->getOpcode();
if (opcode == RVOpcodes::RET) {
printEpilogue();
}
if (opcode != RVOpcodes::LABEL) {
*OS << " ";
}
switch (opcode) {
case RVOpcodes::ADD: *OS << "add "; break; case RVOpcodes::ADDI: *OS << "addi "; break;
case RVOpcodes::ADDW: *OS << "addw "; break; case RVOpcodes::ADDIW: *OS << "addiw "; break;
case RVOpcodes::SUB: *OS << "sub "; break; case RVOpcodes::SUBW: *OS << "subw "; break;
case RVOpcodes::MUL: *OS << "mul "; break; case RVOpcodes::MULW: *OS << "mulw "; break;
case RVOpcodes::DIV: *OS << "div "; break; case RVOpcodes::DIVW: *OS << "divw "; break;
case RVOpcodes::REM: *OS << "rem "; break; case RVOpcodes::REMW: *OS << "remw "; break;
case RVOpcodes::XOR: *OS << "xor "; break; case RVOpcodes::XORI: *OS << "xori "; break;
case RVOpcodes::OR: *OS << "or "; break; case RVOpcodes::ORI: *OS << "ori "; break;
case RVOpcodes::AND: *OS << "and "; break; case RVOpcodes::ANDI: *OS << "andi "; break;
case RVOpcodes::SLL: *OS << "sll "; break; case RVOpcodes::SLLI: *OS << "slli "; break;
case RVOpcodes::SLLW: *OS << "sllw "; break; case RVOpcodes::SLLIW: *OS << "slliw "; break;
case RVOpcodes::SRL: *OS << "srl "; break; case RVOpcodes::SRLI: *OS << "srli "; break;
case RVOpcodes::SRLW: *OS << "srlw "; break; case RVOpcodes::SRLIW: *OS << "srliw "; break;
case RVOpcodes::SRA: *OS << "sra "; break; case RVOpcodes::SRAI: *OS << "srai "; break;
case RVOpcodes::SRAW: *OS << "sraw "; break; case RVOpcodes::SRAIW: *OS << "sraiw "; break;
case RVOpcodes::SLT: *OS << "slt "; break; case RVOpcodes::SLTI: *OS << "slti "; break;
case RVOpcodes::SLTU: *OS << "sltu "; break; case RVOpcodes::SLTIU: *OS << "sltiu "; break;
case RVOpcodes::LW: *OS << "lw "; break; case RVOpcodes::LH: *OS << "lh "; break;
case RVOpcodes::LB: *OS << "lb "; break; case RVOpcodes::LWU: *OS << "lwu "; break;
case RVOpcodes::LHU: *OS << "lhu "; break; case RVOpcodes::LBU: *OS << "lbu "; break;
case RVOpcodes::SW: *OS << "sw "; break; case RVOpcodes::SH: *OS << "sh "; break;
case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break;
case RVOpcodes::SD: *OS << "sd "; 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::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break;
case RVOpcodes::BLT: *OS << "blt "; break; case RVOpcodes::BGE: *OS << "bge "; break;
case RVOpcodes::BLTU: *OS << "bltu "; break; case RVOpcodes::BGEU: *OS << "bgeu "; break;
case RVOpcodes::LI: *OS << "li "; break; case RVOpcodes::LA: *OS << "la "; break;
case RVOpcodes::MV: *OS << "mv "; break; case RVOpcodes::NEG: *OS << "neg "; break;
case RVOpcodes::NEGW: *OS << "negw "; break; case RVOpcodes::SEQZ: *OS << "seqz "; break;
case RVOpcodes::SNEZ: *OS << "snez "; break;
case RVOpcodes::CALL: *OS << "call "; break;
case RVOpcodes::LABEL:
printOperand(instr->getOperands()[0].get());
*OS << ":";
break;
case RVOpcodes::FRAME_LOAD:
case RVOpcodes::FRAME_STORE:
// These should have been eliminated by RegAlloc
throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
default:
throw std::runtime_error("Unknown opcode in AsmPrinter");
}
const auto& operands = instr->getOperands();
if (!operands.empty()) {
if (isMemoryOp(opcode)) {
printOperand(operands[0].get());
*OS << ", ";
printOperand(operands[1].get());
} else {
for (size_t i = 0; i < operands.size(); ++i) {
printOperand(operands[i].get());
if (i < operands.size() - 1) {
*OS << ", ";
}
}
}
}
*OS << "\n";
}
void RISCv64AsmPrinter::printOperand(MachineOperand* op) {
if (!op) return;
switch(op->getKind()) {
case MachineOperand::KIND_REG: {
auto reg_op = static_cast<RegOperand*>(op);
if (reg_op->isVirtual()) {
*OS << "%vreg" << reg_op->getVRegNum();
} else {
*OS << regToString(reg_op->getPReg());
}
break;
}
case MachineOperand::KIND_IMM:
*OS << static_cast<ImmOperand*>(op)->getValue();
break;
case MachineOperand::KIND_LABEL:
*OS << static_cast<LabelOperand*>(op)->getName();
break;
case MachineOperand::KIND_MEM: {
auto mem_op = static_cast<MemOperand*>(op);
printOperand(mem_op->getOffset());
*OS << "(";
printOperand(mem_op->getBase());
*OS << ")";
break;
}
}
}
std::string RISCv64AsmPrinter::regToString(PhysicalReg reg) {
switch (reg) {
case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra";
case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp";
case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0";
case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2";
case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1";
case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1";
case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3";
case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5";
case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7";
case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3";
case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5";
case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7";
case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9";
case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11";
case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4";
case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6";
case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1";
case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3";
case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5";
case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7";
case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9";
case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11";
case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13";
case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15";
case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17";
case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19";
case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21";
case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23";
case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25";
case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27";
case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29";
case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31";
default: return "UNKNOWN_REG";
}
}
} // namespace sysy

File diff suppressed because it is too large Load Diff

635
src/RISCv64ISel.cpp Normal file
View File

@@ -0,0 +1,635 @@
#include "RISCv64ISel.h"
#include <stdexcept>
#include <set>
#include <functional>
#include <cmath> // For std::fabs
#include <limits> // For std::numeric_limits
namespace sysy {
// DAG节点定义 (内部实现)
struct RISCv64ISel::DAGNode {
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR, UNARY, MEMSET };
NodeKind kind;
Value* value = nullptr;
std::vector<DAGNode*> operands;
std::vector<DAGNode*> users;
DAGNode(NodeKind k) : kind(k) {}
};
RISCv64ISel::RISCv64ISel() : vreg_counter(0), local_label_counter(0) {}
// 为一个IR Value获取或分配一个新的虚拟寄存器
unsigned RISCv64ISel::getVReg(Value* val) {
if (!val) {
throw std::runtime_error("Cannot get vreg for a null Value.");
}
if (vreg_map.find(val) == vreg_map.end()) {
if (vreg_counter == 0) {
vreg_counter = 1; // vreg 0 保留
}
vreg_map[val] = vreg_counter++;
}
return vreg_map.at(val);
}
// 主入口函数
std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
F = func;
if (!F) return nullptr;
MFunc = std::make_unique<MachineFunction>(F, this);
vreg_map.clear();
bb_map.clear();
vreg_counter = 0;
local_label_counter = 0;
select();
return std::move(MFunc);
}
// 指令选择主流程
void RISCv64ISel::select() {
for (const auto& bb_ptr : F->getBasicBlocks()) {
auto mbb = std::make_unique<MachineBasicBlock>(bb_ptr->getName(), MFunc.get());
bb_map[bb_ptr.get()] = mbb.get();
MFunc->addBlock(std::move(mbb));
}
if (F->getEntryBlock()) {
for (auto* arg_alloca : F->getEntryBlock()->getArguments()) {
getVReg(arg_alloca);
}
}
for (const auto& bb_ptr : F->getBasicBlocks()) {
selectBasicBlock(bb_ptr.get());
}
for (const auto& bb_ptr : F->getBasicBlocks()) {
CurMBB = bb_map.at(bb_ptr.get());
for (auto succ : bb_ptr->getSuccessors()) {
CurMBB->successors.push_back(bb_map.at(succ));
}
for (auto pred : bb_ptr->getPredecessors()) {
CurMBB->predecessors.push_back(bb_map.at(pred));
}
}
}
// 处理单个基本块
void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
CurMBB = bb_map.at(bb);
auto dag = build_dag(bb);
std::map<Value*, DAGNode*> value_to_node;
for(const auto& node : dag) {
if (node->value) {
value_to_node[node->value] = node.get();
}
}
std::set<DAGNode*> selected_nodes;
std::function<void(DAGNode*)> select_recursive =
[&](DAGNode* node) {
if (!node || selected_nodes.count(node)) return;
for (auto operand : node->operands) {
select_recursive(operand);
}
selectNode(node);
selected_nodes.insert(node);
};
for (const auto& inst_ptr : bb->getInstructions()) {
DAGNode* node_to_select = nullptr;
if (value_to_node.count(inst_ptr.get())) {
node_to_select = value_to_node.at(inst_ptr.get());
} else {
for(const auto& node : dag) {
if(node->value == inst_ptr.get()) {
node_to_select = node.get();
break;
}
}
}
if(node_to_select) {
select_recursive(node_to_select);
}
}
}
// 核心函数为DAG节点选择并生成MachineInstr (忠实移植版)
void RISCv64ISel::selectNode(DAGNode* node) {
switch (node->kind) {
case DAGNode::CONSTANT:
case DAGNode::ALLOCA_ADDR:
if (node->value) getVReg(node->value);
break;
case DAGNode::LOAD: {
auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value;
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
} else {
auto ptr_vreg = getVReg(ptr_val);
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
}
break;
}
case DAGNode::STORE: {
Value* val_to_store = node->operands[0]->value;
Value* ptr_val = node->operands[1]->value;
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
}
auto val_vreg = getVReg(val_to_store);
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE);
instr->addOperand(std::make_unique<RegOperand>(val_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
} else {
auto ptr_vreg = getVReg(ptr_val);
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
}
break;
}
case DAGNode::BINARY: {
auto bin = dynamic_cast<BinaryInst*>(node->value);
Value* lhs = bin->getLhs();
Value* rhs = bin->getRhs();
auto load_val_if_const = [&](Value* val) {
if (auto c = dynamic_cast<ConstantValue*>(val)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(c)));
li->addOperand(std::make_unique<ImmOperand>(c->getInt()));
CurMBB->addInstruction(std::move(li));
}
};
load_val_if_const(lhs);
load_val_if_const(rhs);
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(lhs);
auto rhs_vreg = getVReg(rhs);
if (bin->getKind() == BinaryInst::kAdd) {
if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
if (rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
return;
}
}
}
switch (bin->getKind()) {
case BinaryInst::kAdd: {
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto instr = std::make_unique<MachineInstr>(opcode);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kSub: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kMul: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::MULW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::DIVW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kRem: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::REMW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpEQ: {
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(sub));
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(seqz));
break;
}
case BinaryInst::kICmpNE: {
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(sub));
auto snez = std::make_unique<MachineInstr>(RVOpcodes::SNEZ);
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(snez));
break;
}
case BinaryInst::kICmpLT: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpGT: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpLE: {
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(slt));
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<ImmOperand>(1));
CurMBB->addInstruction(std::move(xori));
break;
}
case BinaryInst::kICmpGE: {
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(slt));
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<ImmOperand>(1));
CurMBB->addInstruction(std::move(xori));
break;
}
default:
throw std::runtime_error("Unsupported binary instruction in ISel");
}
break;
}
case DAGNode::UNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) {
case UnaryInst::kNeg: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case UnaryInst::kNot: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
default:
throw std::runtime_error("Unsupported unary instruction in ISel");
}
break;
}
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
for (size_t i = 0; i < node->operands.size() && i < 8; ++i) {
DAGNode* arg_node = node->operands[i];
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i);
if (arg_node->kind == DAGNode::CONSTANT) {
if (auto const_val = dynamic_cast<ConstantValue*>(arg_node->value)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(arg_preg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
auto src_vreg = getVReg(arg_node->value);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(arg_preg));
mv->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(mv));
}
}
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
CurMBB->addInstruction(std::move(call_instr));
if (!call->getType()->isVoid()) {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call)));
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
CurMBB->addInstruction(std::move(mv_instr));
}
break;
}
case DAGNode::RETURN: {
auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value);
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
Value* ret_val = ret_inst_ir->getReturnValue();
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
li_instr->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li_instr));
} else {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(mv_instr));
}
}
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi));
break;
}
case DAGNode::BRANCH: {
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
br_instr->addOperand(std::make_unique<RegOperand>(getVReg(cond_br->getCondition())));
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
br_instr->addOperand(std::make_unique<LabelOperand>(cond_br->getThenBlock()->getName()));
CurMBB->addInstruction(std::move(br_instr));
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) {
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName()));
CurMBB->addInstruction(std::move(j_instr));
}
break;
}
case DAGNode::MEMSET: {
auto memset = dynamic_cast<MemsetInst*>(node->value);
auto r_dest_addr = getVReg(memset->getPointer());
auto r_num_bytes = getVReg(memset->getSize());
auto r_value_byte = getVReg(memset->getValue());
auto r_counter = getNewVReg();
auto r_end_addr = getNewVReg();
auto r_current_addr = getNewVReg();
auto r_temp_val = getNewVReg();
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rd));
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<RegOperand>(rs2));
CurMBB->addInstruction(std::move(i));
};
auto addi_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, int64_t imm) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rd));
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<ImmOperand>(imm));
CurMBB->addInstruction(std::move(i));
};
auto store_instr = [&](RVOpcodes op, unsigned src, unsigned base, int64_t off) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(src));
i->addOperand(std::make_unique<MemOperand>(std::make_unique<RegOperand>(base), std::make_unique<ImmOperand>(off)));
CurMBB->addInstruction(std::move(i));
};
auto branch_instr = [&](RVOpcodes op, unsigned rs1, unsigned rs2, const std::string& label) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<RegOperand>(rs2));
i->addOperand(std::make_unique<LabelOperand>(label));
CurMBB->addInstruction(std::move(i));
};
auto jump_instr = [&](const std::string& label) {
auto i = std::make_unique<MachineInstr>(RVOpcodes::J);
i->addOperand(std::make_unique<LabelOperand>(label));
CurMBB->addInstruction(std::move(i));
};
auto label_instr = [&](const std::string& name) {
auto i = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
i->addOperand(std::make_unique<LabelOperand>(name));
CurMBB->addInstruction(std::move(i));
};
int unique_id = this->local_label_counter++;
std::string loop_start_label = MFunc->getName() + "_memset_loop_start_" + std::to_string(unique_id);
std::string loop_end_label = MFunc->getName() + "_memset_loop_end_" + std::to_string(unique_id);
std::string remainder_label = MFunc->getName() + "_memset_remainder_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_memset_done_" + std::to_string(unique_id);
addi_instr(RVOpcodes::ANDI, r_temp_val, r_value_byte, 255);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 8);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 16);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 32);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
add_instr(RVOpcodes::ADD, r_end_addr, r_dest_addr, r_num_bytes);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(r_current_addr));
mv->addOperand(std::make_unique<RegOperand>(r_dest_addr));
CurMBB->addInstruction(std::move(mv));
addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8);
add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter);
label_instr(loop_start_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label);
store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8);
jump_instr(loop_start_label);
label_instr(loop_end_label);
label_instr(remainder_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label);
store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1);
jump_instr(remainder_label);
label_instr(done_label);
break;
}
default:
throw std::runtime_error("Unsupported DAGNode kind in ISel");
}
}
// 以下是忠实移植的DAG构建函数
RISCv64ISel::DAGNode* RISCv64ISel::create_node(int kind_int, Value* val, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
auto kind = static_cast<DAGNode::NodeKind>(kind_int);
if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::MEMSET) {
return value_to_node[val];
}
auto node = std::make_unique<DAGNode>(kind);
node->value = val;
DAGNode* raw_node_ptr = node.get();
nodes_storage.push_back(std::move(node));
if (val && !val->getType()->isVoid() && (dynamic_cast<Instruction*>(val) || dynamic_cast<GlobalValue*>(val))) {
value_to_node[val] = raw_node_ptr;
}
return raw_node_ptr;
}
RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(Value* val_ir, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
if (value_to_node.count(val_ir)) {
return value_to_node[val_ir];
} else if (dynamic_cast<ConstantValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (dynamic_cast<GlobalValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (dynamic_cast<AllocaInst*>(val_ir)) {
return create_node(DAGNode::ALLOCA_ADDR, val_ir, value_to_node, nodes_storage);
}
return create_node(DAGNode::LOAD, val_ir, value_to_node, nodes_storage);
}
std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicBlock* bb) {
std::vector<std::unique_ptr<DAGNode>> nodes_storage;
std::map<Value*, DAGNode*> value_to_node;
for (const auto& inst_ptr : bb->getInstructions()) {
Instruction* inst = inst_ptr.get();
if (auto alloca = dynamic_cast<AllocaInst*>(inst)) {
create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage);
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage);
store_node->operands.push_back(get_operand_node(store->getValue(), value_to_node, nodes_storage));
store_node->operands.push_back(get_operand_node(store->getPointer(), value_to_node, nodes_storage));
} else if (auto memset = dynamic_cast<MemsetInst*>(inst)) {
auto memset_node = create_node(DAGNode::MEMSET, memset, value_to_node, nodes_storage);
memset_node->operands.push_back(get_operand_node(memset->getPointer(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getBegin(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getSize(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getValue(), value_to_node, nodes_storage));
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage);
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));
} else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
if(value_to_node.count(bin)) continue;
if (bin->getKind() == BinaryInst::kSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (const_lhs->getInt() == 0) {
auto unary_node = create_node(DAGNode::UNARY, bin, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
continue;
}
}
}
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
} else if (auto un = dynamic_cast<UnaryInst*>(inst)) {
if(value_to_node.count(un)) continue;
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
if(value_to_node.count(call)) continue;
auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage);
for (auto arg : call->getArguments()) {
call_node->operands.push_back(get_operand_node(arg->getValue(), value_to_node, nodes_storage));
}
} else if (auto ret = dynamic_cast<ReturnInst*>(inst)) {
auto ret_node = create_node(DAGNode::RETURN, ret, value_to_node, nodes_storage);
if (ret->hasReturnValue()) {
ret_node->operands.push_back(get_operand_node(ret->getReturnValue(), value_to_node, nodes_storage));
}
} else if (auto cond_br = dynamic_cast<CondBrInst*>(inst)) {
auto br_node = create_node(DAGNode::BRANCH, cond_br, value_to_node, nodes_storage);
br_node->operands.push_back(get_operand_node(cond_br->getCondition(), value_to_node, nodes_storage));
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(inst)) {
create_node(DAGNode::BRANCH, uncond_br, value_to_node, nodes_storage);
}
}
return nodes_storage;
}
} // namespace sysy

54
src/RISCv64Passes.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "RISCv64Passes.h"
#include <iostream>
namespace sysy {
// --- 寄存器分配前优化 ---
void PreRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现寄存器分配前的指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行重排。
//
// 实现思路:
// 1. 分析每个基本块内指令的数据依赖关系,构建依赖图(DAG)。
// 2. 根据目标处理器的流水线特性(指令延迟等),使用列表调度等算法对指令进行重排。
// 3. 此时操作的是虚拟寄存器,只存在真依赖,调度自由度最大。
//
// std::cout << "Running Pre-RA Instruction Scheduler..." << std::endl;
}
// --- 寄存器分配后优化 ---
void PeepholeOptimizer::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现窥孔优化。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行扫描和替换。
//
// 实现思路:
// 1. 维护一个大小固定例如3-5条指令的滑动窗口。
// 2. 识别特定的冗余模式,例如:
// - `mv a0, a1` 后紧跟 `mv a1, a0` (可消除的交换)
// - `sw t0, 12(s0)` 后紧跟 `lw t1, 12(s0)` (冗余加载)
// - 强度削减: `mul x, x, 2` -> `slli x, x, 1`
// 3. 识别后直接修改MachineInstr列表删除、替换或插入指令
//
// std::cout << "Running Post-RA Peephole Optimizer..." << std::endl;
}
void PostRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现寄存器分配后的局部指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 重点关注由寄存器分配器插入的spill/fill代码。
//
// 实现思路:
// 1. 识别出用于spill/fill的lw/sw指令。
// 2. 在不违反数据依赖(包括物理寄存器引入的伪依赖)的前提下,
// 尝试将lw指令向上移动使其与使用它的指令之间有足够的距离以隐藏访存延迟。
// 3. 同样可以尝试将sw指令向下移动。
//
// std::cout << "Running Post-RA Local Scheduler..." << std::endl;
}
} // namespace sysy

322
src/RISCv64RegAlloc.cpp Normal file
View File

@@ -0,0 +1,322 @@
#include "RISCv64RegAlloc.h"
#include "RISCv64ISel.h"
#include <algorithm>
#include <vector>
namespace sysy {
RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
}
void RISCv64RegAlloc::run() {
eliminateFrameIndices();
analyzeLiveness();
buildInterferenceGraph();
colorGraph();
rewriteFunction();
}
void RISCv64RegAlloc::eliminateFrameIndices() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = 0;
Function* F = MFunc->getFunc();
RISCv64ISel* isel = MFunc->getISel();
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
int size = 4;
if (!alloca->getDims().empty()) {
int num_elements = 1;
for (const auto& dim_use : alloca->getDims()) {
if (auto const_dim = dynamic_cast<ConstantValue*>(dim_use->getValue())) {
num_elements *= const_dim->getInt();
}
}
size *= num_elements;
}
current_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca);
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
}
}
}
frame_info.locals_size = current_offset;
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
if (instr_ptr->getOpcode() == RVOpcodes::FRAME_LOAD) {
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg();
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(lw));
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_STORE) {
auto& operands = instr_ptr->getOperands();
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg();
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(src_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(sw));
} else {
new_instructions.push_back(std::move(instr_ptr));
}
}
mbb->getInstructions() = std::move(new_instructions);
}
}
void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def) {
bool is_def = true;
auto opcode = instr->getOpcode();
// 预定义def和use规则
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::RET || opcode == RVOpcodes::J) {
is_def = false;
}
if (opcode == RVOpcodes::CALL) {
// CALL会杀死所有调用者保存寄存器这是一个简化处理
// 同时也使用了传入a0-a7的参数
}
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op.get());
if (reg_op->isVirtual()) {
if (is_def) {
def.insert(reg_op->getVRegNum());
is_def = false;
} else {
use.insert(reg_op->getVRegNum());
}
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op.get());
if (mem_op->getBase()->isVirtual()) {
use.insert(mem_op->getBase()->getVRegNum());
}
}
}
}
void RISCv64RegAlloc::analyzeLiveness() {
bool changed = true;
while (changed) {
changed = false;
for (auto it = MFunc->getBlocks().rbegin(); it != MFunc->getBlocks().rend(); ++it) {
auto& mbb = *it;
LiveSet live_out;
for (auto succ : mbb->successors) {
if (!succ->getInstructions().empty()) {
auto first_instr = succ->getInstructions().front().get();
if (live_in_map.count(first_instr)) {
live_out.insert(live_in_map.at(first_instr).begin(), live_in_map.at(first_instr).end());
}
}
}
for (auto instr_it = mbb->getInstructions().rbegin(); instr_it != mbb->getInstructions().rend(); ++instr_it) {
MachineInstr* instr = instr_it->get();
LiveSet old_live_in = live_in_map[instr];
live_out_map[instr] = live_out;
LiveSet use, def;
getInstrUseDef(instr, use, def);
LiveSet live_in = use;
LiveSet diff = live_out;
for (auto vreg : def) {
diff.erase(vreg);
}
live_in.insert(diff.begin(), diff.end());
live_in_map[instr] = live_in;
live_out = live_in;
if (live_in_map[instr] != old_live_in) {
changed = true;
}
}
}
}
}
void RISCv64RegAlloc::buildInterferenceGraph() {
std::set<unsigned> all_vregs;
for (auto& mbb : MFunc->getBlocks()) {
for(auto& instr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr.get(), use, def);
for(auto u : use) all_vregs.insert(u);
for(auto d : def) all_vregs.insert(d);
}
}
for (auto vreg : all_vregs) { interference_graph[vreg] = {}; }
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr : mbb->getInstructions()) {
LiveSet def, use;
getInstrUseDef(instr.get(), use, def);
const LiveSet& live_out = live_out_map.at(instr.get());
for (unsigned d : def) {
for (unsigned l : live_out) {
if (d != l) {
interference_graph[d].insert(l);
interference_graph[l].insert(d);
}
}
}
}
}
}
void RISCv64RegAlloc::colorGraph() {
std::vector<unsigned> sorted_vregs;
for (auto const& [vreg, neighbors] : interference_graph) {
sorted_vregs.push_back(vreg);
}
std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) {
return interference_graph[a].size() > interference_graph[b].size();
});
for (unsigned vreg : sorted_vregs) {
std::set<PhysicalReg> used_colors;
for (unsigned neighbor : interference_graph.at(vreg)) {
if (color_map.count(neighbor)) {
used_colors.insert(color_map.at(neighbor));
}
}
bool colored = false;
for (PhysicalReg preg : allocable_int_regs) {
if (used_colors.find(preg) == used_colors.end()) {
color_map[vreg] = preg;
colored = true;
break;
}
}
if (!colored) {
spilled_vregs.insert(vreg);
}
}
}
void RISCv64RegAlloc::rewriteFunction() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = frame_info.locals_size;
for (unsigned vreg : spilled_vregs) {
current_offset += 4;
frame_info.spill_offsets[vreg] = -current_offset;
}
frame_info.spill_size = current_offset - frame_info.locals_size;
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr_ptr.get(), use, def);
for (unsigned vreg : use) {
if (spilled_vregs.count(vreg)) {
int offset = frame_info.spill_offsets.at(vreg);
auto load = std::make_unique<MachineInstr>(RVOpcodes::LW);
load->addOperand(std::make_unique<RegOperand>(vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
new_instructions.push_back(std::move(load));
}
}
new_instructions.push_back(std::move(instr_ptr));
for (unsigned vreg : def) {
if (spilled_vregs.count(vreg)) {
int offset = frame_info.spill_offsets.at(vreg);
auto store = std::make_unique<MachineInstr>(RVOpcodes::SW);
store->addOperand(std::make_unique<RegOperand>(vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
new_instructions.push_back(std::move(store));
}
}
}
mbb->getInstructions() = std::move(new_instructions);
}
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 (color_map.count(vreg)) {
reg_op->setPReg(color_map.at(vreg));
} else if (spilled_vregs.count(vreg)) {
reg_op->setPReg(PhysicalReg::T6); // 溢出统一用t6
}
}
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
auto base_reg_op = mem_op->getBase();
if(base_reg_op->isVirtual()){
unsigned vreg = base_reg_op->getVRegNum();
if(color_map.count(vreg)) {
base_reg_op->setPReg(color_map.at(vreg));
} else if (spilled_vregs.count(vreg)) {
base_reg_op->setPReg(PhysicalReg::T6);
}
}
}
}
}
}
}
} // namespace sysy

View File

@@ -38,7 +38,7 @@ void Reg2Mem::DeletePhiInst(){
// 创建一个basicblock // 创建一个basicblock
auto newbasicBlock = function.second->addBasicBlock(); auto newbasicBlock = function.second->addBasicBlock();
std::stringstream ss; std::stringstream ss;
ss << " phidel.L" << pBuilder->getLabelIndex(); ss << "phidel.L" << pBuilder->getLabelIndex();
newbasicBlock->setName(ss.str()); newbasicBlock->setName(ss.str());
ss.str(""); ss.str("");
// // 修改前驱后继关系 // // 修改前驱后继关系
@@ -103,7 +103,7 @@ void Reg2Mem::DeletePhiInst(){
} }
// 删除phi指令 // 删除phi指令
auto &instructions = basicBlock->getInstructions(); auto &instructions = basicBlock->getInstructions();
usedelete(iter->get()); SysYIROptUtils::usedelete(iter->get());
iter = instructions.erase(iter); iter = instructions.erase(iter);
if (basicBlock->getNumInstructions() == 0) { if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) { if (basicBlock->getNumSuccessors() == 1) {
@@ -119,11 +119,4 @@ void Reg2Mem::DeletePhiInst(){
} }
} }
void Reg2Mem::usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
auto val = use->getValue();
val->removeUse(use);
}
}
} // namespace sysy } // namespace sysy

View File

@@ -523,9 +523,6 @@ bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) {
} }
auto ActiveVarAnalysis::getActiveTable() const -> const std::map<BasicBlock *, std::vector<std::set<User *>>> & {
return activeTable;
}
} // namespace sysy } // namespace sysy

565
src/SysYIRCFGOpt.cpp Normal file
View File

@@ -0,0 +1,565 @@
#include "SysYIRCFGOpt.h"
#include "SysYIROptUtils.h"
#include <cassert>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <iostream>
#include "IR.h"
#include "IRBuilder.h"
namespace sysy {
// 删除br后的无用指令
bool SysYCFGOpt::SysYDelInstAfterBr(Function *func) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
bool Branch = false;
auto &instructions = basicBlock->getInstructions();
auto Branchiter = instructions.end();
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
if (Branch)
SysYIROptUtils::usedelete(iter->get());
else if ((*iter)->isTerminator()){
Branch = true;
Branchiter = iter;
}
}
if (Branchiter != instructions.end()) ++Branchiter;
while (Branchiter != instructions.end()) {
changed = true;
Branchiter = instructions.erase(Branchiter);
}
if (Branch) { // 更新前驱后继关系
auto thelastinstinst = basicBlock->getInstructions().end();
--thelastinstinst;
auto &Successors = basicBlock->getSuccessors();
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
(*iterSucc)->removePredecessor(basicBlock.get());
basicBlock->removeSuccessor(*iterSucc);
}
if (thelastinstinst->get()->isUnconditional()) {
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
basicBlock->addSuccessor(branchBlock);
branchBlock->addPredecessor(basicBlock.get());
} else if (thelastinstinst->get()->isConditional()) {
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
basicBlock->addSuccessor(thenBlock);
basicBlock->addSuccessor(elseBlock);
thenBlock->addPredecessor(basicBlock.get());
elseBlock->addPredecessor(basicBlock.get());
}
}
}
return changed;
}
// 合并空基本块
bool SysYCFGOpt::SysYBlockMerge(Function *func) {
bool changed = false;
for (auto blockiter = func->getBasicBlocks().begin();
blockiter != func->getBasicBlocks().end();) {
if (blockiter->get()->getNumSuccessors() == 1) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
// 则将当前块和后继块合并
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
BasicBlock* block = blockiter->get();
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
auto nextarguments = nextBlock->getArguments();
// 删除br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->end();
(--thelastinstinst);
if (thelastinstinst->get()->isUnconditional()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
block->getInstructions().erase(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
block->getInstructions().erase(thelastinstinst);
}
}
}
// 将后继块的指令移动到当前块
// 并将后继块的父指针改为当前块
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
institer->get()->setParent(block);
block->getInstructions().emplace_back(institer->release());
institer = nextBlock->getInstructions().erase(institer);
}
// 合并参数
// TODO是否需要去重?
for (auto &argm : nextarguments) {
argm->setParent(block);
block->insertArgument(argm);
}
// 更新前驱后继关系,类似树节点操作
block->removeSuccessor(nextBlock);
nextBlock->removePredecessor(block);
std::list<BasicBlock *> succshoulddel;
for (auto &succ : nextBlock->getSuccessors()) {
block->addSuccessor(succ);
succ->replacePredecessor(nextBlock, block);
succshoulddel.push_back(succ);
}
for (auto del : succshoulddel) {
nextBlock->removeSuccessor(del);
}
func->removeBasicBlock(nextBlock);
changed = true;
} else {
blockiter++;
}
} else {
blockiter++;
}
}
return changed;
}
// 删除无前驱块兼容SSA后的处理
bool SysYCFGOpt::SysYDelNoPreBLock(Function *func) {
bool changed = false;
for (auto &block : func->getBasicBlocks()) {
block->setreachableFalse();
}
// 对函数基本块做一个拓扑排序,排查不可达基本块
auto entryBlock = func->getEntryBlock();
entryBlock->setreachableTrue();
std::queue<BasicBlock *> blockqueue;
blockqueue.push(entryBlock);
while (!blockqueue.empty()) {
auto block = blockqueue.front();
blockqueue.pop();
for (auto &succ : block->getSuccessors()) {
if (!succ->getreachable()) {
succ->setreachableTrue();
blockqueue.push(succ);
}
}
}
// 删除不可达基本块指令
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();blockIter++) {
if (!blockIter->get()->getreachable())
for (auto &iterInst : blockIter->get()->getInstructions())
SysYIROptUtils::usedelete(iterInst.get());
}
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
if (!blockIter->get()->getreachable()) {
for (auto succblock : blockIter->get()->getSuccessors()) {
int indexphi = 1;
for (auto pred : succblock->getPredecessors()) {
if (pred == blockIter->get()) {
break;
}
indexphi++;
}
for (auto &phiinst : succblock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
phiinst->removeOperand(indexphi);
}
}
// 删除不可达基本块,注意迭代器不可达问题
func->removeBasicBlock((blockIter++)->get());
changed = true;
} else {
blockIter++;
}
}
return changed;
}
// 删除空块
bool SysYCFGOpt::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
bool changed = false;
// 收集不可达基本块
// 这里的不可达基本块是指没有实际指令的基本块
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时也会被视作不可达
auto basicBlocks = func->getBasicBlocks();
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
// 空块儿和后继的基本块的映射
for (auto &basicBlock : basicBlocks) {
if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) {
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
else{
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
// 判断除了最后一个指令之外是不是只有phi指令
bool onlyPhi = true;
for (auto &inst : basicBlock->getInstructions()) {
if (!inst->isPhi() && !inst->isUnconditional()) {
onlyPhi = false;
break;
}
}
if(onlyPhi)
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
// 更新基本块信息,增加必要指令
for (auto &basicBlock : basicBlocks) {
// 把空块转换成只有跳转指令的不可达块
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
if (basicBlock->getNumSuccessors() == 0) {
continue;
}
if (basicBlock->getNumSuccessors() > 1) {
assert("");
}
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
continue;
}
auto thelastinst = basicBlock->getInstructions().end();
--thelastinst;
// 根据br指令传递的后继块信息跳过空块链
if (thelastinst->get()->isUnconditional()) {
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
BasicBlock *thelastBlockOld = nullptr;
// 如果空块链表为多个块
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
}
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
// 更新phi指令的操作数
// 移除thelastBlockOld对应的phi操作数
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
thelastinst->get()->replaceOperand(
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
}
basicBlock->removeSuccessor(OldThenBlock);
OldThenBlock->removePredecessor(basicBlock.get());
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
continue;
}
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
// auto indexInNew = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors().
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
thelastinst->get()->replaceOperand(
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
}
basicBlock->removeSuccessor(OldElseBlock);
OldElseBlock->removePredecessor(basicBlock.get());
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
continue;
}
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
} else {
if (basicBlock->getNumSuccessors() == 1) {
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
auto thelastinst = basicBlock->getInstructions().end();
(--thelastinst);
auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
sysy::BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(
0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
}
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
}
}
}
for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) {
if (EmptyBlocks.find(iter->get()) != EmptyBlocks.end()) {
// EntryBlock跳过
if (iter->get() == func->getEntryBlock()) {
++iter;
continue;
}
for (auto &iterInst : iter->get()->getInstructions())
SysYIROptUtils::usedelete(iterInst.get());
// 删除不可达基本块的phi指令的操作数
for (auto &succ : iter->get()->getSuccessors()) {
int index = 0;
for (auto &pred : succ->getPredecessors()) {
if (pred == iter->get()) {
break;
}
index++;
}
for (auto &instinsucc : succ->getInstructions()) {
if (instinsucc->isPhi()) {
dynamic_cast<PhiInst *>(instinsucc.get())->removeOperand(index);
} else {
break;
}
}
}
func->removeBasicBlock((iter++)->get());
changed = true;
} else {
++iter;
}
}
return changed;
}
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
bool SysYCFGOpt::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &block : basicBlocks) {
if (block->getNumSuccessors() == 0) {
changed = true;
// 如果基本块没有后继块,则添加一个返回指令
if (block->getNumInstructions() == 0) {
pBuilder->setPosition(block.get(), block->end());
pBuilder->createReturnInst();
}
auto thelastinst = block->getInstructions().end();
--thelastinst;
if (thelastinst->get()->getKind() != Instruction::kReturn) {
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
pBuilder->setPosition(block.get(), block->end());
// TODO: 如果int float函数缺少返回值是否需要报错
if (func->getReturnType()->isInt()) {
pBuilder->createReturnInst(ConstantInteger::get(0));
} else if (func->getReturnType()->isFloat()) {
pBuilder->createReturnInst(ConstantFloating::get(0.0F));
} else {
pBuilder->createReturnInst();
}
}
}
}
return changed;
}
// 条件分支转换为无条件分支
// 主要针对已知条件值的分支转换为无条件分支
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
// 确定为 true 或 false 的情况
bool SysYCFGOpt::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
bool changed = false;
for (auto &basicblock : func->getBasicBlocks()) {
if (basicblock->getNumInstructions() == 0)
continue;
auto thelast = basicblock->getInstructions().end();
--thelast;
if (thelast->get()->isConditional()){
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(thelast->get()->getOperand(0));
std::string opname;
int constint = 0;
float constfloat = 0.0F;
bool constint_Use = false;
bool constfloat_Use = false;
if (constOperand != nullptr) {
if (constOperand->isFloat()) {
constfloat = constOperand->getFloat();
constfloat_Use = true;
} else {
constint = constOperand->getInt();
constint_Use = true;
}
}
// 如果可以计算
if (constfloat_Use || constint_Use) {
changed = true;
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
SysYIROptUtils::usedelete(thelast->get());
thelast = basicblock->getInstructions().erase(thelast);
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(thenBlock, {});
int phiindex = 0;
for (auto pred : elseBlock->getPredecessors()) {
phiindex++;
if (pred == basicblock.get()) {
break;
}
}
for (auto &phiinst : elseBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
phiinst->removeOperand(phiindex);
}
basicblock->removeSuccessor(elseBlock);
elseBlock->removePredecessor(basicblock.get());
} else {
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(elseBlock, {});
int phiindex = 0;
for (auto pred : thenBlock->getPredecessors()) {
phiindex++;
if (pred == basicblock.get()) {
break;
}
}
for (auto &phiinst : thenBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
phiinst->removeOperand(phiindex);
}
basicblock->removeSuccessor(thenBlock);
thenBlock->removePredecessor(basicblock.get());
}
}
}
}
return changed;
}
} // namespace sysy

View File

@@ -10,12 +10,78 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
using namespace std;
#include "SysYIRGenerator.h" #include "SysYIRGenerator.h"
using namespace std;
namespace sysy { namespace sysy {
Type* SysYIRGenerator::buildArrayType(Type* baseType, const std::vector<Value*>& dims){
Type* currentType = baseType;
// 从最内层维度开始构建 ArrayType
// 例如对于 int arr[2][3],先处理 [3],再处理 [2]
// 注意SysY 的 dims 是从最外层到最内层,所以我们需要反向迭代
// 或者调整逻辑,使得从内到外构建 ArrayType
// 假设 dims 列表是 [dim1, dim2, dim3...] (例如 [2, 3] for int[2][3])
// 我们需要从最内层维度开始向外构建 ArrayType
for (int i = dims.size() - 1; i >= 0; --i) {
// 维度大小必须是常量,否则无法构建 ArrayType
ConstantInteger* constDim = dynamic_cast<ConstantInteger*>(dims[i]);
if (constDim == nullptr) {
// 如果维度不是常量,可能需要特殊处理,例如将其视为指针
// 对于函数参数 int arr[] 这种,第一个维度可以为未知
// 在这里,我们假设所有声明的数组维度都是常量
assert(false && "Array dimension must be a constant integer!");
return nullptr;
}
unsigned dimSize = constDim->getInt();
currentType = Type::getArrayType(currentType, dimSize);
}
return currentType;
}
Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices) {
// 检查 basePointer 是否为指针类型
if (!basePointer->getType()->isPointer()) {
assert(false && "GEP base pointer must be a pointer type!");
}
// 获取基指针所指向的实际类型 (例如 int* 指向 int, int[2][3]* 指向 int[2][3])
Type* currentElementType = basePointer->getType()->as<PointerType>()->getBaseType();
std::vector<Value*> actualGEPIndices;
// GEP 指令的第一个索引通常是0用于“跳过”基指针指向的聚合类型本身直接指向其第一个元素。
// 例如,对于 AllocaInst 返回的 `int[2][3]*`,第一个 `0` 索引表示从数组的开始而不是指针本身开始索引。
actualGEPIndices.push_back(ConstantInteger::get(0));
// 将用户提供的索引添加到 GEP 操作数中
for (Value* index : indices) {
actualGEPIndices.push_back(index);
}
// 根据索引链计算最终的元素类型
Type* finalTargetType = currentElementType;
// 遍历用户提供的索引不包括我们添加的第一个0逐步确定 GEP 的最终结果类型
// 每个索引都“深入”一个维度
for (size_t i = 0; i < indices.size(); ++i) { // 这里遍历的是用户提供的索引
if (finalTargetType && finalTargetType->isArray()) {
finalTargetType = finalTargetType->as<ArrayType>()->getElementType();
} else {
// 如果索引链还在继续,但当前类型已经不是数组或聚合类型,这通常是一个错误
// 或者表示访问的是标量后续索引无效。此时finalTargetType 已经是最终的标量类型,不能再深入。
// 例如,对 int arr[5]; 访问 arr[i][j] (j 是多余的),这里会停止类型推断。
break;
}
}
// GEP 的结果总是指针类型,指向最终计算出的元素
Type* gepResultType = Type::getPointerType(finalTargetType);
// 创建 GEP 指令。假设 builder.createGetElementPtrInst 的签名为
// (Type* resultType, Value* basePointer, const std::vector<Value*>& indices)
return builder.createGetElementPtrInst(basePointer, actualGEPIndices);
}
/* /*
* @brief: visit compUnit * @brief: visit compUnit
* @details: * @details:
@@ -119,41 +185,111 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
} }
} }
Type* variableType = type;
if (!dims.empty()) { // 如果有维度,说明是数组
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
}
// 对于数组alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
// 对于标量alloca 的类型将是指针指向标量类型,例如 `int*`
AllocaInst* alloca = AllocaInst* alloca =
builder.createAllocaInst(Type::getPointerType(type), dims, name); builder.createAllocaInst(Type::getPointerType(type), dims, name);
if (varDef->initVal() != nullptr) { if (varDef->initVal() != nullptr) {
ValueCounter values; ValueCounter values;
// 这里的varDef->initVal()可能是ScalarInitValue或ArrayInitValue
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(varDef->initVal()->accept(this)); ArrayValueTree* root = std::any_cast<ArrayValueTree *>(varDef->initVal()->accept(this));
Utils::tree2Array(type, root, dims, dims.size(), values, &builder); Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
delete root; delete root;
if (dims.empty()) {
if (dims.empty()) { // 标量变量初始化
builder.createStoreInst(values.getValue(0), alloca); builder.createStoreInst(values.getValue(0), alloca);
} else { } else { // 数组变量初始化
// 对于多维数组使用memset初始化 const std::vector<sysy::Value *> &counterValues = values.getValues();
// 计算每个维度的大小
// 这里的values.getNumbers()返回的是每个维度的大小 int numElements = 1;
// 这里的values.getValues()返回的是每个维度对应的值 std::vector<int> dimSizes;
// 例如对于一个二维数组values.getNumbers()可能是[3, 4]表示3行4列 for (Value *dimVal : dims) {
// values.getValues()可能是[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
// 对于每个维度使用memset将对应的值填充到数组中 int dimSize = constInt->getInt();
// 这里的alloca是一个指向数组的指针 numElements *= dimSize;
const std::vector<unsigned int> & counterNumbers = values.getNumbers(); dimSizes.push_back(dimSize);
const std::vector<sysy::Value *> & counterValues = values.getValues(); }
unsigned begin = 0; // TODO else 错误处理:数组维度必须是常量(对于静态分配)
for (size_t i = 0; i < counterNumbers.size(); i++) { }
unsigned int elementSizeInBytes = type->getSize();
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
bool allValuesAreZero = false;
if (counterValues.empty()) {
allValuesAreZero = true;
}
else {
allValuesAreZero = true;
for (Value *val : counterValues){
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(val)){
if (constInt->getInt() != 0){
allValuesAreZero = false;
break;
}
}
else{
allValuesAreZero = false;
break;
}
}
}
if (allValuesAreZero) {
builder.createMemsetInst(
alloca,
ConstantInteger::get(0),
ConstantInteger::get(totalSizeInBytes),
ConstantInteger::get(0));
}
else {
for (size_t k = 0; k < counterValues.size(); ++k) {
std::vector<Value *> currentIndices;
int tempLinearIndex = k;
// 将线性索引转换为多维索引
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx)
{
currentIndices.insert(currentIndices.begin(),
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
tempLinearIndex /= dimSizes[dimIdx];
}
// 计算元素的地址
Value* elementAddress = getGEPAddressInst(alloca, currentIndices);
// 生成 store 指令 (假设 createStoreInst 接受 Value* value, Value* pointer)
builder.createStoreInst(counterValues[k], elementAddress);
}
}
}
}
else { // 如果没有显式初始化值,默认对数组进行零初始化
if (!dims.empty()) { // 只有数组才需要默认的零初始化
int numElements = 1;
for (Value *dimVal : dims) {
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
numElements *= constInt->getInt();
}
}
unsigned int elementSizeInBytes = type->getSize();
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
builder.createMemsetInst( builder.createMemsetInst(
alloca, ConstantValue::get(static_cast<int>(begin)), alloca,
ConstantValue::get(static_cast<int>(counterNumbers[i])), ConstantInteger::get(0),
counterValues[i]); ConstantInteger::get(totalSizeInBytes),
begin += counterNumbers[i]; ConstantInteger::get(0)
} );
} }
} }
module->addVariable(name, alloca); module->addVariable(name, alloca);
} }
return std::any(); return std::any();
} }
@@ -204,7 +340,6 @@ std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx) {
std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
// 更新作用域 // 更新作用域
module->enterNewScope(); module->enterNewScope();
HasReturnInst = false;
auto name = ctx->Ident()->getText(); auto name = ctx->Ident()->getText();
std::vector<Type *> paramTypes; std::vector<Type *> paramTypes;
@@ -218,7 +353,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
paramNames.push_back(param->Ident()->getText()); paramNames.push_back(param->Ident()->getText());
std::vector<Value *> dims = {}; std::vector<Value *> dims = {};
if (!param->LBRACK().empty()) { if (!param->LBRACK().empty()) {
dims.push_back(ConstantValue::get(-1)); // 第一个维度不确定 dims.push_back(ConstantInteger::get(-1)); // 第一个维度不确定
for (const auto &exp : param->exp()) { for (const auto &exp : param->exp()) {
dims.push_back(std::any_cast<Value *>(visitExp(exp))); dims.push_back(std::any_cast<Value *>(visitExp(exp)));
} }
@@ -240,22 +375,34 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
module->addVariable(paramNames[i], alloca); module->addVariable(paramNames[i], alloca);
} }
// 在处理函数体之前,创建一个新的基本块作为函数体的实际入口
// 这样 entryBB 就可以在完成初始化后跳转到这里
BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry");
// 从 entryBB 无条件跳转到 funcBodyEntry
builder.createUncondBrInst(funcBodyEntry, {});
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
for (auto item : ctx->blockStmt()->blockItem()) { for (auto item : ctx->blockStmt()->blockItem()) {
visitBlockItem(item); visitBlockItem(item);
} }
if(HasReturnInst == false) { // 如果函数没有显式的返回语句,且返回类型不是 void则需要添加一个默认的返回值
// 如果没有return语句则默认返回0 ReturnInst* retinst = nullptr;
if (returnType != Type::getVoidType()) { retinst = dynamic_cast<ReturnInst*>(builder.getBasicBlock()->terminator()->get());
Value* returnValue = ConstantValue::get(0);
if (returnType == Type::getFloatType()) { if (!retinst) {
returnValue = ConstantValue::get(0.0f); if (returnType->isVoid()) {
}
builder.createReturnInst(returnValue);
} else {
builder.createReturnInst(); builder.createReturnInst();
} else if (returnType->isInt()) {
builder.createReturnInst(ConstantInteger::get(0)); // 默认返回 0
} else if (returnType->isFloat()) {
builder.createReturnInst(ConstantFloating::get(0.0f)); // 默认返回 0.0f
} else {
assert(false && "Function with no explicit return and non-void type should return a value.");
} }
} }
module->leaveScope(); module->leaveScope();
return std::any(); return std::any();
@@ -277,28 +424,55 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
dims.push_back(std::any_cast<Value *>(visitExp(exp))); dims.push_back(std::any_cast<Value *>(visitExp(exp)));
} }
auto variable = module->getVariable(name); auto variable = module->getVariable(name); // 获取 AllocaInst 或 GlobalValue
Value* value = std::any_cast<Value *>(visitExp(ctx->exp())); Value* value = std::any_cast<Value *>(visitExp(ctx->exp())); // 右值
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();
// 左值右值类型不同处理 if (variable == nullptr) {
if (variableType != value->getType()) { throw std::runtime_error("Variable " + name + " not found in assignment.");
}
// 计算最终赋值目标元素的类型
// variable 本身应该是一个指针类型 (例如 int* 或 int[2][3]*)
if (!variable->getType()->isPointer()) {
assert(false && "Variable to be assigned must be a pointer type!");
return std::any();
}
Type* targetElementType = variable->getType()->as<PointerType>()->getBaseType(); // 从基指针指向的类型开始
// 模拟 GEP 路径,根据 dims 确定最终元素的类型
for (size_t i = 0; i < dims.size(); ++i) {
if (targetElementType && targetElementType->isArray()) {
targetElementType = targetElementType->as<ArrayType>()->getElementType();
} else {
break; // 如果不是数组类型但还有索引,或者索引超出维度,则停止推断
}
}
// 左值右值类型不同处理:根据最终元素类型进行转换
if (targetElementType != value->getType()) {
ConstantValue * constValue = dynamic_cast<ConstantValue *>(value); ConstantValue * constValue = dynamic_cast<ConstantValue *>(value);
if (constValue != nullptr) { if (constValue != nullptr) {
if (variableType == Type::getFloatType()) { if (targetElementType == Type::getFloatType()) {
value = ConstantValue::get(static_cast<float>(constValue->getInt())); value = ConstantFloating::get(static_cast<float>(constValue->getInt()));
} else { } else { // 假设如果不是浮点型,就是整型
value = ConstantValue::get(static_cast<int>(constValue->getFloat())); value = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
} }
} else { } else {
if (variableType == Type::getFloatType()) { if (targetElementType == Type::getFloatType()) {
value = builder.createIToFInst(value); value = builder.createIToFInst(value);
} else { } else { // 假设如果不是浮点型,就是整型
value = builder.createFtoIInst(value); value = builder.createFtoIInst(value);
} }
} }
} }
builder.createStoreInst(value, variable, dims, variable->getName());
// 计算目标地址:如果 dims 为空,就是变量本身地址;否则通过 GEP 计算
Value* targetAddress = variable;
if (!dims.empty()) {
targetAddress = getGEPAddressInst(variable, dims);
}
builder.createStoreInst(value, targetAddress);
return std::any(); return std::any();
} }
@@ -386,6 +560,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
ctx->stmt(0)->accept(this); ctx->stmt(0)->accept(this);
module->leaveScope(); module->leaveScope();
} }
builder.createUncondBrInst(exitBlock, {});
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock); BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
labelstring << "if_exit.L" << builder.getLabelIndex(); labelstring << "if_exit.L" << builder.getLabelIndex();
@@ -407,6 +582,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring << "while_head.L" << builder.getLabelIndex(); labelstring << "while_head.L" << builder.getLabelIndex();
BasicBlock *headBlock = function->addBasicBlock(labelstring.str()); BasicBlock *headBlock = function->addBasicBlock(labelstring.str());
labelstring.str(""); labelstring.str("");
builder.createUncondBrInst(headBlock, {});
BasicBlock::conectBlocks(curBlock, headBlock); BasicBlock::conectBlocks(curBlock, headBlock);
builder.setPosition(headBlock, headBlock->end()); builder.setPosition(headBlock, headBlock->end());
@@ -478,9 +654,9 @@ std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx) {
ConstantValue * constValue = dynamic_cast<ConstantValue *>(returnValue); ConstantValue * constValue = dynamic_cast<ConstantValue *>(returnValue);
if (constValue != nullptr) { if (constValue != nullptr) {
if (funcType == Type::getFloatType()) { if (funcType == Type::getFloatType()) {
returnValue = ConstantValue::get(static_cast<float>(constValue->getInt())); returnValue = ConstantInteger::get(static_cast<float>(constValue->getInt()));
} else { } else {
returnValue = ConstantValue::get(static_cast<int>(constValue->getFloat())); returnValue = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
} }
} else { } else {
if (funcType == Type::getFloatType()) { if (funcType == Type::getFloatType()) {
@@ -491,56 +667,94 @@ std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx) {
} }
} }
builder.createReturnInst(returnValue); builder.createReturnInst(returnValue);
HasReturnInst = true;
return std::any(); return std::any();
} }
// SysYIRGenerator.cpp (修改部分)
std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) { std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
std::string name = ctx->Ident()->getText(); std::string name = ctx->Ident()->getText();
User* variable = module->getVariable(name); User* variable = module->getVariable(name);
Value* value = nullptr; Value* value = nullptr;
if (variable == nullptr) {
throw std::runtime_error("Variable " + name + " not found.");
}
std::vector<Value *> dims; std::vector<Value *> dims;
for (const auto &exp : ctx->exp()) { for (const auto &exp : ctx->exp()) {
dims.push_back(std::any_cast<Value *>(visitExp(exp))); dims.push_back(std::any_cast<Value *>(visitExp(exp)));
} }
if (variable == nullptr) { // 1. 获取变量的声明维度数量
throw std::runtime_error("Variable " + name + " not found."); unsigned declaredNumDims = 0;
if (AllocaInst* alloc = dynamic_cast<AllocaInst*>(variable)) {
declaredNumDims = alloc->getNumDims();
} else if (GlobalValue* glob = dynamic_cast<GlobalValue*>(variable)) {
declaredNumDims = glob->getNumDims();
} else if (ConstantVariable* constV = dynamic_cast<ConstantVariable*>(variable)) {
declaredNumDims = constV->getNumDims();
} }
bool indicesConstant = true; // 2. 处理常量变量 (ConstantVariable) 且所有索引都是常量的情况
ConstantVariable* constVar = dynamic_cast<ConstantVariable *>(variable);
if (constVar != nullptr) {
bool allIndicesConstant = true;
for (const auto &dim : dims) { for (const auto &dim : dims) {
if (dynamic_cast<ConstantValue *>(dim) == nullptr) { if (dynamic_cast<ConstantValue *>(dim) == nullptr) {
indicesConstant = false; allIndicesConstant = false;
break; break;
} }
} }
if (allIndicesConstant) {
ConstantVariable* constVar = dynamic_cast<ConstantVariable *>(variable); // 如果是常量变量且所有索引都是常量,直接通过 getByIndices 获取编译时值
GlobalValue* globalVar = dynamic_cast<GlobalValue *>(variable); // 这个方法会根据索引深度返回最终的标量值或指向子数组的指针 (作为 ConstantValue/Variable)
AllocaInst* localVar = dynamic_cast<AllocaInst *>(variable); return constVar->getByIndices(dims);
if (constVar != nullptr && indicesConstant) {
// 如果是常量变量,且索引是常量,则直接获取子数组
value = constVar->getByIndices(dims);
} else if (module->isInGlobalArea() && (globalVar != nullptr)) {
assert(indicesConstant);
value = globalVar->getByIndices(dims);
} else {
if ((globalVar != nullptr && globalVar->getNumDims() > dims.size()) ||
(localVar != nullptr && localVar->getNumDims() > dims.size()) ||
(constVar != nullptr && constVar->getNumDims() > dims.size())) {
// value = builder.createLaInst(variable, indices);
// 如果变量是全局变量或局部变量且索引数量小于维度数量则创建createGetSubArray获取子数组
auto getArrayInst =
builder.createGetSubArray(dynamic_cast<LVal *>(variable), dims);
value = getArrayInst->getChildArray();
} else {
value = builder.createLoadInst(variable, dims);
} }
} }
// 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量
// 这里区分标量访问和数组元素/子数组访问
// 检查是否是访问标量变量本身没有索引且声明维度为0
if (dims.empty() && declaredNumDims == 0) {
// 对于标量变量,直接加载其值。
// variable 本身就是指向标量的指针 (e.g., int* %a)
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) {
value = builder.createLoadInst(variable);
} else {
// 如果走到这里且不是AllocaInst/GlobalValue但dims为空且declaredNumDims为0
// 且又不是ConstantVariable (前面已处理),则可能是错误情况。
assert(false && "Unhandled scalar variable type in LValue access.");
return static_cast<Value*>(nullptr);
}
} else {
// 访问数组元素或子数组(有索引,或变量本身是数组/多维指针)
Value* targetAddress = nullptr;
// GEP 的基指针就是变量本身(它是一个指向内存的指针)
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable) || (constVar != nullptr)) {
// 允许对 ConstantVariable (如果它代表全局数组常量) 进行 GEP
targetAddress = getGEPAddressInst(variable, dims);
} else {
// 其他情况(例如尝试对非指针类型或不支持的 LValue 进行 GEP应报错
assert(false && "LValue variable type not supported for GEP or dynamic load.");
return static_cast<Value*>(nullptr);
}
// 现在 targetAddress 持有元素或子数组的地址。
// 需要判断是加载值,还是返回子数组的地址。
// 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址
if (dims.size() < declaredNumDims) {
value = targetAddress;
} else {
// 否则,表示访问的是最终的标量元素,加载其值
// 假设 createLoadInst 接受 Value* pointer
value = builder.createLoadInst(targetAddress);
}
}
return value; return value;
} }
@@ -560,10 +774,10 @@ std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) {
std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) { std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) {
if (ctx->ILITERAL() != nullptr) { if (ctx->ILITERAL() != nullptr) {
int value = std::stol(ctx->ILITERAL()->getText(), nullptr, 0); int value = std::stol(ctx->ILITERAL()->getText(), nullptr, 0);
return static_cast<Value *>(ConstantValue::get(value)); return static_cast<Value *>(ConstantInteger::get(value));
} else if (ctx->FLITERAL() != nullptr) { } else if (ctx->FLITERAL() != nullptr) {
float value = std::stof(ctx->FLITERAL()->getText()); float value = std::stof(ctx->FLITERAL()->getText());
return static_cast<Value *>(ConstantValue::get(value)); return static_cast<Value *>(ConstantFloating::get(value));
} }
throw std::runtime_error("Unknown number type."); throw std::runtime_error("Unknown number type.");
return std::any(); // 不会到达这里 return std::any(); // 不会到达这里
@@ -599,9 +813,9 @@ std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) {
ConstantValue * constValue = dynamic_cast<ConstantValue *>(args[i]); ConstantValue * constValue = dynamic_cast<ConstantValue *>(args[i]);
if (constValue != nullptr) { if (constValue != nullptr) {
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) { if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
args[i] = ConstantValue::get(static_cast<float>(constValue->getInt())); args[i] = ConstantInteger::get(static_cast<float>(constValue->getInt()));
} else { } else {
args[i] = ConstantValue::get(static_cast<int>(constValue->getFloat())); args[i] = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
} }
} else { } else {
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) { if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
@@ -629,9 +843,9 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) {
ConstantValue * constValue = dynamic_cast<ConstantValue *>(value); ConstantValue * constValue = dynamic_cast<ConstantValue *>(value);
if (constValue != nullptr) { if (constValue != nullptr) {
if (constValue->isFloat()) { if (constValue->isFloat()) {
result = ConstantValue::get(-constValue->getFloat()); result = ConstantFloating::get(-constValue->getFloat());
} else { } else {
result = ConstantValue::get(-constValue->getInt()); result = ConstantInteger::get(-constValue->getInt());
} }
} else if (value != nullptr) { } else if (value != nullptr) {
if (value->getType() == Type::getIntType()) { if (value->getType() == Type::getIntType()) {
@@ -648,9 +862,9 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) {
if (constValue != nullptr) { if (constValue != nullptr) {
if (constValue->isFloat()) { if (constValue->isFloat()) {
result = result =
ConstantValue::get(1 - (constValue->getFloat() != 0.0F ? 1 : 0)); ConstantFloating::get(1 - (constValue->getFloat() != 0.0F ? 1 : 0));
} else { } else {
result = ConstantValue::get(1 - (constValue->getInt() != 0 ? 1 : 0)); result = ConstantInteger::get(1 - (constValue->getInt() != 0 ? 1 : 0));
} }
} else if (value != nullptr) { } else if (value != nullptr) {
if (value->getType() == Type::getIntType()) { if (value->getType() == Type::getIntType()) {
@@ -692,13 +906,13 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) {
if (operandType != floatType) { if (operandType != floatType) {
ConstantValue * constValue = dynamic_cast<ConstantValue *>(operand); ConstantValue * constValue = dynamic_cast<ConstantValue *>(operand);
if (constValue != nullptr) if (constValue != nullptr)
operand = ConstantValue::get(static_cast<float>(constValue->getInt())); operand = ConstantFloating::get(static_cast<float>(constValue->getInt()));
else else
operand = builder.createIToFInst(operand); operand = builder.createIToFInst(operand);
} else if (resultType != floatType) { } else if (resultType != floatType) {
ConstantValue* constResult = dynamic_cast<ConstantValue *>(result); ConstantValue* constResult = dynamic_cast<ConstantValue *>(result);
if (constResult != nullptr) if (constResult != nullptr)
result = ConstantValue::get(static_cast<float>(constResult->getInt())); result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
else else
result = builder.createIToFInst(result); result = builder.createIToFInst(result);
} }
@@ -707,14 +921,14 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) {
ConstantValue* constOperand = dynamic_cast<ConstantValue *>(operand); ConstantValue* constOperand = dynamic_cast<ConstantValue *>(operand);
if (opType == SysYParser::MUL) { if (opType == SysYParser::MUL) {
if ((constOperand != nullptr) && (constResult != nullptr)) { if ((constOperand != nullptr) && (constResult != nullptr)) {
result = ConstantValue::get(constResult->getFloat() * result = ConstantFloating::get(constResult->getFloat() *
constOperand->getFloat()); constOperand->getFloat());
} else { } else {
result = builder.createFMulInst(result, operand); result = builder.createFMulInst(result, operand);
} }
} else if (opType == SysYParser::DIV) { } else if (opType == SysYParser::DIV) {
if ((constOperand != nullptr) && (constResult != nullptr)) { if ((constOperand != nullptr) && (constResult != nullptr)) {
result = ConstantValue::get(constResult->getFloat() / result = ConstantFloating::get(constResult->getFloat() /
constOperand->getFloat()); constOperand->getFloat());
} else { } else {
result = builder.createFDivInst(result, operand); result = builder.createFDivInst(result, operand);
@@ -729,17 +943,17 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) {
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand); ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
if (opType == SysYParser::MUL) { if (opType == SysYParser::MUL) {
if ((constOperand != nullptr) && (constResult != nullptr)) if ((constOperand != nullptr) && (constResult != nullptr))
result = ConstantValue::get(constResult->getInt() * constOperand->getInt()); result = ConstantInteger::get(constResult->getInt() * constOperand->getInt());
else else
result = builder.createMulInst(result, operand); result = builder.createMulInst(result, operand);
} else if (opType == SysYParser::DIV) { } else if (opType == SysYParser::DIV) {
if ((constOperand != nullptr) && (constResult != nullptr)) if ((constOperand != nullptr) && (constResult != nullptr))
result = ConstantValue::get(constResult->getInt() / constOperand->getInt()); result = ConstantInteger::get(constResult->getInt() / constOperand->getInt());
else else
result = builder.createDivInst(result, operand); result = builder.createDivInst(result, operand);
} else { } else {
if ((constOperand != nullptr) && (constResult != nullptr)) if ((constOperand != nullptr) && (constResult != nullptr))
result = ConstantValue::get(constResult->getInt() % constOperand->getInt()); result = ConstantInteger::get(constResult->getInt() % constOperand->getInt());
else else
result = builder.createRemInst(result, operand); result = builder.createRemInst(result, operand);
} }
@@ -767,13 +981,13 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) {
if (operandType != floatType) { if (operandType != floatType) {
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand); ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
if (constOperand != nullptr) if (constOperand != nullptr)
operand = ConstantValue::get(static_cast<float>(constOperand->getInt())); operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
else else
operand = builder.createIToFInst(operand); operand = builder.createIToFInst(operand);
} else if (resultType != floatType) { } else if (resultType != floatType) {
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result); ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
if (constResult != nullptr) if (constResult != nullptr)
result = ConstantValue::get(static_cast<float>(constResult->getInt())); result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
else else
result = builder.createIToFInst(result); result = builder.createIToFInst(result);
} }
@@ -782,12 +996,12 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) {
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand); ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
if (opType == SysYParser::ADD) { if (opType == SysYParser::ADD) {
if ((constResult != nullptr) && (constOperand != nullptr)) if ((constResult != nullptr) && (constOperand != nullptr))
result = ConstantValue::get(constResult->getFloat() + constOperand->getFloat()); result = ConstantFloating::get(constResult->getFloat() + constOperand->getFloat());
else else
result = builder.createFAddInst(result, operand); result = builder.createFAddInst(result, operand);
} else { } else {
if ((constResult != nullptr) && (constOperand != nullptr)) if ((constResult != nullptr) && (constOperand != nullptr))
result = ConstantValue::get(constResult->getFloat() - constOperand->getFloat()); result = ConstantFloating::get(constResult->getFloat() - constOperand->getFloat());
else else
result = builder.createFSubInst(result, operand); result = builder.createFSubInst(result, operand);
} }
@@ -796,12 +1010,12 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) {
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand); ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
if (opType == SysYParser::ADD) { if (opType == SysYParser::ADD) {
if ((constResult != nullptr) && (constOperand != nullptr)) if ((constResult != nullptr) && (constOperand != nullptr))
result = ConstantValue::get(constResult->getInt() + constOperand->getInt()); result = ConstantInteger::get(constResult->getInt() + constOperand->getInt());
else else
result = builder.createAddInst(result, operand); result = builder.createAddInst(result, operand);
} else { } else {
if ((constResult != nullptr) && (constOperand != nullptr)) if ((constResult != nullptr) && (constOperand != nullptr))
result = ConstantValue::get(constResult->getInt() - constOperand->getInt()); result = ConstantInteger::get(constResult->getInt() - constOperand->getInt());
else else
result = builder.createSubInst(result, operand); result = builder.createSubInst(result, operand);
} }
@@ -833,10 +1047,10 @@ std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext *ctx) {
auto operand2 = constOperand->isFloat() ? constOperand->getFloat() auto operand2 = constOperand->isFloat() ? constOperand->getFloat()
: constOperand->getInt(); : constOperand->getInt();
if (opType == SysYParser::LT) result = ConstantValue::get(operand1 < operand2 ? 1 : 0); if (opType == SysYParser::LT) result = ConstantInteger::get(operand1 < operand2 ? 1 : 0);
else if (opType == SysYParser::GT) result = ConstantValue::get(operand1 > operand2 ? 1 : 0); else if (opType == SysYParser::GT) result = ConstantInteger::get(operand1 > operand2 ? 1 : 0);
else if (opType == SysYParser::LE) result = ConstantValue::get(operand1 <= operand2 ? 1 : 0); else if (opType == SysYParser::LE) result = ConstantInteger::get(operand1 <= operand2 ? 1 : 0);
else if (opType == SysYParser::GE) result = ConstantValue::get(operand1 >= operand2 ? 1 : 0); else if (opType == SysYParser::GE) result = ConstantInteger::get(operand1 >= operand2 ? 1 : 0);
else assert(false); else assert(false);
} else { } else {
@@ -848,14 +1062,14 @@ std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext *ctx) {
if (resultType == floatType || operandType == floatType) { if (resultType == floatType || operandType == floatType) {
if (resultType != floatType) { if (resultType != floatType) {
if (constResult != nullptr) if (constResult != nullptr)
result = ConstantValue::get(static_cast<float>(constResult->getInt())); result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
else else
result = builder.createIToFInst(result); result = builder.createIToFInst(result);
} }
if (operandType != floatType) { if (operandType != floatType) {
if (constOperand != nullptr) if (constOperand != nullptr)
operand = ConstantValue::get(static_cast<float>(constOperand->getInt())); operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
else else
operand = builder.createIToFInst(operand); operand = builder.createIToFInst(operand);
@@ -901,8 +1115,8 @@ std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext *ctx) {
auto operand2 = constOperand->isFloat() ? constOperand->getFloat() auto operand2 = constOperand->isFloat() ? constOperand->getFloat()
: constOperand->getInt(); : constOperand->getInt();
if (opType == SysYParser::EQ) result = ConstantValue::get(operand1 == operand2 ? 1 : 0); if (opType == SysYParser::EQ) result = ConstantInteger::get(operand1 == operand2 ? 1 : 0);
else if (opType == SysYParser::NE) result = ConstantValue::get(operand1 != operand2 ? 1 : 0); else if (opType == SysYParser::NE) result = ConstantInteger::get(operand1 != operand2 ? 1 : 0);
else assert(false); else assert(false);
} else { } else {
@@ -913,13 +1127,13 @@ std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext *ctx) {
if (resultType == floatType || operandType == floatType) { if (resultType == floatType || operandType == floatType) {
if (resultType != floatType) { if (resultType != floatType) {
if (constResult != nullptr) if (constResult != nullptr)
result = ConstantValue::get(static_cast<float>(constResult->getInt())); result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
else else
result = builder.createIToFInst(result); result = builder.createIToFInst(result);
} }
if (operandType != floatType) { if (operandType != floatType) {
if (constOperand != nullptr) if (constOperand != nullptr)
operand = ConstantValue::get(static_cast<float>(constOperand->getInt())); operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
else else
operand = builder.createIToFInst(operand); operand = builder.createIToFInst(operand);
} }
@@ -943,9 +1157,9 @@ std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext *ctx) {
// 如果只有一个关系表达式则将结果转换为0或1 // 如果只有一个关系表达式则将结果转换为0或1
if (constResult != nullptr) { if (constResult != nullptr) {
if (constResult->isFloat()) if (constResult->isFloat())
result = ConstantValue::get(constResult->getFloat() != 0.0F ? 1 : 0); result = ConstantInteger::get(constResult->getFloat() != 0.0F ? 1 : 0);
else else
result = ConstantValue::get(constResult->getInt() != 0 ? 1 : 0); result = ConstantInteger::get(constResult->getInt() != 0 ? 1 : 0);
} }
} }
@@ -1013,6 +1227,7 @@ void Utils::tree2Array(Type *type, ArrayValueTree *root,
ValueCounter &result, IRBuilder *builder) { ValueCounter &result, IRBuilder *builder) {
Value* value = root->getValue(); Value* value = root->getValue();
auto &children = root->getChildren(); auto &children = root->getChildren();
// 类型转换
if (value != nullptr) { if (value != nullptr) {
if (type == value->getType()) { if (type == value->getType()) {
result.push_back(value); result.push_back(value);
@@ -1020,14 +1235,14 @@ void Utils::tree2Array(Type *type, ArrayValueTree *root,
if (type == Type::getFloatType()) { if (type == Type::getFloatType()) {
ConstantValue* constValue = dynamic_cast<ConstantValue *>(value); ConstantValue* constValue = dynamic_cast<ConstantValue *>(value);
if (constValue != nullptr) if (constValue != nullptr)
result.push_back(ConstantValue::get(static_cast<float>(constValue->getInt()))); result.push_back(ConstantFloating::get(static_cast<float>(constValue->getInt())));
else else
result.push_back(builder->createIToFInst(value)); result.push_back(builder->createIToFInst(value));
} else { } else {
ConstantValue* constValue = dynamic_cast<ConstantValue *>(value); ConstantValue* constValue = dynamic_cast<ConstantValue *>(value);
if (constValue != nullptr) if (constValue != nullptr)
result.push_back(ConstantValue::get(static_cast<int>(constValue->getFloat()))); result.push_back(ConstantInteger::get(static_cast<int>(constValue->getFloat())));
else else
result.push_back(builder->createFtoIInst(value)); result.push_back(builder->createFtoIInst(value));
@@ -1061,9 +1276,9 @@ void Utils::tree2Array(Type *type, ArrayValueTree *root,
int num = blockSize - afterSize + beforeSize; int num = blockSize - afterSize + beforeSize;
if (num > 0) { if (num > 0) {
if (type == Type::getFloatType()) if (type == Type::getFloatType())
result.push_back(ConstantValue::get(0.0F), num); result.push_back(ConstantFloating::get(0.0F), num);
else else
result.push_back(ConstantValue::get(0), num); result.push_back(ConstantInteger::get(0), num);
} }
} }
@@ -1101,7 +1316,7 @@ void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
funcName, pModule, pBuilder); funcName, pModule, pBuilder);
paramTypes.push_back(Type::getIntType()); paramTypes.push_back(Type::getIntType());
paramNames.emplace_back("x"); paramNames.emplace_back("x");
paramDims.push_back(std::vector<Value *>{ConstantValue::get(-1)}); paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
funcName = "getarray"; funcName = "getarray";
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
funcName, pModule, pBuilder); funcName, pModule, pBuilder);
@@ -1117,7 +1332,7 @@ void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
returnType = Type::getIntType(); returnType = Type::getIntType();
paramTypes.push_back(Type::getFloatType()); paramTypes.push_back(Type::getFloatType());
paramNames.emplace_back("x"); paramNames.emplace_back("x");
paramDims.push_back(std::vector<Value *>{ConstantValue::get(-1)}); paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
funcName = "getfarray"; funcName = "getfarray";
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
funcName, pModule, pBuilder); funcName, pModule, pBuilder);
@@ -1141,7 +1356,7 @@ void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
paramTypes.push_back(Type::getIntType()); paramTypes.push_back(Type::getIntType());
paramDims.clear(); paramDims.clear();
paramDims.emplace_back(); paramDims.emplace_back();
paramDims.push_back(std::vector<Value *>{ConstantValue::get(-1)}); paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
paramNames.clear(); paramNames.clear();
paramNames.emplace_back("n"); paramNames.emplace_back("n");
paramNames.emplace_back("a"); paramNames.emplace_back("a");
@@ -1164,7 +1379,7 @@ void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
paramTypes.push_back(Type::getFloatType()); paramTypes.push_back(Type::getFloatType());
paramDims.clear(); paramDims.clear();
paramDims.emplace_back(); paramDims.emplace_back();
paramDims.push_back(std::vector<Value *>{ConstantValue::get(-1)}); paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
paramNames.clear(); paramNames.clear();
paramNames.emplace_back("n"); paramNames.emplace_back("n");
paramNames.emplace_back("a"); paramNames.emplace_back("a");

View File

@@ -1,484 +0,0 @@
#include "SysYIROptPre.h"
#include <cassert>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <iostream>
#include "IR.h"
#include "IRBuilder.h"
namespace sysy {
/**
* use删除operand,以免扰乱后续分析
* instr: 要删除的指令
*/
void SysYOptPre::usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
Value* val = use->getValue();
// std::cout << delete << val->getName() << std::endl;
val->removeUse(use);
}
}
// 删除br后的无用指令
void SysYOptPre::SysYDelInstAfterBr() {
auto &functions = pModule->getFunctions();
for (auto &function : functions) {
auto basicBlocks = function.second->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
bool Branch = false;
auto &instructions = basicBlock->getInstructions();
auto Branchiter = instructions.end();
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
if (Branch)
usedelete(iter->get());
else if ((*iter)->isTerminator()){
Branch = true;
Branchiter = iter;
}
}
if (Branchiter != instructions.end()) ++Branchiter;
while (Branchiter != instructions.end())
Branchiter = instructions.erase(Branchiter);
if (Branch) { // 更新前驱后继关系
auto thelastinstinst = basicBlock->getInstructions().end();
--thelastinstinst;
auto &Successors = basicBlock->getSuccessors();
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
(*iterSucc)->removePredecessor(basicBlock.get());
basicBlock->removeSuccessor(*iterSucc);
}
if (thelastinstinst->get()->isUnconditional()) {
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
basicBlock->addSuccessor(branchBlock);
branchBlock->addPredecessor(basicBlock.get());
} else if (thelastinstinst->get()->isConditional()) {
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
basicBlock->addSuccessor(thenBlock);
basicBlock->addSuccessor(elseBlock);
thenBlock->addPredecessor(basicBlock.get());
elseBlock->addPredecessor(basicBlock.get());
}
}
}
}
}
void SysYOptPre::SysYBlockMerge() {
auto &functions = pModule->getFunctions(); //std::map<std::string, std::unique_ptr<Function>>
for (auto &function : functions) {
// auto basicBlocks = function.second->getBasicBlocks();
auto &func = function.second;
for (auto blockiter = func->getBasicBlocks().begin();
blockiter != func->getBasicBlocks().end();) {
if (blockiter->get()->getNumSuccessors() == 1) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
// 则将当前块和后继块合并
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
BasicBlock* block = blockiter->get();
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
auto nextarguments = nextBlock->getArguments();
// 删除br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->end();
(--thelastinstinst);
if (thelastinstinst->get()->isUnconditional()) {
usedelete(thelastinstinst->get());
block->getInstructions().erase(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
usedelete(thelastinstinst->get());
block->getInstructions().erase(thelastinstinst);
}
}
}
// 将后继块的指令移动到当前块
// 并将后继块的父指针改为当前块
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
institer->get()->setParent(block);
block->getInstructions().emplace_back(institer->release());
institer = nextBlock->getInstructions().erase(institer);
}
// 合并参数
// TODO是否需要去重?
for (auto &argm : nextarguments) {
argm->setParent(block);
block->insertArgument(argm);
}
// 更新前驱后继关系,类似树节点操作
block->removeSuccessor(nextBlock);
nextBlock->removePredecessor(block);
std::list<BasicBlock *> succshoulddel;
for (auto &succ : nextBlock->getSuccessors()) {
block->addSuccessor(succ);
succ->replacePredecessor(nextBlock, block);
succshoulddel.push_back(succ);
}
for (auto del : succshoulddel) {
nextBlock->removeSuccessor(del);
}
func->removeBasicBlock(nextBlock);
} else {
blockiter++;
}
} else {
blockiter++;
}
}
}
}
// 删除无前驱块兼容SSA后的处理
void SysYOptPre::SysYDelNoPreBLock() {
auto &functions = pModule->getFunctions(); // std::map<std::string, std::unique_ptr<sysy::Function>>
for (auto &function : functions) {
auto &func = function.second;
for (auto &block : func->getBasicBlocks()) {
block->setreachableFalse();
}
// 对函数基本块做一个拓扑排序,排查不可达基本块
auto entryBlock = func->getEntryBlock();
entryBlock->setreachableTrue();
std::queue<BasicBlock *> blockqueue;
blockqueue.push(entryBlock);
while (!blockqueue.empty()) {
auto block = blockqueue.front();
blockqueue.pop();
for (auto &succ : block->getSuccessors()) {
if (!succ->getreachable()) {
succ->setreachableTrue();
blockqueue.push(succ);
}
}
}
// 删除不可达基本块指令
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();blockIter++) {
if (!blockIter->get()->getreachable())
for (auto &iterInst : blockIter->get()->getInstructions())
usedelete(iterInst.get());
}
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
if (!blockIter->get()->getreachable()) {
for (auto succblock : blockIter->get()->getSuccessors()) {
int indexphi = 1;
for (auto pred : succblock->getPredecessors()) {
if (pred == blockIter->get()) {
break;
}
indexphi++;
}
for (auto &phiinst : succblock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
phiinst->removeOperand(indexphi);
}
}
// 删除不可达基本块,注意迭代器不可达问题
func->removeBasicBlock((blockIter++)->get());
} else {
blockIter++;
}
}
}
}
void SysYOptPre::SysYDelEmptyBlock() {
auto &functions = pModule->getFunctions();
for (auto &function : functions) {
// 收集不可达基本块
// 这里的不可达基本块是指没有实际指令的基本块
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时也会被视作不可达
auto basicBlocks = function.second->getBasicBlocks();
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
// 空块儿和后继的基本块的映射
for (auto &basicBlock : basicBlocks) {
if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) {
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
else{
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
// 判断除了最后一个指令之外是不是只有phi指令
bool onlyPhi = true;
for (auto &inst : basicBlock->getInstructions()) {
if (!inst->isPhi() && !inst->isUnconditional()) {
onlyPhi = false;
break;
}
}
if(onlyPhi)
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
// 更新基本块信息,增加必要指令
for (auto &basicBlock : basicBlocks) {
// 把空块转换成只有跳转指令的不可达块
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
if (basicBlock->getNumSuccessors() == 0) {
continue;
}
if (basicBlock->getNumSuccessors() > 1) {
assert("");
}
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
continue;
}
auto thelastinst = basicBlock->getInstructions().end();
--thelastinst;
// 根据br指令传递的后继块信息跳过空块链
if (thelastinst->get()->isUnconditional()) {
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
BasicBlock *thelastBlockOld = nullptr;
// 如果空块链表为多个块
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
}
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
// 更新phi指令的操作数
// 移除thelastBlockOld对应的phi操作数
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
thelastinst->get()->replaceOperand(
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
}
basicBlock->removeSuccessor(OldThenBlock);
OldThenBlock->removePredecessor(basicBlock.get());
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
continue;
}
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
// auto indexInNew = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors().
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
thelastinst->get()->replaceOperand(
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
}
basicBlock->removeSuccessor(OldElseBlock);
OldElseBlock->removePredecessor(basicBlock.get());
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
continue;
}
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
} else {
if (basicBlock->getNumSuccessors() == 1) {
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
auto thelastinst = basicBlock->getInstructions().end();
(--thelastinst);
auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
sysy::BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
EmptyBlocks.end()) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(
0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
}
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
if (thelastBlockOld != nullptr) {
int indexphi = 0;
for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
if (pred == thelastBlockOld) {
break;
}
indexphi++;
}
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
} else {
break;
}
}
}
}
}
}
for (auto iter = function.second->getBasicBlocks().begin(); iter != function.second->getBasicBlocks().end();) {
if (EmptyBlocks.find(iter->get()) != EmptyBlocks.end()) {
// EntryBlock跳过
if (iter->get() == function.second->getEntryBlock()) {
++iter;
continue;
}
for (auto &iterInst : iter->get()->getInstructions())
usedelete(iterInst.get());
// 删除不可达基本块的phi指令的操作数
for (auto &succ : iter->get()->getSuccessors()) {
int index = 0;
for (auto &pred : succ->getPredecessors()) {
if (pred == iter->get()) {
break;
}
index++;
}
for (auto &instinsucc : succ->getInstructions()) {
if (instinsucc->isPhi()) {
dynamic_cast<PhiInst *>(instinsucc.get())->removeOperand(index);
} else {
break;
}
}
}
function.second->removeBasicBlock((iter++)->get());
} else {
++iter;
}
}
}
}
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
void SysYOptPre::SysYAddReturn() {
auto &functions = pModule->getFunctions();
for (auto &function : functions) {
auto &func = function.second;
auto basicBlocks = func->getBasicBlocks();
for (auto &block : basicBlocks) {
if (block->getNumSuccessors() == 0) {
// 如果基本块没有后继块,则添加一个返回指令
if (block->getNumInstructions() == 0) {
pBuilder->setPosition(block.get(), block->end());
pBuilder->createReturnInst();
}
auto thelastinst = block->getInstructions().end();
--thelastinst;
if (thelastinst->get()->getKind() != Instruction::kReturn) {
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
pBuilder->setPosition(block.get(), block->end());
// TODO: 如果int float函数缺少返回值是否需要报错
if (func->getReturnType()->isInt()) {
pBuilder->createReturnInst(ConstantValue::get(0));
} else if (func->getReturnType()->isFloat()) {
pBuilder->createReturnInst(ConstantValue::get(0.0F));
} else {
pBuilder->createReturnInst();
}
}
}
}
}
}
} // namespace sysy

36
src/SysYIRPassManager.cpp Normal file
View File

@@ -0,0 +1,36 @@
// PassManager.cpp
#include "SysYIRPassManager.h"
#include <iostream>
namespace sysy {
void PassManager::run(Module& M) {
// 首先运行Module级别的Pass
for (auto& pass : modulePasses) {
std::cout << "Running Module Pass: " << pass->getPassName() << std::endl;
pass->runOnModule(M);
}
// 然后对每个函数运行Function级别的Pass
auto& functions = M.getFunctions();
for (auto& pair : functions) {
Function& F = *(pair.second); // 获取Function的引用
std::cout << " Processing Function: " << F.getName() << std::endl;
// 在每个函数上运行FunctionPasses
bool changedInFunction;
do {
changedInFunction = false;
for (auto& pass : functionPasses) {
// 对于FunctionPasses可以考虑一个迭代执行的循环直到稳定
std::cout << " Running Function Pass: " << pass->getPassName() << std::endl;
changedInFunction |= pass->runOnFunction(F);
}
} while (changedInFunction); // 循环直到函数稳定这模拟了您SysYCFGOpt的while(changed)逻辑
}
// 分析Pass的运行可以在其他Pass需要时触发或者在特定的PassManager阶段触发
// 对于依赖于分析结果的Pass可以在其run方法中通过PassManager::getAnalysis()来获取
}
} // namespace sysy

View File

@@ -3,12 +3,11 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "IR.h" #include "IR.h" // 确保IR.h包含了ArrayType、GetElementPtrInst等的定义
namespace sysy { namespace sysy {
void SysYPrinter::printIR() { void SysYPrinter::printIR() {
const auto &functions = pModule->getFunctions(); const auto &functions = pModule->getFunctions();
//TODO: Print target datalayout and triple (minimal required by LLVM) //TODO: Print target datalayout and triple (minimal required by LLVM)
@@ -36,11 +35,18 @@ std::string SysYPrinter::getTypeString(Type *type) {
return "i32"; return "i32";
} else if (type->isFloat()) { } else if (type->isFloat()) {
return "float"; return "float";
} else if (auto ptrType = dynamic_cast<PointerType*>(type)) { } else if (auto ptrType = dynamic_cast<PointerType*>(type)) {
// 递归打印指针指向的类型,然后加上 '*'
return getTypeString(ptrType->getBaseType()) + "*"; return getTypeString(ptrType->getBaseType()) + "*";
} else if (auto ptrType = dynamic_cast<FunctionType*>(type)) { } else if (auto funcType = dynamic_cast<FunctionType*>(type)) {
return getTypeString(ptrType->getReturnType()); // 对于函数类型,打印其返回类型
// 注意这里可能需要更完整的函数签名打印取决于你的IR表示方式
// 比如:`retType (paramType1, paramType2, ...)`
// 但为了简化和LLVM IR兼容性通常在定义时完整打印
return getTypeString(funcType->getReturnType());
} else if (auto arrayType = dynamic_cast<ArrayType*>(type)) { // 新增:处理数组类型
// 打印格式为 [num_elements x element_type]
return "[" + std::to_string(arrayType->getNumElements()) + " x " + getTypeString(arrayType->getElementType()) + "]";
} }
assert(false && "Unsupported type"); assert(false && "Unsupported type");
return ""; return "";
@@ -51,15 +57,23 @@ std::string SysYPrinter::getValueName(Value *value) {
return "@" + global->getName(); return "@" + global->getName();
} else if (auto inst = dynamic_cast<Instruction*>(value)) { } else if (auto inst = dynamic_cast<Instruction*>(value)) {
return "%" + inst->getName(); return "%" + inst->getName();
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) { } else if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
if (constVal->isFloat()) { return std::to_string(constInt->getInt());
} else if (auto constFloat = dynamic_cast<ConstantFloating*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constFloat->getFloat());
} else if (auto constUndef = dynamic_cast<UndefinedValue*>(value)) { // 如果有Undef类型
return "undef";
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) { // fallback for generic ConstantValue
// 这里的逻辑可能需要根据你ConstantValue的实际设计调整
// 确保它能处理所有可能的ConstantValue
if (constVal->getType()->isFloat()) {
return std::to_string(constVal->getFloat()); return std::to_string(constVal->getFloat());
} }
return std::to_string(constVal->getInt()); return std::to_string(constVal->getInt());
} else if (auto constVar = dynamic_cast<ConstantVariable*>(value)) { } else if (auto constVar = dynamic_cast<ConstantVariable*>(value)) {
return constVar->getName(); return constVar->getName(); // 假设ConstantVariable有自己的名字或通过getByIndices获取值
} }
assert(false && "Unknown value type"); assert(false && "Unknown value type or unable to get value name");
return ""; return "";
} }
@@ -77,44 +91,35 @@ void SysYPrinter::printGlobalVariable() {
for (const auto &global : globals) { for (const auto &global : globals) {
std::cout << "@" << global->getName() << " = global "; std::cout << "@" << global->getName() << " = global ";
auto baseType = dynamic_cast<PointerType *>(global->getType())->getBaseType(); // 全局变量的类型是一个指针,指向其基类型 (可能是 ArrayType 或 Integer/FloatType)
printType(baseType); auto globalVarBaseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
printType(globalVarBaseType); // 打印全局变量的实际类型 (例如 i32 或 [10 x i32])
if (global->getNumDims() > 0) {
// Array type
std::cout << " [";
for (unsigned i = 0; i < global->getNumDims(); i++) {
if (i > 0) std::cout << " x ";
std::cout << getValueName(global->getDim(i));
}
std::cout << "]";
}
std::cout << " "; std::cout << " ";
if (global->getNumDims() > 0) { // 检查是否是数组类型 (通过检查 globalVarBaseType 是否是 ArrayType)
// Array initializer if (globalVarBaseType->isArray()) {
std::cout << "["; // 数组初始化器
auto values = global->getInitValues(); std::cout << "["; // LLVM IR 数组初始化器格式: [type value, type value, ...]
auto counterValues = values.getValues(); auto values = global->getInitValues(); // 假设 getInitValues() 返回一个 ValueCounter
auto counterNumbers = values.getNumbers(); const std::vector<sysy::Value *> &counterValues = values.getValues(); // 获取所有值
for (size_t i = 0; i < counterNumbers.size(); i++) { for (size_t i = 0; i < counterValues.size(); i++) {
if (i > 0) std::cout << ", "; if (i > 0) std::cout << ", ";
if (baseType->isFloat()) { // 打印元素类型,这个元素类型应该是数组的最终元素类型,例如 i32 或 float
std::cout << "float " << dynamic_cast<ConstantValue*>(counterValues[i])->getFloat(); // 可以从 globalVarBaseType 逐层剥离得到最终元素类型,但这里简化为直接从值获取
} else { printType(counterValues[i]->getType());
std::cout << "i32 " << dynamic_cast<ConstantValue*>(counterValues[i])->getInt(); std::cout << " ";
} printValue(counterValues[i]);
} }
std::cout << "]"; std::cout << "]";
} else { } else {
// Scalar initializer // 标量初始化器
if (baseType->isFloat()) { // 假设标量全局变量的初始化值通过 getByIndex(0) 获取
std::cout << "float " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getFloat(); Value* initVal = global->getByIndex(0);
} else { printType(initVal->getType()); // 打印标量值的类型
std::cout << "i32 " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getInt(); std::cout << " ";
} printValue(initVal); // 打印标量值
} }
std::cout << ", align 4" << std::endl; std::cout << ", align 4" << std::endl;
@@ -209,19 +214,19 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kFDiv: std::cout << "fdiv"; break; case Kind::kFDiv: std::cout << "fdiv"; break;
case Kind::kICmpEQ: std::cout << "icmp eq"; break; case Kind::kICmpEQ: std::cout << "icmp eq"; break;
case Kind::kICmpNE: std::cout << "icmp ne"; break; case Kind::kICmpNE: std::cout << "icmp ne"; break;
case Kind::kICmpLT: std::cout << "icmp slt"; break; case Kind::kICmpLT: std::cout << "icmp slt"; break; // LLVM uses slt/sgt for signed less/greater than
case Kind::kICmpGT: std::cout << "icmp sgt"; break; case Kind::kICmpGT: std::cout << "icmp sgt"; break;
case Kind::kICmpLE: std::cout << "icmp sle"; break; case Kind::kICmpLE: std::cout << "icmp sle"; break;
case Kind::kICmpGE: std::cout << "icmp sge"; break; case Kind::kICmpGE: std::cout << "icmp sge"; break;
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break; case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break; // oeq for ordered equal
case Kind::kFCmpNE: std::cout << "fcmp one"; break; case Kind::kFCmpNE: std::cout << "fcmp one"; break; // one for ordered not equal
case Kind::kFCmpLT: std::cout << "fcmp olt"; break; case Kind::kFCmpLT: std::cout << "fcmp olt"; break; // olt for ordered less than
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break; case Kind::kFCmpGT: std::cout << "fcmp ogt"; break; // ogt for ordered greater than
case Kind::kFCmpLE: std::cout << "fcmp ole"; break; case Kind::kFCmpLE: std::cout << "fcmp ole"; break; // ole for ordered less than or equal
case Kind::kFCmpGE: std::cout << "fcmp oge"; break; case Kind::kFCmpGE: std::cout << "fcmp oge"; break; // oge for ordered greater than or equal
case Kind::kAnd: std::cout << "and"; break; case Kind::kAnd: std::cout << "and"; break;
case Kind::kOr: std::cout << "or"; break; case Kind::kOr: std::cout << "or"; break;
default: break; default: break; // Should not reach here
} }
// Types and operands // Types and operands
@@ -238,7 +243,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kNeg: case Kind::kNeg:
case Kind::kNot: case Kind::kNot:
case Kind::kFNeg: case Kind::kFNeg:
case Kind::kFNot:
case Kind::kFtoI: case Kind::kFtoI:
case Kind::kBitFtoI: case Kind::kBitFtoI:
case Kind::kItoF: case Kind::kItoF:
@@ -250,31 +254,39 @@ void SysYPrinter::printInst(Instruction *pInst) {
} }
switch (pInst->getKind()) { switch (pInst->getKind()) {
case Kind::kNeg: std::cout << "sub "; break; case Kind::kNeg: std::cout << "sub "; break; // integer negation is `sub i32 0, operand`
case Kind::kNot: std::cout << "not "; break; case Kind::kNot: std::cout << "xor "; break; // logical/bitwise NOT is `xor i32 -1, operand` or `xor i1 true, operand`
case Kind::kFNeg: std::cout << "fneg "; break; case Kind::kFNeg: std::cout << "fneg "; break; // float negation
case Kind::kFNot: std::cout << "fneg "; break; // FNot not standard, map to fneg case Kind::kFtoI: std::cout << "fptosi "; break; // float to signed integer
case Kind::kFtoI: std::cout << "fptosi "; break; case Kind::kBitFtoI: std::cout << "bitcast "; break; // bitcast float to int
case Kind::kBitFtoI: std::cout << "bitcast "; break; case Kind::kItoF: std::cout << "sitofp "; break; // signed integer to float
case Kind::kItoF: std::cout << "sitofp "; break; case Kind::kBitItoF: std::cout << "bitcast "; break; // bitcast int to float
case Kind::kBitItoF: std::cout << "bitcast "; break; default: break; // Should not reach here
default: break;
} }
printType(unyInst->getType()); printType(unyInst->getOperand()->getType()); // Print operand type
std::cout << " "; std::cout << " ";
// Special handling for negation // Special handling for integer negation and logical NOT
if (pInst->getKind() == Kind::kNeg || pInst->getKind() == Kind::kNot) { if (pInst->getKind() == Kind::kNeg) {
std::cout << "i32 0, "; std::cout << "0, "; // for 'sub i32 0, operand'
} else if (pInst->getKind() == Kind::kNot) {
// For logical NOT (i1 -> i1), use 'xor i1 true, operand'
// For bitwise NOT (i32 -> i32), use 'xor i32 -1, operand'
if (unyInst->getOperand()->getType()->isInt()) { // Assuming i32 for bitwise NOT
std::cout << "NOT, "; // or specific bitmask for NOT
} else { // Assuming i1 for logical NOT
std::cout << "true, ";
}
} }
printValue(pInst->getOperand(0)); printValue(pInst->getOperand(0));
// For bitcast, need to specify destination type // For type conversions (fptosi, sitofp, bitcast), need to specify destination type
if (pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) { if (pInst->getKind() == Kind::kFtoI || pInst->getKind() == Kind::kItoF ||
pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
std::cout << " to "; std::cout << " to ";
printType(unyInst->getType()); printType(unyInst->getType()); // Print result type
} }
std::cout << std::endl; std::cout << std::endl;
@@ -289,7 +301,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
} }
std::cout << "call "; std::cout << "call ";
printType(callInst->getType()); printType(callInst->getType()); // Return type of the call
std::cout << " @" << function->getName() << "("; std::cout << " @" << function->getName() << "(";
auto params = callInst->getArguments(); auto params = callInst->getArguments();
@@ -297,9 +309,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
for (auto &param : params) { for (auto &param : params) {
if (!first) std::cout << ", "; if (!first) std::cout << ", ";
first = false; first = false;
printType(param->getValue()->getType()); printType(param->getValue()->getType()); // Type of argument
std::cout << " "; std::cout << " ";
printValue(param->getValue()); printValue(param->getValue()); // Value of argument
} }
std::cout << ")" << std::endl; std::cout << ")" << std::endl;
@@ -307,7 +319,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kCondBr: { case Kind::kCondBr: {
auto condBrInst = dynamic_cast<CondBrInst *>(pInst); auto condBrInst = dynamic_cast<CondBrInst *>(pInst);
std::cout << "br i1 "; std::cout << "br i1 "; // Condition type should be i1
printValue(condBrInst->getCondition()); printValue(condBrInst->getCondition());
std::cout << ", label %" << condBrInst->getThenBlock()->getName(); std::cout << ", label %" << condBrInst->getThenBlock()->getName();
std::cout << ", label %" << condBrInst->getElseBlock()->getName(); std::cout << ", label %" << condBrInst->getElseBlock()->getName();
@@ -337,14 +349,17 @@ void SysYPrinter::printInst(Instruction *pInst) {
auto allocaInst = dynamic_cast<AllocaInst *>(pInst); auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
std::cout << "%" << allocaInst->getName() << " = alloca "; std::cout << "%" << allocaInst->getName() << " = alloca ";
auto baseType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType(); // AllocaInst 的类型现在应该是一个 PointerType指向正确的 ArrayType 或 ScalarType
printType(baseType); // 例如alloca i32, align 4 或者 alloca [10 x i32], align 4
auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
printType(allocatedType);
// 仍然打印维度信息,如果存在的话
if (allocaInst->getNumDims() > 0) { if (allocaInst->getNumDims() > 0) {
std::cout << ", "; std::cout << ", ";
for (size_t i = 0; i < allocaInst->getNumDims(); i++) { for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
if (i > 0) std::cout << ", "; if (i > 0) std::cout << ", ";
printType(Type::getIntType()); printType(Type::getIntType()); // 维度大小通常是 i32 类型
std::cout << " "; std::cout << " ";
printValue(allocaInst->getDim(i)); printValue(allocaInst->getDim(i));
} }
@@ -356,17 +371,18 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kLoad: { case Kind::kLoad: {
auto loadInst = dynamic_cast<LoadInst *>(pInst); auto loadInst = dynamic_cast<LoadInst *>(pInst);
std::cout << "%" << loadInst->getName() << " = load "; std::cout << "%" << loadInst->getName() << " = load ";
printType(loadInst->getType()); printType(loadInst->getType()); // 加载的结果类型
std::cout << ", "; std::cout << ", ";
printType(loadInst->getPointer()->getType()); printType(loadInst->getPointer()->getType()); // 指针类型
std::cout << " "; std::cout << " ";
printValue(loadInst->getPointer()); printValue(loadInst->getPointer()); // 要加载的地址
// 仍然打印索引信息,如果存在的话
if (loadInst->getNumIndices() > 0) { if (loadInst->getNumIndices() > 0) {
std::cout << ", "; std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
for (size_t i = 0; i < loadInst->getNumIndices(); i++) { for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", "; if (i > 0) std::cout << ", ";
printType(Type::getIntType()); printType(loadInst->getIndex(i)->getType());
std::cout << " "; std::cout << " ";
printValue(loadInst->getIndex(i)); printValue(loadInst->getIndex(i));
} }
@@ -375,44 +391,23 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << ", align 4" << std::endl; std::cout << ", align 4" << std::endl;
} break; } break;
case Kind::kLa: {
auto laInst = dynamic_cast<LaInst *>(pInst);
std::cout << "%" << laInst->getName() << " = getelementptr inbounds ";
auto ptrType = dynamic_cast<PointerType*>(laInst->getPointer()->getType());
printType(ptrType->getBaseType());
std::cout << ", ";
printType(laInst->getPointer()->getType());
std::cout << " ";
printValue(laInst->getPointer());
std::cout << ", ";
for (size_t i = 0; i < laInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(Type::getIntType());
std::cout << " ";
printValue(laInst->getIndex(i));
}
std::cout << std::endl;
} break;
case Kind::kStore: { case Kind::kStore: {
auto storeInst = dynamic_cast<StoreInst *>(pInst); auto storeInst = dynamic_cast<StoreInst *>(pInst);
std::cout << "store "; std::cout << "store ";
printType(storeInst->getValue()->getType()); printType(storeInst->getValue()->getType()); // 要存储的值的类型
std::cout << " "; std::cout << " ";
printValue(storeInst->getValue()); printValue(storeInst->getValue()); // 要存储的值
std::cout << ", "; std::cout << ", ";
printType(storeInst->getPointer()->getType()); printType(storeInst->getPointer()->getType()); // 目标指针的类型
std::cout << " "; std::cout << " ";
printValue(storeInst->getPointer()); printValue(storeInst->getPointer()); // 目标地址
// 仍然打印索引信息,如果存在的话
if (storeInst->getNumIndices() > 0) { if (storeInst->getNumIndices() > 0) {
std::cout << ", "; std::cout << ", indices "; // 或者其他分隔符
for (size_t i = 0; i < storeInst->getNumIndices(); i++) { for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", "; if (i > 0) std::cout << ", ";
printType(Type::getIntType()); printType(storeInst->getIndex(i)->getType());
std::cout << " "; std::cout << " ";
printValue(storeInst->getIndex(i)); printValue(storeInst->getIndex(i));
} }
@@ -421,6 +416,30 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << ", align 4" << std::endl; std::cout << ", align 4" << std::endl;
} break; } break;
case Kind::kGetElementPtr: { // 新增GetElementPtrInst 打印
auto gepInst = dynamic_cast<GetElementPtrInst*>(pInst);
std::cout << "%" << gepInst->getName() << " = getelementptr inbounds "; // 假设总是 inbounds
// GEP 的第一个操作数是基指针,其类型是一个指向聚合类型的指针
// 第一个参数是基指针所指向的聚合类型的类型 (e.g., [10 x i32])
auto basePtrType = dynamic_cast<PointerType*>(gepInst->getBasePointer()->getType());
printType(basePtrType->getBaseType()); // 打印基指针指向的类型
std::cout << ", ";
printType(gepInst->getBasePointer()->getType()); // 打印基指针自身的类型 (e.g., [10 x i32]*)
std::cout << " ";
printValue(gepInst->getBasePointer()); // 打印基指针
// 打印所有索引
for (auto indexVal : gepInst->getIndices()) { // 使用 getIndices() 迭代器
std::cout << ", ";
printType(indexVal->getValue()->getType()); // 打印索引的类型 (通常是 i32)
std::cout << " ";
printValue(indexVal->getValue()); // 打印索引值
}
std::cout << std::endl;
} break;
case Kind::kMemset: { case Kind::kMemset: {
auto memsetInst = dynamic_cast<MemsetInst *>(pInst); auto memsetInst = dynamic_cast<MemsetInst *>(pInst);
std::cout << "call void @llvm.memset.p0."; std::cout << "call void @llvm.memset.p0.";
@@ -433,49 +452,38 @@ void SysYPrinter::printInst(Instruction *pInst) {
printValue(memsetInst->getValue()); printValue(memsetInst->getValue());
std::cout << ", i32 "; std::cout << ", i32 ";
printValue(memsetInst->getSize()); printValue(memsetInst->getSize());
std::cout << ", i1 false)" << std::endl; std::cout << ", i1 false)" << std::endl; // alignment for memset is typically i1
} break; } break;
case Kind::kPhi: { case Kind::kPhi: {
auto phiInst = dynamic_cast<PhiInst *>(pInst); auto phiInst = dynamic_cast<PhiInst *>(pInst);
printValue(phiInst->getOperand(0)); // Phi 指令的名称通常是结果变量
std::cout << " = phi "; std::cout << "%" << phiInst->getName() << " = phi ";
printType(phiInst->getType()); printType(phiInst->getType()); // Phi 结果类型
for (unsigned i = 1; i < phiInst->getNumOperands(); i++) { // Phi 指令的操作数是成对的 [value, basic_block]
if (i > 0) std::cout << ", "; // 这里假设 getOperands() 返回的是 (val1, block1, val2, block2...)
// 如果你的 PhiInst 存储方式是 getIncomingValues() 和 getIncomingBlocks(),请相应调整
// LLVM IR 格式: phi type [value1, block1], [value2, block2]
bool firstPair = true;
for (unsigned i = 0; i < phiInst->getNumOperands() / 2; ++i) { // 遍历成对的操作数
if (!firstPair) std::cout << ", ";
firstPair = false;
std::cout << "[ "; std::cout << "[ ";
printValue(phiInst->getOperand(i)); printValue(phiInst->getOperand(i * 2)); // value
std::cout << ", %";
printValue(phiInst->getOperand(i * 2 + 1)); // block
std::cout << " ]"; std::cout << " ]";
} }
std::cout << std::endl; std::cout << std::endl;
} break; } break;
case Kind::kGetSubArray: { // 以下两个 Kind 应该删除或替换为 kGEP
auto getSubArrayInst = dynamic_cast<GetSubArrayInst *>(pInst); // case Kind::kLa: { /* REMOVED */ } break;
std::cout << "%" << getSubArrayInst->getName() << " = getelementptr inbounds "; // case Kind::kGetSubArray: { /* REMOVED */ } break;
auto ptrType = dynamic_cast<PointerType*>(getSubArrayInst->getFatherArray()->getType());
printType(ptrType->getBaseType());
std::cout << ", ";
printType(getSubArrayInst->getFatherArray()->getType());
std::cout << " ";
printValue(getSubArrayInst->getFatherArray());
std::cout << ", ";
bool firstIndex = true;
for (auto &index : getSubArrayInst->getIndices()) {
if (!firstIndex) std::cout << ", ";
firstIndex = false;
printType(Type::getIntType());
std::cout << " ";
printValue(index->getValue());
}
std::cout << std::endl;
} break;
default: default:
assert(false && "Unsupported instruction kind"); assert(false && "Unsupported instruction kind in SysYPrinter");
break; break;
} }
} }

View File

@@ -0,0 +1,59 @@
#pragma once
#include "IR.h" // 假设IR.h包含了Module, Function, BasicBlock, Instruction, Value, IRBuilder, Type等定义
#include "IRBuilder.h" // 需要IRBuilder来创建新指令
#include "SysYIRPrinter.h" // 新增: 用于调试输出
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <list> // 用于迭代和修改指令列表
#include <algorithm> // for std::reverse (if needed, although not used in final version)
#include <iostream> // MODIFICATION: 用于警告输出
namespace sysy {
/**
* @brief AddressCalculationExpansion Pass
*
* 这是一个IR优化Pass用于将LoadInst和StoreInst中包含的多维数组索引
* 显式地转换为IR中的BinaryInst乘法和加法序列并生成带有线性偏移量的
* LoadInst/StoreInst。
*
* 目的确保在寄存器分配之前所有中间地址计算的结果都有明确的IR指令和对应的虚拟寄存器
* 从而避免在后端DAG构建时临时创建值而导致寄存器分配缺失的问题。
*
* SysY语言特性
* - 无指针类型所有数组访问的基地址是alloca或global的AllocaType/ArrayType
* - 数据类型只有int和float且都占用4字节。
* - LoadInst和StoreInst直接接受多个索引作为额外操作数。
*/
class AddressCalculationExpansion {
private:
Module* pModule;
IRBuilder* pBuilder; // 用于在IR中插入新指令
// 数组元素的固定大小根据SysY特性int和float都是4字节
static const int ELEMENT_SIZE = 4;
// 辅助函数:根据数组的维度信息和当前索引的维度,计算该索引的步长(字节数)
// dims: 包含所有维度大小的vector例如 {2, 3, 4}
// currentDimIndex: 当前正在处理的索引在 dims 中的位置 (0, 1, 2...)
int calculateStride(const std::vector<int>& dims, size_t currentDimIndex) {
int stride = ELEMENT_SIZE; // 最内层元素大小 (4字节)
// 乘以当前维度之后的所有维度的大小
for (size_t i = currentDimIndex + 1; i < dims.size(); ++i) {
stride *= dims[i];
}
return stride;
}
public:
AddressCalculationExpansion(Module* module, IRBuilder* builder)
: pModule(module), pBuilder(builder) {}
// 运行此Pass
bool run();
};
} // namespace sysy

View File

@@ -3,6 +3,7 @@
#include "IR.h" #include "IR.h"
#include "SysYIRAnalyser.h" #include "SysYIRAnalyser.h"
#include "SysYIRPrinter.h" #include "SysYIRPrinter.h"
#include "SysYIROptUtils.h"
namespace sysy { namespace sysy {
@@ -31,9 +32,5 @@ class DeadCodeElimination {
void eliminateDeadGlobals(bool& changed); // 消除无用全局变量 void eliminateDeadGlobals(bool& changed); // 消除无用全局变量
void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点) void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点)
void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储 void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储
bool isGlobal(Value *val);
bool isArr(Value *val);
void usedelete(Instruction *instr);
}; };
} // namespace sysy } // namespace sysy

View File

@@ -49,6 +49,7 @@ class Type {
kLabel, kLabel,
kPointer, kPointer,
kFunction, kFunction,
kArray,
}; };
Kind kind; ///< 表示具体类型的变量 Kind kind; ///< 表示具体类型的变量
@@ -65,6 +66,7 @@ class Type {
static Type* getPointerType(Type *baseType); ///< 返回表示指向baseType类型的Pointer类型的Type指针 static Type* getPointerType(Type *baseType); ///< 返回表示指向baseType类型的Pointer类型的Type指针
static Type* getFunctionType(Type *returnType, const std::vector<Type *> &paramTypes = {}); static Type* getFunctionType(Type *returnType, const std::vector<Type *> &paramTypes = {});
///< 返回表示返回类型为returnType,形参类型列表为paramTypes的函数类型的Type指针 ///< 返回表示返回类型为returnType,形参类型列表为paramTypes的函数类型的Type指针
static Type* getArrayType(Type *elementType, unsigned numElements);
public: public:
Kind getKind() const { return kind; } ///< 返回Type对象代表原始标量类型 Kind getKind() const { return kind; } ///< 返回Type对象代表原始标量类型
@@ -74,6 +76,7 @@ class Type {
bool isLabel() const { return kind == kLabel; } ///< 判定是否为Label类型 bool isLabel() const { return kind == kLabel; } ///< 判定是否为Label类型
bool isPointer() const { return kind == kPointer; } ///< 判定是否为Pointer类型 bool isPointer() const { return kind == kPointer; } ///< 判定是否为Pointer类型
bool isFunction() const { return kind == kFunction; } ///< 判定是否为Function类型 bool isFunction() const { return kind == kFunction; } ///< 判定是否为Function类型
bool isArray() const { return kind == Kind::kArray; }
unsigned getSize() const; ///< 返回类型所占的空间大小(字节) unsigned getSize() const; ///< 返回类型所占的空间大小(字节)
/// 尝试将一个变量转换为给定的Type及其派生类类型的变量 /// 尝试将一个变量转换为给定的Type及其派生类类型的变量
template <typename T> template <typename T>
@@ -115,6 +118,22 @@ class FunctionType : public Type {
unsigned getNumParams() const { return paramTypes.size(); } ///< 获取形参数量 unsigned getNumParams() const { return paramTypes.size(); } ///< 获取形参数量
}; };
class ArrayType : public Type {
public:
// elements数组的元素类型 (例如int[3] 的 elementType 是 int)
// numElements该维度的大小 (例如int[3] 的 numElements 是 3)
static ArrayType *get(Type *elementType, unsigned numElements);
Type *getElementType() const { return elementType; }
unsigned getNumElements() const { return numElements; }
protected:
ArrayType(Type *elementType, unsigned numElements)
: Type(Kind::kArray), elementType(elementType), numElements(numElements) {}
Type *elementType;
unsigned numElements; // 当前维度的大小
};
/*! /*!
* @} * @}
*/ */
@@ -268,6 +287,51 @@ class ValueCounter {
} ///< 清空ValueCounter } ///< 清空ValueCounter
}; };
// --- Refactored ConstantValue and related classes start here ---
using ConstantValVariant = std::variant<int, float>;
// Helper for hashing std::variant
struct VariantHash {
template <class T>
std::size_t operator()(const T& val) const {
return std::hash<T>{}(val);
}
std::size_t operator()(const ConstantValVariant& v) const {
return std::visit(*this, v);
}
};
struct ConstantValueKey {
Type* type;
ConstantValVariant val;
bool operator==(const ConstantValueKey& other) const {
// Assuming Type objects are canonicalized, or add Type::isSame()
// If Type::isSame() is not available and Type objects are not canonicalized,
// this comparison might not be robust enough for structural equivalence of types.
return type == other.type && val == other.val;
}
};
struct ConstantValueHash {
std::size_t operator()(const ConstantValueKey& key) const {
std::size_t typeHash = std::hash<Type*>{}(key.type);
std::size_t valHash = VariantHash{}(key.val);
// A simple way to combine hashes
return typeHash ^ (valHash << 1);
}
};
struct ConstantValueEqual {
bool operator()(const ConstantValueKey& lhs, const ConstantValueKey& rhs) const {
// Assuming Type objects are canonicalized (e.g., Type::getIntType() always returns same pointer)
// If not, and Type::isSame() is intended, it should be added to Type class.
return lhs.type == rhs.type && lhs.val == rhs.val;
}
};
/*! /*!
* Static constants known at compile time. * Static constants known at compile time.
* *
@@ -276,45 +340,135 @@ class ValueCounter {
* `ConstantValue`并不由指令定义, 也不使用任何Value。它的类型为int/float。 * `ConstantValue`并不由指令定义, 也不使用任何Value。它的类型为int/float。
*/ */
template<class T> struct always_false : std::false_type {};
template<class T> constexpr bool always_false_v = always_false<T>::value;
class ConstantValue : public Value { class ConstantValue : public Value {
protected: protected:
/// 定义字面量类型的聚合类型 static std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> mConstantPool;
union {
int iScalar;
float fScalar;
};
protected: public:
explicit ConstantValue(int value, const std::string &name = "") : Value(Type::getIntType(), name), iScalar(value) {} explicit ConstantValue(Type* type, const std::string& name = "") : Value(type, name) {}
explicit ConstantValue(float value, const std::string &name = "") virtual ~ConstantValue() = default;
: Value(Type::getFloatType(), name), fScalar(value) {}
public: virtual size_t hash() const = 0;
static ConstantValue* get(int value); ///< 获取一个int类型的ConstValue *其值为value virtual ConstantValVariant getVal() const = 0;
static ConstantValue* get(float value); ///< 获取一个float类型的ConstValue *其值为value
public: // Static factory method to get a canonical ConstantValue from the pool
static ConstantValue* get(Type* type, ConstantValVariant val);
// Helper methods to access constant values with appropriate casting
int getInt() const { int getInt() const {
assert(isInt()); assert(getType()->isInt() && "Calling getInt() on non-integer type");
return iScalar; return std::get<int>(getVal());
} ///< 返回int类型的值 }
float getFloat() const { float getFloat() const {
assert(isFloat()); assert(getType()->isFloat() && "Calling getFloat() on non-float type");
return fScalar; return std::get<float>(getVal());
} ///< 返回float类型的值 }
template <typename T>
T getValue() const { template<typename T>
if (std::is_same<T, int>::value && isInt()) { T getVal() const {
if constexpr (std::is_same_v<T, int>) {
return getInt(); return getInt();
} } else if constexpr (std::is_same_v<T, float>) {
if (std::is_same<T, float>::value && isFloat()) {
return getFloat(); return getFloat();
} else {
// This ensures a compilation error if an unsupported type is used
static_assert(always_false_v<T>, "Unsupported type for ConstantValue::getValue()");
} }
throw std::bad_cast(); // 或者其他适当的异常处理 }
} ///< 返回值getInt和getFloat统一化整数返回整形浮点返回浮点型
virtual bool isZero() const = 0;
virtual bool isOne() const = 0;
}; };
class ConstantInteger : public ConstantValue {
int constVal;
public:
explicit ConstantInteger(Type* type, int val, const std::string& name = "")
: ConstantValue(type, name), constVal(val) {}
size_t hash() const override {
std::size_t typeHash = std::hash<Type*>{}(getType());
std::size_t valHash = std::hash<int>{}(constVal);
return typeHash ^ (valHash << 1);
}
int getInt() const { return constVal; }
ConstantValVariant getVal() const override { return constVal; }
static ConstantInteger* get(Type* type, int val);
static ConstantInteger* get(int val) { return get(Type::getIntType(), val); }
ConstantInteger* getNeg() const {
assert(getType()->isInt() && "Cannot negate non-integer constant");
return ConstantInteger::get(-constVal);
}
bool isZero() const override { return constVal == 0; }
bool isOne() const override { return constVal == 1; }
};
class ConstantFloating : public ConstantValue {
float constFVal;
public:
explicit ConstantFloating(Type* type, float val, const std::string& name = "")
: ConstantValue(type, name), constFVal(val) {}
size_t hash() const override {
std::size_t typeHash = std::hash<Type*>{}(getType());
std::size_t valHash = std::hash<float>{}(constFVal);
return typeHash ^ (valHash << 1);
}
float getFloat() const { return constFVal; }
ConstantValVariant getVal() const override { return constFVal; }
static ConstantFloating* get(Type* type, float val);
static ConstantFloating* get(float val) { return get(Type::getFloatType(), val); }
ConstantFloating* getNeg() const {
assert(getType()->isFloat() && "Cannot negate non-float constant");
return ConstantFloating::get(-constFVal);
}
bool isZero() const override { return constFVal == 0.0f; }
bool isOne() const override { return constFVal == 1.0f; }
};
class UndefinedValue : public ConstantValue {
private:
static std::unordered_map<Type*, UndefinedValue*> UndefValues;
protected:
explicit UndefinedValue(Type* type, const std::string& name = "")
: ConstantValue(type, name) {
assert(!type->isVoid() && "Cannot create UndefinedValue of void type!");
}
public:
static UndefinedValue* get(Type* type);
size_t hash() const override {
return std::hash<Type*>{}(getType());
}
ConstantValVariant getVal() const override {
if (getType()->isInt()) {
return 0; // Return 0 for undefined integer
} else if (getType()->isFloat()) {
return 0.0f; // Return 0.0f for undefined float
}
assert(false && "UndefinedValue has unexpected type for getValue()");
return 0; // Should not be reached
}
bool isZero() const override { return false; }
bool isOne() const override { return false; }
};
// --- End of refactored ConstantValue and related classes ---
class Instruction; class Instruction;
class Function; class Function;
class BasicBlock; class BasicBlock;
@@ -467,49 +621,6 @@ class User : public Value {
void setOperand(unsigned index, Value *value); ///< 设置操作数 void setOperand(unsigned index, Value *value); ///< 设置操作数
}; };
class GetSubArrayInst;
/**
* 左值 具有地址的对象
*/
class LVal {
friend class GetSubArrayInst;
protected:
LVal *fatherLVal{}; ///< 父左值
std::list<std::unique_ptr<LVal>> childrenLVals; ///< 子左值
GetSubArrayInst *defineInst{}; /// 定义该左值的GetSubArray指令
protected:
LVal() = default;
public:
virtual ~LVal() = default;
virtual std::vector<Value *> getLValDims() const = 0; ///< 获取左值的维度
virtual unsigned getLValNumDims() const = 0; ///< 获取左值的维度数量
public:
LVal* getFatherLVal() const { return fatherLVal; } ///< 获取父左值
const std::list<std::unique_ptr<LVal>>& getChildrenLVals() const {
return childrenLVals;
} ///< 获取子左值列表
LVal* getAncestorLVal() const {
auto curLVal = const_cast<LVal *>(this);
while (curLVal->getFatherLVal() != nullptr) {
curLVal = curLVal->getFatherLVal();
}
return curLVal;
} ///< 获取祖先左值
void setFatherLVal(LVal *father) { fatherLVal = father; } ///< 设置父左值
void setDefineInst(GetSubArrayInst *inst) { defineInst = inst; } ///< 设置定义指令
void addChild(LVal *child) { childrenLVals.emplace_back(child); } ///< 添加子左值
void removeChild(LVal *child) {
auto iter = std::find_if(childrenLVals.begin(), childrenLVals.end(),
[child](const std::unique_ptr<LVal> &ptr) { return ptr.get() == child; });
childrenLVals.erase(iter);
} ///< 移除子左值
GetSubArrayInst* getDefineInst() const { return defineInst; } ///< 获取定义指令
};
/*! /*!
* Base of all concrete instruction types. * Base of all concrete instruction types.
*/ */
@@ -559,15 +670,15 @@ class Instruction : public User {
kAlloca = 0x1UL << 33, kAlloca = 0x1UL << 33,
kLoad = 0x1UL << 34, kLoad = 0x1UL << 34,
kStore = 0x1UL << 35, kStore = 0x1UL << 35,
kLa = 0x1UL << 36, kGetElementPtr = 0x1UL << 36,
kMemset = 0x1UL << 37, kMemset = 0x1UL << 37,
kGetSubArray = 0x1UL << 38, // kGetSubArray = 0x1UL << 38,
// constant // Constant Kind removed as Constants are now Values, not Instructions.
kConstant = 0x1UL << 37, // kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
// phi // phi
kPhi = 0x1UL << 39, kPhi = 0x1UL << 39,
kBitItoF = 0x1UL << 40, kBitItoF = 0x1UL << 40,
kBitFtoI = 0x1UL << 41 kBitFtoI = 0x1UL << 41,
}; };
protected: protected:
@@ -658,14 +769,12 @@ public:
return "Load"; return "Load";
case kStore: case kStore:
return "Store"; return "Store";
case kLa: case kGetElementPtr:
return "La"; return "GetElementPtr";
case kMemset: case kMemset:
return "Memset"; return "Memset";
case kPhi: case kPhi:
return "Phi"; return "Phi";
case kGetSubArray:
return "GetSubArray";
default: default:
return "Unknown"; return "Unknown";
} }
@@ -718,9 +827,8 @@ public:
bool isAlloca() const { return kind == kAlloca; } bool isAlloca() const { return kind == kAlloca; }
bool isLoad() const { return kind == kLoad; } bool isLoad() const { return kind == kLoad; }
bool isStore() const { return kind == kStore; } bool isStore() const { return kind == kStore; }
bool isLa() const { return kind == kLa; } bool isGetElementPtr() const { return kind == kGetElementPtr; }
bool isMemset() const { return kind == kMemset; } bool isMemset() const { return kind == kMemset; }
bool isGetSubArray() const { return kind == kGetSubArray; }
bool isCall() const { return kind == kCall; } bool isCall() const { return kind == kCall; }
bool isReturn() const { return kind == kReturn; } bool isReturn() const { return kind == kReturn; }
bool isDefine() const { bool isDefine() const {
@@ -732,47 +840,54 @@ public:
class Function; class Function;
//! Function call. //! Function call.
class LaInst : public Instruction {
friend class Function;
friend class IRBuilder;
protected:
explicit LaInst(Value *pointer, const std::vector<Value *> &indices = {}, BasicBlock *parent = nullptr,
const std::string &name = "")
: Instruction(Kind::kLa, pointer->getType(), parent, name) {
assert(pointer);
addOperand(pointer);
addOperands(indices);
}
public:
unsigned getNumIndices() const { return getNumOperands() - 1; } ///< 获取索引长度
Value* getPointer() const { return getOperand(0); } ///< 获取目标变量的Value指针
auto getIndices() const { return make_range(std::next(operand_begin()), operand_end()); } ///< 获取索引列表
Value* getIndex(unsigned index) const { return getOperand(index + 1); } ///< 获取位置为index的索引分量
};
class PhiInst : public Instruction { class PhiInst : public Instruction {
friend class IRBuilder; friend class IRBuilder;
friend class Function; friend class Function;
friend class SysySSA;
protected: protected:
Value *map_val; // Phi的旧值
PhiInst(Type *type, Value *lhs, const std::vector<Value *> &rhs, Value *mval, BasicBlock *parent, std::unordered_map<BasicBlock *, Value *> blk2val; ///< 存储每个基本块对应的值
unsigned vsize; ///< 存储值的数量
PhiInst(Type *type,
const std::vector<Value *> &rhs = {},
const std::vector<BasicBlock*> &Blocks = {},
BasicBlock *parent = nullptr,
const std::string &name = "") const std::string &name = "")
: Instruction(Kind::kPhi, type, parent, name) { : Instruction(Kind::kPhi, type, parent, name), vsize(rhs.size()) {
map_val = mval; assert(rhs.size() == Blocks.size() && "PhiInst: rhs and Blocks must have the same size");
addOperand(lhs); for(size_t i = 0; i < rhs.size(); ++i) {
addOperands(rhs); addOperand(rhs[i]);
blk2val[Blocks[i]] = rhs[i];
}
} }
public: public:
Value* getMapVal() { return map_val; } Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
Value* getPointer() const { return getOperand(0); } BasicBlock* getBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
Value* getvalfromBlk(BasicBlock* blk);
BasicBlock* getBlkfromVal(Value* val);
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
void addIncoming(Value *value, BasicBlock *block) {
assert(value && block && "PhiInst: value and block must not be null");
addOperand(value);
addOperand(block);
blk2val[block] = value;
vsize++;
} ///< 添加传入值和对应的基本块
void delValue(Value* val);
void delBlk(BasicBlock* blk);
void replaceBlk(BasicBlock* newBlk, unsigned k);
void replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk);
void refreshB2VMap();
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); } auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
Value* getValue(unsigned index) const { return getOperand(index + 1); }
}; };
@@ -884,7 +999,7 @@ public:
} }
} ///< 根据指令类型进行二元计算eval template模板实现 } ///< 根据指令类型进行二元计算eval template模板实现
static BinaryInst* create(Kind kind, Type *type, Value *lhs, Value *rhs, BasicBlock *parent, const std::string &name = "") { static BinaryInst* create(Kind kind, Type *type, Value *lhs, Value *rhs, BasicBlock *parent, const std::string &name = "") {
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象所以写了个public的方法。 // 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
return new BinaryInst(kind, type, lhs, rhs, parent, name); return new BinaryInst(kind, type, lhs, rhs, parent, name);
} }
}; // class BinaryInst }; // class BinaryInst
@@ -972,7 +1087,7 @@ public:
}; // class CondBrInst }; // class CondBrInst
//! Allocate memory for stack variables, used for non-global variable declartion //! Allocate memory for stack variables, used for non-global variable declartion
class AllocaInst : public Instruction , public LVal { class AllocaInst : public Instruction {
friend class IRBuilder; friend class IRBuilder;
friend class Function; friend class Function;
protected: protected:
@@ -983,14 +1098,6 @@ protected:
} }
public: public:
std::vector<Value *> getLValDims() const override {
std::vector<Value *> dims;
for (const auto &dim : getOperands()) {
dims.emplace_back(dim->getValue());
}
return dims;
} ///< 获取作为左值的维度数组
unsigned getLValNumDims() const override { return getNumOperands(); }
int getNumDims() const { return getNumOperands(); } int getNumDims() const { return getNumOperands(); }
auto getDims() const { return getOperands(); } auto getDims() const { return getOperands(); }
@@ -999,37 +1106,40 @@ public:
}; // class AllocaInst }; // class AllocaInst
class GetSubArrayInst : public Instruction { class GetElementPtrInst : public Instruction {
friend class IRBuilder; friend class IRBuilder; // 如果您有IRBuilder来创建指令需要friend
friend class Function;
public: protected:
GetSubArrayInst(LVal *fatherArray, LVal *childArray, const std::vector<Value *> &indices, // GEP的构造函数
// resultType: GEP计算出的地址的类型 (通常是指向目标元素类型的指针)
// basePointer: 基指针 (第一个操作数)
// indices: 索引列表 (后续操作数)
GetElementPtrInst(Value *basePointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "") BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(Kind::kGetSubArray, Type::getVoidType(), parent, name) { : Instruction(Kind::kGetElementPtr, basePointer->getType(), parent, name) {
auto predicate = [childArray](const std::unique_ptr<LVal> &child) -> bool { return child.get() == childArray; }; assert(basePointer && "GEP base pointer cannot be null!");
if (std::find_if(fatherArray->childrenLVals.begin(), fatherArray->childrenLVals.end(), predicate) == // TODO : 安全检查
fatherArray->childrenLVals.end()) { assert(basePointer->getType()->isPointer() );
fatherArray->childrenLVals.emplace_back(childArray); addOperand(basePointer); // 第一个操作数是基指针
} addOperands(indices); // 随后的操作数是索引
childArray->fatherLVal = fatherArray;
childArray->defineInst = this;
auto fatherArrayValue = dynamic_cast<Value *>(fatherArray);
auto childArrayValue = dynamic_cast<Value *>(childArray);
assert(fatherArrayValue);
assert(childArrayValue);
addOperand(fatherArrayValue);
addOperand(childArrayValue);
addOperands(indices);
} }
public: public:
Value* getFatherArray() const { return getOperand(0); } ///< 获取父数组 Value* getBasePointer() const { return getOperand(0); }
Value* getChildArray() const { return getOperand(1); } ///< 获取子数组 unsigned getNumIndices() const { return getNumOperands() - 1; }
LVal* getFatherLVal() const { return dynamic_cast<LVal *>(getOperand(0)); } ///< 获取父左值 auto getIndices() const { return make_range(std::next(operand_begin()), operand_end());}
LVal* getChildLVal() const { return dynamic_cast<LVal *>(getOperand(1)); } ///< 获取子左值 Value* getIndex(unsigned index) const {
auto getIndices() const { return make_range(std::next(operand_begin(), 2), operand_end()); } ///< 获取索引 assert(index < getNumIndices() && "Index out of bounds for GEP!");
unsigned getNumIndices() const { return getNumOperands() - 2; } ///< 获取索引数量 return getOperand(index + 1);
}
// 静态工厂方法用于创建GEP指令 (如果需要外部直接创建而非通过IRBuilder)
static GetElementPtrInst* create(Type *resultType, Value *basePointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "") {
return new GetElementPtrInst(basePointer, indices, parent, name);
}
}; };
//! Load a value from memory address specified by a pointer value //! Load a value from memory address specified by a pointer value
@@ -1053,22 +1163,7 @@ public:
return make_range(std::next(operand_begin()), operand_end()); return make_range(std::next(operand_begin()), operand_end());
} }
Value* getIndex(int index) const { return getOperand(index + 1); } Value* getIndex(int index) const { return getOperand(index + 1); }
std::list<Value *> getAncestorIndices() const {
std::list<Value *> indices;
for (const auto &index : getIndices()) {
indices.emplace_back(index->getValue());
}
auto curPointer = dynamic_cast<LVal *>(getPointer());
while (curPointer->getFatherLVal() != nullptr) {
auto inserter = std::next(indices.begin());
for (const auto &index : curPointer->getDefineInst()->getIndices()) {
indices.insert(inserter, index->getValue());
}
curPointer = curPointer->getFatherLVal();
}
return indices;
} ///< 获取相对于祖先数组的索引列表
}; // class LoadInst }; // class LoadInst
//! Store a value to memory address specified by a pointer value //! Store a value to memory address specified by a pointer value
@@ -1094,22 +1189,6 @@ public:
return make_range(std::next(operand_begin(), 2), operand_end()); return make_range(std::next(operand_begin(), 2), operand_end());
} }
Value* getIndex(int index) const { return getOperand(index + 2); } Value* getIndex(int index) const { return getOperand(index + 2); }
std::list<Value *> getAncestorIndices() const {
std::list<Value *> indices;
for (const auto &index : getIndices()) {
indices.emplace_back(index->getValue());
}
auto curPointer = dynamic_cast<LVal *>(getPointer());
while (curPointer->getFatherLVal() != nullptr) {
auto inserter = std::next(indices.begin());
for (const auto &index : curPointer->getDefineInst()->getIndices()) {
indices.insert(inserter, index->getValue());
}
curPointer = curPointer->getFatherLVal();
}
return indices;
} ///< 获取相对于祖先数组的索引列表
}; // class StoreInst }; // class StoreInst
@@ -1211,7 +1290,7 @@ protected:
}; };
//! Global value declared at file scope //! Global value declared at file scope
class GlobalValue : public User, public LVal { class GlobalValue : public User {
friend class Module; friend class Module;
protected: protected:
@@ -1230,28 +1309,21 @@ protected:
if (init.size() == 0) { if (init.size() == 0) {
unsigned num = 1; unsigned num = 1;
for (unsigned i = 0; i < numDims; i++) { for (unsigned i = 0; i < numDims; i++) {
num *= dynamic_cast<ConstantValue *>(dims[i])->getInt(); // Assume dims elements are ConstantInteger and cast appropriately
auto dim_val = dynamic_cast<ConstantInteger*>(dims[i]);
assert(dim_val && "GlobalValue dims must be constant integers");
num *= dim_val->getInt();
} }
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) { if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
init.push_back(ConstantValue::get(0.0F), num); init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
} else { } else {
init.push_back(ConstantValue::get(0), num); init.push_back(ConstantInteger::get(0), num); // Use new constant factory
} }
} }
initValues = init; initValues = init;
} }
public: public:
unsigned getLValNumDims() const override { return numDims; } ///< 获取作为左值的维度数量
std::vector<Value *> getLValDims() const override {
std::vector<Value *> dims;
for (const auto &dim : getOperands()) {
dims.emplace_back(dim->getValue());
}
return dims;
} ///< 获取作为左值的维度列表
unsigned getNumDims() const { return numDims; } ///< 获取维度数量 unsigned getNumDims() const { return numDims; } ///< 获取维度数量
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度 Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
auto getDims() const { return getOperands(); } ///< 获取维度列表 auto getDims() const { return getOperands(); } ///< 获取维度列表
@@ -1261,8 +1333,11 @@ public:
Value* getByIndices(const std::vector<Value *> &indices) const { Value* getByIndices(const std::vector<Value *> &indices) const {
int index = 0; int index = 0;
for (size_t i = 0; i < indices.size(); i++) { for (size_t i = 0; i < indices.size(); i++) {
index = dynamic_cast<ConstantValue *>(getDim(i))->getInt() * index + // Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
dynamic_cast<ConstantValue *>(indices[i])->getInt(); auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
assert(dim_val && idx_val && "Dims and indices must be constant integers");
index = dim_val->getInt() * index + idx_val->getInt();
} }
return getByIndex(index); return getByIndex(index);
} ///< 通过多维索引indices获取初始值 } ///< 通过多维索引indices获取初始值
@@ -1270,7 +1345,7 @@ public:
}; // class GlobalValue }; // class GlobalValue
class ConstantVariable : public User, public LVal { class ConstantVariable : public User {
friend class Module; friend class Module;
protected: protected:
@@ -1289,22 +1364,16 @@ class ConstantVariable : public User, public LVal {
} }
public: public:
unsigned getLValNumDims() const override { return numDims; } ///< 获取作为左值的维度数量
std::vector<Value *> getLValDims() const override {
std::vector<Value *> dims;
for (const auto &dim : getOperands()) {
dims.emplace_back(dim->getValue());
}
return dims;
} ///< 获取作为左值的维度列表
Value* getByIndex(unsigned index) const { return initValues.getValue(index); } ///< 通过一维位置index获取值 Value* getByIndex(unsigned index) const { return initValues.getValue(index); } ///< 通过一维位置index获取值
Value* getByIndices(const std::vector<Value *> &indices) const { Value* getByIndices(const std::vector<Value *> &indices) const {
int index = 0; int index = 0;
// 计算偏移量 // 计算偏移量
for (size_t i = 0; i < indices.size(); i++) { for (size_t i = 0; i < indices.size(); i++) {
index = dynamic_cast<ConstantValue *>(getDim(i))->getInt() * index + // Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
dynamic_cast<ConstantValue *>(indices[i])->getInt(); auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
assert(dim_val && idx_val && "Dims and indices must be constant integers");
index = dim_val->getInt() * index + idx_val->getInt();
} }
return getByIndex(index); return getByIndex(index);

View File

@@ -280,46 +280,6 @@ class IRBuilder {
block->getInstructions().emplace(position, inst); block->getInstructions().emplace(position, inst);
return inst; return inst;
} ///< 创建load指令 } ///< 创建load指令
LaInst * createLaInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
std::string newName;
if (name.empty()) {
std::stringstream ss;
ss << tmpIndex;
newName = ss.str();
tmpIndex++;
} else {
newName = name;
}
auto inst = new LaInst(pointer, indices, block, newName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建la指令
GetSubArrayInst * createGetSubArray(LVal *fatherArray, const std::vector<Value *> &indices, const std::string &name = "") {
assert(fatherArray->getLValNumDims() > indices.size());
std::vector<Value *> subDims;
auto dims = fatherArray->getLValDims();
auto iter = std::next(dims.begin(), indices.size());
while (iter != dims.end()) {
subDims.emplace_back(*iter);
iter++;
}
std::string childArrayName;
std::stringstream ss;
ss << "A"
<< "%" << tmpIndex;
childArrayName = ss.str();
tmpIndex++;
auto fatherArrayValue = dynamic_cast<Value *>(fatherArray);
auto childArray = new AllocaInst(fatherArrayValue->getType(), subDims, block, childArrayName);
auto inst = new GetSubArrayInst(fatherArray, childArray, indices, block, childArrayName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建获取部分数组指令
MemsetInst * createMemsetInst(Value *pointer, Value *begin, Value *size, Value *value, const std::string &name = "") { MemsetInst * createMemsetInst(Value *pointer, Value *begin, Value *size, Value *value, const std::string &name = "") {
auto inst = new MemsetInst(pointer, begin, size, value, block, name); auto inst = new MemsetInst(pointer, begin, size, value, block, name);
assert(inst); assert(inst);
@@ -333,17 +293,31 @@ class IRBuilder {
block->getInstructions().emplace(position, inst); block->getInstructions().emplace(position, inst);
return inst; return inst;
} ///< 创建store指令 } ///< 创建store指令
PhiInst * createPhiInst(Type *type, Value *lhs, BasicBlock *parent, const std::string &name = "") { PhiInst * createPhiInst(Type *type, const std::vector<Value*> &vals = {}, const std::vector<BasicBlock*> &blks = {}, const std::string &name = "") {
auto predNum = parent->getNumPredecessors(); auto predNum = block->getNumPredecessors();
std::vector<Value *> rhs; auto inst = new PhiInst(type, vals, blks, block, name);
for (size_t i = 0; i < predNum; i++) {
rhs.push_back(lhs);
}
auto inst = new PhiInst(type, lhs, rhs, lhs, parent, name);
assert(inst); assert(inst);
parent->getInstructions().emplace(parent->begin(), inst); block->getInstructions().emplace(block->begin(), inst);
return inst; return inst;
} ///< 创建Phi指令 } ///< 创建Phi指令
GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
const std::vector<Value *> &indices = {},
const std::string &name = "") {
std::string newName;
if (name.empty()) {
std::stringstream ss;
ss << tmpIndex;
newName = ss.str();
tmpIndex++;
} else {
newName = name;
}
auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
}
}; };
} // namespace sysy } // namespace sysy

View File

@@ -1,59 +1,79 @@
#pragma once // 假设 Mem2Reg.h 看起来像这样 (你需要根据实际情况调整)
#ifndef SYSY_MEM2REG_H
#define SYSY_MEM2REG_H
#include <list> #include <vector>
#include <memory>
#include <stack>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <stack>
#include <queue> // For computeIteratedDomFrontiers
// Include your IR and analysis headers
#include "IR.h" #include "IR.h"
#include "IRBuilder.h" #include "IRBuilder.h"
#include "SysYIRAnalyser.h" #include "SysYIRAnalyser.h"
#include "SysYIROptUtils.h"
namespace sysy { namespace sysy {
/**
* 实现静态单变量赋值核心类 mem2reg
*/
class Mem2Reg { class Mem2Reg {
private: private:
Module *pModule; Module* pModule;
IRBuilder *pBuilder; IRBuilder* pBuilder;
ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析 ControlFlowAnalysis* controlFlowAnalysis;
ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析 ActiveVarAnalysis* activeVarAnalysis;
DataFlowAnalysisUtils dataFlowAnalysisUtils; DataFlowAnalysisUtils dataFlowAnalysisUtils; // If this is part of Mem2Reg or an external helper
public: public:
Mem2Reg(Module *pMoudle, IRBuilder *pBuilder, Mem2Reg(Module* module, IRBuilder* builder, ControlFlowAnalysis* cfa, ActiveVarAnalysis* ava)
ControlFlowAnalysis *pCFA = nullptr, ActiveVarAnalysis *pAVA = nullptr) : : pModule(module), pBuilder(builder), controlFlowAnalysis(cfa), activeVarAnalysis(ava) {}
pModule(pMoudle), pBuilder(pBuilder), controlFlowAnalysis(pCFA), activeVarAnalysis(pAVA), dataFlowAnalysisUtils() // Constructor initializes members
{} // 初始化函数 void run();
void mem2regPipeline(); ///< mem2reg // --- 新增的私有成员变量和方法用于SSA转换上下文 ---
// 这是核心,用于存储 SSA 转换过程中的状态
std::vector<AllocaInst*> currentFunctionAllocas; // 当前函数中所有可提升的 alloca
// alloca -> set of BasicBlocks where it's defined (stored into)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaDefsBlock;
// alloca -> set of BasicBlocks where it's used (loaded from)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaUsesBlock;
private: // BasicBlock -> Map of (PhiInst, Original AllocaInst)
// 用于在 rename 阶段通过 phi 指令找到它代表的原始 alloca
std::unordered_map<BasicBlock*, std::unordered_map<PhiInst*, AllocaInst*>> phiMap;
std::vector<PhiInst*> allPhiInstructions; // 收集所有创建的 Phi 指令以便后续简化和清理
// phi节点的插入需要计算IDF // --- 核心 SSA 转换辅助函数 ---
std::unordered_set<BasicBlock *> computeIterDf(const std::unordered_set<BasicBlock *> &blocks); ///< 计算定义块集合的迭代支配边界 // 计算给定定义块集合的迭代支配边界
std::unordered_set<BasicBlock*> computeIteratedDomFrontiers(const std::unordered_set<BasicBlock*>& blocks);
auto computeValue2Blocks() -> void; ///< 计算value2block的映射(不包括数组和global) // 分析一个 alloca 的所有 uses填充 allocaDefsBlock 和 allocaUsesBlock
void allocaAnalysis(AllocaInst* alloca);
auto preOptimize1() -> void; ///< llvm memtoreg预优化1: 删除不含load的alloc和store // 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型)
auto preOptimize2() -> void; ///< llvm memtoreg预优化2: 针对某个变量的Defblocks只有一个块的情况 bool is_promoted(AllocaInst* alloca);
auto preOptimize3() -> void; ///< llvm memtoreg预优化3: 针对某个变量的所有读写都在同一个块中的情况
auto insertPhi() -> void; ///< 为所有变量的迭代支配边界插入phi结点 // 在迭代支配边界插入 Phi 指令
void insertPhiNodes(Function* func);
auto rename(BasicBlock *block, std::unordered_map<Value *, int> &count, // 递归地重命名基本块中的变量并填充 Phi 指令
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void; ///< 单个块的重命名 // 这里的 `count` 和 `stacks` 是临时的,用于 DFS 过程中传递状态
auto renameAll() -> void; ///< 重命名所有块 void renameBlock(BasicBlock* block,
std::unordered_map<AllocaInst*, Value*>& currentIncomings,
std::unordered_set<BasicBlock*>& visitedBlocks); // 修改为传递 map 和 set
// private helper function. // 简化冗余的 Phi 指令 (当所有输入都相同时)
private: void simplifyphi(PhiInst* phi);
auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引
auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block, // 获取前驱块在后继块前驱列表中的索引,用于 Phi 指令入边
std::list<std::unique_ptr<Instruction>> &instrs) -> void; ///< 消除级联关系 int getPredIndex(BasicBlock* pred, BasicBlock* succ);
auto isGlobal(Value *val) -> bool; ///< 判断是否是全局变量
auto isArr(Value *val) -> bool; ///< 判断是否是数组 // --- Mem2Reg 的主要工作流函数 ---
auto usedelete(Instruction *instr) -> void; ///< 删除指令相关的value-use-user关系 // 对单个函数执行内存到寄存器的提升
bool promoteMemoryToRegisters(Function* func);
}; };
} // namespace sysy } // namespace sysy
#endif // SYSY_MEM2REG_H

View File

@@ -0,0 +1,32 @@
#ifndef RISCV64_ASMPRINTER_H
#define RISCV64_ASMPRINTER_H
#include "RISCv64LLIR.h"
#include <iostream>
namespace sysy {
class RISCv64AsmPrinter {
public:
RISCv64AsmPrinter(MachineFunction* mfunc);
// 主入口
void run(std::ostream& os);
private:
// 打印各个部分
void printPrologue();
void printEpilogue();
void printBasicBlock(MachineBasicBlock* mbb);
void printInstruction(MachineInstr* instr);
// 辅助函数
std::string regToString(PhysicalReg reg);
void printOperand(MachineOperand* op);
MachineFunction* MFunc;
std::ostream* OS;
};
} // namespace sysy
#endif // RISCV64_ASMPRINTER_H

View File

@@ -3,118 +3,23 @@
#include "IR.h" #include "IR.h"
#include <string> #include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <iostream>
#include <functional> // For std::function
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy { namespace sysy {
// RISCv64CodeGen 现在是一个高层驱动器
class RISCv64CodeGen { class RISCv64CodeGen {
public: public:
enum class PhysicalReg {
ZERO, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6,
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31
};
// Move DAGNode and RegAllocResult to public section
struct DAGNode {
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR, UNARY };
NodeKind kind;
Value* value = nullptr; // For IR Value
std::string inst; // Generated RISC-V instruction(s) for this node
std::string result_vreg; // Virtual register assigned to this node's result
std::vector<DAGNode*> operands;
std::vector<DAGNode*> users; // For debugging and potentially optimizations
DAGNode(NodeKind k) : kind(k) {}
// Debugging / helper
std::string getNodeKindString() const {
switch (kind) {
case CONSTANT: return "CONSTANT";
case LOAD: return "LOAD";
case STORE: return "STORE";
case BINARY: return "BINARY";
case CALL: return "CALL";
case RETURN: return "RETURN";
case BRANCH: return "BRANCH";
case ALLOCA_ADDR: return "ALLOCA_ADDR";
case UNARY: return "UNARY";
default: return "UNKNOWN";
}
}
};
struct RegAllocResult {
std::map<std::string, PhysicalReg> vreg_to_preg; // Virtual register to Physical Register mapping
std::map<Value*, int> stack_map; // Value (AllocaInst) to stack offset
int stack_size = 0; // Total stack frame size for locals and spills
};
RISCv64CodeGen(Module* mod) : module(mod) {} RISCv64CodeGen(Module* mod) : module(mod) {}
// 唯一的公共入口点
std::string code_gen(); std::string code_gen();
std::string module_gen();
std::string function_gen(Function* func);
// 修改 basicBlock_gen 的声明,添加 int block_idx 参数
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx);
// DAG related
std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb);
void select_instructions(DAGNode* node, const RegAllocResult& alloc);
// 改变 emit_instructions 的参数,使其可以直接添加汇编指令到 main ss
void emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set<DAGNode*>& emitted_nodes);
// Register Allocation related
std::map<Instruction*, std::set<std::string>> liveness_analysis(Function* func);
std::map<std::string, std::set<std::string>> build_interference_graph(
const std::map<Instruction*, std::set<std::string>>& live_sets);
void color_graph(std::map<std::string, PhysicalReg>& vreg_to_preg,
const std::map<std::string, std::set<std::string>>& interference_graph);
RegAllocResult register_allocation(Function* func);
void eliminate_phi(Function* func); // Phi elimination is typically done before DAG building
// Utility
std::string reg_to_string(PhysicalReg reg);
void print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name);
private: private:
static const std::vector<PhysicalReg> allocable_regs; // 模块级代码生成
std::map<Value*, std::string> value_vreg_map; // Maps IR Value* to its virtual register name std::string module_gen();
// 函数级代码生成 (实现新的流水线)
std::string function_gen(Function* func);
Module* module; Module* module;
int vreg_counter = 0; // Counter for unique virtual register names
int alloca_offset_counter = 0; // Counter for alloca offsets
// 新增一个成员变量来存储当前函数的所有 DAGNode以确保其生命周期贯穿整个函数代码生成
// 这样可以在多个 BasicBlock_gen 调用中访问到完整的 DAG 节点
std::vector<std::unique_ptr<DAGNode>> current_function_dag_nodes;
// 为空标签定义一个伪名称前缀,加上块索引以确保唯一性
const std::string ENTRY_BLOCK_PSEUDO_NAME = "entry_block_";
// !!! 修改get_operand_node 辅助函数现在需要传入 value_to_node 和 nodes_storage 的引用
// 因为它们是 build_dag 局部管理的
DAGNode* get_operand_node(
Value* val_ir,
std::map<Value*, DAGNode*>& value_to_node,
std::vector<std::unique_ptr<DAGNode>>& nodes_storage
);
// !!! 新增create_node 辅助函数也需要传入 value_to_node 和 nodes_storage 的引用
// 并且它应该不再是 lambda而是一个真正的成员函数
DAGNode* create_node(
DAGNode::NodeKind kind,
Value* val,
std::map<Value*, DAGNode*>& value_to_node,
std::vector<std::unique_ptr<DAGNode>>& nodes_storage
);
std::vector<std::unique_ptr<Instruction>> temp_instructions_storage; // 用于存储 build_dag 中创建的临时 BinaryInst
}; };
} // namespace sysy } // namespace sysy

49
src/include/RISCv64ISel.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef RISCV64_ISEL_H
#define RISCV64_ISEL_H
#include "RISCv64LLIR.h"
namespace sysy {
class RISCv64ISel {
public:
RISCv64ISel();
// 模块主入口将一个高层IR函数转换为底层LLIR函数
std::unique_ptr<MachineFunction> runOnFunction(Function* func);
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; }
private:
// DAG节点定义作为ISel的内部实现细节
struct DAGNode;
// 指令选择主流程
void select();
// 为单个基本块生成指令
void selectBasicBlock(BasicBlock* bb);
// 核心函数为DAG节点选择并生成MachineInstr
void selectNode(DAGNode* node);
// DAG 构建相关函数 (从原RISCv64Backend迁移)
std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb);
DAGNode* get_operand_node(Value* val_ir, std::map<Value*, DAGNode*>&, std::vector<std::unique_ptr<DAGNode>>&);
DAGNode* create_node(int kind, Value* val, std::map<Value*, DAGNode*>&, std::vector<std::unique_ptr<DAGNode>>&);
// 状态
Function* F; // 当前处理的高层IR函数
std::unique_ptr<MachineFunction> MFunc; // 正在构建的底层LLIR函数
MachineBasicBlock* CurMBB; // 当前正在处理的机器基本块
// 映射关系
std::map<Value*, unsigned> vreg_map;
std::map<const BasicBlock*, MachineBasicBlock*> bb_map;
unsigned vreg_counter;
int local_label_counter;
};
} // namespace sysy
#endif // RISCV64_ISEL_H

200
src/include/RISCv64LLIR.h Normal file
View File

@@ -0,0 +1,200 @@
#ifndef RISCV64_LLIR_H
#define RISCV64_LLIR_H
#include "IR.h" // 确保包含了您自己的IR头文件
#include <string>
#include <vector>
#include <memory>
#include <cstdint>
#include <map>
// 前向声明,避免循环引用
namespace sysy {
class Function;
class RISCv64ISel;
}
namespace sysy {
// 物理寄存器定义
enum class PhysicalReg {
ZERO, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6,
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31
};
// RISC-V 指令操作码枚举
enum class RVOpcodes {
// 算术指令
ADD, ADDI, ADDW, ADDIW, SUB, SUBW, MUL, MULW, DIV, DIVW, REM, REMW,
// 逻辑指令
XOR, XORI, OR, ORI, AND, ANDI,
// 移位指令
SLL, SLLI, SLLW, SLLIW, SRL, SRLI, SRLW, SRLIW, SRA, SRAI, SRAW, SRAIW,
// 比较指令
SLT, SLTI, SLTU, SLTIU,
// 内存访问指令
LW, LH, LB, LWU, LHU, LBU, SW, SH, SB, LD, SD,
// 控制流指令
J, JAL, JALR, RET,
BEQ, BNE, BLT, BGE, BLTU, BGEU,
// 伪指令
LI, LA, MV, NEG, NEGW, SEQZ, SNEZ,
// 函数调用
CALL,
// 特殊标记,非指令
LABEL,
// 新增伪指令,用于解耦栈帧处理
FRAME_LOAD, // 从栈帧加载 (AllocaInst)
FRAME_STORE, // 保存到栈帧 (AllocaInst)
};
class MachineOperand;
class RegOperand;
class ImmOperand;
class LabelOperand;
class MemOperand;
class MachineInstr;
class MachineBasicBlock;
class MachineFunction;
// 操作数基类
class MachineOperand {
public:
enum OperandKind { KIND_REG, KIND_IMM, KIND_LABEL, KIND_MEM };
MachineOperand(OperandKind kind) : kind(kind) {}
virtual ~MachineOperand() = default;
OperandKind getKind() const { return kind; }
private:
OperandKind kind;
};
// 寄存器操作数
class RegOperand : public MachineOperand {
public:
// 构造虚拟寄存器
RegOperand(unsigned vreg_num)
: MachineOperand(KIND_REG), vreg_num(vreg_num), is_virtual(true) {}
// 构造物理寄存器
RegOperand(PhysicalReg preg)
: MachineOperand(KIND_REG), preg(preg), is_virtual(false) {}
bool isVirtual() const { return is_virtual; }
unsigned getVRegNum() const { return vreg_num; }
PhysicalReg getPReg() const { return preg; }
void setPReg(PhysicalReg new_preg) {
preg = new_preg;
is_virtual = false;
}
private:
unsigned vreg_num = 0;
PhysicalReg preg = PhysicalReg::ZERO;
bool is_virtual;
};
// 立即数操作数
class ImmOperand : public MachineOperand {
public:
ImmOperand(int64_t value) : MachineOperand(KIND_IMM), value(value) {}
int64_t getValue() const { return value; }
private:
int64_t value;
};
// 标签操作数
class LabelOperand : public MachineOperand {
public:
LabelOperand(const std::string& name) : MachineOperand(KIND_LABEL), name(name) {}
const std::string& getName() const { return name; }
private:
std::string name;
};
// 内存操作数, 表示 offset(base_reg)
class MemOperand : public MachineOperand {
public:
MemOperand(std::unique_ptr<RegOperand> base, std::unique_ptr<ImmOperand> offset)
: MachineOperand(KIND_MEM), base(std::move(base)), offset(std::move(offset)) {}
RegOperand* getBase() const { return base.get(); }
ImmOperand* getOffset() const { return offset.get(); }
private:
std::unique_ptr<RegOperand> base;
std::unique_ptr<ImmOperand> offset;
};
// 机器指令
class MachineInstr {
public:
MachineInstr(RVOpcodes opcode) : opcode(opcode) {}
RVOpcodes getOpcode() const { return opcode; }
const std::vector<std::unique_ptr<MachineOperand>>& getOperands() const { return operands; }
std::vector<std::unique_ptr<MachineOperand>>& getOperands() { return operands; }
void addOperand(std::unique_ptr<MachineOperand> operand) {
operands.push_back(std::move(operand));
}
private:
RVOpcodes opcode;
std::vector<std::unique_ptr<MachineOperand>> operands;
};
// 机器基本块
class MachineBasicBlock {
public:
MachineBasicBlock(const std::string& name, MachineFunction* parent)
: name(name), parent(parent) {}
const std::string& getName() const { return name; }
MachineFunction* getParent() const { return parent; }
const std::vector<std::unique_ptr<MachineInstr>>& getInstructions() const { return instructions; }
std::vector<std::unique_ptr<MachineInstr>>& getInstructions() { return instructions; }
void addInstruction(std::unique_ptr<MachineInstr> instr) {
instructions.push_back(std::move(instr));
}
std::vector<MachineBasicBlock*> successors;
std::vector<MachineBasicBlock*> predecessors;
private:
std::string name;
std::vector<std::unique_ptr<MachineInstr>> instructions;
MachineFunction* parent;
};
// 栈帧信息
struct StackFrameInfo {
int locals_size = 0; // 仅为AllocaInst分配的大小
int spill_size = 0; // 仅为溢出分配的大小
int total_size = 0; // 总大小
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
};
// 机器函数
class MachineFunction {
public:
MachineFunction(Function* func, RISCv64ISel* isel) : F(func), name(func->getName()), isel(isel) {}
Function* getFunc() const { return F; }
RISCv64ISel* getISel() const { return isel; }
const std::string& getName() const { return name; }
StackFrameInfo& getFrameInfo() { return frame_info; }
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
blocks.push_back(std::move(block));
}
private:
Function* F;
RISCv64ISel* isel; // 指向创建它的ISel用于获取vreg映射等信息
std::string name;
std::vector<std::unique_ptr<MachineBasicBlock>> blocks;
StackFrameInfo frame_info;
};
} // namespace sysy
#endif // RISCV64_LLIR_H

View File

@@ -0,0 +1,61 @@
#ifndef RISCV64_PASSES_H
#define RISCV64_PASSES_H
#include "RISCv64LLIR.h"
namespace sysy {
/**
* @class Pass
* @brief 所有优化Pass的抽象基类 (可选,但推荐)
* * 定义一个通用的接口,所有优化都应该实现它。
*/
class Pass {
public:
virtual ~Pass() = default;
virtual void runOnMachineFunction(MachineFunction* mfunc) = 0;
};
// --- 寄存器分配前优化 ---
/**
* @class PreRA_Scheduler
* @brief 寄存器分配前的指令调度器
* * 在虚拟寄存器上进行操作,此时调度自由度最大,
* 主要目标是隐藏指令延迟,提高流水线效率。
*/
class PreRA_Scheduler : public Pass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
// --- 寄存器分配后优化 ---
/**
* @class PeepholeOptimizer
* @brief 窥孔优化器
* * 在已分配物理寄存器的指令流上,通过一个小的滑动窗口来查找
* 并替换掉一些冗余或低效的指令模式。
*/
class PeepholeOptimizer : public Pass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
/**
* @class PostRA_Scheduler
* @brief 寄存器分配后的局部指令调度器
* * 主要目标是优化寄存器分配器插入的spill/fill代码(lw/sw)
* 尝试将加载指令提前,以隐藏其访存延迟。
*/
class PostRA_Scheduler : public Pass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
} // namespace sysy
#endif // RISCV64_PASSES_H

View File

@@ -0,0 +1,56 @@
#ifndef RISCV64_REGALLOC_H
#define RISCV64_REGALLOC_H
#include "RISCv64LLIR.h"
namespace sysy {
class RISCv64RegAlloc {
public:
RISCv64RegAlloc(MachineFunction* mfunc);
// 模块主入口
void run();
private:
using LiveSet = std::set<unsigned>; // 活跃虚拟寄存器集合
using InterferenceGraph = std::map<unsigned, std::set<unsigned>>;
// 栈帧管理
void eliminateFrameIndices();
// 活跃性分析
void analyzeLiveness();
// 构建干扰图
void buildInterferenceGraph();
// 图着色分配寄存器
void colorGraph();
// 重写函数替换vreg并插入溢出代码
void rewriteFunction();
// 辅助函数获取指令的Use/Def集合
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
MachineFunction* MFunc;
// 活跃性分析结果
std::map<const MachineInstr*, LiveSet> live_in_map;
std::map<const MachineInstr*, LiveSet> live_out_map;
// 干扰图
InterferenceGraph interference_graph;
// 图着色结果
std::map<unsigned, PhysicalReg> color_map; // vreg -> preg
std::set<unsigned> spilled_vregs; // 被溢出的vreg集合
// 可用的物理寄存器池
std::vector<PhysicalReg> allocable_int_regs;
};
} // namespace sysy
#endif // RISCV64_REGALLOC_H

View File

@@ -2,6 +2,7 @@
#include "IR.h" #include "IR.h"
#include "IRBuilder.h" #include "IRBuilder.h"
#include "SysYIROptUtils.h"
namespace sysy { namespace sysy {
/** /**
@@ -16,8 +17,6 @@ public:
Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {} Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
void DeletePhiInst(); void DeletePhiInst();
// 删除UD关系, 因为删除了phi指令会修改ud关系
void usedelete(Instruction *instr);
}; };
} // namespace sysy } // namespace sysy

196
src/include/SCCP.h Normal file
View File

@@ -0,0 +1,196 @@
#pragma once
#include "IR.h"
namespace sysy {
// 稀疏条件常量传播类
// Sparse Conditional Constant Propagation
/*
伪代码
function SCCP_Optimization(Module):
for each Function in Module:
changed = true
while changed:
changed = false
// 阶段1: 常量传播与折叠
changed |= PropagateConstants(Function)
// 阶段2: 控制流简化
changed |= SimplifyControlFlow(Function)
end while
end for
function PropagateConstants(Function):
// 初始化
executableBlocks = {entryBlock}
valueState = map<Value, State> // 值->状态映射
instWorkList = Queue()
edgeWorkList = Queue()
// 初始化工作列表
for each inst in entryBlock:
instWorkList.push(inst)
// 迭代处理
while !instWorkList.empty() || !edgeWorkList.empty():
// 处理指令工作列表
while !instWorkList.empty():
inst = instWorkList.pop()
// 如果指令是可执行基本块中的
if executableBlocks.contains(inst.parent):
ProcessInstruction(inst)
// 处理边工作列表
while !edgeWorkList.empty():
edge = edgeWorkList.pop()
ProcessEdge(edge)
// 应用常量替换
for each inst in Function:
if valueState[inst] == CONSTANT:
ReplaceWithConstant(inst, valueState[inst].constant)
changed = true
return changed
function ProcessInstruction(Instruction inst):
switch inst.type:
//二元操作
case BINARY_OP:
lhs = GetValueState(inst.operands[0])
rhs = GetValueState(inst.operands[1])
if lhs == CONSTANT && rhs == CONSTANT:
newState = ComputeConstant(inst.op, lhs.value, rhs.value)
UpdateState(inst, newState)
else if lhs == BOTTOM || rhs == BOTTOM:
UpdateState(inst, BOTTOM)
//phi
case PHI:
mergedState =
for each incoming in inst.incomings:
// 检查每个输入的状态
if executableBlocks.contains(incoming.block):
incomingState = GetValueState(incoming.value)
mergedState = Meet(mergedState, incomingState)
UpdateState(inst, mergedState)
// 条件分支
case COND_BRANCH:
cond = GetValueState(inst.condition)
if cond == CONSTANT:
// 判断条件分支
if cond.value == true:
AddEdgeToWorkList(inst.parent, inst.trueTarget)
else:
AddEdgeToWorkList(inst.parent, inst.falseTarget)
else if cond == BOTTOM:
AddEdgeToWorkList(inst.parent, inst.trueTarget)
AddEdgeToWorkList(inst.parent, inst.falseTarget)
case UNCOND_BRANCH:
AddEdgeToWorkList(inst.parent, inst.target)
// 其他指令处理...
function ProcessEdge(Edge edge):
fromBB, toBB = edge
if !executableBlocks.contains(toBB):
executableBlocks.add(toBB)
for each inst in toBB:
if inst is PHI:
instWorkList.push(inst)
else:
instWorkList.push(inst) // 非PHI指令
// 更新PHI节点的输入
for each phi in toBB.phis:
instWorkList.push(phi)
function SimplifyControlFlow(Function):
changed = false
// 标记可达基本块
ReachableBBs = FindReachableBlocks(Function.entry)
// 删除不可达块
for each bb in Function.blocks:
if !ReachableBBs.contains(bb):
RemoveDeadBlock(bb)
changed = true
// 简化条件分支
for each bb in Function.blocks:
terminator = bb.terminator
if terminator is COND_BRANCH:
cond = GetValueState(terminator.condition)
if cond == CONSTANT:
SimplifyBranch(terminator, cond.value)
changed = true
return changed
function RemoveDeadBlock(BasicBlock bb):
// 1. 更新前驱块的分支指令
for each pred in bb.predecessors:
UpdateTerminator(pred, bb)
// 2. 更新后继块的PHI节点
for each succ in bb.successors:
RemovePhiIncoming(succ, bb)
// 3. 删除块内所有指令
for each inst in bb.instructions:
inst.remove()
// 4. 从函数中移除基本块
Function.removeBlock(bb)
function Meet(State a, State b):
if a == : return b
if b == : return a
if a == ⊥ || b == ⊥: return ⊥
if a.value == b.value: return a
return ⊥
function UpdateState(Value v, State newState):
oldState = valueState.get(v, )
if newState != oldState:
valueState[v] = newState
for each user in v.users:
if user is Instruction:
instWorkList.push(user)
*/
enum class LatticeValue {
Top, // (Unknown)
Constant, // c (Constant)
Bottom // ⊥ (Undefined / Varying)
};
// LatticeValue: 用于表示值的状态Top表示未知Constant表示常量Bottom表示未定义或变化的值。
// 这里的LatticeValue用于跟踪每个SSA值变量、指令结果的状态
// 以便在SCCP过程中进行常量传播和控制流简化。
//TODO: 下列数据结构考虑集成到类中,避免重命名问题
static std::set<Instruction *> Worklist;
static std::unordered_set<BasicBlock*> Executable_Blocks;
static std::queue<std::pair<BasicBlock *, BasicBlock *> > Executable_Edges;
static std::map<Value*, LatticeValue> valueState;
class SCCP {
private:
Module *pModule;
public:
SCCP(Module *pMoudle) : pModule(pMoudle) {}
void run();
bool PropagateConstants(Function *function);
bool SimplifyControlFlow(Function *function);
void ProcessInstruction(Instruction *inst);
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
void RemoveDeadBlock(BasicBlock *bb);
void UpdateState(Value *v, LatticeValue newState);
LatticeValue Meet(LatticeValue a, LatticeValue b);
LatticeValue GetValueState(Value *v);
};
} // namespace sysy

View File

@@ -1,340 +0,0 @@
#pragma once
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
#include <ostream>
namespace sysy {
class SysYFormatter : public SysYBaseVisitor {
protected:
std::ostream &os;
int indent = 0;
public:
SysYFormatter(std::ostream &os) : os(os), indent(0) {}
protected:
struct Indentor {
static constexpr int TabSize = 2;
int &indent;
Indentor(int &indent) : indent(indent) { indent += TabSize; }
~Indentor() { indent -= TabSize; }
};
std::ostream &space() { return os << std::string(indent, ' '); }
template <typename T>
std::ostream &interleave(const T &container, const std::string sep = ", ") {
auto b = container.begin(), e = container.end();
(*b)->accept(this);
for (b = std::next(b); b != e; b = std::next(b)) {
os << sep;
(*b)->accept(this);
}
return os;
}
public:
// virtual std::any visitModule(SysYParser::ModuleContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any visitBtype(SysYParser::BtypeContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
space();
if (ctx->CONST())
os << ctx->CONST()->getText() << ' ';
ctx->btype()->accept(this);
os << ' ';
interleave(ctx->varDef(), ", ") << ';' << '\n';
return 0;
}
virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
ctx->lValue()->accept(this);
if (ctx->initValue()) {
os << ' ' << '=' << ' ';
ctx->initValue()->accept(this);
}
return 0;
}
virtual std::any visitInitValue(SysYParser::InitValueContext *ctx) override {
if (not ctx->exp()) {
os << '{';
auto values = ctx->initValue();
if (values.size())
interleave(values, ", ");
os << '}';
}
return 0;
}
virtual std::any visitFunc(SysYParser::FuncContext *ctx) override {
ctx->funcType()->accept(this);
os << ' ' << ctx->ID()->getText() << '(';
if (ctx->funcFParams())
ctx->funcFParams()->accept(this);
os << ')' << ' ';
ctx->blockStmt()->accept(this);
os << '\n';
return 0;
}
virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any
visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
interleave(ctx->funcFParam(), ", ");
return 0;
}
virtual std::any
visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
ctx->btype()->accept(this);
os << ' ' << ctx->ID()->getText();
if (not ctx->LBRACKET().empty()) {
os << '[';
auto exp = ctx->exp();
if (not exp.empty()) {
os << '[';
interleave(exp, "][") << ']';
}
}
return 0;
}
virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override {
os << '{' << '\n';
{
Indentor indentor(indent);
auto items = ctx->blockItem();
if (not items.empty())
interleave(items, "");
}
space() << ctx->RBRACE()->getText() << '\n';
return 0;
}
// virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx)
// override {
// return visitChildren(ctx);
// }
// virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any
visitAssignStmt(SysYParser::AssignStmtContext *ctx) override {
space();
ctx->lValue()->accept(this);
os << " = ";
ctx->exp()->accept(this);
os << ';' << '\n';
return 0;
}
virtual std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override {
space();
ctx->exp()->accept(this);
os << ';' << '\n';
return 0;
}
void wrapBlock(SysYParser::StmtContext *stmt) {
bool isBlock = stmt->blockStmt();
if (isBlock) {
stmt->accept(this);
} else {
os << "{\n";
{
Indentor indentor(indent);
stmt->accept(this);
}
space() << "}\n";
}
};
virtual std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override {
space();
os << ctx->IF()->getText() << " (";
ctx->exp()->accept(this);
os << ") ";
auto stmt = ctx->stmt();
auto ifStmt = stmt[0];
wrapBlock(ifStmt);
if (stmt.size() == 2) {
auto elseStmt = stmt[1];
wrapBlock(elseStmt);
}
return 0;
}
virtual std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override {
space();
os << ctx->WHILE()->getText() << " (";
ctx->exp()->accept(this);
os << ") ";
wrapBlock(ctx->stmt());
return 0;
}
virtual std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override {
space() << ctx->BREAK()->getText() << ';' << '\n';
return 0;
}
virtual std::any
visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override {
space() << ctx->CONTINUE()->getText() << ';' << '\n';
return 0;
}
virtual std::any
visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override {
space() << ctx->RETURN()->getText();
if (ctx->exp()) {
os << ' ';
ctx->exp()->accept(this);
}
os << ';' << '\n';
return 0;
}
// virtual std::any visitEmptyStmt(SysYParser::EmptyStmtContext *ctx)
// override {
// return visitChildren(ctx);
// }
virtual std::any
visitRelationExp(SysYParser::RelationExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op =
ctx->LT() ? "<" : (ctx->LE() ? "<=" : (ctx->GT() ? ">" : ">="));
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any
visitMultiplicativeExp(SysYParser::MultiplicativeExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->MUL() ? "*" : (ctx->DIV() ? "/" : "%");
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
// virtual std::any visitLValueExp(SysYParser::LValueExpContext *ctx)
// override {
// return visitChildren(ctx);
// }
// virtual std::any visitNumberExp(SysYParser::NumberExpContext *ctx)
// override {
// return visitChildren(ctx);
// }
virtual std::any visitAndExp(SysYParser::AndExpContext *ctx) override {
ctx->exp(0)->accept(this);
os << " && ";
ctx->exp(1)->accept(this);
return 0;
}
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
std::string op = ctx->ADD() ? "+" : (ctx->SUB() ? "-" : "!");
os << op;
ctx->exp()->accept(this);
return 0;
}
virtual std::any visitParenExp(SysYParser::ParenExpContext *ctx) override {
os << '(';
ctx->exp()->accept(this);
os << ')';
return 0;
}
virtual std::any visitStringExp(SysYParser::StringExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitOrExp(SysYParser::OrExpContext *ctx) override {
ctx->exp(0)->accept(this);
os << " || ";
ctx->exp(1)->accept(this);
return 0;
}
// virtual std::any visitCallExp(SysYParser::CallExpContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any
visitAdditiveExp(SysYParser::AdditiveExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->ADD() ? "+" : "-";
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any visitEqualExp(SysYParser::EqualExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->EQ() ? "==" : "!=";
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any visitCall(SysYParser::CallContext *ctx) override {
os << ctx->ID()->getText() << '(';
if (ctx->funcRParams())
ctx->funcRParams()->accept(this);
os << ')';
return 0;
}
virtual std::any visitLValue(SysYParser::LValueContext *ctx) override {
os << ctx->ID()->getText();
auto exp = ctx->exp();
if (not exp.empty()) {
os << '[';
interleave(exp, "][") << ']';
}
return 0;
}
virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any visitString(SysYParser::StringContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any
visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
interleave(ctx->exp(), ", ");
return 0;
}
};
} // namespace sysy

View File

@@ -0,0 +1,60 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h"
namespace sysy {
// 优化前对SysY IR的预处理也可以视作部分CFG优化
// 主要包括删除无用指令、合并基本块、删除空块等
// 这些操作可以在SysY IR生成时就完成但为了简化IR生成过程
// 这里将其放在SysY IR生成后进行预处理
// 同时兼容phi节点的处理可以再mem2reg后再次调用优化
//TODO: 可增加的CFG优化和方法
// - 检查基本块跳转关系正确性
// - 简化条件分支Branch Simplification如条件恒真/恒假转为直接跳转
// - 合并连续的跳转指令Jump Threading在合并不可达块中似乎已经实现了
// - 基本块重排序Block Reordering提升局部性
class SysYCFGOpt {
private:
Module *pModule;
IRBuilder *pBuilder;
public:
SysYCFGOpt(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
void SysYOptimizateAfterIR(){
auto &functions = pModule->getFunctions();
for (auto &function : functions) {
bool changed = false;
while(changed){
changed = false;
changed |= SysYCondBr2Br(function.second.get(), pBuilder);
// 删除br后面的无用指令
changed |= SysYDelInstAfterBr(function.second.get());
// 合并空基本块
changed |= SysYBlockMerge(function.second.get());
// 删除无前驱块
changed |= SysYDelNoPreBLock(function.second.get());
// 删除空块
changed |= SysYDelEmptyBlock(function.second.get(), pBuilder);
// 添加return指令
changed |= SysYAddReturn(function.second.get(), pBuilder);
}
}
}
public:
static bool SysYDelInstAfterBr(Function *func); // 删除br后面的指令
static bool SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder); // 空块删除
static bool SysYDelNoPreBLock(Function *func); // 删除无前驱块(不可达块)
static bool SysYBlockMerge(Function *func); // 合并基本块(主要针对嵌套if while的exit块
// 也可以修改IR生成实现回填机制
static bool SysYAddReturn(Function *func, IRBuilder* pBuilder); // 添加return指令(主要针对Void函数)
static bool SysYCondBr2Br(Function *func, IRBuilder* pBuilder); // 条件分支(已知cond的值)转换为无条件分支
};
} // namespace sysy

View File

@@ -62,12 +62,11 @@ private:
public: public:
SysYIRGenerator() = default; SysYIRGenerator() = default;
bool HasReturnInst;
public: public:
Module *get() const { return module.get(); } Module *get() const { return module.get(); }
IRBuilder *getBuilder(){ return &builder; } IRBuilder *getBuilder(){ return &builder; }
public: public:
std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override; std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override;
std::any visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx) override; std::any visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx) override;
@@ -134,6 +133,11 @@ public:
// std::any visitConstExp(SysYParser::ConstExpContext *ctx) override; // std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
public:
// 获取GEP指令的地址
Value* getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices);
// 构建数组类型
Type* buildArrayType(Type* baseType, const std::vector<Value*>& dims);
}; // class SysYIRGenerator }; // class SysYIRGenerator

View File

@@ -1,37 +0,0 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h"
namespace sysy {
// 优化前对SysY IR的预处理也可以视作部分CFG优化
// 主要包括删除无用指令、合并基本块、删除空块等
// 这些操作可以在SysY IR生成时就完成但为了简化IR生成过程
// 这里将其放在SysY IR生成后进行预处理
// 同时兼容phi节点的处理可以再mem2reg后再次调用优化
class SysYOptPre {
private:
Module *pModule;
IRBuilder *pBuilder;
public:
SysYOptPre(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
void SysYOptimizateAfterIR(){
SysYDelInstAfterBr();
SysYBlockMerge();
SysYDelNoPreBLock();
SysYDelEmptyBlock();
SysYAddReturn();
}
void SysYDelInstAfterBr(); // 删除br后面的指令
void SysYDelEmptyBlock(); // 空块删除
void SysYDelNoPreBLock(); // 删除无前驱块
void SysYBlockMerge(); // 合并基本块(主要针对嵌套if while的exit块
// 也可以修改IR生成实现回填机制
void SysYAddReturn(); // 添加return指令(主要针对Void函数)
void usedelete(Instruction *instr); // use删除
};
} // namespace sysy

View File

@@ -0,0 +1,33 @@
#pragma once
#include "IR.h"
namespace sysy {
// 优化工具类,包含一些通用的优化方法
// 这些方法可以在不同的优化 pass 中复用
// 例如删除use关系,判断是否是全局变量等
class SysYIROptUtils{
public:
// 删除use关系
static void usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
Value* val = use->getValue();
val->removeUse(use);
}
}
// 判断是否是全局变量
static bool isGlobal(Value *val) {
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
// 判断是否是数组
static bool isArr(Value *val) {
auto aval = dynamic_cast<AllocaInst *>(val);
return aval != nullptr && aval->getNumDims() != 0;
}
};
}// namespace sysy

59
src/include/SysYIRPass.h Normal file
View File

@@ -0,0 +1,59 @@
#pragma once
#include "IR.h"
namespace sysy {
// 前置声明
class FunctionPass;
class ModulePass;
class AnalysisPass;
class PassManager;
// 抽象基类 Pass
class Pass {
public:
enum PassKind {
PK_Function,
PK_Module,
PK_Analysis
};
Pass(PassKind kind, const std::string& name) : Kind(kind), Name(name) {}
virtual ~Pass() = default;
PassKind getPassKind() const { return Kind; }
const std::string& getPassName() const { return Name; }
// 每个Pass需要实现此方法来执行其逻辑
// 具体的run方法将根据Pass类型在FunctionPass和ModulePass中定义
protected:
PassKind Kind;
std::string Name;
};
// 针对函数的优化遍
class FunctionPass : public Pass {
public:
FunctionPass(const std::string& name) : Pass(PK_Function, name) {}
// 真正的优化逻辑将在此方法中实现
virtual bool runOnFunction(Function& F) = 0;
};
// 针对模块的优化遍
class ModulePass : public Pass {
public:
ModulePass(const std::string& name) : Pass(PK_Module, name) {}
// 真正的优化逻辑将在此方法中实现
virtual bool runOnModule(Module& M) = 0;
};
// 分析遍
class AnalysisPass : public Pass {
public:
AnalysisPass(const std::string& name) : Pass(PK_Analysis, name) {}
// 分析遍通常需要一个模块或函数作为输入,并计算出分析结果
// 具体分析结果的存储和访问方式需要设计
};
} // namespace sysy

View File

@@ -0,0 +1,58 @@
// PassManager.h
#pragma once
#include <vector>
#include <memory>
#include <typeindex> // For std::type_index
#include <unordered_map>
#include "SysYIRPass.h"
#include "IR.h" // 假设你的IR.h定义了Module, Function等
namespace sysy {
class PassManager {
public:
PassManager() = default;
// 添加一个FunctionPass
void addPass(std::unique_ptr<FunctionPass> pass) {
functionPasses.push_back(std::move(pass));
}
// 添加一个ModulePass
void addPass(std::unique_ptr<ModulePass> pass) {
modulePasses.push_back(std::move(pass));
}
// 添加一个AnalysisPass
template<typename T, typename... Args>
T* addAnalysisPass(Args&&... args) {
static_assert(std::is_base_of<AnalysisPass, T>::value, "T must derive from AnalysisPass");
auto analysis = std::make_unique<T>(std::forward<Args>(args)...);
T* rawPtr = analysis.get();
analysisPasses[std::type_index(typeid(T))] = std::move(analysis);
return rawPtr;
}
// 获取分析结果用于其他Pass访问
template<typename T>
T* getAnalysis() {
static_assert(std::is_base_of<AnalysisPass, T>::value, "T must derive from AnalysisPass");
auto it = analysisPasses.find(std::type_index(typeid(T)));
if (it != analysisPasses.end()) {
return static_cast<T*>(it->second.get());
}
return nullptr; // 或者抛出异常
}
// 运行所有注册的遍
void run(Module& M);
private:
std::vector<std::unique_ptr<FunctionPass>> functionPasses;
std::vector<std::unique_ptr<ModulePass>> modulePasses;
std::unordered_map<std::type_index, std::unique_ptr<AnalysisPass>> analysisPasses;
// 未来可以添加AnalysisPass的缓存机制
};
} // namespace sysy

View File

@@ -13,12 +13,13 @@ using namespace antlr4;
#include "SysYIRGenerator.h" #include "SysYIRGenerator.h"
#include "SysYIRPrinter.h" #include "SysYIRPrinter.h"
#include "SysYIROptPre.h" #include "SysYIRCFGOpt.h"
#include "RISCv64Backend.h" #include "RISCv64Backend.h"
#include "SysYIRAnalyser.h" // #include "SysYIRAnalyser.h"
#include "DeadCodeElimination.h" // #include "DeadCodeElimination.h"
#include "Mem2Reg.h" #include "AddressCalculationExpansion.h"
#include "Reg2Mem.h" // #include "Mem2Reg.h"
// #include "Reg2Mem.h"
using namespace sysy; using namespace sysy;
@@ -124,42 +125,41 @@ int main(int argc, char **argv) {
// 无论最终输出是 IR 还是 ASM只要不是停止在 AST 阶段,都会进入此优化流程。 // 无论最终输出是 IR 还是 ASM只要不是停止在 AST 阶段,都会进入此优化流程。
// optLevel = 0 时,执行默认优化。 // optLevel = 0 时,执行默认优化。
// optLevel >= 1 时,执行默认优化 + 额外的 -O1 优化。 // optLevel >= 1 时,执行默认优化 + 额外的 -O1 优化。
cout << "Applying middle-end optimizations (level -O" << optLevel << ")...\n"; if (DEBUG) cout << "Applying middle-end optimizations (level -O" << optLevel << ")...\n";
// 设置 DEBUG 模式(如果指定了 'ird' // 设置 DEBUG 模式(如果指定了 'ird'
if (argStopAfter == "ird") { if (argStopAfter == "ird") {
DEBUG = 1; // 这里可能需要更精细地控制 DEBUG 的开启时机和范围 DEBUG = 1; // 这里可能需要更精细地控制 DEBUG 的开启时机和范围
} }
// 默认优化 pass (在所有优化级别都会执行) // 默认优化 pass (在所有优化级别都会执行)
SysYOptPre optPre(moduleIR, builder); SysYCFGOpt cfgopt(moduleIR, builder);
optPre.SysYOptimizateAfterIR(); cfgopt.SysYOptimizateAfterIR();
ControlFlowAnalysis cfa(moduleIR); // ControlFlowAnalysis cfa(moduleIR);
cfa.init(); // cfa.init();
ActiveVarAnalysis ava; // ActiveVarAnalysis ava;
ava.init(moduleIR); // ava.init(moduleIR);
if (DEBUG) { if (DEBUG) {
cout << "=== After CFA & AVA (Default) ===\n"; cout << "=== After CFA & AVA (Default) ===\n";
SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试 SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试
} }
AddressCalculationExpansion ace(moduleIR, builder);
DeadCodeElimination dce(moduleIR, &cfa, &ava); if (ace.run()) {
dce.runDCEPipeline(); if (DEBUG) cout << "AddressCalculationExpansion made changes.\n";
// 如果 ACE 改变了IR并且 DEBUG 模式开启可以考虑打印IR
if (DEBUG) { if (DEBUG) {
cout << "=== After 1st DCE (Default) ===\n"; cout << "=== After AddressCalculationExpansion ===\n";
SysYPrinter(moduleIR).printIR(); SysYPrinter(moduleIR).printIR();
} }
} else {
if (DEBUG) cout << "AddressCalculationExpansion made no changes.\n";
}
// 根据优化级别,执行额外的优化 pass // 根据优化级别,执行额外的优化 pass
if (optLevel >= 1) { if (optLevel >= 1) {
cout << "Applying additional -O" << optLevel << " optimizations...\n"; if (DEBUG) cout << "Applying additional -O" << optLevel << " optimizations...\n";
// 放置 -O1 及其以上级别要启用的额外优化 pass // 放置 -O1 及其以上级别要启用的额外优化 pass
// 例如: // 例如:
// MyNewOptimizationPass newOpt(moduleIR, builder); // MyNewOptimizationPass newOpt(moduleIR, builder);
@@ -174,28 +174,34 @@ int main(int argc, char **argv) {
// MyCustomOpt2 opt2_pass(moduleIR, builder, &cfa); // 假设需要CFA // MyCustomOpt2 opt2_pass(moduleIR, builder, &cfa); // 假设需要CFA
// opt2_pass.run(); // opt2_pass.run();
// ... 更多 -O1 特有的优化 // ... 更多 -O1 特有的优化
// DeadCodeElimination dce(moduleIR, &cfa, &ava);
// dce.runDCEPipeline();
// if (DEBUG) {
// cout << "=== After 1st DCE (Default) ===\n";
// SysYPrinter(moduleIR).printIR();
// }
Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava); // Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava);
mem2reg.mem2regPipeline(); // mem2reg.mem2regPipeline();
if (DEBUG) { // if (DEBUG) {
cout << "=== After Mem2Reg (Default) ===\n"; // cout << "=== After Mem2Reg (Default) ===\n";
SysYPrinter(moduleIR).printIR(); // SysYPrinter(moduleIR).printIR();
} // }
Reg2Mem reg2mem(moduleIR, builder); // Reg2Mem reg2mem(moduleIR, builder);
reg2mem.DeletePhiInst(); // reg2mem.DeletePhiInst();
if (DEBUG) { // if (DEBUG) {
cout << "=== After Reg2Mem (Default) ===\n"; // cout << "=== After Reg2Mem (Default) ===\n";
SysYPrinter(moduleIR).printIR(); // SysYPrinter(moduleIR).printIR();
} // }
dce.runDCEPipeline(); // 第二次 DCE (默认) // dce.runDCEPipeline(); // 第二次 DCE (默认)
if (DEBUG) { // if (DEBUG) {
cout << "=== After 2nd DCE (Default) ===\n"; // cout << "=== After 2nd DCE (Default) ===\n";
SysYPrinter(moduleIR).printIR(); // SysYPrinter(moduleIR).printIR();
} // }
} else { } else {
cout << "No additional middle-end optimizations applied for -O" << optLevel << ".\n"; if (DEBUG) cout << "No additional middle-end optimizations applied for -O" << optLevel << ".\n";
} }
// 5. 根据 argStopAfter 决定后续操作 // 5. 根据 argStopAfter 决定后续操作
@@ -212,7 +218,7 @@ int main(int argc, char **argv) {
// 设置 DEBUG 模式(如果指定了 'asmd' // 设置 DEBUG 模式(如果指定了 'asmd'
if (argStopAfter == "asmd") { if (argStopAfter == "asmd") {
DEBUG = 1; DEBUG = 1;
DEEPDEBUG = 1; // DEEPDEBUG = 1;
} }
sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR
string asmCode = codegen.code_gen(); string asmCode = codegen.code_gen();

View File

@@ -20,7 +20,12 @@ TESTDATA_DIR="${SCRIPT_DIR}/testdata"
# 定义编译器 (这里假设 gcc 在 VM 内部是可用的) # 定义编译器 (这里假设 gcc 在 VM 内部是可用的)
GCC_NATIVE="gcc" # VM 内部的 gcc GCC_NATIVE="gcc" # VM 内部的 gcc
# 不再需要 QEMU_RISCV64因为直接执行
# --- 新增功能: 初始化变量 ---
TIMEOUT_SECONDS=5 # 默认运行时超时时间为 5 秒
COMPILE_TIMEOUT_SECONDS=10 # 默认编译超时时间为 10 秒
TOTAL_CASES=0
PASSED_CASES=0
# 显示帮助信息的函数 # 显示帮助信息的函数
show_help() { show_help() {
@@ -30,30 +35,31 @@ show_help() {
echo "" echo ""
echo "选项:" echo "选项:"
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。" echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
echo " -t, --timeout N 设置每个测试用例的运行时超时为 N 秒 (默认: 5)。"
echo " -ct, --compile-timeout M 设置 gcc 编译的超时时间为 M 秒 (默认: 10)。"
echo " -h, --help 显示此帮助信息并退出。" echo " -h, --help 显示此帮助信息并退出。"
echo "" echo ""
echo "执行步骤:" echo "执行步骤:"
echo "1. 遍历 'tmp/' 目录下的所有 .s 汇编文件。" echo "1. 遍历 'tmp/' 目录下的所有 .s 汇编文件。"
echo "2. 使用 VM 内部的 gcc 将 .s 文件汇编并链接为可执行文件 (链接 -L./lib -lsysy_riscv -static)。" echo "2. 在指定的超时时间内使用 VM 内部的 gcc 将 .s 文件汇编并链接为可执行文件。"
echo "3. 直接运行编译后的可执行文件。" echo "3. 在指定的超时时间内运行编译后的可执行文件。"
echo "4. 根据对应的 testdata/*.out 文件内容(最后一行是否为整数)决定是进行返回值比较、标准输出比较,或两者都进行。" echo "4. 根据对应的 .out 文件内容进行返回值和/或标准输出比较。"
echo "5. 如果没有对应的 .in/.out 文件,则打印可执行文件的返回值。" echo "5. 输出比较时会忽略行尾多余的换行符。"
echo "6. 输出比较时会忽略行尾多余的换行符。" echo "6. 所有测试结束后,报告总通过率。"
} }
# 清理临时文件的函数 # 清理临时文件的函数
clean_tmp() { clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}" echo "正在清理临时目录: ${TMP_DIR}"
# 清理所有由本脚本和 runit.sh 生成的文件
rm -rf "${TMP_DIR}"/*.s \ rm -rf "${TMP_DIR}"/*.s \
"${TMP_DIR}"/*_sysyc_riscv64 \ "${TMP_DIR}"/*_sysyc_riscv64 \
"${TMP_DIR}"/*_sysyc_riscv64.actual_out \ "${TMP_DIR}"/*_sysyc_riscv64.actual_out \
"${TMP_DIR}"/*_sysyc_riscv64.expected_stdout \ "${TMP_DIR}"/*_sysyc_riscv64.expected_stdout \
"${TMP_DIR}"/*_sysyc_riscv64.o # 以防生成了 .o 文件 "${TMP_DIR}"/*_sysyc_riscv64.o
echo "清理完成。" echo "清理完成。"
} }
# 如果临时目录不存在,则创建它 (尽管 runit.sh 应该已经创建了) # 如果临时目录不存在,则创建它
mkdir -p "${TMP_DIR}" mkdir -p "${TMP_DIR}"
# 解析命令行参数 # 解析命令行参数
@@ -63,6 +69,24 @@ while [[ "$#" -gt 0 ]]; do
clean_tmp clean_tmp
exit 0 exit 0
;; ;;
-t|--timeout)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
TIMEOUT_SECONDS="$2"
shift # 移过参数值
else
echo "错误: --timeout 需要一个正整数参数。" >&2
exit 1
fi
;;
-ct|--compile-timeout)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
COMPILE_TIMEOUT_SECONDS="$2"
shift # 移过参数值
else
echo "错误: --compile-timeout 需要一个正整数参数。" >&2
exit 1
fi
;;
-h|--help) -h|--help)
show_help show_help
exit 0 exit 0
@@ -73,30 +97,33 @@ while [[ "$#" -gt 0 ]]; do
exit 1 exit 1
;; ;;
esac esac
shift # 移过参数名
done done
echo "SysY VM 内部测试运行器启动..." echo "SysY VM 内部测试运行器启动..."
echo "编译超时设置为: ${COMPILE_TIMEOUT_SECONDS}"
echo "运行时超时设置为: ${TIMEOUT_SECONDS}"
echo "汇编文件目录: ${TMP_DIR}" echo "汇编文件目录: ${TMP_DIR}"
echo "库文件目录: ${LIB_DIR}" echo "库文件目录: ${LIB_DIR}"
echo "测试数据目录: ${TESTDATA_DIR}" echo "测试数据目录: ${TESTDATA_DIR}"
echo "" echo ""
# 查找 tmp 目录下的所有 .s 汇编文件 # 查找 tmp 目录下的所有 .s 汇编文件
s_files=$(find "${TMP_DIR}" -maxdepth 1 -name "*.s")
TOTAL_CASES=$(echo "$s_files" | wc -w)
# 遍历找到的每个 .s 文件 # 遍历找到的每个 .s 文件
find "${TMP_DIR}" -maxdepth 1 -name "*.s" | while read s_file; do echo "$s_files" | while read s_file; do
# --- 新增功能: 初始化用例通过状态 ---
is_passed=1 # 1 表示通过, 0 表示失败
# 从 .s 文件名中提取原始的测试用例名称部分 # 从 .s 文件名中提取原始的测试用例名称部分
# 例如:从 functional_21_if_test2_sysyc_riscv64.s 提取 functional_21_if_test2
base_name_from_s_file=$(basename "$s_file" .s) base_name_from_s_file=$(basename "$s_file" .s)
# 这一步得到的是 'functional_21_if_test2' 或 'performance_2024-2D0-22'
original_test_name_underscored=$(echo "$base_name_from_s_file" | sed 's/_sysyc_riscv64$//') original_test_name_underscored=$(echo "$base_name_from_s_file" | sed 's/_sysyc_riscv64$//')
# 将 `original_test_name_underscored` 分割成类别和文件名 # 将 `original_test_name_underscored` 分割成类别和文件名
# 例如:'functional_21_if_test2' 分割为 'functional' 和 '21_if_test2'
category=$(echo "$original_test_name_underscored" | cut -d'_' -f1) category=$(echo "$original_test_name_underscored" | cut -d'_' -f1)
# cut -d'_' -f2- 会从第二个下划线开始获取所有剩余部分
test_file_base=$(echo "$original_test_name_underscored" | cut -d'_' -f2-) test_file_base=$(echo "$original_test_name_underscored" | cut -d'_' -f2-)
# 构建原始的相对路径,例如:'functional/21_if_test2'
original_relative_path="${category}/${test_file_base}" original_relative_path="${category}/${test_file_base}"
# 定义可执行文件、输入文件、参考输出文件和实际输出文件的路径 # 定义可执行文件、输入文件、参考输出文件和实际输出文件的路径
@@ -109,109 +136,112 @@ find "${TMP_DIR}" -maxdepth 1 -name "*.s" | while read s_file; do
echo " 对应的测试用例路径: ${original_relative_path}" echo " 对应的测试用例路径: ${original_relative_path}"
# 步骤 1: 使用 VM 内部的 gcc 编译 .s 到可执行文件 # 步骤 1: 使用 VM 内部的 gcc 编译 .s 到可执行文件
# 注意:这里假设 gcc 在 VM 环境中可用,且 ./lib 是相对于当前脚本运行目录 echo " 使用 gcc 汇编并链接 (超时 ${COMPILE_TIMEOUT_SECONDS}s)..."
echo " 使用 gcc 汇编并链接: ${GCC_NATIVE} \"${s_file}\" -o \"${executable_file}\" -L\"${LIB_DIR}\" -lsysy_riscv -static -g" # --- 修改点: 为 gcc 增加 timeout ---
"${GCC_NATIVE}" "${s_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static -g timeout ${COMPILE_TIMEOUT_SECONDS} "${GCC_NATIVE}" "${s_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static -g
if [ $? -ne 0 ]; then GCC_STATUS=$?
echo -e "\e[31m错误: GCC 汇编/链接 ${s_file} 失败\e[0m" if [ $GCC_STATUS -eq 124 ]; then
continue echo -e "\e[31m错误: GCC 编译/链接 ${s_file} 超时 (超过 ${COMPILE_TIMEOUT_SECONDS} 秒)\e[0m"
fi is_passed=0
elif [ $GCC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: GCC 汇编/链接 ${s_file} 失败,退出码: ${GCC_STATUS}\e[0m"
is_passed=0
else
echo " 生成的可执行文件: ${executable_file}" echo " 生成的可执行文件: ${executable_file}"
echo " 正在执行 (超时 ${TIMEOUT_SECONDS}s): \"${executable_file}\""
# 步骤 2: 执行编译后的文件并比较/报告结果 # 步骤 2: 执行编译后的文件并比较/报告结果
# 直接执行可执行文件,不再通过 qemu-riscv64
echo " 正在执行: \"${executable_file}\"" # 修改点:移除多余的 ./
# 检查是否存在 .out 文件
if [ -f "${output_reference_file}" ]; then if [ -f "${output_reference_file}" ]; then
# 尝试从 .out 文件中提取期望的返回码和期望的标准输出
# 获取 .out 文件的最后一行,去除空白字符
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]') LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
# 检查最后一行是否为纯整数 (允许正负号)
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
# 假设最后一行是期望的返回码
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED" EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
# 创建一个只包含期望标准输出的临时文件 (所有行除了最后一行)
EXPECTED_STDOUT_FILE="${TMP_DIR}/${base_name_from_s_file}.expected_stdout" EXPECTED_STDOUT_FILE="${TMP_DIR}/${base_name_from_s_file}.expected_stdout"
# 使用 head -n -1 来获取除了最后一行之外的所有行。如果文件只有一行,则生成一个空文件。
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}" head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
echo " 检测到 .out 文件同时包含标准输出和期望的返回码。" echo " 检测到 .out 文件同时包含标准输出和期望的返回码。"
echo " 期望返回码: ${EXPECTED_RETURN_CODE}" echo " 期望返回码: ${EXPECTED_RETURN_CODE}"
if [ -s "${EXPECTED_STDOUT_FILE}" ]; then # -s 检查文件是否非空
echo " 期望标准输出文件: ${EXPECTED_STDOUT_FILE}"
else
echo " 期望标准输出为空。"
fi
# 执行程序,捕获实际返回码和实际标准输出
if [ -f "${input_file}" ]; then if [ -f "${input_file}" ]; then
echo " 使用输入文件: ${input_file}" timeout ${TIMEOUT_SECONDS} "${executable_file}" < "${input_file}" > "${output_actual_file}"
"${executable_file}" < "${input_file}" > "${output_actual_file}" # 修改点:移除多余的 ./
else else
"${executable_file}" > "${output_actual_file}" # 修改点:移除多余的 ./ timeout ${TIMEOUT_SECONDS} "${executable_file}" > "${output_actual_file}"
fi fi
ACTUAL_RETURN_CODE=$? # 捕获执行状态 ACTUAL_RETURN_CODE=$?
# 比较实际返回码与期望返回码 if [ "$ACTUAL_RETURN_CODE" -eq 124 ]; then
echo -e "\e[31m 执行超时: ${original_relative_path}.sy 运行超过 ${TIMEOUT_SECONDS} 秒\e[0m"
is_passed=0
else
if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then
echo -e "\e[32m 返回码测试成功: ${original_relative_path}.sy 的返回码 (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m" echo -e "\e[32m 返回码测试成功: (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m"
else else
echo -e "\e[31m 返回码测试失败: ${original_relative_path}.sy 的返回码不匹配。期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m" echo -e "\e[31m 返回码测试失败: 期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m"
is_passed=0
fi fi
# 比较实际标准输出与期望标准输出,忽略文件末尾的换行符差异
if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[32m 标准输出测试成功: 输出与 ${original_relative_path}.sy 的参考输出匹配 (忽略行尾换行符差异)\e[0m" echo -e "\e[32m 标准输出测试成功\e[0m"
else else
echo -e "\e[31m 标准输出测试失败: ${original_relative_path}.sy 的输出不匹配\e[0m" echo -e "\e[31m 标准输出测试失败\e[0m"
echo " 差异 (可能包含行尾换行符差异):" echo " 差异:"
diff "${output_actual_file}" "${EXPECTED_STDOUT_FILE}" # 显示原始差异以便调试 diff "${output_actual_file}" "${EXPECTED_STDOUT_FILE}"
is_passed=0
fi
fi fi
else else
# 最后一行不是纯整数,将整个 .out 文件为纯标准输出 echo " 检测到 .out 文件为纯标准输出参考。"
echo " 检测到 .out 文件为纯标准输出参考。正在与输出文件比较: ${output_reference_file}"
# 执行程序,并将输出重定向到临时文件
if [ -f "${input_file}" ]; then if [ -f "${input_file}" ]; then
echo " 使用输入文件: ${input_file}" timeout ${TIMEOUT_SECONDS} "${executable_file}" < "${input_file}" > "${output_actual_file}"
"${executable_file}" < "${input_file}" > "${output_actual_file}" # 修改点:移除多余的 ./
else else
"${executable_file}" > "${output_actual_file}" # 修改点:移除多余的 ./ timeout ${TIMEOUT_SECONDS} "${executable_file}" > "${output_actual_file}"
fi fi
EXEC_STATUS=$? # 捕获执行状态 EXEC_STATUS=$?
if [ $EXEC_STATUS -eq 124 ]; then
echo -e "\e[31m 执行超时: ${original_relative_path}.sy 运行超过 ${TIMEOUT_SECONDS} 秒\e[0m"
is_passed=0
else
if [ $EXEC_STATUS -ne 0 ]; then if [ $EXEC_STATUS -ne 0 ]; then
echo -e "\e[33m警告: 可执行文件 ${original_relative_path}.sy 以非零状态 ${EXEC_STATUS} 退出 (纯输出比较模式)。请检查程序逻辑或其是否应返回此状态。\e[0m" echo -e "\e[33m警告: 程序以非零状态 ${EXEC_STATUS} 退出 (纯输出比较模式)。\e[0m"
fi
if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else
echo -e "\e[31m 失败: 输出不匹配\e[0m"
echo " 差异:"
diff "${output_actual_file}" "${output_reference_file}"
is_passed=0
fi
fi
fi
else
echo " 未找到 .out 文件。正在运行并报告返回码。"
timeout ${TIMEOUT_SECONDS} "${executable_file}"
EXEC_STATUS=$?
if [ $EXEC_STATUS -eq 124 ]; then
echo -e "\e[31m 执行超时: ${original_relative_path}.sy 运行超过 ${TIMEOUT_SECONDS} 秒\e[0m"
is_passed=0
else
echo " ${original_relative_path}.sy 的返回码: ${EXEC_STATUS}"
fi
fi
fi fi
# 比较实际输出与参考输出,忽略文件末尾的换行符差异 # --- 新增功能: 更新通过用例计数 ---
if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then if [ "$is_passed" -eq 1 ]; then
echo -e "\e[32m 成功: 输出与 ${original_relative_path}.sy 的参考输出匹配 (忽略行尾换行符差异)\e[0m" ((PASSED_CASES++))
else
echo -e "\e[31m 失败: ${original_relative_path}.sy 的输出不匹配\e[0m"
echo " 差异 (可能包含行尾换行符差异):"
diff "${output_actual_file}" "${output_reference_file}" # 显示原始差异以便调试
fi fi
fi echo "" # 为测试用例之间添加一个空行
elif [ -f "${input_file}" ]; then
# 只有 .in 文件存在,使用输入运行并报告退出码(无参考输出)
echo " 使用输入文件: ${input_file}"
echo " 没有 .out 文件进行比较。正在运行并报告返回码。"
"${executable_file}" < "${input_file}" # 修改点:移除多余的 ./
EXEC_STATUS=$?
echo " ${original_relative_path}.sy 的返回码: ${EXEC_STATUS}"
else
# .in 和 .out 文件都不存在,只运行并报告退出码
echo " 未找到 .in 或 .out 文件。正在运行并报告返回码。"
"${executable_file}" # 修改点:移除多余的 ./
EXEC_STATUS=$?
echo " ${original_relative_path}.sy 的返回码: ${EXEC_STATUS}"
fi
echo "" # 为测试用例之间添加一个空行,以提高可读性
done done
echo "脚本完成。" # --- 新增功能: 打印最终总结 ---
echo "========================================"
echo "测试完成"
echo "测试通过率: [${PASSED_CASES}/${TOTAL_CASES}]"
echo "========================================"
if [ "$PASSED_CASES" -eq "$TOTAL_CASES" ]; then
exit 0
else
exit 1
fi

View File

@@ -9,45 +9,40 @@ TESTDATA_DIR="${SCRIPT_DIR}/../testdata"
BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin" BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin"
LIB_DIR="${SCRIPT_DIR}/../lib" LIB_DIR="${SCRIPT_DIR}/../lib"
# TMP_DIR="${SCRIPT_DIR}/tmp" # TMP_DIR="${SCRIPT_DIR}/tmp"
TMP_DIR="/home/ladev987/paraComp/debug/share_folder/tmp" TMP_DIR="${SCRIPT_DIR}/tmp"
# 定义编译器和模拟器 # 定义编译器和模拟器
SYSYC="${BUILD_BIN_DIR}/sysyc" SYSYC="${BUILD_BIN_DIR}/sysyc"
GCC_RISCV64="riscv64-linux-gnu-gcc" GCC_RISCV64="riscv64-linux-gnu-gcc"
QEMU_RISCV64="qemu-riscv64" QEMU_RISCV64="qemu-riscv64"
# 标志,用于确定是否应该生成和运行可执行文件 # --- 新增功能: 初始化变量 ---
EXECUTE_MODE=false EXECUTE_MODE=false
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
TOTAL_CASES=0
PASSED_CASES=0
FAILED_CASES_LIST="" # 用于存储未通过的测例列表
# 显示帮助信息的函数 # 显示帮助信息的函数
show_help() { show_help() {
echo "用法: $0 [选项]" echo "用法: $0 [选项]"
echo "此脚本用于编译 .sy 文件,并可选择性地运行它们进行测试。" echo "此脚本用于按文件名前缀数字升序编译和测试 .sy 文件。"
echo "" echo ""
echo "选项:" echo "选项:"
echo " -e, --executable 编译为可执行文件运行可执行文件,并比较输出(如果存在 .in/.out 文件)。" echo " -e, --executable 编译为可执行文件运行测试。"
echo " 如果 .out 文件的最后一行是整数,则将其视为期望的返回值进行比较,其余内容视为期望的标准输出。"
echo " 如果 .out 文件的最后一行不是整数,则将整个 .out 文件视为期望的标准输出进行比较。"
echo " 输出比较时会忽略行尾多余的换行符。"
echo " 如果不存在 .in/.out 文件,则打印返回码。"
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。" echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 执行超时为 N 秒 (默认: 5)。"
echo " -h, --help 显示此帮助信息并退出。" echo " -h, --help 显示此帮助信息并退出。"
echo ""
echo "编译步骤:"
echo "1. 调用 sysyc 将 .sy 编译为 .s (RISC-V 汇编)。"
echo "2. 调用 riscv64-linux-gnu-gcc 将 .s 编译为可执行文件,并链接 -L../lib/ -lsysy_riscv -static。"
echo "3. 调用 qemu-riscv64 执行编译后的文件。"
echo "4. 根据 .out 文件内容(最后一行是否为整数)决定是进行返回值比较、标准输出比较,或两者都进行。"
echo "5. 如果没有 .in/.out 文件,则打印可执行文件的返回值。"
} }
# 清理临时文件的函数 # 清理临时文件的函数
clean_tmp() { clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}" echo "正在清理临时目录: ${TMP_DIR}"
rm -rf "${TMP_DIR}"/* rm -rf "${TMP_DIR}"/*
# 如果需要,也可以根据 clean.sh 示例清理其他特定文件
# rm -rf "${SCRIPT_DIR}"/*.s "${SCRIPT_DIR}"/*.ll "${SCRIPT_DIR}"/*clang "${SCRIPT_DIR}"/*sysyc
# rm -rf "${SCRIPT_DIR}"/*_riscv64
} }
# 如果临时目录不存在,则创建它 # 如果临时目录不存在,则创建它
@@ -58,12 +53,20 @@ while [[ "$#" -gt 0 ]]; do
case "$1" in case "$1" in
-e|--executable) -e|--executable)
EXECUTE_MODE=true EXECUTE_MODE=true
shift
;; ;;
-c|--clean) -c|--clean)
clean_tmp clean_tmp
exit 0 exit 0
;; ;;
-sct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
;;
-gct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi
;;
-et)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi
;;
-h|--help) -h|--help)
show_help show_help
exit 0 exit 0
@@ -74,150 +77,175 @@ while [[ "$#" -gt 0 ]]; do
exit 1 exit 1
;; ;;
esac esac
shift
done done
echo "SysY 测试运行器启动..." echo "SysY 测试运行器启动..."
echo "输入目录: ${TESTDATA_DIR}" echo "输入目录: ${TESTDATA_DIR}"
echo "临时目录: ${TMP_DIR}" echo "临时目录: ${TMP_DIR}"
echo "执行模式已启用: ${EXECUTE_MODE}" echo "执行模式: ${EXECUTE_MODE}"
if ${EXECUTE_MODE}; then
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
fi
echo "" echo ""
# 查找 testdata 目录及其子目录中的所有 .sy 文件 # --- 修改点: 查找所有 .sy 文件并按文件名前缀数字排序 ---
# 遍历找到的每个 .sy 文件 sy_files=$(find "${TESTDATA_DIR}" -name "*.sy" | sort -V)
find "${TESTDATA_DIR}" -name "*.sy" | while read sy_file; do TOTAL_CASES=$(echo "$sy_files" | wc -w)
# 获取 .sy 文件的基本名称例如21_if_test2
# 这也处理了文件位于子目录中的情况例如functional/21_if_test2.sy # --- 本次修复: 使用 here-string (<<<) 代替管道 (|) 来避免子 shell 问题 ---
# 这样可以确保循环内的 PASSED_CASES 变量修改在循环结束后依然有效
while IFS= read -r sy_file; do
is_passed=1 # 1 表示通过, 0 表示失败
relative_path_no_ext=$(realpath --relative-to="${TESTDATA_DIR}" "${sy_file%.*}") relative_path_no_ext=$(realpath --relative-to="${TESTDATA_DIR}" "${sy_file%.*}")
# 将斜杠替换为下划线,用于输出文件名,以避免冲突并保持结构
output_base_name=$(echo "${relative_path_no_ext}" | tr '/' '_') output_base_name=$(echo "${relative_path_no_ext}" | tr '/' '_')
# 定义汇编文件、可执行文件、输入文件和输出文件的路径
assembly_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.s" assembly_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.s"
executable_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64" executable_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64"
input_file="${sy_file%.*}.in" input_file="${sy_file%.*}.in"
output_reference_file="${sy_file%.*}.out" output_reference_file="${sy_file%.*}.out"
output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out" output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out"
echo "正在处理: $(basename "$sy_file")" echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
echo " SY 文件: ${sy_file}"
# 步骤 1: 使用 sysyc 编译 .sy 到 .s # 步骤 1: 使用 sysyc 编译 .sy 到 .s
echo " 使用 sysyc 编译: ${SYSYC} -s asm \"${sy_file}\" > \"${assembly_file}\"" echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
"${SYSYC}" -s asm "${sy_file}" > "${assembly_file}" timeout ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
if [ $? -ne 0 ]; then SYSYC_STATUS=$?
echo -e "\e[31m错误: SysY 编译 ${sy_file} 失败\e[0m" if [ $SYSYC_STATUS -eq 124 ]; then
continue echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m"
is_passed=0
elif [ $SYSYC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} 失败,退出码: ${SYSYC_STATUS}\e[0m"
is_passed=0
fi fi
echo " 生成的汇编文件: ${assembly_file}"
# 只有当 EXECUTE_MODE 为 true 时才继续生成和执行可执行文件 # 只有当 EXECUTE_MODE 为 true 且上一步成功时才继续
if ${EXECUTE_MODE}; then if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then
# 步骤 2: 使用 riscv64-linux-gnu-gcc 编译 .s 到可执行文件 # 步骤 2: 使用 riscv64-linux-gnu-gcc 编译 .s 到可执行文件
echo " 使用 gcc 编译: ${GCC_RISCV64} \"${assembly_file}\" -o \"${executable_file}\" -L\"${LIB_DIR}\" -lsysy_riscv -static" echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
"${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static timeout ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
if [ $? -ne 0 ]; then GCC_STATUS=$?
echo -e "\e[31m错误: GCC 编译 ${assembly_file} 失败\e[0m" if [ $GCC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: GCC 编译 ${assembly_file} 超时\e[0m"
is_passed=0
elif [ $GCC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: GCC 编译 ${assembly_file} 失败,退出码: ${GCC_STATUS}\e[0m"
is_passed=0
fi
elif ! ${EXECUTE_MODE}; then
echo " 跳过执行模式。仅生成汇编文件。"
# 如果只编译不执行,只要编译成功就算通过
if [ "$is_passed" -eq 1 ]; then
((PASSED_CASES++))
else
# --- 本次修改点 ---
FAILED_CASES_LIST+="${relative_path_no_ext}.sy\n"
fi
echo ""
continue continue
fi fi
echo " 生成的可执行文件: ${executable_file}"
# 步骤 3, 4, 5: 执行编译后的文件并比较/报告结果 # 步骤 3, 4, 5: 只有当编译都成功时才执行
echo " 正在执行: ${QEMU_RISCV664} \"${executable_file}\"" if [ "$is_passed" -eq 1 ]; then
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
# 检查是否存在 .out 文件 # 准备执行命令
exec_cmd="${QEMU_RISCV64} \"${executable_file}\""
if [ -f "${input_file}" ]; then
exec_cmd+=" < \"${input_file}\""
fi
exec_cmd+=" > \"${output_actual_file}\""
# 执行并捕获返回码
eval "timeout ${EXEC_TIMEOUT} ${exec_cmd}"
ACTUAL_RETURN_CODE=$?
if [ "$ACTUAL_RETURN_CODE" -eq 124 ]; then
echo -e "\e[31m 执行超时: ${sy_file} 运行超过 ${EXEC_TIMEOUT} 秒\e[0m"
is_passed=0
else
# 检查是否存在 .out 文件以进行比较
if [ -f "${output_reference_file}" ]; then if [ -f "${output_reference_file}" ]; then
# 尝试从 .out 文件中提取期望的返回码和期望的标准输出
# 获取 .out 文件的最后一行,去除空白字符
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]') LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
# 检查最后一行是否为纯整数 (允许正负号)
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
# 假设最后一行是期望的返回码
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED" EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
# 创建一个只包含期望标准输出的临时文件 (所有行除了最后一行)
EXPECTED_STDOUT_FILE="${TMP_DIR}/${output_base_name}_sysyc_riscv64.expected_stdout" EXPECTED_STDOUT_FILE="${TMP_DIR}/${output_base_name}_sysyc_riscv64.expected_stdout"
# 使用 head -n -1 来获取除了最后一行之外的所有行。如果文件只有一行,则生成一个空文件。
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}" head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
echo " 检测到 .out 文件同时包含标准输出和期望的返回码。" # 比较返回码
echo " 期望返回码: ${EXPECTED_RETURN_CODE}"
if [ -s "${EXPECTED_STDOUT_FILE}" ]; then # -s 检查文件是否非空
echo " 期望标准输出文件: ${EXPECTED_STDOUT_FILE}"
else
echo " 期望标准输出为空。"
fi
# 执行程序,捕获实际返回码和实际标准输出
if [ -f "${input_file}" ]; then
echo " 使用输入文件: ${input_file}"
"${QEMU_RISCV64}" "${executable_file}" < "${input_file}" > "${output_actual_file}"
else
"${QEMU_RISCV64}" "${executable_file}" > "${output_actual_file}"
fi
ACTUAL_RETURN_CODE=$? # 捕获执行状态
# 比较实际返回码与期望返回码
if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then
echo -e "\e[32m 返回码测试成功: ${sy_file} 的返回码 (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m" echo -e "\e[32m 返回码测试成功: (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m"
else else
echo -e "\e[31m 返回码测试失败: ${sy_file} 的返回码不匹配。期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m" echo -e "\e[31m 返回码测试失败: 期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m"
is_passed=0
fi fi
# 比较标准输出
# 比较实际标准输出与期望标准输出,忽略文件末尾的换行符差异
# 使用 sed 命令去除文件末尾的所有换行符,再通过 diff 进行比较
if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[32m 标准输出测试成功: 输出与 ${sy_file} 的参考输出匹配 (忽略行尾换行符差异)\e[0m" echo -e "\e[32m 标准输出测试成功\e[0m"
else else
echo -e "\e[31m 标准输出测试失败: ${sy_file} 的输出不匹配\e[0m" echo -e "\e[31m 标准输出测试失败\e[0m"
echo " 差异 (可能包含行尾换行符差异):" is_passed=0
diff "${output_actual_file}" "${EXPECTED_STDOUT_FILE}" # 显示原始差异以便调试 echo -e " \e[36m---------- 期望输出 ----------\e[0m"
cat "${EXPECTED_STDOUT_FILE}"
echo -e " \e[36m---------- 实际输出 ----------\e[0m"
cat "${output_actual_file}"
echo -e " \e[36m------------------------------\e[0m"
fi fi
else else
# 最后一行不是纯整数,将整个 .out 文件视为纯标准输出 # 纯标准输出比较
echo " 检测到 .out 文件为纯标准输出参考。正在与输出文件比较: ${output_reference_file}" if [ $ACTUAL_RETURN_CODE -ne 0 ]; then
echo -e "\e[33m警告: 程序以非零状态 ${ACTUAL_RETURN_CODE} 退出 (纯输出比较模式)。\e[0m"
# 使用输入文件(如果存在)运行可执行文件,并将输出重定向到临时文件
if [ -f "${input_file}" ]; then
echo " 使用输入文件: ${input_file}"
"${QEMU_RISCV64}" "${executable_file}" < "${input_file}" > "${output_actual_file}"
else
"${QEMU_RISCV64}" "${executable_file}" > "${output_actual_file}"
fi fi
EXEC_STATUS=$? # 捕获执行状态
if [ $EXEC_STATUS -ne 0 ]; then
echo -e "\e[33m警告: 可执行文件 ${sy_file} 以非零状态 ${EXEC_STATUS} 退出 (纯输出比较模式)。请检查程序逻辑或其是否应返回此状态。\e[0m"
fi
# 比较实际输出与参考输出,忽略文件末尾的换行符差异
if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then if diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与 ${sy_file} 的参考输出匹配 (忽略行尾换行符差异)\e[0m" echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else else
echo -e "\e[31m 失败: ${sy_file}输出不匹配\e[0m" echo -e "\e[31m 失败: 输出不匹配\e[0m"
echo " 差异 (可能包含行尾换行符差异):" is_passed=0
diff "${output_actual_file}" "${output_reference_file}" # 显示原始差异以便调试 echo -e " \e[36m---------- 期望输出 ----------\e[0m"
cat "${output_reference_file}"
echo -e " \e[36m---------- 实际输出 ----------\e[0m"
cat "${output_actual_file}"
echo -e " \e[36m------------------------------\e[0m"
fi fi
fi fi
elif [ -f "${input_file}" ]; then
# 只有 .in 文件存在,使用输入运行并报告退出码(无参考输出)
echo " 使用输入文件: ${input_file}"
echo " 没有 .out 文件进行比较。正在运行并报告返回码。"
"${QEMU_RISCV64}" "${executable_file}" < "${input_file}"
EXEC_STATUS=$?
echo " ${sy_file} 的返回码: ${EXEC_STATUS}"
else
# .in 和 .out 文件都不存在,只运行并报告退出码
echo " 未找到 .in 或 .out 文件。正在运行并报告返回码。"
"${QEMU_RISCV64}" "${executable_file}"
EXEC_STATUS=$?
echo " ${sy_file} 的返回码: ${EXEC_STATUS}"
fi
else else
echo " 跳过执行模式。仅生成汇编文件。" # 没有 .out 文件,只报告返回码
echo " 无参考输出文件。程序返回码: ${ACTUAL_RETURN_CODE}"
fi
fi
fi fi
echo "" # 为测试用例之间添加一个空行,以提高可读性
done
echo "脚本完成。" # 更新通过用例计数
# --- 本次修改点 ---
if [ "$is_passed" -eq 1 ]; then
((PASSED_CASES++))
else
# 将失败的用例名称添加到列表中
FAILED_CASES_LIST+="${relative_path_no_ext}.sy\n"
fi
echo "" # 添加空行以提高可读性
done <<< "$sy_files"
# --- 新增功能: 打印最终总结 ---
echo "========================================"
echo "测试完成"
echo "测试通过率: [${PASSED_CASES}/${TOTAL_CASES}]"
# --- 本次修改点: 打印未通过的测例列表 ---
if [ -n "$FAILED_CASES_LIST" ]; then
echo ""
echo -e "\e[31m未通过的测例:\e[0m"
# 使用 -e 来解释换行符 \n
echo -e "${FAILED_CASES_LIST}"
fi
echo "========================================"
if [ "$PASSED_CASES" -eq "$TOTAL_CASES" ]; then
exit 0
else
exit 1
fi

1
testdata/functional/00_main.out vendored Normal file
View File

@@ -0,0 +1 @@
3

3
testdata/functional/00_main.sy vendored Normal file
View File

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

View File

@@ -1,2 +1 @@
10 10
0

8
testdata/functional/01_var_defn2.sy vendored Normal file
View File

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

1
testdata/functional/02_var_defn3.out vendored Normal file
View File

@@ -0,0 +1 @@
5

8
testdata/functional/02_var_defn3.sy vendored Normal file
View File

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

1
testdata/functional/03_arr_defn2.out vendored Normal file
View File

@@ -0,0 +1 @@
0

4
testdata/functional/03_arr_defn2.sy vendored Normal file
View File

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

1
testdata/functional/04_arr_defn3.out vendored Normal file
View File

@@ -0,0 +1 @@
14

9
testdata/functional/04_arr_defn3.sy vendored Normal file
View File

@@ -0,0 +1,9 @@
//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];
}

1
testdata/functional/05_arr_defn4.out vendored Normal file
View File

@@ -0,0 +1 @@
21

9
testdata/functional/05_arr_defn4.sy vendored Normal file
View File

@@ -0,0 +1,9 @@
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

@@ -0,0 +1 @@
5

View File

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

View File

@@ -0,0 +1 @@
5

View File

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

View File

@@ -0,0 +1 @@
4

View File

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

1
testdata/functional/09_func_defn.out vendored Normal file
View File

@@ -0,0 +1 @@
9

11
testdata/functional/09_func_defn.sy vendored Normal file
View File

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

View File

@@ -0,0 +1 @@
4

View File

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

1
testdata/functional/11_add2.out vendored Normal file
View File

@@ -0,0 +1 @@
9

7
testdata/functional/11_add2.sy vendored Normal file
View File

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

1
testdata/functional/12_addc.out vendored Normal file
View File

@@ -0,0 +1 @@
15

5
testdata/functional/12_addc.sy vendored Normal file
View File

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

1
testdata/functional/13_sub2.out vendored Normal file
View File

@@ -0,0 +1 @@
248

7
testdata/functional/13_sub2.sy vendored Normal file
View File

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

1
testdata/functional/14_subc.out vendored Normal file
View File

@@ -0,0 +1 @@
8

6
testdata/functional/14_subc.sy vendored Normal file
View File

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

1
testdata/functional/15_mul.out vendored Normal file
View File

@@ -0,0 +1 @@
50

7
testdata/functional/15_mul.sy vendored Normal file
View File

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

1
testdata/functional/16_mulc.out vendored Normal file
View File

@@ -0,0 +1 @@
25

5
testdata/functional/16_mulc.sy vendored Normal file
View File

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

1
testdata/functional/17_div.out vendored Normal file
View File

@@ -0,0 +1 @@
2

7
testdata/functional/17_div.sy vendored Normal file
View File

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

1
testdata/functional/18_divc.out vendored Normal file
View File

@@ -0,0 +1 @@
2

5
testdata/functional/18_divc.sy vendored Normal file
View File

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

1
testdata/functional/19_mod.out vendored Normal file
View File

@@ -0,0 +1 @@
3

6
testdata/functional/19_mod.sy vendored Normal file
View File

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

1
testdata/functional/20_rem.out vendored Normal file
View File

@@ -0,0 +1 @@
1

6
testdata/functional/20_rem.sy vendored Normal file
View File

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

0
testdata/functional/21_if_test2.out vendored Executable file → Normal file
View File

0
testdata/functional/21_if_test2.sy vendored Executable file → Normal file
View File

1
testdata/functional/22_if_test3.out vendored Normal file
View File

@@ -0,0 +1 @@
25

18
testdata/functional/22_if_test3.sy vendored Normal file
View File

@@ -0,0 +1,18 @@
// 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());
}

1
testdata/functional/23_if_test4.out vendored Normal file
View File

@@ -0,0 +1 @@
25

18
testdata/functional/23_if_test4.sy vendored Normal file
View File

@@ -0,0 +1,18 @@
// 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_());
}

1
testdata/functional/24_if_test5.out vendored Normal file
View File

@@ -0,0 +1 @@
25

18
testdata/functional/24_if_test5.sy vendored Normal file
View File

@@ -0,0 +1,18 @@
// 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());
}

2
testdata/functional/25_while_if.out vendored Normal file
View File

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

31
testdata/functional/25_while_if.sy vendored Normal file
View File

@@ -0,0 +1,31 @@
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;
}

0
testdata/functional/26_while_test1.out vendored Executable file → Normal file
View File

0
testdata/functional/26_while_test1.sy vendored Executable file → Normal file
View File

View File

@@ -0,0 +1 @@
54

31
testdata/functional/27_while_test2.sy vendored Normal file
View File

@@ -0,0 +1,31 @@
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

@@ -0,0 +1 @@
23

55
testdata/functional/28_while_test3.sy vendored Normal file
View File

@@ -0,0 +1,55 @@
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();
}

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