|
|
|
|
@ -41,6 +41,67 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
|
|
|
|
|
if (!ctx) return BlockFlow::Continue;
|
|
|
|
|
|
|
|
|
|
if (!ctx->bType() || (!ctx->bType()->INT() && !ctx->bType()->FLOAT())) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 常量声明"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto* def : ctx->constDef()) {
|
|
|
|
|
if (def) def->accept(this);
|
|
|
|
|
}
|
|
|
|
|
return BlockFlow::Continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) {
|
|
|
|
|
if (!ctx || !ctx->ID()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "常量定义缺少名称"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ctx->constIndex().empty()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "暂不支持数组常量声明"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string var_name = ctx->ID()->getText();
|
|
|
|
|
|
|
|
|
|
bool is_float = false;
|
|
|
|
|
auto* parent_decl = dynamic_cast<SysYParser::ConstDeclContext*>(ctx->parent);
|
|
|
|
|
if (parent_decl && parent_decl->bType() && parent_decl->bType()->FLOAT()) {
|
|
|
|
|
is_float = true;
|
|
|
|
|
}
|
|
|
|
|
auto base_ty = is_float ? ir::Type::GetFloatType() : ir::Type::GetInt32Type();
|
|
|
|
|
|
|
|
|
|
ir::ConstantValue* init_const = nullptr;
|
|
|
|
|
if (auto* init_val = ctx->constInitVal()) {
|
|
|
|
|
if (init_val->constExp()) {
|
|
|
|
|
auto val_any = init_val->constExp()->accept(this);
|
|
|
|
|
ir::Value* val = std::any_cast<ir::Value*>(val_any);
|
|
|
|
|
init_const = dynamic_cast<ir::ConstantValue*>(val);
|
|
|
|
|
if (!init_const) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "常量初始化必须是编译期常量: " + var_name));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录常量值供后续直接使用
|
|
|
|
|
const_values_[var_name] = init_const;
|
|
|
|
|
|
|
|
|
|
if (func_ == nullptr) {
|
|
|
|
|
auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const);
|
|
|
|
|
storage_map_[var_name] = gv;
|
|
|
|
|
} else {
|
|
|
|
|
ir::Value* slot = is_float ? builder_.CreateAllocaFloat(module_.GetContext().NextTemp())
|
|
|
|
|
: builder_.CreateAllocaI32(module_.GetContext().NextTemp());
|
|
|
|
|
storage_map_[var_name] = slot;
|
|
|
|
|
builder_.CreateStore(init_const, slot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BlockFlow::Continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 变量声明的 IR 生成目前也是最小实现:
|
|
|
|
|
// - 先检查声明的基础类型,支持 int 和 float;
|
|
|
|
|
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
|
|
|
|
|
@ -59,15 +120,7 @@ std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (auto* const_decl = ctx->constDecl()) {
|
|
|
|
|
// 稍后实现 constDecl
|
|
|
|
|
if (!const_decl->bType() || (!const_decl->bType()->INT() && !const_decl->bType()->FLOAT())) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 常量声明"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* const_def : const_decl->constDef()) {
|
|
|
|
|
if (const_def) {
|
|
|
|
|
const_def->accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return const_decl->accept(this);
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明"));
|
|
|
|
|
}
|
|
|
|
|
|