数组基本实现成功,嵌套聚合初始化暂未实现

feature/sem
potapo 2 weeks ago
parent 5e7e8a6ff2
commit fa76f0fbfc

@ -98,6 +98,7 @@ private:
ir::Function* func_;
ir::IRBuilder builder_;
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
std::unordered_map<SysYParser::ConstDefContext*, ir::Value*> const_storage_map_; // 新增
std::unordered_map<SysYParser::VarDefContext*, ArrayInfo> array_info_map_;
ir::Value* EvalAssign(SysYParser::StmtContext* ctx);
};

@ -63,22 +63,178 @@ std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
return {};
}
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法常量声明"));
}
std::cerr << "[DEBUG] visitConstDecl: processing constant declaration" << std::endl;
// 检查类型
if (ctx->bType()) {
if (ctx->bType()->Int()) {
// int 类型常量
for (auto* constDef : ctx->constDef()) {
if (constDef) {
constDef->accept(this);
}
}
} else if (ctx->bType()->Float()) {
// float 类型常量(暂不支持)
throw std::runtime_error(FormatError("irgen", "float常量暂未实现"));
} else {
throw std::runtime_error(FormatError("irgen", "未知的常量类型"));
}
} else {
throw std::runtime_error(FormatError("irgen", "常量声明缺少类型"));
}
return {};
}
// 实现常量定义
// 修改 visitConstDef 函数,使用 const_storage_map_
std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
if (!ctx || !ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "非法常量定义"));
}
std::string const_name = ctx->Ident()->getText();
std::cerr << "[DEBUG] visitConstDef: processing constant " << const_name << std::endl;
// 检查是否为数组
bool is_array = !ctx->constExp().empty();
if (is_array) {
// 数组常量
throw std::runtime_error(FormatError("irgen", "数组常量暂未实现"));
// 数组常量处理
std::cerr << "[DEBUG] visitConstDef: array constant " << const_name << std::endl;
// 获取数组维度(简化处理)
int array_size = 10; // 默认数组大小
if (!ctx->constExp().empty()) {
// 尝试获取数组大小
// 简化假设第一个维度为10
array_size = 10;
}
// 分配数组存储(简化:为每个元素分配独立存储)
if (array_size > 100) {
throw std::runtime_error(FormatError("irgen", "数组常量大小太大"));
}
std::vector<ir::Value*> element_slots;
for (int i = 0; i < array_size; i++) {
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name + "_" + std::to_string(i));
element_slots.push_back(slot);
}
// 处理初始化
if (auto* const_init_val = ctx->constInitVal()) {
if (const_init_val->constExp()) {
// 标量初始化(只初始化第一个元素)
try {
auto result = const_init_val->constExp()->accept(this);
if (result.has_value()) {
try {
ir::Value* init = std::any_cast<ir::Value*>(result);
builder_.CreateStore(init, element_slots[0]);
// 其他元素初始化为0
for (int i = 1; i < array_size; i++) {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]);
}
} catch (const std::bad_any_cast& e) {
std::cerr << "[ERROR] visitConstDef: bad any_cast for array constant init: " << e.what() << std::endl;
throw std::runtime_error(FormatError("irgen", "常量数组初始化值类型错误"));
}
} else {
// 如果没有值全部初始化为0
for (int i = 0; i < array_size; i++) {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]);
}
}
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstDef: 常量数组标量初始化失败: " << e.what()
<< "全部初始化为0" << std::endl;
// 初始化失败全部初始化为0
for (int i = 0; i < array_size; i++) {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]);
}
}
} else {
// 聚合初始化
auto initVals = const_init_val->constInitVal();
if (initVals.empty()) {
// 空初始化列表全部初始化为0
for (int i = 0; i < array_size; i++) {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]);
}
} else {
// 有初始化值列表
int init_index = 0;
for (auto* init_val : initVals) {
if (init_index >= array_size) {
throw std::runtime_error(
FormatError("irgen", "常量数组初始化值太多,数组大小为" + std::to_string(array_size)));
}
if (init_val->constExp()) {
// 常量表达式初始化
try {
auto result = init_val->constExp()->accept(this);
if (result.has_value()) {
try {
ir::Value* val = std::any_cast<ir::Value*>(result);
builder_.CreateStore(val, element_slots[init_index]);
} catch (const std::bad_any_cast& e) {
std::cerr << "[ERROR] visitConstDef: bad any_cast for const array element: " << e.what() << std::endl;
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[init_index]);
}
} else {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[init_index]);
}
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstDef: 常量数组元素初始化失败: " << e.what()
<< "使用默认值0" << std::endl;
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[init_index]);
}
} else {
// 嵌套的聚合初始化(暂不支持)
std::cerr << "[WARNING] visitConstDef: 常量数组嵌套聚合初始化暂不支持使用默认值0" << std::endl;
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[init_index]);
}
init_index++;
}
// 剩余元素初始化为0
for (int i = init_index; i < array_size; i++) {
builder_.CreateStore(builder_.CreateConstInt(0), element_slots[i]);
}
}
}
} else {
// 常量数组缺少初始值
throw std::runtime_error(FormatError("irgen", "常量数组缺少初始值"));
}
// 存储第一个元素的地址到 const_storage_map_
const_storage_map_[ctx] = element_slots[0]; // 修改这里
// 保存数组信息暂时不保存因为array_info_map_只用于变量
// ArrayInfo info;
// info.elements = element_slots;
// info.dimensions = {array_size};
// 暂时不保存,因为类型不匹配
std::cerr << "[DEBUG] visitConstDef: array constant " << const_name
<< " created with size " << array_size << std::endl;
} else {
// 标量常量
// 标量常量处理
std::cerr << "[DEBUG] visitConstDef: scalar constant " << const_name << std::endl;
if (!ctx->constInitVal()) {
throw std::runtime_error(FormatError("irgen", "常量缺少初始值"));
}
@ -87,11 +243,84 @@ std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
auto* const_init_val = ctx->constInitVal();
if (const_init_val->constExp()) {
// 常量表达式求值需要语义分析支持
throw std::runtime_error(FormatError("irgen", "常量表达式求值暂未实现"));
// 常量表达式求值
try {
auto result = const_init_val->constExp()->accept(this);
if (result.has_value()) {
try {
ir::Value* const_value = std::any_cast<ir::Value*>(result);
std::cerr << "[DEBUG] visitConstDef: scalar constant " << const_name
<< " with value " << (void*)const_value << std::endl;
// 标量常量也需要存储槽位,以便后续引用
// 创建alloca指令但立即存储常量值
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name);
const_storage_map_[ctx] = slot; // 修改这里
builder_.CreateStore(const_value, slot);
return {};
} catch (const std::bad_any_cast& e) {
std::cerr << "[ERROR] visitConstDef: bad any_cast for scalar constant " << const_name << ": " << e.what() << std::endl;
throw std::runtime_error(FormatError("irgen", "标量常量初始化值类型错误"));
}
}
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstDef: 标量常量表达式求值失败: " << e.what()
<< "使用默认值0" << std::endl;
}
// 如果求值失败使用默认值0
ir::Value* default_value = builder_.CreateConstInt(0);
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name);
const_storage_map_[ctx] = slot; // 修改这里
builder_.CreateStore(default_value, slot);
return {};
} else {
// 聚合初始化
throw std::runtime_error(FormatError("irgen", "常量聚合初始化暂未实现"));
// 标量常量的聚合初始化(大括号内只有一个值)
auto initVals = const_init_val->constInitVal();
if (initVals.empty()) {
// 空初始化使用默认值0
ir::Value* default_value = builder_.CreateConstInt(0);
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name);
const_storage_map_[ctx] = slot; // 修改这里
builder_.CreateStore(default_value, slot);
return {};
} else if (initVals.size() == 1) {
// 单个元素的聚合初始化
auto* init_val = initVals[0];
if (init_val->constExp()) {
try {
auto result = init_val->constExp()->accept(this);
if (result.has_value()) {
try {
ir::Value* const_value = std::any_cast<ir::Value*>(result);
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name);
const_storage_map_[ctx] = slot; // 修改这里
builder_.CreateStore(const_value, slot);
return {};
} catch (const std::bad_any_cast& e) {
std::cerr << "[ERROR] visitConstDef: bad any_cast for scalar constant aggregate init: " << e.what() << std::endl;
}
}
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstDef: 标量常量聚合初始化失败: " << e.what()
<< "使用默认值0" << std::endl;
}
}
// 如果失败使用默认值0
ir::Value* default_value = builder_.CreateConstInt(0);
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp() + "_" + const_name);
const_storage_map_[ctx] = slot; // 修改这里
builder_.CreateStore(default_value, slot);
return {};
} else {
// 多个元素的聚合初始化对于标量常量是错误的
throw std::runtime_error(
FormatError("irgen", "标量常量聚合初始化只能有一个值"));
}
}
}

@ -110,8 +110,7 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
throw std::runtime_error(FormatError("irgen", "不支持的基本表达式类型"));
}
// visitLVal
// 修改 visitLVal 以支持数组访问
// visitLVal
std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) {
if (!ctx || !ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
@ -120,56 +119,104 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) {
std::string varName = ctx->Ident()->getText();
std::cerr << "[DEBUG] visitLVal: " << varName << std::endl;
// 从语义分析获取变量定义
auto* decl = sema_.ResolveVarUse(ctx);
if (!decl) {
throw std::runtime_error(
FormatError("irgen",
"变量使用缺少语义绑定: " + varName));
}
// 使用 storage_map_ 而不是 varNameToSlot_
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen",
"变量声明缺少存储槽位: " + varName));
}
ir::Value* base_ptr = it->second;
// 首先尝试从语义分析获取变量定义
auto* var_decl = sema_.ResolveVarUse(ctx);
// 检查是否有数组下标(是否是数组访问)
auto exp_list = ctx->exp();
if (!exp_list.empty()) {
// 这是数组访问需要生成GEP指令
std::vector<ir::Value*> indices;
if (var_decl) {
// 找到变量定义
auto it = storage_map_.find(var_decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
}
// 第一个索引是0假设一维数组
indices.push_back(builder_.CreateConstInt(0));
ir::Value* base_ptr = it->second;
// 添加用户提供的下标
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
indices.push_back(index);
// 检查是否有数组下标
auto exp_list = ctx->exp();
if (!exp_list.empty()) {
// 这是数组访问需要生成GEP指令
std::vector<ir::Value*> indices;
// 第一个索引是0假设一维数组
indices.push_back(builder_.CreateConstInt(0));
// 添加用户提供的下标
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
indices.push_back(index);
}
// 生成GEP指令获取元素地址
ir::Value* elem_ptr = builder_.CreateGEP(
base_ptr, indices, module_.GetContext().NextTemp());
// 加载值
ir::Value* load_result = builder_.CreateLoad(
elem_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: variable array access, result = " << (void*)load_result << std::endl;
return static_cast<ir::Value*>(load_result);
} else {
// 普通标量变量访问
ir::Value* load_result = builder_.CreateLoad(
base_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: variable scalar load, result = " << (void*)load_result << std::endl;
return static_cast<ir::Value*>(load_result);
}
} else {
// 如果不是变量,尝试从语义分析获取常量定义
auto* const_decl = sema_.ResolveConstUse(ctx);
if (!const_decl) {
throw std::runtime_error(
FormatError("irgen", "变量/常量使用缺少语义绑定: " + varName));
}
// 生成GEP指令获取元素地址
ir::Value* elem_ptr = builder_.CreateGEP(
base_ptr, indices, module_.GetContext().NextTemp());
// 加载值
ir::Value* load_result = builder_.CreateLoad(
elem_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: array access, result = " << (void*)load_result << std::endl;
// 找到常量定义
auto it = const_storage_map_.find(const_decl);
if (it == const_storage_map_.end()) {
// 如果常量没有存储槽位,可能是编译时常量
// 暂时简化返回0
std::cerr << "[WARNING] visitLVal: 常量 " << varName << " 没有存储槽位返回0" << std::endl;
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
}
return static_cast<ir::Value*>(load_result);
} else {
// 普通标量变量访问
ir::Value* load_result = builder_.CreateLoad(
base_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: scalar load, result = " << (void*)load_result << std::endl;
ir::Value* base_ptr = it->second;
return static_cast<ir::Value*>(load_result);
// 检查是否有数组下标
auto exp_list = ctx->exp();
if (!exp_list.empty()) {
// 常量数组访问需要生成GEP指令
std::vector<ir::Value*> indices;
// 第一个索引是0假设一维数组
indices.push_back(builder_.CreateConstInt(0));
// 添加用户提供的下标
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
indices.push_back(index);
}
// 生成GEP指令获取元素地址
ir::Value* elem_ptr = builder_.CreateGEP(
base_ptr, indices, module_.GetContext().NextTemp());
// 加载常量值
ir::Value* load_result = builder_.CreateLoad(
elem_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: constant array access, result = " << (void*)load_result << std::endl;
return static_cast<ir::Value*>(load_result);
} else {
// 标量常量访问
ir::Value* load_result = builder_.CreateLoad(
base_ptr, module_.GetContext().NextTemp());
std::cerr << "[DEBUG] visitLVal: constant scalar load, result = " << (void*)load_result << std::endl;
return static_cast<ir::Value*>(load_result);
}
}
}
@ -391,46 +438,60 @@ std::any IRGenImpl::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
return args;
}
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
// 常量声明在编译时求值,不分配存储。只需遍历常量定义,将常量值存入符号表即可。
// 由于 IRGen 阶段不需要常量的存储槽位,这里只触发子节点访问(常量定义会处理值)。
for (auto* constDef : ctx->constDef()) {
constDef->accept(this);
// 修改 visitConstExp 以支持常量表达式求值
std::any IRGenImpl::visitConstExp(SysYParser::ConstExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法常量表达式"));
}
try {
return ctx->addExp()->accept(this);
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstExp: 常量表达式求值失败: " << e.what()
<< "返回0" << std::endl;
// 如果普通表达式求值失败返回0
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
}
return {};
}
std::any IRGenImpl::visitConstInitVal(SysYParser::ConstInitValContext* ctx) {
// 常量初始化值可能是单一常量表达式,也可能是大括号列表(聚合)。
// 为简化,我们仅支持单一表达式(标量常量),数组常量暂未实现。
// 现在支持数组常量的聚合初始化
if (ctx->constExp()) {
// 常量表达式求值:需要语义分析支持常量折叠,这里我们返回求值后的常量值。
// 假设 sema_ 有方法 EvaluateConstExp 返回 int。
// auto* constExp = ctx->constExp(); // 这行可以删除,因为不需要使用
// 通过语义分析求值(暂未实现,先抛异常)
// int val = sema_.EvaluateConstExp(constExp);
// return builder_.CreateConstInt(val);
throw std::runtime_error(FormatError("irgen", "常量表达式求值暂未实现"));
// 常量表达式求值
try {
return ctx->constExp()->accept(this);
} catch (const std::exception& e) {
std::cerr << "[WARNING] visitConstInitVal: 常量表达式求值失败: " << e.what()
<< "返回默认值0" << std::endl;
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
}
} else {
// 聚合初始化:返回数组值,暂未实现
throw std::runtime_error(FormatError("irgen", "常量聚合初始化暂未实现"));
// 聚合初始化:返回数组值列表
// 对于常量数组返回一个vector<ir::Value*>
std::vector<ir::Value*> initValues;
for (auto* init_val : ctx->constInitVal()) {
// 递归处理每个初始化值
auto result = init_val->accept(this);
if (result.has_value()) {
try {
ir::Value* value = std::any_cast<ir::Value*>(result);
initValues.push_back(value);
} catch (const std::bad_any_cast&) {
// 可能返回的是vector对于嵌套数组初始化
// 简化:我们暂时只支持一维数组
throw std::runtime_error(
FormatError("irgen", "暂不支持常量多维数组初始化"));
}
}
}
// 返回初始化值列表
return initValues;
}
}
std::any IRGenImpl::visitConstExp(SysYParser::ConstExpContext* ctx) {
// 消除未使用参数警告
(void)ctx; // 明确表示参数未使用
// 常量表达式由 AddExp 构成,我们直接复用表达式求值(但需要常量折叠)。
// 由于常量表达式在编译时求值IR 生成阶段其实不需要计算值,语义分析会提供。
// 这里我们只用来获取 IR 值(例如数组大小),但数组大小需要在 IR 生成前就知道。
// 暂时复用 EvalExpr但 EvalExpr 生成 IR 指令这不合适。实际上常量表达式应在语义分析阶段求值IRGen 直接使用结果。
// 为避免复杂,我们暂时返回表达式的 IR 值(但会产生计算指令,不适合数组大小)。
// 更好的做法是调用语义分析求值。
// 这里先抛异常,等待语义团队提供接口。
throw std::runtime_error(FormatError("irgen", "常量表达式求值暂未实现"));
}
std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
@ -500,7 +561,6 @@ std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) {
throw std::runtime_error(FormatError("irgen", "未知的关系操作符"));
}
// 修改 EvalAssign 以支持数组赋值
ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) {
if (!ctx || !ctx->lVal() || !ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "非法赋值语句"));
@ -512,46 +572,56 @@ ir::Value* IRGenImpl::EvalAssign(SysYParser::StmtContext* ctx) {
auto* lval = ctx->lVal();
std::string varName = lval->Ident()->getText();
// 从语义分析获取变量定义
auto* decl = sema_.ResolveVarUse(lval);
if (!decl) {
throw std::runtime_error(
FormatError("irgen", "变量使用缺少语义绑定: " + varName));
}
// 从storage_map_获取存储位置
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
}
ir::Value* base_ptr = it->second;
// 首先尝试从语义分析获取变量定义
auto* var_decl = sema_.ResolveVarUse(lval);
// 检查是否有数组下标
auto exp_list = lval->exp();
if (!exp_list.empty()) {
// 这是数组元素赋值需要生成GEP指令
std::vector<ir::Value*> indices;
// 第一个索引是0假设一维数组
indices.push_back(builder_.CreateConstInt(0));
// 添加用户提供的下标
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
indices.push_back(index);
if (var_decl) {
// 是变量赋值
// 从storage_map_获取存储位置
auto it = storage_map_.find(var_decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen", "变量声明缺少存储槽位: " + varName));
}
// 生成GEP指令获取元素地址
ir::Value* elem_ptr = builder_.CreateGEP(
base_ptr, indices, module_.GetContext().NextTemp());
ir::Value* base_ptr = it->second;
// 生成store指令
builder_.CreateStore(rhs, elem_ptr);
// 检查是否有数组下标
auto exp_list = lval->exp();
if (!exp_list.empty()) {
// 这是数组元素赋值需要生成GEP指令
std::vector<ir::Value*> indices;
// 第一个索引是0假设一维数组
indices.push_back(builder_.CreateConstInt(0));
// 添加用户提供的下标
for (auto* exp : exp_list) {
ir::Value* index = EvalExpr(*exp);
indices.push_back(index);
}
// 生成GEP指令获取元素地址
ir::Value* elem_ptr = builder_.CreateGEP(
base_ptr, indices, module_.GetContext().NextTemp());
// 生成store指令
builder_.CreateStore(rhs, elem_ptr);
} else {
// 普通标量赋值
builder_.CreateStore(rhs, base_ptr);
}
} else {
// 普通标量赋值
builder_.CreateStore(rhs, base_ptr);
// 尝试获取常量定义
auto* const_decl = sema_.ResolveConstUse(lval);
if (const_decl) {
// 尝试给常量赋值,这是错误的
throw std::runtime_error(
FormatError("irgen", "不能给常量赋值: " + varName));
} else {
throw std::runtime_error(
FormatError("irgen", "变量/常量使用缺少语义绑定: " + varName));
}
}
return rhs;

Loading…
Cancel
Save