fix(sem)解决常量数组初始化错误问题

mxr 2 weeks ago
parent c8f40ea09a
commit e79d677644

@ -90,9 +90,17 @@ class SymbolTable {
float float_val;
};
};
void flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const;
void fillArray(
std::vector<ConstValue>& values,
size_t& index,
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,
size_t dim_idx,
std::shared_ptr<ir::Type> base_type) const;
void fillZero(std::vector<ConstValue>& values, size_t& index,
const std::vector<int>& dims, size_t dim_idx,
std::shared_ptr<ir::Type> base_type) const;
std::vector<ConstValue> EvaluateConstInitVal(
SysYParser::ConstInitValContext* ctx,
const std::vector<int>& dims,

@ -383,7 +383,10 @@ SymbolTable::ConstValue SymbolTable::EvaluatePrimaryExp(SysYParser::PrimaryExpCo
auto lval = ctx->lVal();
if (!lval->Ident()) throw std::runtime_error("常量表达式求值:无效左值");
std::string name = lval->Ident()->getText();
DEBUG_MSG(" 左值标识符: " << name);
const Symbol* sym = lookup(name);
DEBUG_MSG(" 找到符号: kind=" << (int)sym->kind << ", value="
<< (sym->is_int_const ? std::to_string(sym->const_value.i32) : std::to_string(sym->const_value.f32)));
if (!sym) throw std::runtime_error("常量表达式求值:未定义的标识符 " + name);
if (sym->kind != SymbolKind::Constant)
throw std::runtime_error("常量表达式求值:标识符 " + name + " 不是常量");
@ -405,6 +408,7 @@ SymbolTable::ConstValue SymbolTable::EvaluatePrimaryExp(SysYParser::PrimaryExpCo
ConstValue val;
val.kind = ConstValue::FLOAT;
val.float_val = ParseFloatLiteral(text);
DEBUG_MSG(" 浮点字面量: " << text << " -> " << val.float_val);
return val;
}
else if (ctx->HEX_INT() || ctx->OCTAL_INT() || ctx->DECIMAL_INT() || ctx->ZERO()) {
@ -416,6 +420,7 @@ SymbolTable::ConstValue SymbolTable::EvaluatePrimaryExp(SysYParser::PrimaryExpCo
ConstValue val;
val.kind = ConstValue::INT;
val.int_val = static_cast<int>(ParseIntegerLiteral(text));
DEBUG_MSG(" 整数字面量: " << text << " -> " << val.int_val);
return val;
}
else if (ctx->exp()) {
@ -435,6 +440,8 @@ SymbolTable::ConstValue SymbolTable::EvaluateUnaryExp(SysYParser::UnaryExpContex
else if (ctx->unaryOp()) {
ConstValue operand = EvaluateUnaryExp(ctx->unaryExp());
std::string op = ctx->unaryOp()->getText();
DEBUG_MSG("EvaluateUnaryExp: 操作符=" << op);
DEBUG_MSG(" 操作数=" << (operand.kind==ConstValue::INT ? std::to_string(operand.int_val) : std::to_string(operand.float_val)));
if (op == "+") {
return operand;
@ -470,10 +477,15 @@ SymbolTable::ConstValue SymbolTable::EvaluateMulExp(SysYParser::MulExpContext* c
if (!ctx) throw std::runtime_error("常量表达式求值:无效 MulExp");
if (ctx->mulExp()) {
DEBUG_MSG("EvaluateMulExp: 左子表达式");
ConstValue left = EvaluateMulExp(ctx->mulExp());
DEBUG_MSG(" 左值=" << (left.kind==ConstValue::INT ? std::to_string(left.int_val) : std::to_string(left.float_val)));
ConstValue right = EvaluateUnaryExp(ctx->unaryExp());
std::string op;
DEBUG_MSG(" 运算符=" << op);
DEBUG_MSG(" 右值=" << (right.kind==ConstValue::INT ? std::to_string(right.int_val) : std::to_string(right.float_val)));
if (ctx->MulOp()) op = "*";
else if (ctx->DivOp()) op = "/";
else if (ctx->QuoOp()) op = "%";
@ -550,7 +562,9 @@ SymbolTable::ConstValue SymbolTable::EvaluateAddExp(SysYParser::AddExpContext* c
int SymbolTable::EvaluateConstExp(SysYParser::ConstExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error("常量表达式求值:无效 ConstExp");
DEBUG_MSG("EvaluateConstExp: 表达式文本=" << ctx->getText());
ConstValue val = EvaluateAddExp(ctx->addExp());
DEBUG_MSG(" 求值结果: " << (val.kind==ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val)));
if (val.kind == ConstValue::INT) {
return val.int_val;
} else {
@ -566,7 +580,9 @@ int SymbolTable::EvaluateConstExp(SysYParser::ConstExpContext* ctx) const {
float SymbolTable::EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const {
if (!ctx || !ctx->addExp())
throw std::runtime_error("常量表达式求值:无效 ConstExp");
DEBUG_MSG("EvaluateConstExpFloat: 表达式文本=" << ctx->getText());
ConstValue val = EvaluateAddExp(ctx->addExp());
DEBUG_MSG(" 求值结果: " << (val.kind==ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val)));
if (val.kind == ConstValue::INT) {
return static_cast<float>(val.int_val);
} else {
@ -574,47 +590,97 @@ float SymbolTable::EvaluateConstExpFloat(SysYParser::ConstExpContext* ctx) const
}
}
void SymbolTable::flattenInit(SysYParser::ConstInitValContext* ctx,
std::vector<ConstValue>& out,
std::shared_ptr<ir::Type> base_type) const {
if (!ctx) return;
// 获取当前初始化列表的文本(用于调试)
std::string ctxText;
if (ctx->constExp()) {
ctxText = ctx->constExp()->getText();
} else {
ctxText = "{ ... }";
}
if (ctx->constExp()) {
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
DEBUG_MSG("处理常量表达式: " << ctxText
<< " 类型=" << (val.kind == ConstValue::INT ? "INT" : "FLOAT")
<< " 值=" << (val.kind == ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val))
<< " 目标类型=" << (base_type->IsInt32() ? "Int32" : "Float"));
// 整型数组不能接受浮点常量
if (base_type->IsInt32() && val.kind == ConstValue::FLOAT) {
DEBUG_MSG("错误:整型数组遇到浮点常量,值=" << val.float_val);
throw std::runtime_error("常量初始化:整型数组不能使用浮点常量");
// 递归填充函数,按维度填充值
void SymbolTable::fillArray(
std::vector<ConstValue>& values, // 存储最终所有元素(行优先)
size_t& index, // 当前填充到的位置
SysYParser::ConstInitValContext* ctx, // 当前初始化列表节点
const std::vector<int>& dims, // 剩余维度
size_t dim_idx, // 当前维度索引
std::shared_ptr<ir::Type> base_type) const // 元素基本类型
{
DEBUG_MSG("fillArray: 进入dim_idx=" << dim_idx
<< ", 剩余维度=" << (dims.size() - dim_idx)
<< ", 当前index=" << index);
// 如果已经是最内层(单个元素)
if (dim_idx == dims.size()) {
// 必须是单个表达式
if (!ctx || !ctx->constExp()) {
throw std::runtime_error("初始化值不是标量");
}
// 浮点数组接受整型常量,并隐式转换
if (base_type->IsFloat() && val.kind == ConstValue::INT) {
DEBUG_MSG("浮点数组接收整型常量,隐式转换为浮点: " << val.int_val);
val.kind = ConstValue::FLOAT;
val.float_val = static_cast<float>(val.int_val);
ConstValue val = EvaluateAddExp(ctx->constExp()->addExp());
// 类型检查和转换...
DEBUG_MSG(" 填充标量值: index=" << index
<< ", 值=" << (val.kind == ConstValue::INT ? std::to_string(val.int_val) : std::to_string(val.float_val)));
values[index++] = val;
return;
}
// 当前维度的元素个数
size_t cur_dim_size = dims[dim_idx];
DEBUG_MSG(" 当前维度大小=" << cur_dim_size << ", 是否是花括号列表=" << (ctx && !ctx->constExp()));
// 如果是花括号列表,则按子项填充
if (ctx && !ctx->constExp()) { // 花括号
auto sub_vals = ctx->constInitVal();
DEBUG_MSG(" 花括号列表,子项数量=" << sub_vals.size());
// 对于每个子项,填充一个子数组
for (size_t i = 0; i < cur_dim_size; ++i) {
DEBUG_MSG(" 处理子项 " << i << " / " << cur_dim_size);
if (i < sub_vals.size()) {
fillArray(values, index, sub_vals[i], dims, dim_idx + 1, base_type);
} else {
// 子项不足,填充零
DEBUG_MSG(" 子项不足,填充零");
fillZero(values, index, dims, dim_idx + 1, base_type);
}
}
out.push_back(val);
} else {
DEBUG_MSG("进入花括号初始化列表: " << ctxText);
// 花括号初始化列表:递归展开所有子项
for (auto* sub : ctx->constInitVal()) {
flattenInit(sub, out, base_type);
// 不是花括号,即单个值,应视为对当前维度第一个元素的初始化,其余补零
// 第一个子数组
DEBUG_MSG(" 单个值(非花括号),将填充第一个子数组,其余补零");
if (ctx && ctx->constExp()) {
fillArray(values, index, ctx, dims, dim_idx + 1, base_type);
} else {
DEBUG_MSG(" 无初始化值,第一个子数组也补零");
fillZero(values, index, dims, dim_idx + 1, base_type);
}
// 剩余子数组补零
for (size_t i = 1; i < cur_dim_size; ++i) {
DEBUG_MSG(" 填充第" << i << "个子数组为零");
fillZero(values, index, dims, dim_idx + 1, base_type);
}
}
DEBUG_MSG("fillArray: 退出index=" << index);
}
// 填充指定数量的零
void SymbolTable::fillZero(std::vector<ConstValue>& values, size_t& index,
const std::vector<int>& dims, size_t dim_idx,
std::shared_ptr<ir::Type> base_type) const
{
DEBUG_MSG("fillZero: 进入dim_idx=" << dim_idx << ", 当前index=" << index);
if (dim_idx == dims.size()) {
ConstValue zero;
if (base_type->IsInt32()) {
zero.kind = ConstValue::INT;
zero.int_val = 0;
} else {
zero.kind = ConstValue::FLOAT;
zero.float_val = 0.0f;
}
DEBUG_MSG("退出花括号初始化列表");
DEBUG_MSG(" 填充零值: index=" << index);
values[index++] = zero;
return;
}
size_t cur_dim_size = dims[dim_idx];
DEBUG_MSG(" fillZero 当前维度大小=" << cur_dim_size);
for (size_t i = 0; i < cur_dim_size; ++i) {
DEBUG_MSG(" fillZero 子项 " << i);
fillZero(values, index, dims, dim_idx + 1, base_type);
}
DEBUG_MSG("fillZero: 退出");
}
std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
@ -624,6 +690,7 @@ std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
// ========== 1. 标量常量dims 为空)==========
if (dims.empty()) {
DEBUG_MSG(" 标量常量初始化,表达式=" << ctx->getText());
if (!ctx || !ctx->constExp()) {
throw std::runtime_error("标量常量初始化必须使用单个表达式");
}
@ -649,32 +716,22 @@ std::vector<SymbolTable::ConstValue> SymbolTable::EvaluateConstInitVal(
// ========== 2. 数组常量dims 非空)==========
// 计算数组总元素个数
DEBUG_MSG("EvaluateConstInitVal: 开始,维度=" << dims.size());
size_t total = 1;
for (int d : dims) total *= d;
DEBUG_MSG(" 数组常量初始化,总元素数=" << total);
std::vector<ConstValue> values(total);
size_t index = 0;
fillArray(values, index, ctx, dims, 0, base_type);
// 展平初始化列表(递归处理花括号)
std::vector<ConstValue> flat;
flattenInit(ctx, flat, base_type);
// 检查数量是否超过数组容量
if (flat.size() > total) {
throw std::runtime_error("常量初始化:提供的初始值数量超过数组元素总数");
}
// 不足的部分补零
if (flat.size() < total) {
ConstValue zero;
if (base_type->IsInt32()) {
zero.kind = ConstValue::INT;
zero.int_val = 0;
} else {
zero.kind = ConstValue::FLOAT;
zero.float_val = 0.0f;
}
flat.resize(total, zero);
DEBUG_MSG("EvaluateConstInitVal: 填充完成最终index=" << index);
// 可选:打印所有填充的值
for (size_t i = 0; i < values.size(); ++i) {
DEBUG_MSG(" values[" << i << "] = " << (values[i].kind == ConstValue::INT ? std::to_string(values[i].int_val) : std::to_string(values[i].float_val)));
}
return flat;
return values;
}
int SymbolTable::EvaluateConstExpression(SysYParser::ExpContext* ctx) const {

Loading…
Cancel
Save