#include "irgen/IRGen.h" #include #include #include #include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少语句块")); } const auto saved_const_env = const_env_; const auto saved_const_float_env = const_float_env_; for (auto* item : ctx->blockItem()) { if (item) { if (VisitBlockItemResult(*item) == BlockFlow::Terminated) { break; } } } const_env_ = saved_const_env; const_float_env_ = saved_const_float_env; return {}; } IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult( SysYParser::BlockItemContext& item) { return std::any_cast(item.accept(this)); } std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少块内项")); } if (ctx->decl()) { ctx->decl()->accept(this); return BlockFlow::Continue; } if (ctx->stmt()) { return ctx->stmt()->accept(this); } throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明")); } std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } if (ctx->constDecl()) { return ctx->constDecl()->accept(this); } if (ctx->varDecl()) { return ctx->varDecl()->accept(this); } return {}; } // ─── 工具:扁平化 constInitValue ────────────────────────────────────────── // 将嵌套的 const 初始化列表展开为长度 total 的整数数组。 // 遵循 C99 数组初始化规则: // - 标量直接填一格 // - 大括号子列表对齐到 sub_size 边界,填满后补零 void IRGenImpl::FlattenConstInit(SysYParser::ConstInitValueContext* ctx, const std::vector& dims, int dim_idx, std::vector& out, int& pos) { if (!ctx) return; if (ctx->constExp()) { // 标量叶节点 out[pos++] = EvalConstExpr(ctx->constExp()); return; } // 大括号列表 int sub_size = 1; for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i]; int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1; int start = pos; for (auto* item : ctx->constInitValue()) { if (!item || pos >= start + agg_size) break; if (item->constExp()) { // 标量:直接填当前位置 out[pos++] = EvalConstExpr(item->constExp()); } else { // 嵌套大括号:对齐到 sub_size 边界 if (sub_size > 1) { int offset = pos - start; int rem = offset % sub_size; if (rem != 0) pos += sub_size - rem; } int sub_start = pos; FlattenConstInit(item, dims, dim_idx + 1, out, pos); // 补零到子聚合末尾 int sub_end = sub_start + sub_size; while (pos < sub_end && pos < start + agg_size) out[pos++] = 0; } } // 剩余补零 while (pos < start + agg_size) out[pos++] = 0; } void IRGenImpl::FlattenConstInitFloat(SysYParser::ConstInitValueContext* ctx, const std::vector& dims, int dim_idx, std::vector& out, int& pos) { if (!ctx) return; if (ctx->constExp()) { out[pos++] = EvalConstExprAsFloat(ctx->constExp()); return; } int sub_size = 1; for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i]; int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1; int start = pos; for (auto* item : ctx->constInitValue()) { if (!item || pos >= start + agg_size) break; if (item->constExp()) { out[pos++] = EvalConstExprAsFloat(item->constExp()); } else { if (sub_size > 1) { int offset = pos - start; int rem = offset % sub_size; if (rem != 0) pos += sub_size - rem; } int sub_start = pos; FlattenConstInitFloat(item, dims, dim_idx + 1, out, pos); int sub_end = sub_start + sub_size; while (pos < sub_end && pos < start + agg_size) out[pos++] = 0.0f; } } while (pos < start + agg_size) out[pos++] = 0.0f; } // ─── 工具:扁平化 initValue ─────────────────────────────────────────────── void IRGenImpl::FlattenInit(SysYParser::InitValueContext* ctx, const std::vector& dims, int dim_idx, std::vector& out, int& pos) { if (!ctx) return; if (ctx->exp()) { out[pos++] = EvalExpr(*ctx->exp()); return; } int sub_size = 1; for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i]; int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1; int start = pos; for (auto* item : ctx->initValue()) { if (!item || pos >= start + agg_size) break; if (item->exp()) { out[pos++] = EvalExpr(*item->exp()); } else { if (sub_size > 1) { int offset = pos - start; int rem = offset % sub_size; if (rem != 0) pos += sub_size - rem; // zeros already in out } int sub_start = pos; FlattenInit(item, dims, dim_idx + 1, out, pos); int sub_end = sub_start + sub_size; while (pos < sub_end && pos < start + agg_size) pos++; // zeros } } while (pos < start + agg_size) pos++; // zeros } void IRGenImpl::FlattenGlobalInitInt(SysYParser::InitValueContext* ctx, const std::vector& dims, int dim_idx, std::vector& out, int& pos) { if (!ctx) return; if (ctx->exp()) { out[pos++] = EvalExpAsConst(ctx->exp()); return; } int sub_size = 1; for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i]; int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1; int start = pos; for (auto* item : ctx->initValue()) { if (!item || pos >= start + agg_size) break; if (item->exp()) { out[pos++] = EvalExpAsConst(item->exp()); } else { if (sub_size > 1) { int offset = pos - start; int rem = offset % sub_size; if (rem != 0) pos += sub_size - rem; } int sub_start = pos; FlattenGlobalInitInt(item, dims, dim_idx + 1, out, pos); int sub_end = sub_start + sub_size; while (pos < sub_end && pos < start + agg_size) out[pos++] = 0; } } while (pos < start + agg_size) out[pos++] = 0; } void IRGenImpl::FlattenGlobalInitFloat(SysYParser::InitValueContext* ctx, const std::vector& dims, int dim_idx, std::vector& out, int& pos) { if (!ctx) return; if (ctx->exp()) { out[pos++] = EvalExpAsConstFloat(ctx->exp()); return; } int sub_size = 1; for (int i = dim_idx + 1; i < (int)dims.size(); i++) sub_size *= dims[i]; int agg_size = (dim_idx < (int)dims.size()) ? dims[dim_idx] * sub_size : 1; int start = pos; for (auto* item : ctx->initValue()) { if (!item || pos >= start + agg_size) break; if (item->exp()) { out[pos++] = EvalExpAsConstFloat(item->exp()); } else { if (sub_size > 1) { int offset = pos - start; int rem = offset % sub_size; if (rem != 0) pos += sub_size - rem; } int sub_start = pos; FlattenGlobalInitFloat(item, dims, dim_idx + 1, out, pos); int sub_end = sub_start + sub_size; while (pos < sub_end && pos < start + agg_size) out[pos++] = 0.0f; } } while (pos < start + agg_size) out[pos++] = 0.0f; } // ─── const 声明 ─────────────────────────────────────────────────────────── std::any IRGenImpl::visitConstDecl(SysYParser::ConstDeclContext* ctx) { if (!ctx) return {}; if (!ctx->btype()) { throw std::runtime_error(FormatError("irgen", "缺少类型声明")); } if (ctx->btype()->INT()) { current_decl_type_ = ir::Type::GetInt32Type(); } else if (ctx->btype()->FLOAT()) { current_decl_type_ = ir::Type::GetFloat32Type(); } else { throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float const 声明")); } for (auto* def : ctx->constDef()) { if (def) def->accept(this); } current_decl_type_ = nullptr; return {}; } std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) { if (!ctx || !ctx->ID()) return {}; const std::string name = ctx->ID()->getText(); // ── 标量 const ──────────────────────────────────────────────────────── if (ctx->LBRACK().empty()) { if (!ctx->constInitValue() || !ctx->constInitValue()->constExp()) { throw std::runtime_error(FormatError("irgen", "const 标量声明缺少初始值")); } const bool is_float_const = current_decl_type_ && current_decl_type_->IsFloat32(); if (is_float_const) { float fval = EvalConstExprAsFloat(ctx->constInitValue()->constExp()); const_float_env_[name] = fval; if (IsGlobalScope()) { std::int32_t bits = 0; std::memcpy(&bits, &fval, sizeof(bits)); auto* gv = module_.CreateGlobalVar( name, static_cast(bits), 1, ir::Type::GetPtrFloat32Type()); global_storage_[name] = gv; } else { auto* slot = CreateEntryAllocaF32(module_.GetContext().NextTemp()); named_storage_[name] = slot; builder_.CreateStore(module_.GetContext().GetConstFloat(fval), slot); } } else { int ival = EvalConstExpr(ctx->constInitValue()->constExp()); const_env_[name] = ival; // 存入编译期环境 if (IsGlobalScope()) { auto* gv = module_.CreateGlobalVar(name, ival); global_storage_[name] = gv; } else { auto* slot = CreateEntryAllocaI32(module_.GetContext().NextTemp()); named_storage_[name] = slot; builder_.CreateStore(builder_.CreateConstInt(ival), slot); } } return {}; } // ── 数组 const ──────────────────────────────────────────────────────── std::vector dims; for (auto* ce : ctx->constExp()) { dims.push_back(EvalConstExpr(ce)); } int total = 1; for (int d : dims) total *= d; const bool is_float_const = current_decl_type_ && current_decl_type_->IsFloat32(); if (is_float_const) { std::vector flat(total, 0.0f); if (ctx->constInitValue()) { int pos = 0; FlattenConstInitFloat(ctx->constInitValue(), dims, 0, flat, pos); } std::vector init_bits; init_bits.reserve(flat.size()); for (float v : flat) { std::int32_t bits = 0; std::memcpy(&bits, &v, sizeof(bits)); init_bits.push_back(static_cast(bits)); } if (IsGlobalScope()) { auto* gv = module_.CreateGlobalVar( name, 0, total, ir::Type::GetPtrFloat32Type(), std::move(init_bits)); global_storage_[name] = gv; global_array_dims_[name] = dims; } else { auto* slot = CreateEntryAllocaF32Array(total, module_.GetContext().NextTemp()); named_storage_[name] = slot; local_array_dims_[name] = dims; for (int i = 0; i < total; i++) { auto* idx = builder_.CreateConstInt(i); auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp()); builder_.CreateStore(module_.GetContext().GetConstFloat(flat[i]), ptr); } } return {}; } // 扁平化初始化值 std::vector flat(total, 0); if (ctx->constInitValue()) { int pos = 0; FlattenConstInit(ctx->constInitValue(), dims, 0, flat, pos); } if (IsGlobalScope()) { auto* gv = module_.CreateGlobalVar(name, 0, total, ir::Type::GetPtrInt32Type(), std::move(flat)); global_storage_[name] = gv; global_array_dims_[name] = dims; } else { // 局部 const 数组:alloca + 逐元素 store auto* slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp()); named_storage_[name] = slot; local_array_dims_[name] = dims; for (int i = 0; i < total; i++) { auto* idx = builder_.CreateConstInt(i); auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp()); builder_.CreateStore(builder_.CreateConstInt(flat[i]), ptr); } } return {}; } // ─── var 声明 ───────────────────────────────────────────────────────────── std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } if (!ctx->btype()) { throw std::runtime_error(FormatError("irgen", "缺少类型声明")); } // 设置当前声明类型 if (ctx->btype()->INT()) { current_decl_type_ = ir::Type::GetInt32Type(); } else if (ctx->btype()->FLOAT()) { current_decl_type_ = ir::Type::GetFloat32Type(); } else { throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 变量声明")); } for (auto* var_def : ctx->varDef()) { if (!var_def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } var_def->accept(this); } current_decl_type_ = nullptr; // 清理 return {}; } std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx || !ctx->ID()) { throw std::runtime_error(FormatError("irgen", "变量定义缺少名称")); } const std::string name = ctx->ID()->getText(); // ── 数组变量 ────────────────────────────────────────────────────────── if (!ctx->LBRACK().empty()) { std::vector dims; for (auto* ce : ctx->constExp()) { dims.push_back(EvalConstExpr(ce)); } int total = 1; for (int d : dims) total *= d; if (IsGlobalScope()) { std::vector init_elems; if (auto* init_val = ctx->initValue()) { if (current_decl_type_->IsFloat32()) { std::vector flat(total, 0.0f); int pos = 0; FlattenGlobalInitFloat(init_val, dims, 0, flat, pos); init_elems.reserve(flat.size()); for (float v : flat) { std::int32_t bits = 0; std::memcpy(&bits, &v, sizeof(bits)); init_elems.push_back(static_cast(bits)); } } else { init_elems.assign(total, 0); int pos = 0; FlattenGlobalInitInt(init_val, dims, 0, init_elems, pos); } } auto* gv = module_.CreateGlobalVar( name, 0, total, current_decl_type_->IsFloat32() ? ir::Type::GetPtrFloat32Type() : ir::Type::GetPtrInt32Type(), std::move(init_elems)); storage_map_[ctx] = gv; global_storage_[name] = gv; global_array_dims_[name] = dims; } else { // 根据当前声明类型创建数组alloca ir::AllocaInst* slot; if (current_decl_type_->IsFloat32()) { slot = CreateEntryAllocaF32Array(total, module_.GetContext().NextTemp()); } else { slot = CreateEntryAllocaArray(total, module_.GetContext().NextTemp()); } storage_map_[ctx] = slot; named_storage_[name] = slot; local_array_dims_[name] = dims; // 先零初始化:float 数组走 memset,int 数组维持逐元素 store。 if (current_decl_type_->IsFloat32()) { if (total > 0) { auto* memset_fn = module_.FindFunction("memset"); if (!memset_fn) { memset_fn = module_.CreateFunction( "memset", ir::Type::GetVoidType(), {ir::Type::GetPtrFloat32Type(), ir::Type::GetInt32Type(), ir::Type::GetInt32Type()}); memset_fn->SetExternal(true); } builder_.CreateCall( memset_fn, {slot, builder_.CreateConstInt(0), builder_.CreateConstInt(total * 4)}, module_.GetContext().NextTemp()); } } else { for (int i = 0; i < total; i++) { auto* idx = builder_.CreateConstInt(i); auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp()); builder_.CreateStore(builder_.CreateConstInt(0), ptr); } } // 如果有初始化列表,覆盖零 if (auto* init_val = ctx->initValue()) { std::vector flat(total, nullptr); int pos = 0; FlattenInit(init_val, dims, 0, flat, pos); for (int i = 0; i < total; i++) { if (flat[i] != nullptr) { auto* idx = builder_.CreateConstInt(i); auto* ptr = builder_.CreateGep(slot, idx, module_.GetContext().NextTemp()); ir::Value* val = flat[i]; if (ptr->GetType()->IsPtrFloat32()) { val = CastToFloat(val); } else { val = CastToInt(val); } builder_.CreateStore(val, ptr); } } } } return {}; } // ── 标量变量 ────────────────────────────────────────────────────────── if (IsGlobalScope()) { int init_bits_or_int = 0; if (current_decl_type_->IsFloat32()) { float fval = 0.0f; if (auto* init_value = ctx->initValue()) { if (!init_value->exp()) { throw std::runtime_error( FormatError("irgen", "全局标量变量仅支持表达式初始化")); } fval = EvalExpAsConstFloat(init_value->exp()); } std::int32_t bits = 0; std::memcpy(&bits, &fval, sizeof(bits)); init_bits_or_int = static_cast(bits); } else { if (auto* init_value = ctx->initValue()) { if (!init_value->exp()) { throw std::runtime_error( FormatError("irgen", "全局标量变量仅支持表达式初始化")); } init_bits_or_int = EvalExpAsConst(init_value->exp()); } } auto* gv = module_.CreateGlobalVar( name, init_bits_or_int, 1, current_decl_type_->IsFloat32() ? ir::Type::GetPtrFloat32Type() : ir::Type::GetPtrInt32Type()); storage_map_[ctx] = gv; global_storage_[name] = gv; return {}; } // 局部标量 if (storage_map_.find(ctx) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } // 根据当前声明类型创建alloca ir::AllocaInst* slot; if (current_decl_type_->IsFloat32()) { slot = CreateEntryAllocaF32(module_.GetContext().NextTemp()); } else { slot = CreateEntryAllocaI32(module_.GetContext().NextTemp()); } storage_map_[ctx] = slot; named_storage_[name] = slot; ir::Value* init = nullptr; if (auto* init_value = ctx->initValue()) { if (!init_value->exp()) { throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化到标量")); } init = EvalExpr(*init_value->exp()); } else { if (current_decl_type_->IsFloat32()) { init = module_.GetContext().GetConstFloat(0.0f); } else { init = builder_.CreateConstInt(0); } } if (current_decl_type_->IsFloat32()) { init = CastToFloat(init); } else { init = CastToInt(init); } builder_.CreateStore(init, slot); return {}; }