[midend]修改constdecl的逻辑区分局部常量和全局常量声明逻辑,提供方法访问全局变量,常量的维度信息,修改GlobalValue,ConstantVariable的继承父类(User->Value)维度信息保存在Type中。
This commit is contained in:
@@ -132,8 +132,8 @@ std::any SysYIRGenerator::visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *c
|
||||
return std::any();
|
||||
}
|
||||
|
||||
std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx){
|
||||
Type* type = std::any_cast<Type *>(visitBType(ctx->bType()));
|
||||
std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
|
||||
Type *type = std::any_cast<Type *>(visitBType(ctx->bType()));
|
||||
for (const auto constDef : ctx->constDef()) {
|
||||
std::vector<Value *> dims = {};
|
||||
std::string name = constDef->Ident()->getText();
|
||||
@@ -144,19 +144,112 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx){
|
||||
}
|
||||
}
|
||||
|
||||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
||||
Type *variableType = type;
|
||||
if (!dims.empty()) {
|
||||
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
||||
}
|
||||
|
||||
// 显式地为局部常量在栈上分配空间
|
||||
// alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*`
|
||||
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), {}, name);
|
||||
|
||||
ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
||||
ValueCounter values;
|
||||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||||
delete root;
|
||||
|
||||
// 创建局部常量,并更新符号表
|
||||
Type* variableType = type;
|
||||
if (!dims.empty()) {
|
||||
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
||||
// 根据维度信息进行 store 初始化
|
||||
if (dims.empty()) { // 标量常量初始化
|
||||
// 局部常量必须有初始值,且通常是单个值
|
||||
if (!values.getValues().empty()) {
|
||||
builder.createStoreInst(values.getValue(0), alloca);
|
||||
} else {
|
||||
// 错误处理:局部标量常量缺少初始化值
|
||||
// 或者可以考虑默认初始化为0,但这通常不符合常量的语义
|
||||
assert(false && "Local scalar constant must have an initialization value!");
|
||||
return std::any(); // 直接返回,避免继续执行
|
||||
}
|
||||
} else { // 数组常量初始化
|
||||
const std::vector<sysy::Value *> &counterValues = values.getValues();
|
||||
const std::vector<unsigned> &counterNumbers = values.getNumbers();
|
||||
int numElements = 1;
|
||||
std::vector<int> dimSizes;
|
||||
for (Value *dimVal : dims) {
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
|
||||
int dimSize = constInt->getInt();
|
||||
numElements *= dimSize;
|
||||
dimSizes.push_back(dimSize);
|
||||
}
|
||||
// TODO else 错误处理:数组维度必须是常量(对于静态分配)
|
||||
else {
|
||||
assert(false && "Array dimension must be a constant integer!");
|
||||
return std::any(); // 直接返回,避免继续执行
|
||||
}
|
||||
}
|
||||
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 {
|
||||
int linearIndexOffset = 0; // 用于追踪当前处理的线性索引的偏移量
|
||||
for (int k = 0; k < counterValues.size(); ++k) {
|
||||
// 当前 Value 的值和重复次数
|
||||
Value *currentValue = counterValues[k];
|
||||
unsigned currentRepeatNum = counterNumbers[k];
|
||||
|
||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||
std::vector<Value *> currentIndices;
|
||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||
currentIndices.insert(currentIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// 对于局部数组,alloca 本身就是 GEP 的基指针。
|
||||
// GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
||||
std::vector<Value *> gepIndicesForInit;
|
||||
gepIndicesForInit.push_back(ConstantInteger::get(0));
|
||||
gepIndicesForInit.insert(gepIndicesForInit.end(), currentIndices.begin(), currentIndices.end());
|
||||
|
||||
// 计算元素的地址
|
||||
Value *elementAddress = getGEPAddressInst(alloca, gepIndicesForInit);
|
||||
// 生成 store 指令
|
||||
builder.createStoreInst(currentValue, elementAddress);
|
||||
}
|
||||
// 更新线性索引偏移量,以便下一次迭代从正确的位置开始
|
||||
linearIndexOffset += currentRepeatNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
module->createConstVar(name, Type::getPointerType(variableType), values, dims);
|
||||
|
||||
// 更新符号表,将常量名称与 AllocaInst 关联起来
|
||||
module->addVariable(name, alloca);
|
||||
}
|
||||
return 0;
|
||||
return std::any();
|
||||
}
|
||||
|
||||
std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||||
|
||||
Reference in New Issue
Block a user