diff --git a/include/ir/IR.h b/include/ir/IR.h index 1faced7..544c1d0 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -45,6 +45,7 @@ class Value; class User; class ConstantValue; class ConstantInt; +class ConstantFloat; class GlobalValue; class Instruction; class BasicBlock; @@ -129,6 +130,8 @@ class Value { bool IsInt1() const; bool IsInt32() const; bool IsPtrInt32() const; + bool IsFloat() const; + bool IsPtrFloat() const; bool IsConstant() const; bool IsInstruction() const; bool IsUser() const; diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index bca31b9..f05c636 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -60,11 +60,24 @@ class IRGenImpl final : public SysYBaseVisitor { const SemanticContext& sema_; ir::Function* func_; ir::IRBuilder builder_; - // 名称绑定由 Sema 负责;IRGen 只维护"变量名 -> 存储槽位"的代码生成状态。 - std::unordered_map storage_map_; + // 考虑到嵌套作用域(全局、函数、语句块),使用 vector 模拟栈来管理 storage_map_ 和 const_values_ + std::vector> storage_map_stack_; + std::vector> const_values_stack_; + + // 用于在栈中查找变量 + ir::Value* FindStorage(const std::string& name) const { + for (auto it = storage_map_stack_.rbegin(); it != storage_map_stack_.rend(); ++it) { + if (it->count(name)) return it->at(name); + } + return nullptr; + } - // 记录常量名到常量值的映射,用于后续生成指令时直接替换 - std::unordered_map const_values_; + ir::ConstantValue* FindConst(const std::string& name) const { + for (auto it = const_values_stack_.rbegin(); it != const_values_stack_.rend(); ++it) { + if (it->count(name)) return it->at(name); + } + return nullptr; + } // 用于 break 和 continue 跳转的目标位置 ir::BasicBlock* current_loop_cond_bb_ = nullptr; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index acb9400..ac86cb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(compiler ) target_link_libraries(compiler PRIVATE frontend + ir utils ) diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 64fcf8f..04ef65b 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -64,7 +64,8 @@ LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) { throw std::runtime_error( FormatError("ir", "IRBuilder::CreateLoad 缺少 ptr")); } - return insert_block_->Append(Type::GetInt32Type(), ptr, name); + auto val_ty = (ptr->GetType() && ptr->GetType()->IsPtrFloat()) ? Type::GetFloatType() : Type::GetInt32Type(); + return insert_block_->Append(val_ty, ptr, name); } StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) { @@ -108,7 +109,8 @@ UnaryInst* IRBuilder::CreateNeg(Value* operand, const std::string& name) { if (!operand) { throw std::runtime_error(FormatError("ir", "IRBuilder::CreateNeg 缺少操作数")); } - return insert_block_->Append(Opcode::Neg, Type::GetInt32Type(), operand, name); + auto val_ty = (operand->GetType() && operand->GetType()->IsFloat()) ? Type::GetFloatType() : Type::GetInt32Type(); + return insert_block_->Append(Opcode::Neg, val_ty, operand, name); } CmpInst* IRBuilder::CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name) { diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 673b069..252973a 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -75,8 +75,8 @@ BinaryInst::BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, type_->GetKind() != lhs->GetType()->GetKind()) { throw std::runtime_error(FormatError("ir", "BinaryInst 类型不匹配")); } - if (!type_->IsInt32()) { - throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32")); + if (!type_->IsInt32() && !type_->IsFloat()) { + throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32 或 float")); } AddOperand(lhs); AddOperand(rhs); @@ -101,8 +101,8 @@ UnaryInst::UnaryInst(Opcode op, std::shared_ptr ty, Value* operand, if (type_->GetKind() != operand->GetType()->GetKind()) { throw std::runtime_error(FormatError("ir", "UnaryInst 类型不匹配")); } - if (!type_->IsInt32()) { - throw std::runtime_error(FormatError("ir", "UnaryInst 当前只支持 i32")); + if (!type_->IsInt32() && !type_->IsFloat()) { + throw std::runtime_error(FormatError("ir", "UnaryInst 当前只支持 i32 或 float")); } AddOperand(operand); } @@ -124,8 +124,8 @@ Value* ReturnInst::GetValue() const { return GetOperand(0); } AllocaInst::AllocaInst(std::shared_ptr ptr_ty, std::string name) : Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)) { - if (!type_ || !type_->IsPtrInt32()) { - throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32*")); + if (!type_ || (!type_->IsPtrInt32() && !type_->IsPtrFloat())) { + throw std::runtime_error(FormatError("ir", "AllocaInst 当前只支持 i32* 或 float*")); } } @@ -134,12 +134,19 @@ LoadInst::LoadInst(std::shared_ptr val_ty, Value* ptr, std::string name) if (!ptr) { throw std::runtime_error(FormatError("ir", "LoadInst 缺少 ptr")); } - if (!type_ || !type_->IsInt32()) { - throw std::runtime_error(FormatError("ir", "LoadInst 当前只支持加载 i32")); + if (!type_ || (!type_->IsInt32() && !type_->IsFloat())) { + throw std::runtime_error(FormatError("ir", "LoadInst 当前只支持加载 i32 或 float")); } - if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) { - throw std::runtime_error( - FormatError("ir", "LoadInst 当前只支持从 i32* 加载")); + if (type_->IsInt32()) { + if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) { + throw std::runtime_error( + FormatError("ir", "LoadInst 当前只支持从 i32* 加载")); + } + } else if (type_->IsFloat()) { + if (!ptr->GetType() || !ptr->GetType()->IsPtrFloat()) { + throw std::runtime_error( + FormatError("ir", "LoadInst 当前只支持从 float* 加载")); + } } AddOperand(ptr); } @@ -157,12 +164,19 @@ StoreInst::StoreInst(std::shared_ptr void_ty, Value* val, Value* ptr) if (!type_ || !type_->IsVoid()) { throw std::runtime_error(FormatError("ir", "StoreInst 返回类型必须为 void")); } - if (!val->GetType() || !val->GetType()->IsInt32()) { - throw std::runtime_error(FormatError("ir", "StoreInst 当前只支持存储 i32")); - } - if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) { - throw std::runtime_error( - FormatError("ir", "StoreInst 当前只支持写入 i32*")); + if (!val->GetType() || (!val->GetType()->IsInt32() && !val->GetType()->IsFloat())) { + throw std::runtime_error(FormatError("ir", "StoreInst 当前只支持存储 i32 或 float")); + } + if (val->GetType()->IsInt32()) { + if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) { + throw std::runtime_error( + FormatError("ir", "StoreInst 当前只支持写入 i32*")); + } + } else if (val->GetType()->IsFloat()) { + if (!ptr->GetType() || !ptr->GetType()->IsPtrFloat()) { + throw std::runtime_error( + FormatError("ir", "StoreInst 当前只支持写入 float*")); + } } AddOperand(val); AddOperand(ptr); diff --git a/src/ir/Type.cpp b/src/ir/Type.cpp index c32d640..d5471fd 100644 --- a/src/ir/Type.cpp +++ b/src/ir/Type.cpp @@ -25,6 +25,16 @@ const std::shared_ptr& Type::GetPtrInt32Type() { return type; } +const std::shared_ptr& Type::GetFloatType() { + static std::shared_ptr ty = std::make_shared(Kind::Float); + return ty; +} + +const std::shared_ptr& Type::GetPtrFloatType() { + static std::shared_ptr ty = std::make_shared(Kind::PtrFloat); + return ty; +} + Type::Kind Type::GetKind() const { return kind_; } bool Type::IsVoid() const { return kind_ == Kind::Void; } @@ -35,4 +45,8 @@ bool Type::IsInt32() const { return kind_ == Kind::Int32; } bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; } +bool Type::IsFloat() const { return kind_ == Kind::Float; } + +bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; } + } // namespace ir diff --git a/src/ir/Value.cpp b/src/ir/Value.cpp index e3a81ec..455f7ed 100644 --- a/src/ir/Value.cpp +++ b/src/ir/Value.cpp @@ -80,38 +80,6 @@ void Value::ReplaceAllUsesWith(Value* new_value) { } } -User::User(std::shared_ptr ty, std::string name) - : Value(std::move(ty), std::move(name)) {} - -size_t User::GetNumOperands() const { return operands_.size(); } - -Value* User::GetOperand(size_t index) const { - if (index >= operands_.size()) { - throw std::out_of_range("Operand index out of range"); - } - return operands_[index]; -} - -void User::SetOperand(size_t index, Value* value) { - if (index >= operands_.size()) { - throw std::out_of_range("Operand index out of range"); - } - if (operands_[index]) { - operands_[index]->RemoveUse(this, index); - } - operands_[index] = value; - if (value) { - value->AddUse(this, index); - } -} - -void User::AddOperand(Value* value) { - operands_.push_back(value); - if (value) { - value->AddUse(this, operands_.size() - 1); - } -} - Argument::Argument(std::shared_ptr ty, std::string name, Function* parent, size_t arg_no) : Value(std::move(ty), std::move(name)), parent_(parent), arg_no_(arg_no) {} @@ -128,56 +96,7 @@ ConstantInt::ConstantInt(std::shared_ptr ty, int v) ConstantFloat::ConstantFloat(std::shared_ptr ty, float v) : ConstantValue(std::move(ty), ""), value_(v) {} -GlobalValue::GlobalValue(std::shared_ptr ty, std::string name) - : User(std::move(ty), std::move(name)) {} - GlobalVariable::GlobalVariable(std::string name, std::shared_ptr type, ConstantValue* init) : GlobalValue(std::move(type), std::move(name)), init_(init) {} -Type::Type(Kind k) : kind_(k) {} - -const std::shared_ptr& Type::GetVoidType() { - static std::shared_ptr ty = std::make_shared(Kind::Void); - return ty; -} - -const std::shared_ptr& Type::GetInt1Type() { - static std::shared_ptr ty = std::make_shared(Kind::Int1); - return ty; -} - -const std::shared_ptr& Type::GetInt32Type() { - static std::shared_ptr ty = std::make_shared(Kind::Int32); - return ty; -} - -const std::shared_ptr& Type::GetPtrInt32Type() { - static std::shared_ptr ty = std::make_shared(Kind::PtrInt32); - return ty; -} - -const std::shared_ptr& Type::GetFloatType() { - static std::shared_ptr ty = std::make_shared(Kind::Float); - return ty; -} - -const std::shared_ptr& Type::GetPtrFloatType() { - static std::shared_ptr ty = std::make_shared(Kind::PtrFloat); - return ty; -} - -Type::Kind Type::GetKind() const { return kind_; } - -bool Type::IsVoid() const { return kind_ == Kind::Void; } - -bool Type::IsInt1() const { return kind_ == Kind::Int1; } - -bool Type::IsInt32() const { return kind_ == Kind::Int32; } - -bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; } - -bool Type::IsFloat() const { return kind_ == Kind::Float; } - -bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; } - } // namespace ir diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 40c2ef5..3ec1d1d 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -10,6 +10,11 @@ std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少语句块")); } + + // 压入局部作用域 + storage_map_stack_.push_back({}); + const_values_stack_.push_back({}); + bool terminated = false; for (auto* item : ctx->blockItem()) { if (item) { @@ -19,6 +24,11 @@ std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) { } } } + + // 弹出局部作用域 + storage_map_stack_.pop_back(); + const_values_stack_.pop_back(); + return terminated ? BlockFlow::Terminated : BlockFlow::Continue; } @@ -87,15 +97,21 @@ std::any IRGenImpl::visitConstDef(SysYParser::ConstDefContext* ctx) { } // 记录常量值供后续直接使用 - const_values_[var_name] = init_const; + if (!const_values_stack_.empty()) { + const_values_stack_.back()[var_name] = init_const; + } if (func_ == nullptr) { auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const); - storage_map_[var_name] = gv; + if (!storage_map_stack_.empty()) { + storage_map_stack_.back()[var_name] = gv; + } } else { ir::Value* slot = is_float ? builder_.CreateAllocaFloat(module_.GetContext().NextTemp()) : builder_.CreateAllocaI32(module_.GetContext().NextTemp()); - storage_map_[var_name] = slot; + if (!storage_map_stack_.empty()) { + storage_map_stack_.back()[var_name] = slot; + } builder_.CreateStore(init_const, slot); } @@ -144,7 +160,7 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { throw std::runtime_error(FormatError("irgen", "暂不支持数组声明")); } std::string var_name = ctx->ID()->getText(); - if (storage_map_.find(var_name) != storage_map_.end()) { + if (!storage_map_stack_.empty() && storage_map_stack_.back().find(var_name) != storage_map_stack_.back().end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } @@ -177,11 +193,13 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { } auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const); - storage_map_[var_name] = gv; + if (!storage_map_stack_.empty()) { + storage_map_stack_.back()[var_name] = gv; + } } else { // 局部作用域 - auto* ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type(); + auto ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type(); // 简化处理,暂用 builder 创建 alloca // 需要在 builder 中扩展 CreateAllocaFloat,此处简化直接按 I32 Alloca 的名称调用,或添加新接口 // 为了不大幅改动 Builder,我们复用 AllocaInst,或者添加 CreateAlloca @@ -192,7 +210,9 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); } - storage_map_[var_name] = slot; + if (!storage_map_stack_.empty()) { + storage_map_stack_.back()[var_name] = slot; + } ir::Value* init = nullptr; if (auto* init_val = ctx->initVal()) { diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 0384e40..46a9571 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -47,14 +47,14 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { "变量使用缺少语义绑定:" + lval_ctx->ID()->getText())); } std::string var_name = lval_ctx->ID()->getText(); - auto it = storage_map_.find(var_name); - if (it == storage_map_.end()) { + ir::Value* slot = FindStorage(var_name); + if (!slot) { throw std::runtime_error( FormatError("irgen", "变量声明缺少存储槽位:" + var_name)); } return static_cast( - builder_.CreateLoad(it->second, module_.GetContext().NextTemp())); + builder_.CreateLoad(slot, module_.GetContext().NextTemp())); } // 处理 number if (ctx->number()) { @@ -65,11 +65,21 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { std::any IRGenImpl::visitNumber(SysYParser::NumberContext* ctx) { - if (!ctx || !ctx->intConst()) { - throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量")); + if (!ctx) { + throw std::runtime_error(FormatError("irgen", "缺少字面量节点")); } - return static_cast( - builder_.CreateConstInt(std::stoi(ctx->intConst()->getText()))); + if (ctx->intConst()) { + // 可能是 0x, 0X, 0 开头的八进制等,目前 std::stoi 会处理十进制, + // 为了支持 16 进制/8 进制建议使用 std::stoi(str, nullptr, 0) + std::string text = ctx->intConst()->getText(); + return static_cast( + builder_.CreateConstInt(std::stoi(text, nullptr, 0))); + } else if (ctx->floatConst()) { + std::string text = ctx->floatConst()->getText(); + return static_cast( + module_.GetContext().GetConstFloat(std::stof(text))); + } + throw std::runtime_error(FormatError("irgen", "不支持的字面量")); } // 变量使用的处理流程: @@ -86,9 +96,9 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) { std::string var_name = ctx->ID()->getText(); // 优先检查是否为已记录的常量,如果是则直接返回常量值,不再生成 Load 指令 - auto it_const = const_values_.find(var_name); - if (it_const != const_values_.end()) { - return static_cast(it_const->second); + ir::ConstantValue* const_val = FindConst(var_name); + if (const_val) { + return static_cast(const_val); } const auto* decl = sema_.ResolveObjectUse(ctx); @@ -98,14 +108,14 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) { "变量使用缺少语义绑定:" + ctx->ID()->getText())); } // 使用变量名查找存储槽位 - auto it = storage_map_.find(var_name); - if (it == storage_map_.end()) { + ir::Value* slot = FindStorage(var_name); + if (!slot) { throw std::runtime_error( FormatError("irgen", "变量声明缺少存储槽位:" + var_name)); } return static_cast( - builder_.CreateLoad(it->second, module_.GetContext().NextTemp())); + builder_.CreateLoad(slot, module_.GetContext().NextTemp())); } @@ -158,7 +168,7 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { // 从 Sema 或 Module 中查找函数 // 目前简化处理,直接从 Module 中查找(如果是当前文件内定义的) // 或者依赖 Sema 给出解析结果 - const sem::FunctionBinding* func_binding = sema_.ResolveFunctionCall(ctx); + const FunctionBinding* func_binding = sema_.ResolveFunctionCall(ctx); if (!func_binding) { throw std::runtime_error(FormatError("irgen", "未找到函数声明:" + func_name)); } @@ -177,9 +187,9 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { // 可能是外部函数如 putint, getint 等 // 如果没有在 module_ 中,则需要创建一个只有声明的 Function std::shared_ptr ret_ty; - if (func_binding->GetReturnType()->IsInt()) { + if (func_binding->return_type == SemanticType::Int) { ret_ty = ir::Type::GetInt32Type(); - } else if (func_binding->GetReturnType()->IsFloat()) { + } else if (func_binding->return_type == SemanticType::Float) { ret_ty = ir::Type::GetFloatType(); } else { ret_ty = ir::Type::GetVoidType(); @@ -202,10 +212,17 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { // 判断是正号还是负号 if (ctx->addUnaryOp()->SUB()) { - // 负号:生成 sub 0, operand(LLVM IR 中没有 neg 指令) - ir::Value* zero = builder_.CreateConstInt(0); - return static_cast( - builder_.CreateSub(zero, operand, module_.GetContext().NextTemp())); + // 负号:如果是整数生成 sub 0, operand,浮点数生成 fsub 0.0, operand + if (operand->GetType()->IsFloat()) { + ir::Value* zero = module_.GetContext().GetConstFloat(0.0f); + // 此处暂且假设 CreateSub 可以处理浮点数(如果底层有 fsub 则更好) + return static_cast( + builder_.CreateSub(zero, operand, module_.GetContext().NextTemp())); + } else { + ir::Value* zero = builder_.CreateConstInt(0); + return static_cast( + builder_.CreateSub(zero, operand, module_.GetContext().NextTemp())); + } } else if (ctx->addUnaryOp()->ADD()) { // 正号:直接返回操作数(+x 等价于 x) return operand; diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index bf4580f..5b57d2a 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -38,6 +38,10 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少编译单元")); } + // 初始化全局作用域 + storage_map_stack_.push_back({}); + const_values_stack_.push_back({}); + // 遍历所有 topLevelItem for (auto* item : ctx->topLevelItem()) { if (!item) continue; @@ -47,6 +51,11 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) { item->decl()->accept(this); } } + + // 退出全局作用域 + storage_map_stack_.pop_back(); + const_values_stack_.pop_back(); + return {}; } @@ -69,7 +78,7 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少函数定义")); } - if (!ctx->blockStmt()) { + if (!ctx->block()) { throw std::runtime_error(FormatError("irgen", "函数体为空")); } if (!ctx->ID()) { @@ -89,7 +98,10 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type); builder_.SetInsertPoint(func_->GetEntry()); - storage_map_.clear(); + + // 进入函数作用域,压入一个新的 map + storage_map_stack_.push_back({}); + const_values_stack_.push_back({}); if (ctx->funcFParams()) { for (auto* paramCtx : ctx->funcFParams()->funcFParam()) { @@ -115,13 +127,18 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { } builder_.CreateStore(arg, alloca_inst); - storage_map_[arg_name] = alloca_inst; + storage_map_stack_.back()[arg_name] = alloca_inst; } } - ctx->blockStmt()->accept(this); + ctx->block()->accept(this); VerifyFunctionStructure(*func_); func_ = nullptr; + + // 退出函数作用域,弹出 map + storage_map_stack_.pop_back(); + const_values_stack_.pop_back(); + return {}; } diff --git a/src/irgen/IRGenStmt.cpp b/src/irgen/IRGenStmt.cpp index e44bd0a..e04c215 100644 --- a/src/irgen/IRGenStmt.cpp +++ b/src/irgen/IRGenStmt.cpp @@ -35,12 +35,19 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) { FormatError("irgen", "变量使用缺少语义绑定:" + lval_ctx->ID()->getText())); } std::string var_name = lval_ctx->ID()->getText(); - auto it = storage_map_.find(var_name); - if (it == storage_map_.end()) { + ir::Value* slot = FindStorage(var_name); + if (!slot) { throw std::runtime_error( FormatError("irgen", "变量声明缺少存储槽位:" + var_name)); } - builder_.CreateStore(rhs, it->second); + + // 如果 rhs 和 slot 的基类型不匹配,需要在这里做类型转换 + // 为了简化并能通过当前测试,如果底层没有 float/int 转换指令 + // 如果真的遇到 float 赋值给 int,或者 int 赋值给 float,并且这里直接抛异常 + // 说明我们需要补齐类型转换指令(但当前没有),先忽略隐式转换或让 StoreInst 自行报错。 + // 但是这里最可能的原因是 rhs 在经过表达式求值后,类型丢失了 float 的标志。 + + builder_.CreateStore(rhs, slot); return BlockFlow::Continue; } diff --git a/终端信息.txt b/终端信息.txt new file mode 100644 index 0000000..ae54c24 --- /dev/null +++ b/终端信息.txt @@ -0,0 +1,19 @@ +(base) root@HP:/home/hp/nudt-compiler-cpp/build# make -j$(nproc) +[ 2%] Built target utils +[ 2%] Building CXX object src/ir/CMakeFiles/ir_core.dir/Type.cpp.o +[ 3%] Building CXX object src/ir/CMakeFiles/ir_core.dir/Value.cpp.o +[ 73%] Built target antlr4_runtime +[ 75%] Built target sem +[ 79%] Built target frontend +[ 80%] Linking CXX static library libir_core.a +[ 84%] Built target ir_core +[ 85%] Built target ir_analysis +[ 89%] Built target ir_passes +[ 94%] Built target mir_core +[ 97%] Built target irgen +[ 99%] Built target mir_passes +[ 99%] Linking CXX executable ../bin/compiler +[100%] Built target compiler +(base) root@HP:/home/hp/nudt-compiler-cpp/build# cd .. +(base) root@HP:/home/hp/nudt-compiler-cpp# ./scripts/verify_ir.sh test/test_case/functional/09_func_defn.sy --run +[error] [irgen] 变量声明缺少存储槽位:a \ No newline at end of file