From 6f63c4c7ba2412d0e44afc68d6bed5b2813e369c Mon Sep 17 00:00:00 2001 From: hp <1278334840@qq.com> Date: Mon, 6 Apr 2026 21:00:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=A3=B0=E6=98=8E=E4=B8=8E=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96+=E4=BF=AE=E6=94=B9=E4=BA=86.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + include/ir/IR.h | 32 ++++++++++-- src/ir/Context.cpp | 8 +++ src/ir/IRBuilder.cpp | 7 +++ src/ir/Module.cpp | 9 ++++ src/ir/Value.cpp | 91 +++++++++++++++++++++++++++++++++ src/irgen/IRGenDecl.cpp | 108 ++++++++++++++++++++++++++++++---------- src/irgen/IRGenFunc.cpp | 11 ++-- 8 files changed, 232 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 51f5f27..d321707 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ compile_commands.json .idea/ .fleet/ .vs/ +.trae/ *.code-workspace # CLion diff --git a/include/ir/IR.h b/include/ir/IR.h index 06f837f..24119af 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -83,17 +83,19 @@ class Context { ~Context(); // 去重创建 i32 常量。 ConstantInt* GetConstInt(int v); + ConstantFloat* GetConstFloat(float v); std::string NextTemp(); private: std::unordered_map> const_ints_; + std::unordered_map> const_floats_; int temp_index_ = -1; }; class Type { public: - enum class Kind { Void, Int1, Int32, PtrInt32 }; + enum class Kind { Void, Int1, Int32, PtrInt32, Float, PtrFloat }; explicit Type(Kind k); // 使用静态共享对象获取类型。 // 同一类型可直接比较返回值是否相等,例如: @@ -102,11 +104,15 @@ class Type { static const std::shared_ptr& GetInt1Type(); static const std::shared_ptr& GetInt32Type(); static const std::shared_ptr& GetPtrInt32Type(); + static const std::shared_ptr& GetFloatType(); + static const std::shared_ptr& GetPtrFloatType(); Kind GetKind() const; bool IsVoid() const; bool IsInt1() const; bool IsInt32() const; bool IsPtrInt32() const; + bool IsFloat() const; + bool IsPtrFloat() const; private: Kind kind_; @@ -154,6 +160,15 @@ class ConstantInt : public ConstantValue { int value_{}; }; +class ConstantFloat : public ConstantValue { + public: + ConstantFloat(std::shared_ptr ty, float v); + float GetValue() const { return value_; } + + private: + float value_{}; +}; + // 后续还需要扩展更多指令类型。 // 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 }; @@ -177,13 +192,19 @@ class User : public Value { std::vector operands_; }; -// GlobalValue 是全局值/全局变量体系的空壳占位类。 -// 当前只补齐类层次,具体初始化器、打印和链接语义后续再补。 class GlobalValue : public User { public: GlobalValue(std::shared_ptr ty, std::string name); }; +class GlobalVariable : public GlobalValue { + public: + GlobalVariable(std::string name, std::shared_ptr type, ConstantValue* init); + ConstantValue* GetInitializer() const { return init_; } + private: + ConstantValue* init_ = nullptr; +}; + class Instruction : public User { public: Instruction(Opcode op, std::shared_ptr ty, std::string name = ""); @@ -327,10 +348,14 @@ class Module { Function* CreateFunction(const std::string& name, std::shared_ptr ret_type); const std::vector>& GetFunctions() const; + + GlobalVariable* CreateGlobalVariable(const std::string& name, std::shared_ptr type, ConstantValue* init); + const std::vector>& GetGlobalVariables() const; private: Context context_; std::vector> functions_; + std::vector> global_variables_; }; class IRBuilder { @@ -348,6 +373,7 @@ class IRBuilder { BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name); UnaryInst* CreateNeg(Value* operand, 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); diff --git a/src/ir/Context.cpp b/src/ir/Context.cpp index 5f32c65..7be22e5 100644 --- a/src/ir/Context.cpp +++ b/src/ir/Context.cpp @@ -15,6 +15,14 @@ ConstantInt* Context::GetConstInt(int v) { return inserted->second.get(); } +ConstantFloat* Context::GetConstFloat(float v) { + auto it = const_floats_.find(v); + if (it != const_floats_.end()) return it->second.get(); + auto inserted = + const_floats_.emplace(v, std::make_unique(Type::GetFloatType(), v)).first; + return inserted->second.get(); +} + std::string Context::NextTemp() { std::ostringstream oss; oss << "%t" << ++temp_index_; diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 3569ab6..37041c8 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 未设置插入点")); diff --git a/src/ir/Module.cpp b/src/ir/Module.cpp index 928efdc..3c31d5b 100644 --- a/src/ir/Module.cpp +++ b/src/ir/Module.cpp @@ -18,4 +18,13 @@ const std::vector>& Module::GetFunctions() const { return functions_; } +GlobalVariable* Module::CreateGlobalVariable(const std::string& name, std::shared_ptr type, ConstantValue* init) { + global_variables_.push_back(std::make_unique(name, std::move(type), init)); + return global_variables_.back().get(); +} + +const std::vector>& Module::GetGlobalVariables() const { + return global_variables_; +} + } // namespace ir diff --git a/src/ir/Value.cpp b/src/ir/Value.cpp index 12a06b4..d8cbc8b 100644 --- a/src/ir/Value.cpp +++ b/src/ir/Value.cpp @@ -24,6 +24,10 @@ bool Value::IsInt32() const { return type_ && type_->IsInt32(); } bool Value::IsPtrInt32() const { return type_ && type_->IsPtrInt32(); } +bool Value::IsFloat() const { return type_ && type_->IsFloat(); } + +bool Value::IsPtrFloat() const { return type_ && type_->IsPtrFloat(); } + bool Value::IsConstant() const { return dynamic_cast(this) != nullptr; } @@ -76,10 +80,97 @@ void Value::ReplaceAllUsesWith(Value* new_value) { } } +User::User(std::shared_ptr ty, std::string name) + : Value(std::move(ty), std::move(name)) {} + +size_t User::GetNumOperands() const { return operands_.size(); } + +Value* User::GetOperand(size_t index) const { + if (index >= operands_.size()) { + throw std::out_of_range("Operand index out of range"); + } + return operands_[index]; +} + +void User::SetOperand(size_t index, Value* value) { + if (index >= operands_.size()) { + throw std::out_of_range("Operand index out of range"); + } + if (operands_[index]) { + operands_[index]->RemoveUse(this, index); + } + operands_[index] = value; + if (value) { + value->AddUse(this, index); + } +} + +void User::AddOperand(Value* value) { + operands_.push_back(value); + if (value) { + value->AddUse(this, operands_.size() - 1); + } +} + ConstantValue::ConstantValue(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) {} +ConstantFloat::ConstantFloat(std::shared_ptr ty, float v) + : ConstantValue(std::move(ty), ""), value_(v) {} + +GlobalValue::GlobalValue(std::shared_ptr ty, std::string name) + : User(std::move(ty), std::move(name)) {} + +GlobalVariable::GlobalVariable(std::string name, std::shared_ptr type, ConstantValue* init) + : GlobalValue(std::move(type), std::move(name)), init_(init) {} + +Type::Type(Kind k) : kind_(k) {} + +const std::shared_ptr& Type::GetVoidType() { + static std::shared_ptr ty = std::make_shared(Kind::Void); + return ty; +} + +const std::shared_ptr& Type::GetInt1Type() { + static std::shared_ptr ty = std::make_shared(Kind::Int1); + return ty; +} + +const std::shared_ptr& Type::GetInt32Type() { + static std::shared_ptr ty = std::make_shared(Kind::Int32); + return ty; +} + +const std::shared_ptr& Type::GetPtrInt32Type() { + static std::shared_ptr ty = std::make_shared(Kind::PtrInt32); + return ty; +} + +const std::shared_ptr& Type::GetFloatType() { + static std::shared_ptr ty = std::make_shared(Kind::Float); + return ty; +} + +const std::shared_ptr& Type::GetPtrFloatType() { + static std::shared_ptr ty = std::make_shared(Kind::PtrFloat); + return ty; +} + +Type::Kind Type::GetKind() const { return kind_; } + +bool Type::IsVoid() const { return kind_ == Kind::Void; } + +bool Type::IsInt1() const { return kind_ == Kind::Int1; } + +bool Type::IsInt32() const { return kind_ == Kind::Int32; } + +bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; } + +bool Type::IsFloat() const { return kind_ == Kind::Float; } + +bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; } + } // namespace ir diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 1cd0db8..ebc29e0 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -42,30 +42,34 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) { } // 变量声明的 IR 生成目前也是最小实现: -// - 先检查声明的基础类型,当前仅支持局部 int; +// - 先检查声明的基础类型,支持 int 和 float; // - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。 -// -// 和更完整的版本相比,这里还没有: -// - 一个 Decl 中多个变量定义的顺序处理; -// - const、数组、全局变量等不同声明形态; -// - 更丰富的类型系统。 std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } - // 当前语法中 decl 包含 constDecl 或 varDecl,这里只支持 varDecl - auto* var_decl = ctx->varDecl(); - if (!var_decl) { - throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明")); - } - if (!var_decl->bType() || !var_decl->bType()->INT()) { - throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明")); - } - // 遍历所有 varDef - for (auto* var_def : var_decl->varDef()) { - if (var_def) { - var_def->accept(this); + // 当前语法中 decl 包含 constDecl 或 varDecl + if (auto* var_decl = ctx->varDecl()) { + if (!var_decl->bType() || (!var_decl->bType()->INT() && !var_decl->bType()->FLOAT())) { + throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 变量声明")); + } + for (auto* var_def : var_decl->varDef()) { + if (var_def) { + var_def->accept(this); + } + } + } else if (auto* const_decl = ctx->constDecl()) { + // 稍后实现 constDecl + if (!const_decl->bType() || (!const_decl->bType()->INT() && !const_decl->bType()->FLOAT())) { + throw std::runtime_error(FormatError("irgen", "当前仅支持 int/float 常量声明")); } + for (auto* const_def : const_decl->constDef()) { + if (const_def) { + const_def->accept(this); + } + } + } else { + throw std::runtime_error(FormatError("irgen", "当前仅支持变量声明")); } return BlockFlow::Continue; } @@ -90,18 +94,68 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (storage_map_.find(var_name) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } - auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); - storage_map_[var_name] = slot; - ir::Value* init = nullptr; - if (auto* init_val = ctx->initVal()) { - if (!init_val->exp()) { - throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); + // Determine base type from parent varDecl or constDecl + bool is_float = false; + auto* parent_decl = dynamic_cast(ctx->parent); + if (parent_decl && parent_decl->bType() && parent_decl->bType()->FLOAT()) { + is_float = true; + } + auto base_ty = is_float ? ir::Type::GetFloatType() : ir::Type::GetInt32Type(); + + if (func_ == nullptr) { + // 全局作用域 + ir::ConstantValue* init_const = nullptr; + if (auto* init_val = ctx->initVal()) { + if (!init_val->exp()) { + throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); + } + auto* val = EvalExpr(*init_val->exp()); + init_const = dynamic_cast(val); + if (!init_const) { + throw std::runtime_error(FormatError("irgen", "全局变量初始化必须是常量")); + } + } else { + if (is_float) { + init_const = module_.GetContext().GetConstFloat(0.0f); + } else { + init_const = module_.GetContext().GetConstInt(0); + } } - init = EvalExpr(*init_val->exp()); + + auto* gv = module_.CreateGlobalVariable(var_name, base_ty, init_const); + storage_map_[var_name] = gv; + } else { - init = builder_.CreateConstInt(0); + // 局部作用域 + auto* ptr_ty = is_float ? ir::Type::GetPtrFloatType() : ir::Type::GetPtrInt32Type(); + // 简化处理,暂用 builder 创建 alloca + // 需要在 builder 中扩展 CreateAllocaFloat,此处简化直接按 I32 Alloca 的名称调用,或添加新接口 + // 为了不大幅改动 Builder,我们复用 AllocaInst,或者添加 CreateAlloca + ir::Value* slot = nullptr; + if (is_float) { + slot = builder_.CreateAllocaFloat(module_.GetContext().NextTemp()); + } else { + slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); + } + + storage_map_[var_name] = slot; + + ir::Value* init = nullptr; + if (auto* init_val = ctx->initVal()) { + if (!init_val->exp()) { + throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); + } + init = EvalExpr(*init_val->exp()); + } else { + if (is_float) { + init = module_.GetContext().GetConstFloat(0.0f); + } else { + init = module_.GetContext().GetConstInt(0); + } + } + builder_.CreateStore(init, slot); } - builder_.CreateStore(init, slot); + return BlockFlow::Continue; } diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index 4ee5b3e..0c8472e 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -38,15 +38,16 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少编译单元")); } - // 遍历所有 topLevelItem,找到 funcDef + // 遍历所有 topLevelItem for (auto* item : ctx->topLevelItem()) { - if (item && item->funcDef()) { + if (!item) continue; + if (item->funcDef()) { item->funcDef()->accept(this); - // 当前只支持单个函数,找到第一个后就返回 - return {}; + } else if (item->decl()) { + item->decl()->accept(this); } } - throw std::runtime_error(FormatError("irgen", "缺少函数定义")); + return {}; } // 函数 IR 生成当前实现了: