From affccfb27c274b3f2cf43c6654d34ab47333b01d Mon Sep 17 00:00:00 2001 From: LuoHello <2901023943@qq.com> Date: Thu, 26 Mar 2026 19:00:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20FunctionType=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=9A=E6=89=A9=E5=B1=95=20CreateFunction=20?= =?UTF-8?q?=E4=BB=A5=E6=94=AF=E6=8C=81=20FunctionType=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20IR=20=E7=94=9F=E6=88=90=E5=92=8C=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ir/IR.h | 36 +++++++-- include/irgen/IRGen.h | 7 ++ result.txt | 166 ++++++++++++++++++++++++++++++++++++++++ src/ir/Function.cpp | 15 +++- src/ir/IRBuilder.cpp | 33 +++++++- src/ir/IRPrinter.cpp | 47 ++++++++++-- src/ir/Instruction.cpp | 24 +++++- src/ir/Module.cpp | 4 +- src/ir/Value.cpp | 4 +- src/irgen/IRGenDecl.cpp | 18 ++++- src/irgen/IRGenExp.cpp | 87 ++++++++++++++++++--- src/irgen/IRGenFunc.cpp | 125 ++++++++++++++++++++++-------- src/irgen/IRGenStmt.cpp | 54 +++++++++++-- test.c | 1 + test.sy | 1 + test2.sy | 1 + 16 files changed, 549 insertions(+), 74 deletions(-) create mode 100644 result.txt create mode 100644 test.c create mode 100644 test.sy create mode 100644 test2.sy diff --git a/include/ir/IR.h b/include/ir/IR.h index 4ea12dc..891c59e 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -214,9 +214,14 @@ class ConstantInt : public ConstantValue { private: int value_{}; }; +//function 参数占位类,目前仅保存类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。 +class Argument : public Value { + public: + Argument(std::shared_ptr ty, std::string name); +}; -// 后续还需要扩展更多指令类型。 -enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret }; +// 后续还需要扩展更多指令类型。add call instruction 只是最小占位,后续可以继续补 sub/mul/div/rem、br/condbr、phi、gep 等指令。 +enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret, Call }; // User 是所有“会使用其他 Value 作为输入”的 IR 对象的抽象基类。 // 当前实现中只有 Instruction 继承自 User。 @@ -326,16 +331,32 @@ class BasicBlock : public Value { // 形参和调用,通常需要引入专门的函数类型表示。 class Function : public Value { public: - // 当前构造函数接收的也是返回类型,而不是完整函数类型。 - Function(std::string name, std::shared_ptr ret_type); + // 当前构造函数接收完整的 FunctionType。 + Function(std::string name, std::shared_ptr func_type); BasicBlock* CreateBlock(const std::string& name); BasicBlock* GetEntry(); const BasicBlock* GetEntry() const; const std::vector>& GetBlocks() const; + // 函数增加参数的接口,目前仅保存参数类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。注意这里是直接在 Function 上管理参数列表,而不是通过一个单独的 FunctionType 来表达完整函数签名,这也是当前最小实现的一个简化点。 + Argument* AddArgument(std::unique_ptr arg); + const std::vector>& GetArguments() const; private: BasicBlock* entry_ = nullptr; std::vector> blocks_; + std::vector> arguments_; +}; + +class CallInst : public Instruction { + public: + CallInst(std::shared_ptr ret_ty, Function* callee, + const std::vector& args, std::string name); + Function* GetCallee() const; + const std::vector& GetArgs() const; + + private: + Function* callee_; + std::vector args_; }; class Module { @@ -343,9 +364,9 @@ class Module { Module() = default; Context& GetContext(); const Context& GetContext() const; - // 创建函数时当前只显式传入返回类型,尚未接入完整的 FunctionType。 + // 创建函数时传入完整的 FunctionType。 Function* CreateFunction(const std::string& name, - std::shared_ptr ret_type); + std::shared_ptr func_type); const std::vector>& GetFunctions() const; private: @@ -365,9 +386,12 @@ class IRBuilder { const std::string& name); BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name); AllocaInst* CreateAllocaI32(const std::string& name); + AllocaInst* CreateAllocaFloat(const std::string& name); LoadInst* CreateLoad(Value* ptr, const std::string& name); StoreInst* CreateStore(Value* val, Value* ptr); ReturnInst* CreateRet(Value* v); + CallInst* CreateCall(Function* callee, const std::vector& args, + const std::string& name); private: Context& ctx_; diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index 30b71c7..9006b3f 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -40,8 +40,13 @@ class IRGenImpl final : public SysYBaseVisitor { std::any visitStmt(SysYParser::StmtContext* ctx) override; // 表达式 + // 基本表达式(变量、常量、括号表达式)直接翻译为 IR 中的值;函数调用和一元运算需要特殊处理。 std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override; + // 一元表达式包括函数调用和一元运算,需要特殊处理 + std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override; + // 其他二元表达式按照优先级分层访问,最终调用 visitLVal 来处理变量访问。变量引用 std::any visitLVal(SysYParser::LValContext* ctx) override; + // 加法表达式、乘法表达式、关系表达式、相等表达式、条件表达式分别对应不同的访问函数,按照优先级分层访问,最终调用 visitLVal 来处理变量访问 std::any visitAddExp(SysYParser::AddExpContext* ctx) override; std::any visitMulExp(SysYParser::MulExpContext* ctx) override; std::any visitRelExp(SysYParser::RelExpContext* ctx) override; @@ -72,6 +77,8 @@ class IRGenImpl final : public SysYBaseVisitor { ir::IRBuilder builder_; // 名称绑定由 Sema 负责;IRGen 只维护“声明 -> 存储槽位”的代码生成状态。 std::unordered_map storage_map_; + std::unordered_map param_map_; + std::unordered_map global_map_; // 循环栈,用于 break/continue struct LoopContext { diff --git a/result.txt b/result.txt new file mode 100644 index 0000000..9c10863 --- /dev/null +++ b/result.txt @@ -0,0 +1,166 @@ +========== test/test_case/functional/09_func_defn.sy ========== +compUnit +|-- decl +| `-- varDecl +| |-- bType +| | `-- Int: int +| |-- varDef +| | `-- Ident: a +| `-- Semi: ; +|-- funcDef +| |-- funcType +| | `-- Int: int +| |-- Ident: func +| |-- L_PAREN: ( +| |-- funcFParams +| | `-- funcFParam +| | |-- bType +| | | `-- Int: int +| | `-- Ident: p +| |-- R_PAREN: ) +| `-- block +| |-- L_BRACE: { +| |-- blockItem +| | `-- stmt +| | |-- lVal +| | | `-- Ident: p +| | |-- Assign: = +| | |-- exp +| | | `-- addExp +| | | |-- addExp +| | | | `-- mulExp +| | | | `-- unaryExp +| | | | `-- primaryExp +| | | | `-- lVal +| | | | `-- Ident: p +| | | |-- SubOp: - +| | | `-- mulExp +| | | `-- unaryExp +| | | `-- primaryExp +| | | `-- DECIMAL_INT: 1 +| | `-- Semi: ; +| |-- blockItem +| | `-- stmt +| | |-- Return: return +| | |-- exp +| | | `-- addExp +| | | `-- mulExp +| | | `-- unaryExp +| | | `-- primaryExp +| | | `-- lVal +| | | `-- Ident: p +| | `-- Semi: ; +| `-- R_BRACE: } +|-- funcDef +| |-- funcType +| | `-- Int: int +| |-- Ident: main +| |-- L_PAREN: ( +| |-- R_PAREN: ) +| `-- block +| |-- L_BRACE: { +| |-- blockItem +| | `-- decl +| | `-- varDecl +| | |-- bType +| | | `-- Int: int +| | |-- varDef +| | | `-- Ident: b +| | `-- Semi: ; +| |-- blockItem +| | `-- stmt +| | |-- lVal +| | | `-- Ident: a +| | |-- Assign: = +| | |-- exp +| | | `-- addExp +| | | `-- mulExp +| | | `-- unaryExp +| | | `-- primaryExp +| | | `-- DECIMAL_INT: 10 +| | `-- Semi: ; +| |-- blockItem +| | `-- stmt +| | |-- lVal +| | | `-- Ident: b +| | |-- Assign: = +| | |-- exp +| | | `-- addExp +| | | `-- mulExp +| | | `-- unaryExp +| | | |-- Ident: func +| | | |-- L_PAREN: ( +| | | |-- funcRParams +| | | | `-- exp +| | | | `-- addExp +| | | | `-- mulExp +| | | | `-- unaryExp +| | | | `-- primaryExp +| | | | `-- lVal +| | | | `-- Ident: a +| | | `-- R_PAREN: ) +| | `-- Semi: ; +| |-- blockItem +| | `-- stmt +| | |-- Return: return +| | |-- exp +| | | `-- addExp +| | | `-- mulExp +| | | `-- unaryExp +| | | `-- primaryExp +| | | `-- lVal +| | | `-- Ident: b +| | `-- Semi: ; +| `-- R_BRACE: } +`-- EOF: +[DEBUG] CheckVarDef: a base_type: int is_array: 0 dim_count: 0 +[DEBUG] 符号添加完成: a type_kind: 1 is_array: 0 +[DEBUG] 进入函数: func 返回类型: int +[DEBUG] 添加参数: p type_kind: 1 +[DEBUG] visitStmt: Assign ExpStmt +[DEBUG] CheckExp: p-1 +[DEBUG] visitUnaryExp: p +[DEBUG] visitPrimaryExp: p +[DEBUG] visitUnaryExp: 1 +[DEBUG] visitPrimaryExp: 1 +[DEBUG] visitStmt: Return ExpStmt +[DEBUG] 检测到 return 语句 +[DEBUG] visitReturnStmtInternal 被调用 +[DEBUG] 有返回值的 return +[DEBUG] CheckExp: p +[DEBUG] visitUnaryExp: p +[DEBUG] visitPrimaryExp: p +[DEBUG] 设置 current_func_has_return_ = true +[DEBUG] 函数 func has_return: 1 return_type_is_void: 0 +[DEBUG] 进入函数: main 返回类型: int +[DEBUG] CheckVarDef: b base_type: int is_array: 0 dim_count: 0 +[DEBUG] 符号添加完成: b type_kind: 1 is_array: 0 +[DEBUG] visitStmt: Assign ExpStmt +[DEBUG] CheckLValue 绑定变量: a +[DEBUG] CheckExp: 10 +[DEBUG] visitUnaryExp: 10 +[DEBUG] visitPrimaryExp: 10 +[DEBUG] visitStmt: Assign ExpStmt +[DEBUG] CheckLValue 绑定变量: b +[DEBUG] CheckExp: func(a) +[DEBUG] visitUnaryExp: func(a) +[DEBUG] 函数调用: func +[DEBUG] CheckFuncCall: func +[DEBUG] 处理函数调用参数: +[DEBUG] CheckExp: a +[DEBUG] visitUnaryExp: a +[DEBUG] visitPrimaryExp: a +[DEBUG] CheckLValue 绑定变量: a +[DEBUG] 检查参数 0: 实参类型 1 形参类型 1 +[DEBUG] visitStmt: Return ExpStmt +[DEBUG] 检测到 return 语句 +[DEBUG] visitReturnStmtInternal 被调用 +[DEBUG] 有返回值的 return +[DEBUG] CheckExp: b +[DEBUG] visitUnaryExp: b +[DEBUG] visitPrimaryExp: b +[DEBUG] CheckLValue 绑定变量: b +[DEBUG] 设置 current_func_has_return_ = true +[DEBUG] 函数 main has_return: 1 return_type_is_void: 0 +[error] [irgen] 变量声明缺少存储槽位: a + diff --git a/src/ir/Function.cpp b/src/ir/Function.cpp index cf14d48..3652f77 100644 --- a/src/ir/Function.cpp +++ b/src/ir/Function.cpp @@ -5,10 +5,21 @@ namespace ir { -Function::Function(std::string name, std::shared_ptr ret_type) - : Value(std::move(ret_type), std::move(name)) { +Function::Function(std::string name, std::shared_ptr func_type) + : Value(std::move(func_type), std::move(name)) { entry_ = CreateBlock("entry"); } +// 向函数添加参数的实现。 +Argument* Function::AddArgument(std::unique_ptr arg) {// 独占所有权,自动释放内存 + if (!arg) return nullptr; // 1. 检查参数是否为空 + auto* ptr = arg.get(); // 2. 获取原始指针(用于返回) + arguments_.push_back(std::move(arg)); // 3. 将参数所有权转移到函数的参数列表中,arg已经是空指针了,不能再使用arg了 + return ptr; // 4. 返回参数指针,方便调用者使用 +} +// 获取函数参数列表的实现。 +const std::vector>& Function::GetArguments() const { + return arguments_; +} BasicBlock* Function::CreateBlock(const std::string& name) { auto block = std::make_unique(name); diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 90f03c4..5bf992b 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -49,6 +49,13 @@ AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) { return insert_block_->Append(Type::GetPtrInt32Type(), name); } +AllocaInst* IRBuilder::CreateAllocaFloat(const std::string& name) { + if (!insert_block_) { + throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); + } + return insert_block_->Append(Type::GetPtrFloatType(), name); +} + LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) { if (!insert_block_) { throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); @@ -57,7 +64,16 @@ 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 ptr_ty = ptr->GetType(); + std::shared_ptr elem_ty; + if (ptr_ty->IsPtrInt32()) { + elem_ty = Type::GetInt32Type(); + } else if (ptr_ty->IsPtrFloat()) { + elem_ty = Type::GetFloatType(); + } else { + throw std::runtime_error(FormatError("ir", "不支持的指针类型")); + } + return insert_block_->Append(elem_ty, ptr, name); } StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) { @@ -85,5 +101,20 @@ ReturnInst* IRBuilder::CreateRet(Value* v) { } return insert_block_->Append(Type::GetVoidType(), v); } +// 注意:当前 CreateCall 仅支持直接调用 Function,且不支持变长参数列表等复杂特性。 +// 创建函数调用指令的实现,被调用的函数,参数列表,返回值临时变量名 +CallInst* IRBuilder::CreateCall(Function* callee, + const std::vector& args, + const std::string& name) { + if (!insert_block_) { + throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); + } + if (!callee) { //被调用的函数不能为空 + throw std::runtime_error(FormatError("ir", "IRBuilder::CreateCall 缺少 callee")); + } + auto func_ty = std::static_pointer_cast(callee->GetType()); + auto ret_ty = func_ty->GetReturnType(); + return insert_block_->Append(ret_ty, callee, args, name); +} } // namespace ir diff --git a/src/ir/IRPrinter.cpp b/src/ir/IRPrinter.cpp index 5b11d63..28f1e88 100644 --- a/src/ir/IRPrinter.cpp +++ b/src/ir/IRPrinter.cpp @@ -43,6 +43,8 @@ static const char* OpcodeToString(Opcode op) { return "store"; case Opcode::Ret: return "ret"; + case Opcode::Call: + return "call"; } return "?"; } @@ -56,8 +58,15 @@ static std::string ValueToString(const Value* v) { void IRPrinter::Print(const Module& module, std::ostream& os) { for (const auto& func : module.GetFunctions()) { - os << "define " << TypeToString(*func->GetType()) << " @" << func->GetName() - << "() {\n"; + auto* func_ty = static_cast(func->GetType().get()); + os << "define " << TypeToString(*func_ty->GetReturnType()) << " @" << func->GetName() << "("; + bool first = true; + for (const auto& arg : func->GetArguments()) { + if (!first) os << ", "; + first = false; + os << TypeToString(*arg->GetType()) << " " << arg->GetName(); + } + os << ") {\n"; for (const auto& bb : func->GetBlocks()) { if (!bb) { continue; @@ -79,19 +88,31 @@ void IRPrinter::Print(const Module& module, std::ostream& os) { } case Opcode::Alloca: { auto* alloca = static_cast(inst); - os << " " << alloca->GetName() << " = alloca i32\n"; + std::string elem_ty_str; + if (alloca->GetType()->IsPtrInt32()) { + elem_ty_str = "i32"; + } else if (alloca->GetType()->IsPtrFloat()) { + elem_ty_str = "float"; + } else { + elem_ty_str = TypeToString(*alloca->GetType()); + } + os << " " << alloca->GetName() << " = alloca " << elem_ty_str << "\n"; break; } case Opcode::Load: { auto* load = static_cast(inst); - os << " " << load->GetName() << " = load i32, i32* " + os << " " << load->GetName() << " = load " + << TypeToString(*load->GetType()) << ", " + << TypeToString(*load->GetPtr()->GetType()) << " " << ValueToString(load->GetPtr()) << "\n"; break; } case Opcode::Store: { auto* store = static_cast(inst); - os << " store i32 " << ValueToString(store->GetValue()) - << ", i32* " << ValueToString(store->GetPtr()) << "\n"; + os << " store " << TypeToString(*store->GetValue()->GetType()) << " " + << ValueToString(store->GetValue()) + << ", " << TypeToString(*store->GetPtr()->GetType()) << " " + << ValueToString(store->GetPtr()) << "\n"; break; } case Opcode::Ret: { @@ -100,6 +121,20 @@ void IRPrinter::Print(const Module& module, std::ostream& os) { << ValueToString(ret->GetValue()) << "\n"; break; } + // CallInst类在 include/ir/IR.h 中定义 + case Opcode::Call: { + auto* call = static_cast(inst); + os << " " << call->GetName() << " = call " + << TypeToString(*call->GetType()) << " @" << call->GetCallee()->GetName() << "("; + bool first = true; + for (auto* arg : call->GetArgs()) { + if (!first) os << ", "; + first = false; + os << TypeToString(*arg->GetType()) << " " << ValueToString(arg); + } + os << ")\n"; + break; + } } } } diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 7928716..396dbf6 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -61,8 +61,9 @@ void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; } BinaryInst::BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, Value* rhs, std::string name) : Instruction(op, std::move(ty), std::move(name)) { - if (op != Opcode::Add) { - throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 Add")); + // 当前 BinaryInst 仅支持 Add/Sub/Mul,且操作数和结果必须都是 i32。 + if (op != Opcode::Add && op != Opcode::Sub && op != Opcode::Mul) { + throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 Add/Sub/Mul")); } if (!lhs || !rhs) { throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数")); @@ -148,4 +149,23 @@ Value* StoreInst::GetValue() const { return GetOperand(0); } Value* StoreInst::GetPtr() const { return GetOperand(1); } +CallInst::CallInst(std::shared_ptr ret_ty, Function* callee, + const std::vector& args, std::string name) + : Instruction(Opcode::Call, std::move(ret_ty), std::move(name)), + callee_(callee), args_(args) { + if (!callee_) { + throw std::runtime_error(FormatError("ir", "CallInst 缺少被调用函数")); + } + for (auto* arg : args_) { + if (!arg) { + throw std::runtime_error(FormatError("ir", "CallInst 参数不能为 null")); + } + AddOperand(arg); + } +} + +Function* CallInst::GetCallee() const { return callee_; } + +const std::vector& CallInst::GetArgs() const { return args_; } + } // namespace ir diff --git a/src/ir/Module.cpp b/src/ir/Module.cpp index 928efdc..811aa09 100644 --- a/src/ir/Module.cpp +++ b/src/ir/Module.cpp @@ -9,8 +9,8 @@ Context& Module::GetContext() { return context_; } const Context& Module::GetContext() const { return context_; } Function* Module::CreateFunction(const std::string& name, - std::shared_ptr ret_type) { - functions_.push_back(std::make_unique(name, std::move(ret_type))); + std::shared_ptr func_type) { + functions_.push_back(std::make_unique(name, std::move(func_type))); return functions_.back().get(); } diff --git a/src/ir/Value.cpp b/src/ir/Value.cpp index 2e9f4c1..a4fd6f4 100644 --- a/src/ir/Value.cpp +++ b/src/ir/Value.cpp @@ -77,7 +77,9 @@ void Value::ReplaceAllUsesWith(Value* new_value) { ConstantValue::ConstantValue(std::shared_ptr ty, std::string name) : Value(std::move(ty), std::move(name)) {} +Argument::Argument(std::shared_ptr ty, std::string name) + : Value(std::move(ty), std::move(name)) {} + ConstantInt::ConstantInt(std::shared_ptr ty, int v) : ConstantValue(std::move(ty), ""), value_(v) {} - } // namespace ir diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 7ca55d0..5b2d446 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -44,7 +44,7 @@ std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { return {}; } - +// 处理变量定义的函数,包括全局变量和局部变量的定义。全局变量会被记录在 global_map_ 中,局部变量会被 std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量定义")); @@ -56,12 +56,22 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { } std::string varName = ctx->Ident()->getText(); - + // 防止同一个变量被多次分配存储空间。 if (storage_map_.find(ctx) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位: " + varName)); } - - // 分配存储 + // 区分全局变量和局部变量,func_ 记录当前正在生成IR的函数,如果 func_ 为空则说明当前在处理全局变量,否则在处理局部变量 + if (!func_) { + // 全局变量(简化):用全局占位符记录为 i32*,Default 不直接插入指令 + // 全局变量:在数据段分配 + // TODO:真正的全局变量应该存储值本身,而不是指针,这里为了简化实现先使用指针占位,后续可以改为直接存储值 + auto* global = new ir::GlobalValue(ir::Type::GetPtrInt32Type(), varName); + global_map_[varName] = global; + // 对全局初始化暂不支持,默认为0 + return {}; + } + + // 分配存储(局部变量) auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); storage_map_[ctx] = slot; diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 90d07b1..6e5ffcc 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -70,6 +70,60 @@ std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { throw std::runtime_error(FormatError("irgen", "不支持的基本表达式类型")); } +std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { + if (!ctx) { + throw std::runtime_error(FormatError("irgen", "缺少一元表达式")); + } + + if (ctx->primaryExp()) { + return ctx->primaryExp()->accept(this); + } + + if (ctx->Ident() && ctx->L_PAREN()) { + std::string funcName = ctx->Ident()->getText(); + ir::Function* callee = nullptr; + for (auto& f : module_.GetFunctions()) { + if (f->GetName() == funcName) { + callee = f.get(); + break; + } + } + if (!callee) { + throw std::runtime_error(FormatError("irgen", "找不到函数: " + funcName)); + } + + std::vector args; + if (ctx->funcRParams()) { + for (auto* exp : ctx->funcRParams()->exp()) { + args.push_back(EvalExpr(*exp)); + } + } + + ir::Value* result = builder_.CreateCall(callee, args, module_.GetContext().NextTemp()); + return result; + } + + if (ctx->unaryOp() && ctx->unaryExp()) { + auto* operand = std::any_cast(ctx->unaryExp()->accept(this)); + if (ctx->unaryOp()->AddOp()) { + return operand; + } + if (ctx->unaryOp()->SubOp()) { + auto* zero = builder_.CreateConstInt(0); + return builder_.CreateBinary(ir::Opcode::Sub, zero, operand, + module_.GetContext().NextTemp()); + } + if (ctx->unaryOp()->NotOp()) { + // 逻辑非暂不支持,先默认 0/1 取反 + // 这里简化:如果 operand ==0 返回1,否则返回0。(不做真实比较) + // 需要后续完善比较指令。 + return operand; + } + } + + throw std::runtime_error(FormatError("irgen", "不支持的 unaryExp")); +} + // 左值(变量)处理 // 1. 先通过语义分析结果把变量使用绑定回声明; // 2. 再通过 storage_map_ 找到该声明对应的栈槽位; @@ -83,21 +137,36 @@ std::any IRGenImpl::visitLVal(SysYParser::LValContext* ctx) { // 从语义分析获取变量定义 auto* decl = sema_.ResolveVarUse(ctx); - if (!decl) { - throw std::runtime_error( - FormatError("irgen", - "变量使用缺少语义绑定: " + varName)); + ir::Value* ptr = nullptr; + if (decl) { + auto it = storage_map_.find(decl); + if (it != storage_map_.end()) { + ptr = it->second; + } } - - auto it = storage_map_.find(decl); - if (it == storage_map_.end()) { + + if (!ptr) { + auto it2 = param_map_.find(varName); + if (it2 != param_map_.end()) { + ptr = it2->second; + } + } + + if (!ptr) { + auto it3 = global_map_.find(varName); + if (it3 != global_map_.end()) { + ptr = it3->second; + } + } + + if (!ptr) { throw std::runtime_error( FormatError("irgen", "变量声明缺少存储槽位: " + varName)); } - + return static_cast( - builder_.CreateLoad(it->second, module_.GetContext().NextTemp())); + builder_.CreateLoad(ptr, module_.GetContext().NextTemp())); } diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index 87f3ac8..d47f970 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -33,26 +33,21 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少编译单元")); } - - // 获取所有函数定义 - auto funcDefs = ctx->funcDef(); - - // 找到 main 函数 - SysYParser::FuncDefContext* mainFunc = nullptr; - for (auto* funcDef : funcDefs) { - if (funcDef->Ident() && funcDef->Ident()->getText() == "main") { - mainFunc = funcDef; - break; + + // 处理全局变量声明 + for (auto* decl : ctx->decl()) { + if (decl) { + decl->accept(this); } } - - if (!mainFunc) { - throw std::runtime_error(FormatError("irgen", "缺少main函数")); + + // 处理所有函数定义 + for (auto* funcDef : ctx->funcDef()) { + if (funcDef) { + funcDef->accept(this); + } } - - // 生成 main 函数 - mainFunc->accept(this); - + return {}; } @@ -60,39 +55,101 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少函数定义")); } - - // 使用 Ident() 而不是 ID() + if (!ctx->Ident()) { throw std::runtime_error(FormatError("irgen", "缺少函数名")); } - + std::string funcName = ctx->Ident()->getText(); - - // 检查函数体 - 使用 block() 而不是 blockStmt() + if (!ctx->block()) { throw std::runtime_error(FormatError("irgen", "函数体为空")); } - - // 检查返回类型 - 使用 Int() 而不是 INT() - if (!ctx->funcType() || !ctx->funcType()->Int()) { - throw std::runtime_error(FormatError("irgen", "当前仅支持int函数")); + + std::shared_ptr ret_type = ir::Type::GetInt32Type(); + if (ctx->funcType()) { + if (ctx->funcType()->Void()) { + ret_type = ir::Type::GetVoidType(); + } else if (ctx->funcType()->Int()) { + ret_type = ir::Type::GetInt32Type(); + } else if (ctx->funcType()->Float()) { + ret_type = ir::Type::GetFloatType(); + } } - - // 创建函数 - func_ = module_.CreateFunction(funcName, ir::Type::GetInt32Type()); + + std::vector> param_types; + if (ctx->funcFParams()) { + for (auto* param : ctx->funcFParams()->funcFParam()) { + if (!param || !param->bType()) continue; + std::shared_ptr param_ty; + if (param->bType()->Int()) { + param_ty = ir::Type::GetInt32Type(); + } else if (param->bType()->Float()) { + param_ty = ir::Type::GetFloatType(); + } else { + param_ty = ir::Type::GetInt32Type(); + } + if (!param->L_BRACK().empty()) { + if (param_ty->IsInt32()) { + param_ty = ir::Type::GetPtrInt32Type(); + } else if (param_ty->IsFloat()) { + param_ty = ir::Type::GetPtrFloatType(); + } + } + param_types.push_back(param_ty); + } + } + + auto func_type = ir::Type::GetFunctionType(ret_type, param_types); + func_ = module_.CreateFunction(funcName, func_type); builder_.SetInsertPoint(func_->GetEntry()); storage_map_.clear(); - - // 生成函数体 - 使用 block() 而不是 blockStmt() + param_map_.clear(); + + // 函数参数 (按照语义分析、symbol table 定义顺序) + if (ctx->funcFParams()) { + for (auto* param : ctx->funcFParams()->funcFParam()) { + if (!param || !param->Ident()) continue; + std::string name = param->Ident()->getText(); + std::shared_ptr param_ty; + if (param->bType()->Int()) { + param_ty = ir::Type::GetInt32Type(); + } else if (param->bType()->Float()) { + param_ty = ir::Type::GetFloatType(); + } else { + param_ty = ir::Type::GetInt32Type(); + } + if (!param->L_BRACK().empty()) { + if (param_ty->IsInt32()) { + param_ty = ir::Type::GetPtrInt32Type(); + } else if (param_ty->IsFloat()) { + param_ty = ir::Type::GetPtrFloatType(); + } + } + auto* arg = func_->AddArgument(std::make_unique(param_ty, name)); + ir::AllocaInst* slot; + if (param_ty->IsInt32() || param_ty->IsPtrInt32()) { + slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); + } else if (param_ty->IsFloat() || param_ty->IsPtrFloat()) { + slot = builder_.CreateAllocaFloat(module_.GetContext().NextTemp()); + } else { + throw std::runtime_error(FormatError("irgen", "不支持的参数类型")); + } + builder_.CreateStore(arg, slot); + param_map_[name] = slot; + } + } + + // 生成函数体 ctx->block()->accept(this); - - // 确保函数有返回值 + if (!func_->GetEntry()->HasTerminator()) { auto retVal = builder_.CreateConstInt(0); builder_.CreateRet(retVal); } - + VerifyFunctionStructure(*func_); + func_ = nullptr; return {}; } diff --git a/src/irgen/IRGenStmt.cpp b/src/irgen/IRGenStmt.cpp index fef78ea..cd78d93 100644 --- a/src/irgen/IRGenStmt.cpp +++ b/src/irgen/IRGenStmt.cpp @@ -19,26 +19,30 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少语句")); } - + // return 语句 - 通过 Return() 关键字判断 if (ctx->Return()) { return HandleReturnStmt(ctx); } - + + // 赋值语句 + if (ctx->lVal() && ctx->Assign() && ctx->exp()) { + return HandleAssignStmt(ctx); + } + // 块语句 if (ctx->block()) { return ctx->block()->accept(this); } - + // 空语句或表达式语句(先计算表达式) if (ctx->exp()) { EvalExpr(*ctx->exp()); return BlockFlow::Continue; } - + throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型")); } - IRGenImpl::BlockFlow IRGenImpl::HandleReturnStmt(SysYParser::StmtContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少 return 语句")); @@ -83,6 +87,42 @@ IRGenImpl::BlockFlow IRGenImpl::HandleContinueStmt(SysYParser::StmtContext* ctx) // 赋值语句(待实现) IRGenImpl::BlockFlow IRGenImpl::HandleAssignStmt(SysYParser::StmtContext* ctx) { - // TODO: 实现赋值 - throw std::runtime_error(FormatError("irgen", "赋值语句暂未实现")); + if (!ctx || !ctx->lVal() || !ctx->exp()) { + throw std::runtime_error(FormatError("irgen", "非法赋值语句")); + } + + ir::Value* rhs = EvalExpr(*ctx->exp()); + if (!rhs) { + throw std::runtime_error(FormatError("irgen", "赋值 RHS 计算失败")); + } + + auto* lval = ctx->lVal(); + auto* decl = sema_.ResolveVarUse(lval); + ir::Value* ptr = nullptr; + if (decl) { + auto it = storage_map_.find(decl); + if (it != storage_map_.end()) { + ptr = it->second; + } + } + + if (!ptr && lval->Ident()) { + auto it = param_map_.find(lval->Ident()->getText()); + if (it != param_map_.end()) { + ptr = it->second; + } + if (!ptr) { + auto it2 = global_map_.find(lval->Ident()->getText()); + if (it2 != global_map_.end()) { + ptr = it2->second; + } + } + } + + if (!ptr) { + throw std::runtime_error(FormatError("irgen", "赋值目标缺少存储槽位: " + lval->getText())); + } + + builder_.CreateStore(rhs, ptr); + return BlockFlow::Continue; } diff --git a/test.c b/test.c new file mode 100644 index 0000000..76e8197 --- /dev/null +++ b/test.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/test.sy b/test.sy new file mode 100644 index 0000000..76e8197 --- /dev/null +++ b/test.sy @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/test2.sy b/test2.sy new file mode 100644 index 0000000..05e7a96 --- /dev/null +++ b/test2.sy @@ -0,0 +1 @@ +int add(int a, int b) { return a + b; } int main() { return add(1, 2); }