From d8486b731396246a69bc14b55acb5f474b02ce87 Mon Sep 17 00:00:00 2001 From: hp <1278334840@qq.com> Date: Mon, 6 Apr 2026 21:38:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=8F=8A=E5=8F=82=E6=95=B0=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ir/IR.h | 14 +++++++++++- include/irgen/IRGen.h | 1 + src/ir/IRBuilder.cpp | 10 +++++++++ src/ir/IRPrinter.cpp | 34 ++++++++++++++++++++++++++-- src/ir/Instruction.cpp | 14 ++++++++++++ src/irgen/IRGenExp.cpp | 51 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 119 insertions(+), 5 deletions(-) diff --git a/include/ir/IR.h b/include/ir/IR.h index 4982988..1faced7 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -181,7 +181,7 @@ class ConstantFloat : public ConstantValue { // 后续还需要扩展更多指令类型。 // enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret }; -enum class Opcode { Add, Sub, Mul, Div, Mod, Neg, Alloca, Load, Store, Ret, Cmp, Zext, Br, CondBr }; +enum class Opcode { Add, Sub, Mul, Div, Mod, Neg, Alloca, Load, Store, Ret, Cmp, Zext, Br, CondBr, Call }; enum class CmpOp { Eq, Ne, Lt, Gt, Le, Ge }; @@ -298,6 +298,17 @@ class CondBranchInst : public Instruction { BasicBlock* GetFalseBlock() const; }; +class CallInst : public Instruction { + public: + CallInst(Function* func, std::vector args, std::string name = ""); + Function* GetFunc() const; + const std::vector& GetArgs() const; + + private: + Function* func_; + std::vector args_; +}; + // BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。 // 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。 class BasicBlock : public Value { @@ -395,6 +406,7 @@ class IRBuilder { ZextInst* CreateZext(Value* val, const std::string& name); BranchInst* CreateBr(BasicBlock* dest); CondBranchInst* CreateCondBr(Value* cond, BasicBlock* true_bb, BasicBlock* false_bb); + CallInst* CreateCall(Function* func, std::vector args, const std::string& name); private: Context& ctx_; diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index fec791a..b56d538 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -43,6 +43,7 @@ class IRGenImpl final : public SysYBaseVisitor { std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override; std::any visitCondUnaryExp(SysYParser::CondUnaryExpContext* ctx) override; std::any visitCond(SysYParser::CondContext* ctx) override; + std::any visitFuncRParams(SysYParser::FuncRParamsContext* ctx) override; private: enum class BlockFlow { diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 37041c8..64fcf8f 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -151,4 +151,14 @@ CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_bb, BasicB return insert_block_->Append(cond, true_bb, false_bb); } +CallInst* IRBuilder::CreateCall(Function* func, std::vector args, const std::string& name) { + if (!insert_block_) { + throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); + } + if (!func) { + throw std::runtime_error(FormatError("ir", "IRBuilder::CreateCall 缺少目标函数")); + } + return insert_block_->Append(func, std::move(args), name); +} + } // namespace ir diff --git a/src/ir/IRPrinter.cpp b/src/ir/IRPrinter.cpp index 40cfc77..00a037f 100644 --- a/src/ir/IRPrinter.cpp +++ b/src/ir/IRPrinter.cpp @@ -22,6 +22,10 @@ static const char* TypeToString(const Type& ty) { return "i32"; case Type::Kind::PtrInt32: return "i32*"; + case Type::Kind::Float: + return "float"; + case Type::Kind::PtrFloat: + return "float*"; } throw std::runtime_error(FormatError("ir", "未知类型")); } @@ -55,6 +59,8 @@ static const char* OpcodeToString(Opcode op) { case Opcode::Br: case Opcode::CondBr: return "br"; + case Opcode::Call: + return "call"; } return "?"; } @@ -81,6 +87,9 @@ static std::string ValueToString(const Value* v) { if (auto* ci = dynamic_cast(v)) { return std::to_string(ci->GetValue()); } + if (auto* cf = dynamic_cast(v)) { + return std::to_string(cf->GetValue()); + } return v ? v->GetName() : ""; } @@ -101,8 +110,13 @@ static std::string PrintLabelDef(const Value* bb) { void IRPrinter::Print(const Module& module, std::ostream& os) { for (const auto& func : module.GetFunctions()) { - os << "define " << TypeToString(*func->GetType()) << " @" << func->GetName() - << "() {\n"; + os << "define " << TypeToString(*func->GetType()) << " @" << func->GetName() << "("; + const auto& args = func->GetArgs(); + for (size_t i = 0; i < args.size(); ++i) { + if (i > 0) os << ", "; + os << TypeToString(*args[i]->GetType()) << " " << args[i]->GetName(); + } + os << ") {\n"; for (const auto& bb : func->GetBlocks()) { if (!bb) { continue; @@ -184,6 +198,22 @@ void IRPrinter::Print(const Module& module, std::ostream& os) { << ", label " << PrintLabel(cbr->GetFalseBlock()) << "\n"; break; } + case Opcode::Call: { + auto* call = static_cast(inst); + if (call->GetType()->IsVoid()) { + os << " call void @" << call->GetFunc()->GetName() << "("; + } else { + os << " " << call->GetName() << " = call " << TypeToString(*call->GetType()) + << " @" << call->GetFunc()->GetName() << "("; + } + for (size_t i = 0; i < call->GetArgs().size(); ++i) { + if (i > 0) os << ", "; + auto* arg = call->GetArgs()[i]; + os << TypeToString(*arg->GetType()) << " " << ValueToString(arg); + } + os << ")\n"; + break; + } } } } diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 9ae696c..673b069 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -231,4 +231,18 @@ Value* CondBranchInst::GetCond() const { return GetOperand(0); } BasicBlock* CondBranchInst::GetTrueBlock() const { return static_cast(GetOperand(1)); } BasicBlock* CondBranchInst::GetFalseBlock() const { return static_cast(GetOperand(2)); } +CallInst::CallInst(Function* func, std::vector args, std::string name) + : Instruction(Opcode::Call, func->GetType(), std::move(name)), func_(func), args_(std::move(args)) { + if (!func) { + throw std::runtime_error(FormatError("ir", "CallInst 缺少目标函数")); + } + AddOperand(func); + for (auto* arg : args_) { + AddOperand(arg); + } +} + +Function* CallInst::GetFunc() const { return func_; } +const std::vector& CallInst::GetArgs() const { return args_; } + } // namespace ir diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 4565c6e..5ddec76 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -144,9 +144,48 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { } // 处理函数调用(unaryExp : ID LPAREN funcRParams? RPAREN) - // 当前暂不支持,留给后续扩展 if (ctx->ID()) { - throw std::runtime_error(FormatError("irgen", "暂不支持函数调用")); + std::string func_name = ctx->ID()->getText(); + + // 从 Sema 或 Module 中查找函数 + // 目前简化处理,直接从 Module 中查找(如果是当前文件内定义的) + // 或者依赖 Sema 给出解析结果 + const sem::FunctionBinding* func_binding = sema_.ResolveFunctionCall(ctx); + if (!func_binding) { + throw std::runtime_error(FormatError("irgen", "未找到函数声明:" + func_name)); + } + + // 假设 func_binding 能够找到对应的 ir::Function* + // 这里如果 sema 不提供直接拿 ir::Function 的方式,需要遍历 module_.GetFunctions() 查找 + ir::Function* target_func = nullptr; + for (const auto& f : module_.GetFunctions()) { + if (f->GetName() == func_name) { + target_func = f.get(); + break; + } + } + + if (!target_func) { + // 可能是外部函数如 putint, getint 等 + // 如果没有在 module_ 中,则需要创建一个只有声明的 Function + std::shared_ptr ret_ty; + if (func_binding->GetReturnType()->IsInt()) { + ret_ty = ir::Type::GetInt32Type(); + } else if (func_binding->GetReturnType()->IsFloat()) { + ret_ty = ir::Type::GetFloatType(); + } else { + ret_ty = ir::Type::GetVoidType(); + } + target_func = module_.CreateFunction(func_name, ret_ty); + // 对于外部函数,如果需要传递参数,可能还需要在 target_func 中 AddArgument,不过外部声明通常不需要形参块。 + } + + std::vector args; + if (ctx->funcRParams()) { + args = std::any_cast>(ctx->funcRParams()->accept(this)); + } + + return static_cast(builder_.CreateCall(target_func, args, module_.GetContext().NextTemp())); } // 处理一元运算符(unaryExp : addUnaryOp unaryExp) @@ -326,4 +365,12 @@ std::any IRGenImpl::visitCond(SysYParser::CondContext* ctx) { throw std::runtime_error(FormatError("irgen", "非法条件表达式")); } return ctx->lOrExp()->accept(this); +} + +std::any IRGenImpl::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) { + std::vector args; + for (auto* exp : ctx->exp()) { + args.push_back(EvalExpr(*exp)); + } + return args; } \ No newline at end of file