完善 FunctionType 支持:扩展 CreateFunction 以支持 FunctionType,更新 IR 生成和打印

feature/sem
LuoHello 2 weeks ago
parent 310c93feac
commit affccfb27c

@ -214,9 +214,14 @@ class ConstantInt : public ConstantValue {
private:
int value_{};
};
//function 参数占位类,目前仅保存类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。
class Argument : public Value {
public:
Argument(std::shared_ptr<Type> 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<Type> ret_type);
// 当前构造函数接收完整的 FunctionType
Function(std::string name, std::shared_ptr<FunctionType> func_type);
BasicBlock* CreateBlock(const std::string& name);
BasicBlock* GetEntry();
const BasicBlock* GetEntry() const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
// 函数增加参数的接口,目前仅保存参数类型和名字,后续可扩展更多属性(例如是否为数组参数、数组维度等)。注意这里是直接在 Function 上管理参数列表,而不是通过一个单独的 FunctionType 来表达完整函数签名,这也是当前最小实现的一个简化点。
Argument* AddArgument(std::unique_ptr<Argument> arg);
const std::vector<std::unique_ptr<Argument>>& GetArguments() const;
private:
BasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<BasicBlock>> blocks_;
std::vector<std::unique_ptr<Argument>> arguments_;
};
class CallInst : public Instruction {
public:
CallInst(std::shared_ptr<Type> ret_ty, Function* callee,
const std::vector<Value*>& args, std::string name);
Function* GetCallee() const;
const std::vector<Value*>& GetArgs() const;
private:
Function* callee_;
std::vector<Value*> 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<Type> ret_type);
std::shared_ptr<FunctionType> func_type);
const std::vector<std::unique_ptr<Function>>& 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<Value*>& args,
const std::string& name);
private:
Context& ctx_;

@ -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<SysYParser::VarDefContext*, ir::Value*> storage_map_;
std::unordered_map<std::string, ir::Value*> param_map_;
std::unordered_map<std::string, ir::Value*> global_map_;
// 循环栈,用于 break/continue
struct LoopContext {

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

@ -5,10 +5,21 @@
namespace ir {
Function::Function(std::string name, std::shared_ptr<Type> ret_type)
: Value(std::move(ret_type), std::move(name)) {
Function::Function(std::string name, std::shared_ptr<FunctionType> func_type)
: Value(std::move(func_type), std::move(name)) {
entry_ = CreateBlock("entry");
}
// 向函数添加参数的实现。
Argument* Function::AddArgument(std::unique_ptr<Argument> 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<std::unique_ptr<Argument>>& Function::GetArguments() const {
return arguments_;
}
BasicBlock* Function::CreateBlock(const std::string& name) {
auto block = std::make_unique<BasicBlock>(name);

@ -49,6 +49,13 @@ AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name);
}
AllocaInst* IRBuilder::CreateAllocaFloat(const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<AllocaInst>(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<LoadInst>(Type::GetInt32Type(), ptr, name);
auto ptr_ty = ptr->GetType();
std::shared_ptr<Type> 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<LoadInst>(elem_ty, ptr, name);
}
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
@ -85,5 +101,20 @@ ReturnInst* IRBuilder::CreateRet(Value* v) {
}
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
}
// 注意:当前 CreateCall 仅支持直接调用 Function且不支持变长参数列表等复杂特性。
// 创建函数调用指令的实现,被调用的函数,参数列表,返回值临时变量名
CallInst* IRBuilder::CreateCall(Function* callee,
const std::vector<Value*>& 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<FunctionType>(callee->GetType());
auto ret_ty = func_ty->GetReturnType();
return insert_block_->Append<CallInst>(ret_ty, callee, args, name);
}
} // namespace ir

@ -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<const FunctionType*>(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<const AllocaInst*>(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<const LoadInst*>(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<const StoreInst*>(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<const CallInst*>(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;
}
}
}
}

@ -61,8 +61,9 @@ void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; }
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> 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<Type> ret_ty, Function* callee,
const std::vector<Value*>& 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<Value*>& CallInst::GetArgs() const { return args_; }
} // namespace ir

@ -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<Type> ret_type) {
functions_.push_back(std::make_unique<Function>(name, std::move(ret_type)));
std::shared_ptr<FunctionType> func_type) {
functions_.push_back(std::make_unique<Function>(name, std::move(func_type)));
return functions_.back().get();
}

@ -77,7 +77,9 @@ void Value::ReplaceAllUsesWith(Value* new_value) {
ConstantValue::ConstantValue(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
Argument::Argument(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
ConstantInt::ConstantInt(std::shared_ptr<Type> ty, int v)
: ConstantValue(std::move(ty), ""), value_(v) {}
} // namespace ir

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

@ -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<ir::Value*> 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<ir::Value*>(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<ir::Value*>(
builder_.CreateLoad(it->second, module_.GetContext().NextTemp()));
builder_.CreateLoad(ptr, module_.GetContext().NextTemp()));
}

@ -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<ir::Type> 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<std::shared_ptr<ir::Type>> param_types;
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->bType()) continue;
std::shared_ptr<ir::Type> 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<ir::Type> 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<ir::Argument>(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 {};
}

@ -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;
}

@ -0,0 +1 @@
int main() { return 0; }

@ -0,0 +1 @@
int main() { return 0; }

@ -0,0 +1 @@
int add(int a, int b) { return a + b; } int main() { return add(1, 2); }
Loading…
Cancel
Save