feat: 支持函数调用及参数传递

hp 3 days ago
parent 4064885a1e
commit d8486b7313

@ -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<Value*> args, std::string name = "");
Function* GetFunc() const;
const std::vector<Value*>& GetArgs() const;
private:
Function* func_;
std::vector<Value*> 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<Value*> args, const std::string& name);
private:
Context& ctx_;

@ -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 {

@ -151,4 +151,14 @@ CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_bb, BasicB
return insert_block_->Append<CondBranchInst>(cond, true_bb, false_bb);
}
CallInst* IRBuilder::CreateCall(Function* func, std::vector<Value*> 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<CallInst>(func, std::move(args), name);
}
} // namespace ir

@ -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<const ConstantInt*>(v)) {
return std::to_string(ci->GetValue());
}
if (auto* cf = dynamic_cast<const ConstantFloat*>(v)) {
return std::to_string(cf->GetValue());
}
return v ? v->GetName() : "<null>";
}
@ -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<const CallInst*>(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;
}
}
}
}

@ -231,4 +231,18 @@ Value* CondBranchInst::GetCond() const { return GetOperand(0); }
BasicBlock* CondBranchInst::GetTrueBlock() const { return static_cast<BasicBlock*>(GetOperand(1)); }
BasicBlock* CondBranchInst::GetFalseBlock() const { return static_cast<BasicBlock*>(GetOperand(2)); }
CallInst::CallInst(Function* func, std::vector<Value*> 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<Value*>& CallInst::GetArgs() const { return args_; }
} // namespace ir

@ -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<ir::Type> 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<ir::Value*> args;
if (ctx->funcRParams()) {
args = std::any_cast<std::vector<ir::Value*>>(ctx->funcRParams()->accept(this));
}
return static_cast<ir::Value*>(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<ir::Value*> args;
for (auto* exp : ctx->exp()) {
args.push_back(EvalExpr(*exp));
}
return args;
}
Loading…
Cancel
Save