|
|
|
|
@ -42,30 +42,34 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 变量声明的 IR 生成目前也是最小实现:
|
|
|
|
|
// - 先检查声明的基础类型,当前仅支持局部 int;
|
|
|
|
|
// - 先检查声明的基础类型,支持 int 和 float;
|
|
|
|
|
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
|
|
|
|
|
//
|
|
|
|
|
// 和更完整的版本相比,这里还没有:
|
|
|
|
|
// - 一个 Decl 中多个变量定义的顺序处理;
|
|
|
|
|
// - const、数组、全局变量等不同声明形态;
|
|
|
|
|
// - 更丰富的类型系统。
|
|
|
|
|
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
|
|
|
|
|
if (!ctx) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
|
|
|
|
|
}
|
|
|
|
|
// 当前语法中 decl 包含 constDecl 或 varDecl,这里只支持 varDecl
|
|
|
|
|
auto* var_decl = ctx->varDecl();
|
|
|
|
|
if (!var_decl) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明"));
|
|
|
|
|
}
|
|
|
|
|
if (!var_decl->bType() || !var_decl->bType()->INT()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
|
|
|
|
|
}
|
|
|
|
|
// 遍历所有 varDef
|
|
|
|
|
for (auto* var_def : var_decl->varDef()) {
|
|
|
|
|
if (var_def) {
|
|
|
|
|
var_def->accept(this);
|
|
|
|
|
// 当前语法中 decl 包含 constDecl 或 varDecl
|
|
|
|
|
if (auto* var_decl = ctx->varDecl()) {
|
|
|
|
|
if (!var_decl->bType() || (!var_decl->bType()->INT() && !var_decl->bType()->FLOAT())) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 变量声明"));
|
|
|
|
|
}
|
|
|
|
|
for (auto* var_def : var_decl->varDef()) {
|
|
|
|
|
if (var_def) {
|
|
|
|
|
var_def->accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明"));
|
|
|
|
|
}
|
|
|
|
|
return BlockFlow::Continue;
|
|
|
|
|
}
|
|
|
|
|
@ -90,18 +94,68 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
|
|
|
|
|
if (storage_map_.find(var_name) != storage_map_.end()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
|
|
|
|
|
}
|
|
|
|
|
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
|
|
|
|
|
storage_map_[var_name] = slot;
|
|
|
|
|
|
|
|
|
|
ir::Value* init = nullptr;
|
|
|
|
|
if (auto* init_val = ctx->initVal()) {
|
|
|
|
|
if (!init_val->exp()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
|
|
// Determine base type from parent varDecl or constDecl
|
|
|
|
|
bool is_float = false;
|
|
|
|
|
auto* parent_decl = dynamic_cast<SysYParser::VarDeclContext*>(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();
|
|
|
|
|
|
|
|
|
|
if (func_ == nullptr) {
|
|
|
|
|
// 全局作用域
|
|
|
|
|
ir::ConstantValue* init_const = nullptr;
|
|
|
|
|
if (auto* init_val = ctx->initVal()) {
|
|
|
|
|
if (!init_val->exp()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
|
|
}
|
|
|
|
|
auto* val = EvalExpr(*init_val->exp());
|
|
|
|
|
init_const = dynamic_cast<ir::ConstantValue*>(val);
|
|
|
|
|
if (!init_const) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "全局变量初始化必须是常量"));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (is_float) {
|
|
|
|
|
init_const = module_.GetContext().GetConstFloat(0.0f);
|
|
|
|
|
} else {
|
|
|
|
|
init_const = module_.GetContext().GetConstInt(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
init = EvalExpr(*init_val->exp());
|
|
|
|
|
|
|
|
|
|
auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const);
|
|
|
|
|
storage_map_[var_name] = gv;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
init = builder_.CreateConstInt(0);
|
|
|
|
|
// 局部作用域
|
|
|
|
|
auto* ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type();
|
|
|
|
|
// 简化处理,暂用 builder 创建 alloca
|
|
|
|
|
// 需要在 builder 中扩展 CreateAllocaFloat,此处简化直接按 I32 Alloca 的名称调用,或添加新接口
|
|
|
|
|
// 为了不大幅改动 Builder,我们复用 AllocaInst,或者添加 CreateAlloca
|
|
|
|
|
ir::Value* slot = nullptr;
|
|
|
|
|
if (is_float) {
|
|
|
|
|
slot = builder_.CreateAllocaFloat(module_.GetContext().NextTemp());
|
|
|
|
|
} else {
|
|
|
|
|
slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
storage_map_[var_name] = slot;
|
|
|
|
|
|
|
|
|
|
ir::Value* init = nullptr;
|
|
|
|
|
if (auto* init_val = ctx->initVal()) {
|
|
|
|
|
if (!init_val->exp()) {
|
|
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
|
|
}
|
|
|
|
|
init = EvalExpr(*init_val->exp());
|
|
|
|
|
} else {
|
|
|
|
|
if (is_float) {
|
|
|
|
|
init = module_.GetContext().GetConstFloat(0.0f);
|
|
|
|
|
} else {
|
|
|
|
|
init = module_.GetContext().GetConstInt(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
builder_.CreateStore(init, slot);
|
|
|
|
|
}
|
|
|
|
|
builder_.CreateStore(init, slot);
|
|
|
|
|
|
|
|
|
|
return BlockFlow::Continue;
|
|
|
|
|
}
|
|
|
|
|
|