[midend]修改constdecl的逻辑区分局部常量和全局常量声明逻辑,提供方法访问全局变量,常量的维度信息,修改GlobalValue,ConstantVariable的继承父类(User->Value)维度信息保存在Type中。
This commit is contained in:
@ -1351,7 +1351,7 @@ protected:
|
||||
};
|
||||
|
||||
//! Global value declared at file scope
|
||||
class GlobalValue : public User {
|
||||
class GlobalValue : public Value {
|
||||
friend class Module;
|
||||
|
||||
protected:
|
||||
@ -1363,9 +1363,10 @@ protected:
|
||||
GlobalValue(Module *parent, Type *type, const std::string &name,
|
||||
const std::vector<Value *> &dims = {},
|
||||
ValueCounter init = {})
|
||||
: User(type, name), parent(parent) {
|
||||
: Value(type, name), parent(parent) {
|
||||
assert(type->isPointer());
|
||||
addOperands(dims);
|
||||
// addOperands(dims);
|
||||
// 维度信息已经被记录到Type中,dim只是为了方便初始化
|
||||
numDims = dims.size();
|
||||
if (init.size() == 0) {
|
||||
unsigned num = 1;
|
||||
@ -1385,20 +1386,34 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
||||
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
||||
auto getDims() const { return getOperands(); } ///< 获取维度列表
|
||||
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
||||
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
||||
// auto getDims() const { return getOperands(); } ///< 获取维度列表
|
||||
unsigned getNumIndices() const {
|
||||
return numDims;
|
||||
} ///< 获取维度数量
|
||||
unsigned getIndex(unsigned index) const {
|
||||
assert(index < getNumIndices() && "Index out of bounds for GlobalValue!");
|
||||
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
|
||||
for (unsigned i = 0; i < index; i++) {
|
||||
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
|
||||
}
|
||||
return GlobalValueType->as<ArrayType>()->getNumElements();
|
||||
} ///< 获取维度大小(从第0个开始)
|
||||
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;
|
||||
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||||
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
|
||||
// GlobalValueType->as<ArrayType>()->getNumElements();
|
||||
auto dim_val = GlobalValueType->as<ArrayType>()->getNumElements();
|
||||
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();
|
||||
index = dim_val * index + idx_val->getInt();
|
||||
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
|
||||
}
|
||||
return getByIndex(index);
|
||||
} ///< 通过多维索引indices获取初始值
|
||||
@ -1406,7 +1421,7 @@ public:
|
||||
}; // class GlobalValue
|
||||
|
||||
|
||||
class ConstantVariable : public User {
|
||||
class ConstantVariable : public Value {
|
||||
friend class Module;
|
||||
|
||||
protected:
|
||||
@ -1417,31 +1432,45 @@ class ConstantVariable : public User {
|
||||
protected:
|
||||
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init,
|
||||
const std::vector<Value *> &dims = {})
|
||||
: User(type, name), parent(parent) {
|
||||
: Value(type, name), parent(parent) {
|
||||
assert(type->isPointer());
|
||||
numDims = dims.size();
|
||||
initValues = init;
|
||||
addOperands(dims);
|
||||
// addOperands(dims); 同GlobalValue,维度信息已经被记录到Type中,dim只是为了方便初始化
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned getNumIndices() const {
|
||||
return numDims;
|
||||
} ///< 获取索引数量
|
||||
unsigned getIndex(unsigned index) const {
|
||||
assert(index < getNumIndices() && "Index out of bounds for ConstantVariable!");
|
||||
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
|
||||
for (unsigned i = 0; i < index; i++) {
|
||||
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
|
||||
}
|
||||
return ConstantVariableType->as<ArrayType>()->getNumElements();
|
||||
} ///< 获取索引个数(从第0个开始)
|
||||
Value* getByIndex(unsigned index) const { return initValues.getValue(index); } ///< 通过一维位置index获取值
|
||||
Value* getByIndices(const std::vector<Value *> &indices) const {
|
||||
int index = 0;
|
||||
// 计算偏移量
|
||||
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||||
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
|
||||
// ConstantVariableType->as<ArrayType>()->getNumElements();
|
||||
auto dim_val = ConstantVariableType->as<ArrayType>()->getNumElements();
|
||||
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();
|
||||
index = dim_val * index + idx_val->getInt();
|
||||
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
|
||||
}
|
||||
|
||||
return getByIndex(index);
|
||||
} ///< 通过多维索引indices获取初始值
|
||||
unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
||||
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
||||
auto getDims() const { return getOperands(); } ///< 获取维度列表
|
||||
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
||||
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
||||
// auto getDims() const { return getOperands(); } ///< 获取维度列表
|
||||
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
||||
};
|
||||
|
||||
@ -1457,7 +1486,7 @@ class SymbolTable {
|
||||
SymbolTableNode *curNode{}; ///< 当前所在的作用域(符号表节点)
|
||||
std::map<std::string, unsigned> variableIndex; ///< 变量命名索引表
|
||||
std::vector<std::unique_ptr<GlobalValue>> globals; ///< 全局变量列表
|
||||
std::vector<std::unique_ptr<ConstantVariable>> consts; ///< 常量列表
|
||||
std::vector<std::unique_ptr<ConstantVariable>> globalconsts; ///< 全局常量列表
|
||||
std::vector<std::unique_ptr<SymbolTableNode>> nodeList; ///< 符号表节点列表
|
||||
|
||||
public:
|
||||
@ -1466,7 +1495,7 @@ class SymbolTable {
|
||||
Value* getVariable(const std::string &name) const; ///< 根据名字name以及当前作用域获取变量
|
||||
Value* addVariable(const std::string &name, Value *variable); ///< 添加变量
|
||||
std::vector<std::unique_ptr<GlobalValue>>& getGlobals(); ///< 获取全局变量列表
|
||||
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const; ///< 获取常量列表
|
||||
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const; ///< 获取全局常量列表
|
||||
void enterNewScope(); ///< 进入新的作用域
|
||||
void leaveScope(); ///< 离开作用域
|
||||
bool isInGlobalScope() const; ///< 是否位于全局作用域
|
||||
|
||||
@ -652,6 +652,7 @@ Function * CallInst::getCallee() const { return dynamic_cast<Function *>(getOper
|
||||
|
||||
/**
|
||||
* 获取变量指针
|
||||
* 如果在当前作用域或父作用域中找到变量,则返回该变量的指针,否则返回nullptr
|
||||
*/
|
||||
auto SymbolTable::getVariable(const std::string &name) const -> Value * {
|
||||
auto node = curNode;
|
||||
@ -688,7 +689,7 @@ auto SymbolTable::addVariable(const std::string &name, Value *variable) -> Value
|
||||
if (global != nullptr) {
|
||||
globals.emplace_back(global);
|
||||
} else if (constvar != nullptr) {
|
||||
consts.emplace_back(constvar);
|
||||
globalconsts.emplace_back(constvar);
|
||||
}
|
||||
|
||||
result = variable;
|
||||
@ -703,7 +704,7 @@ auto SymbolTable::getGlobals() -> std::vector<std::unique_ptr<GlobalValue>> & {
|
||||
/**
|
||||
* 获取常量
|
||||
*/
|
||||
auto SymbolTable::getConsts() const -> const std::vector<std::unique_ptr<ConstantVariable>> & { return consts; }
|
||||
auto SymbolTable::getConsts() const -> const std::vector<std::unique_ptr<ConstantVariable>> & { return globalconsts; }
|
||||
/**
|
||||
* 进入新的作用域
|
||||
*/
|
||||
|
||||
@ -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