|
|
|
|
@ -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;
|
|
|
|
|
|