From fa76f0fbfc8d9a5e18574a38d5a46845f4104a15 Mon Sep 17 00:00:00 2001 From: potapo <2720187907@qq.com> Date: Fri, 27 Mar 2026 21:16:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E7=BB=84=E5=9F=BA=E6=9C=AC=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=88=90=E5=8A=9F=EF=BC=8C=E5=B5=8C=E5=A5=97=E8=81=9A?= =?UTF-8?q?=E5=90=88=E5=88=9D=E5=A7=8B=E5=8C=96=E6=9A=82=E6=9C=AA=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/irgen/IRGen.h | 1 + src/irgen/IRGenDecl.cpp | 243 ++++++++++++++++++++++++++++++++- src/irgen/IRGenExp.cpp | 292 +++++++++++++++++++++++++--------------- 3 files changed, 418 insertions(+), 118 deletions(-) diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index 918229d..d0ed404 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -98,6 +98,7 @@ private: ir::Function* func_; ir::IRBuilder builder_; std::unordered_map storage_map_; + std::unordered_map const_storage_map_; // 新增 std::unordered_map array_info_map_; ir::Value* EvalAssign(SysYParser::StmtContext* ctx); }; diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 12dce7b..e41a6fd 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -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 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(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(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(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(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", "标量常量聚合初始化只能有一个值")); + } } } diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index b0cb31f..7f7e7ef 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -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 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 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(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(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(builder_.CreateConstInt(0)); + } - return static_cast(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(load_result); + // 检查是否有数组下标 + auto exp_list = ctx->exp(); + if (!exp_list.empty()) { + // 常量数组访问,需要生成GEP指令 + std::vector 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(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(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(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(builder_.CreateConstInt(0)); + } } else { - // 聚合初始化:返回数组值,暂未实现 - throw std::runtime_error(FormatError("irgen", "常量聚合初始化暂未实现")); + // 聚合初始化:返回数组值列表 + // 对于常量数组,返回一个vector + std::vector initValues; + + for (auto* init_val : ctx->constInitVal()) { + // 递归处理每个初始化值 + auto result = init_val->accept(this); + if (result.has_value()) { + try { + ir::Value* value = std::any_cast(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 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 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;