feat: 支持带有参数的函数定义

hp
hp 3 days ago
parent 6f63c4c7ba
commit 4064885a1e

@ -144,6 +144,16 @@ class Value {
std::vector<Use> uses_;
};
class Argument : public Value {
public:
Argument(std::shared_ptr<Type> ty, std::string name, Function* parent, size_t arg_no);
Function* GetParent() const;
size_t GetArgNo() const;
private:
Function* parent_;
size_t arg_no_;
};
// ConstantValue 是常量体系的基类。
// 当前只实现了 ConstantInt后续可继续扩展更多常量种类。
class ConstantValue : public Value {
@ -334,9 +344,13 @@ class Function : public Value {
const BasicBlock* GetEntry() const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
Argument* AddArgument(std::shared_ptr<Type> ty, std::string name);
const std::vector<std::unique_ptr<Argument>>& GetArgs() const;
private:
BasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<BasicBlock>> blocks_;
std::vector<std::unique_ptr<Argument>> args_;
};
class Module {

@ -29,4 +29,15 @@ const std::vector<std::unique_ptr<BasicBlock>>& Function::GetBlocks() const {
return blocks_;
}
Argument* Function::AddArgument(std::shared_ptr<Type> ty, std::string name) {
auto arg = std::make_unique<Argument>(std::move(ty), std::move(name), this, args_.size());
auto* ptr = arg.get();
args_.push_back(std::move(arg));
return ptr;
}
const std::vector<std::unique_ptr<Argument>>& Function::GetArgs() const {
return args_;
}
} // namespace ir

@ -112,6 +112,13 @@ void User::AddOperand(Value* value) {
}
}
Argument::Argument(std::shared_ptr<Type> ty, std::string name, Function* parent, size_t arg_no)
: Value(std::move(ty), std::move(name)), parent_(parent), arg_no_(arg_no) {}
Function* Argument::GetParent() const { return parent_; }
size_t Argument::GetArgNo() const { return arg_no_; }
ConstantValue::ConstantValue(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}

@ -69,22 +69,59 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
if (!ctx->block()) {
if (!ctx->blockStmt()) {
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
if (!ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
}
if (!ctx->funcType() || !ctx->funcType()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持无参 int 函数"));
std::shared_ptr<ir::Type> ret_type;
if (ctx->funcType()->INT()) {
ret_type = ir::Type::GetInt32Type();
} else if (ctx->funcType()->FLOAT()) {
ret_type = ir::Type::GetFloatType();
} else if (ctx->funcType()->VOID()) {
ret_type = ir::Type::GetVoidType();
} else {
throw std::runtime_error(FormatError("irgen", "未知的函数返回类型"));
}
func_ = module_.CreateFunction(ctx->ID()->getText(), ir::Type::GetInt32Type());
func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type);
builder_.SetInsertPoint(func_->GetEntry());
storage_map_.clear();
ctx->block()->accept(this);
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
if (ctx->funcFParams()) {
for (auto* paramCtx : ctx->funcFParams()->funcFParam()) {
std::shared_ptr<ir::Type> param_type;
bool is_array = !paramCtx->LBRACK().empty();
if (paramCtx->bType()->INT()) {
param_type = is_array ? ir::Type::GetPtrInt32Type() : ir::Type::GetInt32Type();
} else if (paramCtx->bType()->FLOAT()) {
param_type = is_array ? ir::Type::GetPtrFloatType() : ir::Type::GetFloatType();
} else {
throw std::runtime_error(FormatError("irgen", "未知的参数类型"));
}
std::string arg_name = paramCtx->ID()->getText();
auto* arg = func_->AddArgument(param_type, "%arg" + std::to_string(func_->GetArgs().size()));
ir::Instruction* alloca_inst;
if (param_type->IsInt32() || param_type->IsPtrInt32()) {
alloca_inst = builder_.CreateAllocaI32(arg_name + ".addr");
} else {
alloca_inst = builder_.CreateAllocaFloat(arg_name + ".addr");
}
builder_.CreateStore(arg, alloca_inst);
storage_map_[arg_name] = alloca_inst;
}
}
ctx->blockStmt()->accept(this);
VerifyFunctionStructure(*func_);
func_ = nullptr;
return {};
}

Loading…
Cancel
Save