#include "irgen/IRGen.h" #include #include #include #include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" namespace { int ParseIntLiteral(const std::string& text) { size_t parsed = 0; long long value = std::stoll(text, &parsed, 0); if (parsed != text.size()) { throw std::runtime_error(FormatError("irgen", "非法整数字面量: " + text)); } if (value < std::numeric_limits::min() || value > std::numeric_limits::max()) { throw std::runtime_error(FormatError("irgen", "整数字面量越界: " + text)); } return static_cast(value); } double ParseFloatLiteral(const std::string& text) { if (text.find("0x") == 0 || text.find("0X") == 0) { // 手动解析十六进制浮点数常量 // 格式: 0x[hex_digits][.[hex_digits]][p|P[+|-][decimal_digits]] std::string hex_part; std::string exp_part; size_t p_pos = text.find_first_of("pP"); if (p_pos != std::string::npos) { hex_part = text.substr(0, p_pos); exp_part = text.substr(p_pos + 1); } else { hex_part = text; exp_part = "0"; } // 解析十六进制部分 double mantissa = 0.0; double frac = 0.0; double frac_divisor = 1.0; bool in_frac = false; for (size_t i = 2; i < hex_part.size(); i++) { char c = hex_part[i]; if (c == '.') { in_frac = true; continue; } int digit; if (c >= '0' && c <= '9') { digit = c - '0'; } else if (c >= 'a' && c <= 'f') { digit = 10 + (c - 'a'); } else if (c >= 'A' && c <= 'F') { digit = 10 + (c - 'A'); } else { throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text)); } if (in_frac) { frac_divisor *= 16.0; frac += digit / frac_divisor; } else { mantissa = mantissa * 16.0 + digit; } } mantissa += frac; // 解析指数部分 int exponent = 0; if (!exp_part.empty()) { try { exponent = std::stoi(exp_part); } catch (...) { throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text)); } } return mantissa * std::pow(2.0, exponent); } else { // 解析十进制浮点数常量 char* end = nullptr; double value = std::strtod(text.c_str(), &end); if (end == text.c_str()) { throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text)); } if (static_cast(end - text.c_str()) != text.size()) { throw std::runtime_error(FormatError("irgen", "非法浮点字面量: " + text)); } return value; } } void CollectInitExprs(SysYParser::InitValContext* init, std::vector& out, const std::vector& dims, size_t dim_idx = 0) { if (!init) { return; } if (init->exp()) { out.push_back(init->exp()); return; } // 计算当前维度的大小 size_t current_dim_size = 1; for (size_t i = dim_idx; i < dims.size(); ++i) { current_dim_size *= dims[i]; } size_t start_pos = out.size(); auto nested_inits = init->initVal(); if (dims.empty()) { // 标量,直接处理 for (auto* nested : nested_inits) { CollectInitExprs(nested, out, dims, dim_idx); } } else if (dim_idx < dims.size() - 1) { // 多维数组,递归处理每个子数组 size_t sub_dim_size = 1; for (size_t i = dim_idx + 1; i < dims.size(); ++i) { sub_dim_size *= dims[i]; } for (auto* nested : nested_inits) { if (out.size() >= start_pos + current_dim_size) { break; } CollectInitExprs(nested, out, dims, dim_idx + 1); } } else { // 一维数组,直接展平所有初始化表达式 for (auto* nested : nested_inits) { if (out.size() >= start_pos + current_dim_size) { break; } CollectInitExprs(nested, out, dims, dim_idx); } } // 确保不超过当前维度的大小 if (out.size() > start_pos + current_dim_size) { // 截断超出的部分 out.resize(start_pos + current_dim_size); } // 补齐到当前维度大小 while (out.size() < start_pos + current_dim_size) { out.push_back(nullptr); } } void CollectConstInitExprs(SysYParser::ConstInitValContext* init, std::vector& out, const std::vector& dims, size_t dim_idx = 0) { if (!init) { return; } if (init->constExp()) { out.push_back(init->constExp()); return; } // 计算当前维度的大小 size_t current_dim_size = 1; for (size_t i = dim_idx; i < dims.size(); ++i) { current_dim_size *= dims[i]; } size_t start_pos = out.size(); auto nested_inits = init->constInitVal(); if (dims.empty()) { // 标量,直接处理 for (auto* nested : nested_inits) { CollectConstInitExprs(nested, out, dims, dim_idx); } } else if (dim_idx < dims.size() - 1) { // 多维数组,递归处理每个子数组 size_t sub_dim_size = 1; for (size_t i = dim_idx + 1; i < dims.size(); ++i) { sub_dim_size *= dims[i]; } for (auto* nested : nested_inits) { if (out.size() >= start_pos + current_dim_size) { break; } CollectConstInitExprs(nested, out, dims, dim_idx + 1); } } else { // 一维数组,直接展平所有初始化表达式 for (auto* nested : nested_inits) { if (out.size() >= start_pos + current_dim_size) { break; } CollectConstInitExprs(nested, out, dims, dim_idx); } } // 确保不超过当前维度的大小 if (out.size() > start_pos + current_dim_size) { // 截断超出的部分 out.resize(start_pos + current_dim_size); } // 补齐到当前维度大小 while (out.size() < start_pos + current_dim_size) { out.push_back(nullptr); } } } // namespace ir::AllocaInst* IRGenImpl::CreateEntryBlockAlloca(std::shared_ptr elem_ty, const std::string& name, ir::Value* count) { if (!func_ || func_->GetBlocks().empty()) { throw std::runtime_error(FormatError("irgen", "无法在入口块分配栈空间:函数未定义或无基本块")); } auto* entry_block = func_->GetBlocks().front().get(); auto* alloca = entry_block->InsertAlloca(elem_ty, name, count); return alloca; } std::shared_ptr IRGenImpl::ResolveBType( SysYParser::BTypeContext* btype) const { if (!btype) { throw std::runtime_error(FormatError("irgen", "缺少基础类型")); } if (btype->Int()) { return ir::Type::GetInt32Type(); } if (btype->Float()) { return ir::Type::GetFloat32Type(); } throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 类型")); } std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少语句块")); } // 进入新的作用域,保存当前常量映射状态 const_value_history_.push_back(const_value_map_); local_const_stack_.emplace_back(); bool terminated = false; for (auto* item : ctx->blockItem()) { if (item) { if (VisitBlockItemResult(*item) == BlockFlow::Terminated) { // 当前语法要求 return 为块内最后一条语句;命中后可停止生成。 terminated = true; break; } } } // 退出作用域,恢复常量映射状态 const_value_map_ = const_value_history_.back(); const_value_history_.pop_back(); local_const_stack_.pop_back(); return terminated ? BlockFlow::Terminated : BlockFlow::Continue; } 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", "暂不支持的语句或声明")); } // 变量声明的 IR 生成目前也是最小实现: // - 先检查声明的基础类型,当前仅支持局部 int; // - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。 // // 和更完整的版本相比,这里还没有: // - 一个 Decl 中多个变量定义的顺序处理; // - const、数组、全局变量等不同声明形态; // - 更丰富的类型系统。 std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } if (ctx->constDecl()) { auto* const_decl = ctx->constDecl(); if (!const_decl || !const_decl->bType()) { throw std::runtime_error(FormatError("irgen", "非法常量声明")); } auto elem_ty = ResolveBType(const_decl->bType()); const bool is_float = elem_ty->IsFloat32(); for (auto* def : const_decl->constDef()) { if (!def || !def->Ident()) { continue; } const std::string name = def->Ident()->getText(); if (def->constExp().empty()) { if (!is_float && def->constInitVal() && def->constInitVal()->constExp()) { int const_value = EvalConstIntExpr(*def->constInitVal()->constExp()); if (!func_) { // 只对全局整型常量进行常量折叠 const_value_map_[name] = const_value; } } if (func_) { // 局部常量:分配栈空间 auto* slot = builder_.CreateAlloca(elem_ty, module_.GetContext().NextTemp()); const_storage_map_[def] = slot; ir::Value* init_elem = nullptr; if (def->constInitVal() && def->constInitVal()->constExp()) { init_elem = CastValueTo( std::any_cast(def->constInitVal()->constExp()->accept(this)), elem_ty); } else { init_elem = is_float ? static_cast(builder_.CreateConstFloat(0.0)) : static_cast(builder_.CreateConstInt(0)); } builder_.CreateStore(init_elem, slot); } else { // 全局常量:创建全局变量 if (is_float) { double init_value = 0.0; if (def->constInitVal() && def->constInitVal()->constExp()) { init_value = EvalConstFloatExpr(*def->constInitVal()->constExp()); } auto* global = module_.CreateGlobalF32(name, init_value); const_global_storage_map_[def] = global; } else { int init_value = 0; if (def->constInitVal() && def->constInitVal()->constExp()) { init_value = EvalConstIntExpr(*def->constInitVal()->constExp()); } auto* global = module_.CreateGlobalI32(name, init_value); const_global_storage_map_[def] = global; } } continue; } auto extents = EvalArrayExtents(def->constExp()); size_t total_extent = 1; for (int extent : extents) { total_extent *= static_cast(extent); } const_array_extents_map_[def] = extents; if (!func_) { std::vector init_exprs; bool has_init = false; if (def->constInitVal()) { has_init = true; CollectConstInitExprs(def->constInitVal(), init_exprs, extents); if (init_exprs.size() > total_extent) { throw std::runtime_error(FormatError("irgen", "数组初始化元素过多")); } } std::vector init_values; std::vector init_float_values; if (is_float) { if (has_init) { init_float_values.reserve(total_extent); for (size_t index = 0; index < total_extent; ++index) { if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) { double value = 0.0; auto* cf = dynamic_cast(CastValueTo( std::any_cast(init_exprs[index]->addExp()->accept(this)), ir::Type::GetFloat32Type())); if (cf) { value = cf->GetValue(); } init_float_values.push_back(value); } else { init_float_values.push_back(0.0); } } size_t trailing_zeros = 0; while (trailing_zeros < init_float_values.size() && init_float_values[init_float_values.size() - 1 - trailing_zeros] == 0.0) { trailing_zeros++; } if (trailing_zeros > 0) { init_float_values.resize(init_float_values.size() - trailing_zeros); } auto* global = module_.CreateGlobalArrayF32(name, total_extent, init_float_values); const_global_storage_map_[def] = global; } else { auto* global = module_.CreateGlobalArrayF32(name, total_extent, {}); const_global_storage_map_[def] = global; } } else { if (has_init) { init_values.reserve(total_extent); for (size_t index = 0; index < total_extent; ++index) { if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) { int value = 0; auto* ci = dynamic_cast(CastValueTo( std::any_cast(init_exprs[index]->addExp()->accept(this)), ir::Type::GetInt32Type())); if (ci) { value = ci->GetValue(); } init_values.push_back(value); } else { init_values.push_back(0); } } size_t trailing_zeros = 0; while (trailing_zeros < init_values.size() && init_values[init_values.size() - 1 - trailing_zeros] == 0) { trailing_zeros++; } if (trailing_zeros > 0) { init_values.resize(init_values.size() - trailing_zeros); } auto* global = module_.CreateGlobalArrayI32(name, total_extent, init_values); const_global_storage_map_[def] = global; } else { auto* global = module_.CreateGlobalArrayI32(name, total_extent, {}); const_global_storage_map_[def] = global; } } continue; } auto* slot = builder_.CreateAlloca(elem_ty, module_.GetContext().NextTemp(), builder_.CreateConstInt(static_cast(total_extent))); const_storage_map_[def] = slot; std::vector init_exprs; CollectConstInitExprs(def->constInitVal(), init_exprs, extents); if (init_exprs.size() > total_extent) { throw std::runtime_error(FormatError("irgen", "数组初始化元素过多")); } for (size_t index = 0; index < total_extent; ++index) { auto* idx = builder_.CreateConstInt(static_cast(index)); auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp()); ir::Value* init_elem = nullptr; if (index < init_exprs.size() && init_exprs[index] && init_exprs[index]->addExp()) { init_elem = CastValueTo( std::any_cast(init_exprs[index]->addExp()->accept(this)), elem_ty); } else { init_elem = is_float ? static_cast(builder_.CreateConstFloat(0.0)) : static_cast(builder_.CreateConstInt(0)); } builder_.CreateStore(init_elem, ptr); } } return {}; } if (!ctx->varDecl()) { throw std::runtime_error(FormatError("irgen", "当前不支持 const 声明")); } ctx->varDecl()->accept(this); return {}; } std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } if (!ctx->bType() || (!ctx->bType()->Int() && !ctx->bType()->Float())) { throw std::runtime_error( FormatError("irgen", "当前仅支持局部 int/float 变量声明")); } const auto& defs = ctx->varDef(); if (defs.empty()) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } for (auto* def : defs) { if (!def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } def->accept(this); } return {}; } // 当前仍是教学用的最小版本,因此这里只支持: // - 局部 int 变量; // - 标量初始化; // - 一个 VarDef 对应一个槽位。 std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量定义")); } if (!ctx->Ident()) { throw std::runtime_error(FormatError("irgen", "变量声明缺少名称")); } const std::string name = ctx->Ident()->getText(); auto* var_decl = dynamic_cast(ctx->parent); auto elem_ty = ResolveBType(var_decl ? var_decl->bType() : nullptr); const bool is_float = elem_ty->IsFloat32(); if (name.empty()) { throw std::runtime_error(FormatError("irgen", "变量声明缺少名称")); } const bool is_array = !ctx->constExp().empty(); std::vector extents; size_t total_extent = 1; if (is_array) { extents = EvalArrayExtents(ctx->constExp()); for (int extent : extents) { total_extent *= static_cast(extent); } array_extents_map_[ctx] = extents; } if (!func_) { if (global_storage_map_.find(ctx) != global_storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成全局变量")); } if (is_array) { std::vector init_exprs; bool has_init = false; if (auto* init_value = ctx->initVal()) { has_init = true; CollectInitExprs(init_value, init_exprs, extents); if (init_exprs.size() > total_extent) { throw std::runtime_error(FormatError("irgen", "数组初始化元素过多")); } } std::vector init_values; std::vector init_float_values; if (is_float) { if (has_init) { init_float_values.reserve(total_extent); for (size_t index = 0; index < total_extent; ++index) { if (index < init_exprs.size() && init_exprs[index]) { double value = 0.0; auto* folded = EvalExpr(*init_exprs[index]); auto* cf = dynamic_cast(CastValueTo(folded, ir::Type::GetFloat32Type())); if (cf) { value = cf->GetValue(); } init_float_values.push_back(value); } else { init_float_values.push_back(0.0); } } size_t trailing_zeros = 0; while (trailing_zeros < init_float_values.size() && init_float_values[init_float_values.size() - 1 - trailing_zeros] == 0.0) { trailing_zeros++; } if (trailing_zeros > 0) { init_float_values.resize(init_float_values.size() - trailing_zeros); } auto* global = module_.CreateGlobalArrayF32(name, total_extent, init_float_values); global_storage_map_[ctx] = global; } else { auto* global = module_.CreateGlobalArrayF32(name, total_extent, {}); global_storage_map_[ctx] = global; } } else { if (has_init) { init_values.reserve(total_extent); for (size_t index = 0; index < total_extent; ++index) { if (index < init_exprs.size() && init_exprs[index]) { int value = 0; auto* folded = EvalExpr(*init_exprs[index]); auto* ci = dynamic_cast(CastValueTo(folded, ir::Type::GetInt32Type())); if (ci) { value = ci->GetValue(); } init_values.push_back(value); } else { init_values.push_back(0); } } size_t trailing_zeros = 0; while (trailing_zeros < init_values.size() && init_values[init_values.size() - 1 - trailing_zeros] == 0) { trailing_zeros++; } if (trailing_zeros > 0) { init_values.resize(init_values.size() - trailing_zeros); } auto* global = module_.CreateGlobalArrayI32(name, total_extent, init_values); global_storage_map_[ctx] = global; } else { auto* global = module_.CreateGlobalArrayI32(name, total_extent, {}); global_storage_map_[ctx] = global; } } return {}; } int init = 0; double init_float = 0.0; if (auto* init_value = ctx->initVal()) { if (!init_value->exp()) { throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); } auto* folded = EvalExpr(*init_value->exp()); if (is_float) { auto* cf = dynamic_cast(CastValueTo(folded, ir::Type::GetFloat32Type())); if (!cf) { throw std::runtime_error( FormatError("irgen", "全局浮点初始化必须是常量表达式")); } init_float = cf->GetValue(); } else { auto* ci = dynamic_cast(CastValueTo(folded, ir::Type::GetInt32Type())); if (!ci) { throw std::runtime_error( FormatError("irgen", "全局整型初始化必须是常量表达式")); } init = ci->GetValue(); } } auto* global = is_float ? module_.CreateGlobalF32(name, init_float) : module_.CreateGlobalI32(name, init); global_storage_map_[ctx] = global; return {}; } // 检查是否已经在当前作用域中声明 if (storage_map_.find(ctx) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } ir::Value* count = nullptr; if (is_array) { count = builder_.CreateConstInt(static_cast(total_extent)); } auto* slot = CreateEntryBlockAlloca(elem_ty, module_.GetContext().NextTemp(), count); storage_map_[ctx] = slot; if (is_array) { std::vector init_exprs; if (auto* init_value = ctx->initVal()) { CollectInitExprs(init_value, init_exprs, extents); if (init_exprs.size() > total_extent) { throw std::runtime_error(FormatError("irgen", "数组初始化元素过多")); } // 对于小数组(<=10000元素),直接生成完整初始化 if (total_extent <= 10000) { for (size_t index = 0; index < total_extent; ++index) { auto* idx = builder_.CreateConstInt(static_cast(index)); auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp()); ir::Value* init_elem = nullptr; if (index < init_exprs.size() && init_exprs[index]) { init_elem = CastValueTo(EvalExpr(*init_exprs[index]), elem_ty); } else { init_elem = is_float ? static_cast(builder_.CreateConstFloat(0.0)) : static_cast(builder_.CreateConstInt(0)); } builder_.CreateStore(init_elem, ptr); } } else { // 对于大数组,生成循环初始化零,然后初始化非零元素 auto* func = builder_.GetInsertBlock()->GetParent(); auto* loop_cond = func->CreateBlock("zero.init.cond"); auto* loop_body = func->CreateBlock("zero.init.body"); auto* loop_end = func->CreateBlock("zero.init.end"); auto* counter = builder_.CreateAlloca(ir::Type::GetInt32Type(), module_.GetContext().NextTemp()); builder_.CreateStore(builder_.CreateConstInt(0), counter); builder_.CreateBr(loop_cond); builder_.SetInsertPoint(loop_cond); auto* counter_val = builder_.CreateLoad(counter, module_.GetContext().NextTemp()); auto* cond = builder_.CreateICmp(ir::Opcode::Lt, counter_val, builder_.CreateConstInt(static_cast(total_extent)), module_.GetContext().NextTemp()); builder_.CreateCondBr(cond, loop_body, loop_end); builder_.SetInsertPoint(loop_body); auto* idx = builder_.CreateLoad(counter, module_.GetContext().NextTemp()); auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp()); auto* zero = is_float ? static_cast(builder_.CreateConstFloat(0.0)) : static_cast(builder_.CreateConstInt(0)); builder_.CreateStore(zero, ptr); auto* new_counter = builder_.CreateAdd(builder_.CreateLoad(counter, module_.GetContext().NextTemp()), builder_.CreateConstInt(1), module_.GetContext().NextTemp()); builder_.CreateStore(new_counter, counter); builder_.CreateBr(loop_cond); builder_.SetInsertPoint(loop_end); // 初始化非零元素 for (size_t index = 0; index < init_exprs.size(); ++index) { if (init_exprs[index]) { auto* idx = builder_.CreateConstInt(static_cast(index)); auto* ptr = builder_.CreateGEP(slot, idx, module_.GetContext().NextTemp()); ir::Value* init_elem = CastValueTo(EvalExpr(*init_exprs[index]), elem_ty); builder_.CreateStore(init_elem, ptr); } } } } // 如果没有初始化列表,不生成任何初始化代码(局部变量默认不初始化) return {}; } ir::Value* init = nullptr; if (auto* init_value = ctx->initVal()) { if (!init_value->exp()) { throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); } init = CastValueTo(EvalExpr(*init_value->exp()), elem_ty); } else { init = is_float ? static_cast(builder_.CreateConstFloat(0.0)) : static_cast(builder_.CreateConstInt(0)); } builder_.CreateStore(init, slot); return {}; }