deploy-20250820-3 #1
@@ -22,7 +22,7 @@ add_executable(sysyc
|
||||
SysYIRGenerator.cpp
|
||||
SysYIRPrinter.cpp
|
||||
SysYIRCFGOpt.cpp
|
||||
SysYIRAnalyser.cpp
|
||||
# SysYIRAnalyser.cpp
|
||||
# DeadCodeElimination.cpp
|
||||
AddressCalculationExpansion.cpp
|
||||
# Mem2Reg.cpp
|
||||
|
||||
53
src/IR.cpp
53
src/IR.cpp
@@ -49,6 +49,11 @@ auto Type::getFunctionType(Type *returnType, const std::vector<Type *> ¶mTyp
|
||||
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 {
|
||||
switch (kind) {
|
||||
case kInt:
|
||||
@@ -58,6 +63,10 @@ auto Type::getSize() const -> unsigned {
|
||||
case kPointer:
|
||||
case kFunction:
|
||||
return 8;
|
||||
case Kind::kArray: {
|
||||
const ArrayType* arrType = static_cast<const ArrayType*>(this);
|
||||
return arrType->getElementType()->getSize() * arrType->getNumElements();
|
||||
}
|
||||
case kVoid:
|
||||
return 0;
|
||||
}
|
||||
@@ -95,6 +104,11 @@ FunctionType*FunctionType::get(Type *returnType, const std::vector<Type *> ¶
|
||||
return result.first->get();
|
||||
}
|
||||
|
||||
ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
|
||||
// TODO:可以考虑在这里添加缓存,避免重复创建相同的数组类型
|
||||
return new ArrayType(elementType, numElements);
|
||||
}
|
||||
|
||||
void Value::replaceAllUsesWith(Value *value) {
|
||||
for (auto &use : uses) {
|
||||
use->getUser()->setOperand(use->getIndex(), value);
|
||||
@@ -465,44 +479,7 @@ Function * Function::clone(const std::string &suffix) const {
|
||||
break;
|
||||
}
|
||||
|
||||
case Instruction::kLa: {
|
||||
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;
|
||||
}
|
||||
// TODO:复制GEP指令
|
||||
|
||||
case Instruction::kMemset: {
|
||||
auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst);
|
||||
|
||||
@@ -15,6 +15,73 @@
|
||||
using namespace std;
|
||||
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
|
||||
* @details:
|
||||
@@ -118,24 +185,28 @@ 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 =
|
||||
builder.createAllocaInst(Type::getPointerType(type), dims, name);
|
||||
|
||||
if (varDef->initVal() != nullptr) {
|
||||
ValueCounter values;
|
||||
// 这里的varDef->initVal()可能是ScalarInitValue或ArrayInitValue
|
||||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(varDef->initVal()->accept(this));
|
||||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||||
delete root;
|
||||
if (dims.empty()) {
|
||||
|
||||
if (dims.empty()) { // 标量变量初始化
|
||||
builder.createStoreInst(values.getValue(0), alloca);
|
||||
} else{
|
||||
// **数组变量初始化**
|
||||
} else { // 数组变量初始化
|
||||
const std::vector<sysy::Value *> &counterValues = values.getValues();
|
||||
|
||||
// 计算数组的**总元素数量**和**总字节大小**
|
||||
int numElements = 1;
|
||||
// 存储每个维度的实际整数大小,用于索引计算
|
||||
std::vector<int> dimSizes;
|
||||
for (Value *dimVal : dims) {
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
|
||||
@@ -145,12 +216,11 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||||
}
|
||||
// TODO else 错误处理:数组维度必须是常量(对于静态分配)
|
||||
}
|
||||
unsigned int elementSizeInBytes = type->getSize(); // 获取单个元素的大小(字节)
|
||||
unsigned int elementSizeInBytes = type->getSize();
|
||||
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
|
||||
|
||||
// **判断是否可以进行全零初始化优化**
|
||||
bool allValuesAreZero = false;
|
||||
if (counterValues.empty()) { // 例如 int arr[3] = {}; 或 int arr[3][4] = {};
|
||||
if (counterValues.empty()) {
|
||||
allValuesAreZero = true;
|
||||
}
|
||||
else {
|
||||
@@ -163,7 +233,6 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||||
}
|
||||
}
|
||||
else{
|
||||
// 如果值不是常量,我们通常不能确定它是否为零,所以不进行 memset 优化
|
||||
allValuesAreZero = false;
|
||||
break;
|
||||
}
|
||||
@@ -171,64 +240,51 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||||
}
|
||||
|
||||
if (allValuesAreZero) {
|
||||
// 如果所有初始化值都是零(或没有明确初始化但语法允许),使用 memset 优化
|
||||
builder.createMemsetInst(
|
||||
alloca, // 目标数组的起始地址
|
||||
ConstantInteger::get(0), // 偏移量(通常为0),后续删除
|
||||
alloca,
|
||||
ConstantInteger::get(0),
|
||||
ConstantInteger::get(totalSizeInBytes),
|
||||
ConstantInteger::get(0)); // 填充的总字节数
|
||||
ConstantInteger::get(0));
|
||||
}
|
||||
else {
|
||||
// **逐元素存储:遍历所有初始值,并为每个值生成一个 store 指令**
|
||||
for (size_t k = 0; k < counterValues.size(); ++k) {
|
||||
// 用于存储当前元素的索引列表
|
||||
std::vector<Value *> currentIndices;
|
||||
int tempLinearIndex = k; // 临时线性索引,用于计算多维索引
|
||||
int tempLinearIndex = k;
|
||||
|
||||
// **将线性索引转换为多维索引**
|
||||
// 这个循环从最内层维度开始倒推,计算每个维度的索引
|
||||
// 假设是行主序(row-major order),这是 C/C++ 数组的标准存储方式
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx)
|
||||
{
|
||||
// 计算当前维度的索引,并插入到列表的最前面
|
||||
currentIndices.insert(currentIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
// 更新线性索引,用于计算下一个更高维度的索引
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// **生成 store 指令,传入值、基指针和计算出的索引列表**
|
||||
// 你的 builder.createStoreInst 签名需要能够接受这些参数
|
||||
// 假设你的 builder.createStoreInst(Value *val, Value *ptr, const std::vector<Value *> &indices, ...)
|
||||
builder.createStoreInst(counterValues[k], alloca, currentIndices);
|
||||
// 计算元素的地址
|
||||
Value* elementAddress = getGEPAddressInst(alloca, currentIndices);
|
||||
// 生成 store 指令 (假设 createStoreInst 接受 Value* value, Value* pointer)
|
||||
builder.createStoreInst(counterValues[k], elementAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // **如果没有显式初始化值,默认对数组进行零初始化**
|
||||
if (!dims.empty())
|
||||
{ // 只有数组才需要默认的零初始化
|
||||
else { // 如果没有显式初始化值,默认对数组进行零初始化
|
||||
if (!dims.empty()) { // 只有数组才需要默认的零初始化
|
||||
int numElements = 1;
|
||||
for (Value *dimVal : dims)
|
||||
{
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal))
|
||||
{
|
||||
for (Value *dimVal : dims) {
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
|
||||
numElements *= constInt->getInt();
|
||||
}
|
||||
}
|
||||
unsigned int elementSizeInBytes = type->getSize();
|
||||
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
|
||||
|
||||
// 使用 memset 将整个数组清零
|
||||
builder.createMemsetInst(
|
||||
alloca,
|
||||
ConstantInteger::get(0),
|
||||
ConstantInteger::get(totalSizeInBytes),
|
||||
ConstantInteger::get(0)
|
||||
); // 填充的总字节数
|
||||
);
|
||||
}
|
||||
// 标量变量如果没有初始化值,通常不生成额外的初始化指令,因为其内存已分配但未赋值。
|
||||
}
|
||||
|
||||
module->addVariable(name, alloca);
|
||||
@@ -357,28 +413,55 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
|
||||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||||
}
|
||||
|
||||
auto variable = module->getVariable(name);
|
||||
Value* value = std::any_cast<Value *>(visitExp(ctx->exp()));
|
||||
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();
|
||||
auto variable = module->getVariable(name); // 获取 AllocaInst 或 GlobalValue
|
||||
Value* value = std::any_cast<Value *>(visitExp(ctx->exp())); // 右值
|
||||
|
||||
// 左值右值类型不同处理
|
||||
if (variableType != value->getType()) {
|
||||
if (variable == nullptr) {
|
||||
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);
|
||||
if (constValue != nullptr) {
|
||||
if (variableType == Type::getFloatType()) {
|
||||
value = ConstantInteger::get(static_cast<float>(constValue->getInt()));
|
||||
} else {
|
||||
value = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
|
||||
if (targetElementType == Type::getFloatType()) {
|
||||
value = ConstantFloating::get(static_cast<float>(constValue->getInt()));
|
||||
} else { // 假设如果不是浮点型,就是整型
|
||||
value = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
|
||||
}
|
||||
} else {
|
||||
if (variableType == Type::getFloatType()) {
|
||||
if (targetElementType == Type::getFloatType()) {
|
||||
value = builder.createIToFInst(value);
|
||||
} else {
|
||||
} else { // 假设如果不是浮点型,就是整型
|
||||
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();
|
||||
}
|
||||
@@ -576,51 +659,89 @@ std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx) {
|
||||
}
|
||||
|
||||
|
||||
// SysYIRGenerator.cpp (修改部分)
|
||||
|
||||
std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
|
||||
std::string name = ctx->Ident()->getText();
|
||||
User* variable = module->getVariable(name);
|
||||
|
||||
Value* value = nullptr;
|
||||
if (variable == nullptr) {
|
||||
throw std::runtime_error("Variable " + name + " not found.");
|
||||
}
|
||||
std::vector<Value *> dims;
|
||||
for (const auto &exp : ctx->exp()) {
|
||||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||||
}
|
||||
|
||||
if (variable == nullptr) {
|
||||
throw std::runtime_error("Variable " + name + " not found.");
|
||||
// 1. 获取变量的声明维度数量
|
||||
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) {
|
||||
if (dynamic_cast<ConstantValue *>(dim) == nullptr) {
|
||||
indicesConstant = false;
|
||||
allIndicesConstant = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ConstantVariable* constVar = dynamic_cast<ConstantVariable *>(variable);
|
||||
GlobalValue* globalVar = dynamic_cast<GlobalValue *>(variable);
|
||||
AllocaInst* localVar = dynamic_cast<AllocaInst *>(variable);
|
||||
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);
|
||||
if (allIndicesConstant) {
|
||||
// 如果是常量变量且所有索引都是常量,直接通过 getByIndices 获取编译时值
|
||||
// 这个方法会根据索引深度返回最终的标量值或指向子数组的指针 (作为 ConstantValue/Variable)
|
||||
return constVar->getByIndices(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "IR.h"
|
||||
#include "IR.h" // 确保IR.h包含了ArrayType、GetElementPtrInst等的定义
|
||||
|
||||
namespace sysy {
|
||||
|
||||
void SysYPrinter::printIR() {
|
||||
|
||||
const auto &functions = pModule->getFunctions();
|
||||
|
||||
//TODO: Print target datalayout and triple (minimal required by LLVM)
|
||||
@@ -36,11 +35,18 @@ std::string SysYPrinter::getTypeString(Type *type) {
|
||||
return "i32";
|
||||
} else if (type->isFloat()) {
|
||||
return "float";
|
||||
|
||||
} else if (auto ptrType = dynamic_cast<PointerType*>(type)) {
|
||||
// 递归打印指针指向的类型,然后加上 '*'
|
||||
return getTypeString(ptrType->getBaseType()) + "*";
|
||||
} else if (auto ptrType = dynamic_cast<FunctionType*>(type)) {
|
||||
return getTypeString(ptrType->getReturnType());
|
||||
} else if (auto funcType = dynamic_cast<FunctionType*>(type)) {
|
||||
// 对于函数类型,打印其返回类型
|
||||
// 注意:这里可能需要更完整的函数签名打印,取决于你的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");
|
||||
return "";
|
||||
@@ -51,15 +57,23 @@ std::string SysYPrinter::getValueName(Value *value) {
|
||||
return "@" + global->getName();
|
||||
} else if (auto inst = dynamic_cast<Instruction*>(value)) {
|
||||
return "%" + inst->getName();
|
||||
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) {
|
||||
if (constVal->isFloat()) {
|
||||
} else if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
|
||||
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->getInt());
|
||||
} 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 "";
|
||||
}
|
||||
|
||||
@@ -77,44 +91,35 @@ void SysYPrinter::printGlobalVariable() {
|
||||
for (const auto &global : globals) {
|
||||
std::cout << "@" << global->getName() << " = global ";
|
||||
|
||||
auto baseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
|
||||
printType(baseType);
|
||||
|
||||
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 << "]";
|
||||
}
|
||||
// 全局变量的类型是一个指针,指向其基类型 (可能是 ArrayType 或 Integer/FloatType)
|
||||
auto globalVarBaseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
|
||||
printType(globalVarBaseType); // 打印全局变量的实际类型 (例如 i32 或 [10 x i32])
|
||||
|
||||
std::cout << " ";
|
||||
|
||||
if (global->getNumDims() > 0) {
|
||||
// Array initializer
|
||||
std::cout << "[";
|
||||
auto values = global->getInitValues();
|
||||
auto counterValues = values.getValues();
|
||||
auto counterNumbers = values.getNumbers();
|
||||
// 检查是否是数组类型 (通过检查 globalVarBaseType 是否是 ArrayType)
|
||||
if (globalVarBaseType->isArray()) {
|
||||
// 数组初始化器
|
||||
std::cout << "["; // LLVM IR 数组初始化器格式: [type value, type value, ...]
|
||||
auto values = global->getInitValues(); // 假设 getInitValues() 返回一个 ValueCounter
|
||||
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 (baseType->isFloat()) {
|
||||
std::cout << "float " << dynamic_cast<ConstantValue*>(counterValues[i])->getFloat();
|
||||
} else {
|
||||
std::cout << "i32 " << dynamic_cast<ConstantValue*>(counterValues[i])->getInt();
|
||||
}
|
||||
// 打印元素类型,这个元素类型应该是数组的最终元素类型,例如 i32 或 float
|
||||
// 可以从 globalVarBaseType 逐层剥离得到最终元素类型,但这里简化为直接从值获取
|
||||
printType(counterValues[i]->getType());
|
||||
std::cout << " ";
|
||||
printValue(counterValues[i]);
|
||||
}
|
||||
std::cout << "]";
|
||||
} else {
|
||||
// Scalar initializer
|
||||
if (baseType->isFloat()) {
|
||||
std::cout << "float " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getFloat();
|
||||
} else {
|
||||
std::cout << "i32 " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getInt();
|
||||
}
|
||||
// 标量初始化器
|
||||
// 假设标量全局变量的初始化值通过 getByIndex(0) 获取
|
||||
Value* initVal = global->getByIndex(0);
|
||||
printType(initVal->getType()); // 打印标量值的类型
|
||||
std::cout << " ";
|
||||
printValue(initVal); // 打印标量值
|
||||
}
|
||||
|
||||
std::cout << ", align 4" << std::endl;
|
||||
@@ -209,19 +214,19 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kFDiv: std::cout << "fdiv"; break;
|
||||
case Kind::kICmpEQ: std::cout << "icmp eq"; 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::kICmpLE: std::cout << "icmp sle"; break;
|
||||
case Kind::kICmpGE: std::cout << "icmp sge"; break;
|
||||
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break;
|
||||
case Kind::kFCmpNE: std::cout << "fcmp one"; break;
|
||||
case Kind::kFCmpLT: std::cout << "fcmp olt"; break;
|
||||
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break;
|
||||
case Kind::kFCmpLE: std::cout << "fcmp ole"; break;
|
||||
case Kind::kFCmpGE: std::cout << "fcmp oge"; break;
|
||||
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break; // oeq for ordered equal
|
||||
case Kind::kFCmpNE: std::cout << "fcmp one"; break; // one for ordered not equal
|
||||
case Kind::kFCmpLT: std::cout << "fcmp olt"; break; // olt for ordered less than
|
||||
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break; // ogt for ordered greater than
|
||||
case Kind::kFCmpLE: std::cout << "fcmp ole"; break; // ole for ordered less than or equal
|
||||
case Kind::kFCmpGE: std::cout << "fcmp oge"; break; // oge for ordered greater than or equal
|
||||
case Kind::kAnd: std::cout << "and"; break;
|
||||
case Kind::kOr: std::cout << "or"; break;
|
||||
default: break;
|
||||
default: break; // Should not reach here
|
||||
}
|
||||
|
||||
// Types and operands
|
||||
@@ -238,7 +243,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kNeg:
|
||||
case Kind::kNot:
|
||||
case Kind::kFNeg:
|
||||
case Kind::kFNot:
|
||||
case Kind::kFtoI:
|
||||
case Kind::kBitFtoI:
|
||||
case Kind::kItoF:
|
||||
@@ -250,31 +254,39 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
}
|
||||
|
||||
switch (pInst->getKind()) {
|
||||
case Kind::kNeg: std::cout << "sub "; break;
|
||||
case Kind::kNot: std::cout << "not "; break;
|
||||
case Kind::kFNeg: std::cout << "fneg "; break;
|
||||
case Kind::kFNot: std::cout << "fneg "; break; // FNot not standard, map to fneg
|
||||
case Kind::kFtoI: std::cout << "fptosi "; break;
|
||||
case Kind::kBitFtoI: std::cout << "bitcast "; break;
|
||||
case Kind::kItoF: std::cout << "sitofp "; break;
|
||||
case Kind::kBitItoF: std::cout << "bitcast "; break;
|
||||
default: break;
|
||||
case Kind::kNeg: std::cout << "sub "; break; // integer negation is `sub i32 0, operand`
|
||||
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; // float negation
|
||||
case Kind::kFtoI: std::cout << "fptosi "; break; // float to signed integer
|
||||
case Kind::kBitFtoI: std::cout << "bitcast "; break; // bitcast float to int
|
||||
case Kind::kItoF: std::cout << "sitofp "; break; // signed integer to float
|
||||
case Kind::kBitItoF: std::cout << "bitcast "; break; // bitcast int to float
|
||||
default: break; // Should not reach here
|
||||
}
|
||||
|
||||
printType(unyInst->getType());
|
||||
printType(unyInst->getOperand()->getType()); // Print operand type
|
||||
std::cout << " ";
|
||||
|
||||
// Special handling for negation
|
||||
if (pInst->getKind() == Kind::kNeg || pInst->getKind() == Kind::kNot) {
|
||||
std::cout << "i32 0, ";
|
||||
// Special handling for integer negation and logical NOT
|
||||
if (pInst->getKind() == Kind::kNeg) {
|
||||
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));
|
||||
|
||||
// For bitcast, need to specify destination type
|
||||
if (pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
|
||||
// For type conversions (fptosi, sitofp, bitcast), need to specify destination type
|
||||
if (pInst->getKind() == Kind::kFtoI || pInst->getKind() == Kind::kItoF ||
|
||||
pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
|
||||
std::cout << " to ";
|
||||
printType(unyInst->getType());
|
||||
printType(unyInst->getType()); // Print result type
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
@@ -289,7 +301,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
}
|
||||
|
||||
std::cout << "call ";
|
||||
printType(callInst->getType());
|
||||
printType(callInst->getType()); // Return type of the call
|
||||
std::cout << " @" << function->getName() << "(";
|
||||
|
||||
auto params = callInst->getArguments();
|
||||
@@ -297,9 +309,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
for (auto ¶m : params) {
|
||||
if (!first) std::cout << ", ";
|
||||
first = false;
|
||||
printType(param->getValue()->getType());
|
||||
printType(param->getValue()->getType()); // Type of argument
|
||||
std::cout << " ";
|
||||
printValue(param->getValue());
|
||||
printValue(param->getValue()); // Value of argument
|
||||
}
|
||||
|
||||
std::cout << ")" << std::endl;
|
||||
@@ -307,7 +319,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
|
||||
case Kind::kCondBr: {
|
||||
auto condBrInst = dynamic_cast<CondBrInst *>(pInst);
|
||||
std::cout << "br i1 ";
|
||||
std::cout << "br i1 "; // Condition type should be i1
|
||||
printValue(condBrInst->getCondition());
|
||||
std::cout << ", label %" << condBrInst->getThenBlock()->getName();
|
||||
std::cout << ", label %" << condBrInst->getElseBlock()->getName();
|
||||
@@ -337,14 +349,17 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
|
||||
std::cout << "%" << allocaInst->getName() << " = alloca ";
|
||||
|
||||
auto baseType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
|
||||
printType(baseType);
|
||||
// AllocaInst 的类型现在应该是一个 PointerType,指向正确的 ArrayType 或 ScalarType
|
||||
// 例如:alloca i32, align 4 或者 alloca [10 x i32], align 4
|
||||
auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
|
||||
printType(allocatedType);
|
||||
|
||||
// 仍然打印维度信息,如果存在的话
|
||||
if (allocaInst->getNumDims() > 0) {
|
||||
std::cout << ", ";
|
||||
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
printType(Type::getIntType()); // 维度大小通常是 i32 类型
|
||||
std::cout << " ";
|
||||
printValue(allocaInst->getDim(i));
|
||||
}
|
||||
@@ -356,17 +371,18 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kLoad: {
|
||||
auto loadInst = dynamic_cast<LoadInst *>(pInst);
|
||||
std::cout << "%" << loadInst->getName() << " = load ";
|
||||
printType(loadInst->getType());
|
||||
printType(loadInst->getType()); // 加载的结果类型
|
||||
std::cout << ", ";
|
||||
printType(loadInst->getPointer()->getType());
|
||||
printType(loadInst->getPointer()->getType()); // 指针类型
|
||||
std::cout << " ";
|
||||
printValue(loadInst->getPointer());
|
||||
printValue(loadInst->getPointer()); // 要加载的地址
|
||||
|
||||
// 仍然打印索引信息,如果存在的话
|
||||
if (loadInst->getNumIndices() > 0) {
|
||||
std::cout << ", ";
|
||||
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
|
||||
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
printType(loadInst->getIndex(i)->getType());
|
||||
std::cout << " ";
|
||||
printValue(loadInst->getIndex(i));
|
||||
}
|
||||
@@ -375,44 +391,23 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
std::cout << ", align 4" << std::endl;
|
||||
} 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: {
|
||||
auto storeInst = dynamic_cast<StoreInst *>(pInst);
|
||||
std::cout << "store ";
|
||||
printType(storeInst->getValue()->getType());
|
||||
printType(storeInst->getValue()->getType()); // 要存储的值的类型
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getValue());
|
||||
printValue(storeInst->getValue()); // 要存储的值
|
||||
std::cout << ", ";
|
||||
printType(storeInst->getPointer()->getType());
|
||||
printType(storeInst->getPointer()->getType()); // 目标指针的类型
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getPointer());
|
||||
printValue(storeInst->getPointer()); // 目标地址
|
||||
|
||||
// 仍然打印索引信息,如果存在的话
|
||||
if (storeInst->getNumIndices() > 0) {
|
||||
std::cout << ", ";
|
||||
std::cout << ", indices "; // 或者其他分隔符
|
||||
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
printType(storeInst->getIndex(i)->getType());
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getIndex(i));
|
||||
}
|
||||
@@ -421,6 +416,30 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
std::cout << ", align 4" << std::endl;
|
||||
} 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: {
|
||||
auto memsetInst = dynamic_cast<MemsetInst *>(pInst);
|
||||
std::cout << "call void @llvm.memset.p0.";
|
||||
@@ -433,49 +452,38 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
printValue(memsetInst->getValue());
|
||||
std::cout << ", i32 ";
|
||||
printValue(memsetInst->getSize());
|
||||
std::cout << ", i1 false)" << std::endl;
|
||||
std::cout << ", i1 false)" << std::endl; // alignment for memset is typically i1
|
||||
} break;
|
||||
|
||||
case Kind::kPhi: {
|
||||
auto phiInst = dynamic_cast<PhiInst *>(pInst);
|
||||
printValue(phiInst->getOperand(0));
|
||||
std::cout << " = phi ";
|
||||
printType(phiInst->getType());
|
||||
// Phi 指令的名称通常是结果变量
|
||||
std::cout << "%" << phiInst->getName() << " = phi ";
|
||||
printType(phiInst->getType()); // Phi 结果类型
|
||||
|
||||
for (unsigned i = 1; i < phiInst->getNumOperands(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
// Phi 指令的操作数是成对的 [value, basic_block]
|
||||
// 这里假设 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 << "[ ";
|
||||
printValue(phiInst->getOperand(i));
|
||||
printValue(phiInst->getOperand(i * 2)); // value
|
||||
std::cout << ", %";
|
||||
printValue(phiInst->getOperand(i * 2 + 1)); // block
|
||||
std::cout << " ]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kGetSubArray: {
|
||||
auto getSubArrayInst = dynamic_cast<GetSubArrayInst *>(pInst);
|
||||
std::cout << "%" << getSubArrayInst->getName() << " = getelementptr inbounds ";
|
||||
|
||||
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;
|
||||
// 以下两个 Kind 应该删除或替换为 kGEP
|
||||
// case Kind::kLa: { /* REMOVED */ } break;
|
||||
// case Kind::kGetSubArray: { /* REMOVED */ } break;
|
||||
|
||||
default:
|
||||
assert(false && "Unsupported instruction kind");
|
||||
assert(false && "Unsupported instruction kind in SysYPrinter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
218
src/include/IR.h
218
src/include/IR.h
@@ -49,6 +49,7 @@ class Type {
|
||||
kLabel,
|
||||
kPointer,
|
||||
kFunction,
|
||||
kArray,
|
||||
};
|
||||
|
||||
Kind kind; ///< 表示具体类型的变量
|
||||
@@ -65,6 +66,7 @@ class Type {
|
||||
static Type* getPointerType(Type *baseType); ///< 返回表示指向baseType类型的Pointer类型的Type指针
|
||||
static Type* getFunctionType(Type *returnType, const std::vector<Type *> ¶mTypes = {});
|
||||
///< 返回表示返回类型为returnType,形参类型列表为paramTypes的函数类型的Type指针
|
||||
static Type* getArrayType(Type *elementType, unsigned numElements);
|
||||
|
||||
public:
|
||||
Kind getKind() const { return kind; } ///< 返回Type对象代表原始标量类型
|
||||
@@ -74,6 +76,7 @@ class Type {
|
||||
bool isLabel() const { return kind == kLabel; } ///< 判定是否为Label类型
|
||||
bool isPointer() const { return kind == kPointer; } ///< 判定是否为Pointer类型
|
||||
bool isFunction() const { return kind == kFunction; } ///< 判定是否为Function类型
|
||||
bool isArray() const { return kind == Kind::kArray; }
|
||||
unsigned getSize() const; ///< 返回类型所占的空间大小(字节)
|
||||
/// 尝试将一个变量转换为给定的Type及其派生类类型的变量
|
||||
template <typename T>
|
||||
@@ -115,6 +118,22 @@ class FunctionType : public Type {
|
||||
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; // 当前维度的大小
|
||||
};
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
@@ -602,49 +621,6 @@ class User : public 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.
|
||||
*/
|
||||
@@ -694,15 +670,15 @@ class Instruction : public User {
|
||||
kAlloca = 0x1UL << 33,
|
||||
kLoad = 0x1UL << 34,
|
||||
kStore = 0x1UL << 35,
|
||||
kLa = 0x1UL << 36,
|
||||
kGetElementPtr = 0x1UL << 36,
|
||||
kMemset = 0x1UL << 37,
|
||||
kGetSubArray = 0x1UL << 38,
|
||||
// kGetSubArray = 0x1UL << 38,
|
||||
// Constant Kind removed as Constants are now Values, not Instructions.
|
||||
// kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
|
||||
// phi
|
||||
kPhi = 0x1UL << 39,
|
||||
kBitItoF = 0x1UL << 40,
|
||||
kBitFtoI = 0x1UL << 41
|
||||
kBitFtoI = 0x1UL << 41,
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -793,14 +769,12 @@ public:
|
||||
return "Load";
|
||||
case kStore:
|
||||
return "Store";
|
||||
case kLa:
|
||||
return "La";
|
||||
case kGetElementPtr:
|
||||
return "GetElementPtr";
|
||||
case kMemset:
|
||||
return "Memset";
|
||||
case kPhi:
|
||||
return "Phi";
|
||||
case kGetSubArray:
|
||||
return "GetSubArray";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -853,9 +827,8 @@ public:
|
||||
bool isAlloca() const { return kind == kAlloca; }
|
||||
bool isLoad() const { return kind == kLoad; }
|
||||
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 isGetSubArray() const { return kind == kGetSubArray; }
|
||||
bool isCall() const { return kind == kCall; }
|
||||
bool isReturn() const { return kind == kReturn; }
|
||||
bool isDefine() const {
|
||||
@@ -867,26 +840,6 @@ public:
|
||||
class Function;
|
||||
//! 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 {
|
||||
friend class IRBuilder;
|
||||
friend class Function;
|
||||
@@ -1134,7 +1087,7 @@ public:
|
||||
}; // class CondBrInst
|
||||
|
||||
//! 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 Function;
|
||||
protected:
|
||||
@@ -1145,14 +1098,6 @@ protected:
|
||||
}
|
||||
|
||||
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(); }
|
||||
auto getDims() const { return getOperands(); }
|
||||
@@ -1161,37 +1106,40 @@ public:
|
||||
}; // class AllocaInst
|
||||
|
||||
|
||||
class GetSubArrayInst : public Instruction {
|
||||
friend class IRBuilder;
|
||||
friend class Function;
|
||||
class GetElementPtrInst : public Instruction {
|
||||
friend class IRBuilder; // 如果您有IRBuilder来创建指令,需要friend
|
||||
|
||||
public:
|
||||
GetSubArrayInst(LVal *fatherArray, LVal *childArray, const std::vector<Value *> &indices,
|
||||
protected:
|
||||
// GEP的构造函数:
|
||||
// resultType: GEP计算出的地址的类型 (通常是指向目标元素类型的指针)
|
||||
// basePointer: 基指针 (第一个操作数)
|
||||
// indices: 索引列表 (后续操作数)
|
||||
GetElementPtrInst(Value *basePointer,
|
||||
const std::vector<Value *> &indices = {},
|
||||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||||
: Instruction(Kind::kGetSubArray, Type::getVoidType(), parent, name) {
|
||||
auto predicate = [childArray](const std::unique_ptr<LVal> &child) -> bool { return child.get() == childArray; };
|
||||
if (std::find_if(fatherArray->childrenLVals.begin(), fatherArray->childrenLVals.end(), predicate) ==
|
||||
fatherArray->childrenLVals.end()) {
|
||||
fatherArray->childrenLVals.emplace_back(childArray);
|
||||
}
|
||||
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);
|
||||
: Instruction(Kind::kGetElementPtr, basePointer->getType(), parent, name) {
|
||||
assert(basePointer && "GEP base pointer cannot be null!");
|
||||
// TODO : 安全检查
|
||||
assert(basePointer->getType()->isPointer() );
|
||||
addOperand(basePointer); // 第一个操作数是基指针
|
||||
addOperands(indices); // 随后的操作数是索引
|
||||
}
|
||||
|
||||
public:
|
||||
Value* getFatherArray() const { return getOperand(0); } ///< 获取父数组
|
||||
Value* getChildArray() const { return getOperand(1); } ///< 获取子数组
|
||||
LVal* getFatherLVal() const { return dynamic_cast<LVal *>(getOperand(0)); } ///< 获取父左值
|
||||
LVal* getChildLVal() const { return dynamic_cast<LVal *>(getOperand(1)); } ///< 获取子左值
|
||||
auto getIndices() const { return make_range(std::next(operand_begin(), 2), operand_end()); } ///< 获取索引
|
||||
unsigned getNumIndices() const { return getNumOperands() - 2; } ///< 获取索引数量
|
||||
public:
|
||||
Value* getBasePointer() const { return getOperand(0); }
|
||||
unsigned getNumIndices() const { return getNumOperands() - 1; }
|
||||
auto getIndices() const { return make_range(std::next(operand_begin()), operand_end());}
|
||||
Value* getIndex(unsigned index) const {
|
||||
assert(index < getNumIndices() && "Index out of bounds for GEP!");
|
||||
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
|
||||
@@ -1215,22 +1163,7 @@ public:
|
||||
return make_range(std::next(operand_begin()), operand_end());
|
||||
}
|
||||
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
|
||||
|
||||
//! Store a value to memory address specified by a pointer value
|
||||
@@ -1256,22 +1189,6 @@ public:
|
||||
return make_range(std::next(operand_begin(), 2), operand_end());
|
||||
}
|
||||
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
|
||||
|
||||
@@ -1373,7 +1290,7 @@ protected:
|
||||
};
|
||||
|
||||
//! Global value declared at file scope
|
||||
class GlobalValue : public User, public LVal {
|
||||
class GlobalValue : public User {
|
||||
friend class Module;
|
||||
|
||||
protected:
|
||||
@@ -1407,16 +1324,6 @@ protected:
|
||||
}
|
||||
|
||||
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; } ///< 获取维度数量
|
||||
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
||||
auto getDims() const { return getOperands(); } ///< 获取维度列表
|
||||
@@ -1438,7 +1345,7 @@ public:
|
||||
}; // class GlobalValue
|
||||
|
||||
|
||||
class ConstantVariable : public User, public LVal {
|
||||
class ConstantVariable : public User {
|
||||
friend class Module;
|
||||
|
||||
protected:
|
||||
@@ -1457,15 +1364,6 @@ class ConstantVariable : public User, public LVal {
|
||||
}
|
||||
|
||||
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* getByIndices(const std::vector<Value *> &indices) const {
|
||||
int index = 0;
|
||||
|
||||
@@ -280,46 +280,6 @@ class IRBuilder {
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建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 = "") {
|
||||
auto inst = new MemsetInst(pointer, begin, size, value, block, name);
|
||||
assert(inst);
|
||||
@@ -340,6 +300,24 @@ class IRBuilder {
|
||||
block->getInstructions().emplace(block->begin(), inst);
|
||||
return inst;
|
||||
} ///< 创建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
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
Module *get() const { return module.get(); }
|
||||
IRBuilder *getBuilder(){ return &builder; }
|
||||
public:
|
||||
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override;
|
||||
|
||||
std::any visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx) override;
|
||||
@@ -134,6 +135,11 @@ public:
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ using namespace antlr4;
|
||||
#include "SysYIRPrinter.h"
|
||||
#include "SysYIRCFGOpt.h"
|
||||
#include "RISCv64Backend.h"
|
||||
#include "SysYIRAnalyser.h"
|
||||
// #include "SysYIRAnalyser.h"
|
||||
// #include "DeadCodeElimination.h"
|
||||
#include "AddressCalculationExpansion.h"
|
||||
// #include "Mem2Reg.h"
|
||||
@@ -135,10 +135,10 @@ int main(int argc, char **argv) {
|
||||
SysYCFGOpt cfgopt(moduleIR, builder);
|
||||
cfgopt.SysYOptimizateAfterIR();
|
||||
|
||||
ControlFlowAnalysis cfa(moduleIR);
|
||||
cfa.init();
|
||||
ActiveVarAnalysis ava;
|
||||
ava.init(moduleIR);
|
||||
// ControlFlowAnalysis cfa(moduleIR);
|
||||
// cfa.init();
|
||||
// ActiveVarAnalysis ava;
|
||||
// ava.init(moduleIR);
|
||||
|
||||
if (DEBUG) {
|
||||
cout << "=== After CFA & AVA (Default) ===\n";
|
||||
|
||||
Reference in New Issue
Block a user