From 7efc0b9ad4bdd4e0a263ec68fe972a7b4749f60d Mon Sep 17 00:00:00 2001 From: lc <18783417278@163.com> Date: Mon, 30 Mar 2026 20:31:28 +0800 Subject: [PATCH] =?UTF-8?q?=E2=80=9CIRGen=E9=83=A8=E5=88=86=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=EF=BC=9A=E6=94=AF=E6=8C=81=E4=B8=80=E5=85=83=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E7=AC=A6=EF=BC=88=E6=AD=A3=E8=B4=9F=E5=8F=B7=EF=BC=89?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ir/IR.h | 12 ++++++++++-- include/irgen/IRGen.h | 1 + src/ir/IRBuilder.cpp | 10 ++++++++++ src/ir/IRPrinter.cpp | 10 ++++++++++ src/ir/Instruction.cpp | 23 +++++++++++++++++++++++ src/irgen/IRGenExp.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 2 deletions(-) diff --git a/include/ir/IR.h b/include/ir/IR.h index ed38827..6af2d96 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -153,7 +153,7 @@ class ConstantInt : public ConstantValue { // 后续还需要扩展更多指令类型。 // enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret }; -enum class Opcode { Add, Sub, Mul, Div, Mod, Alloca, Load, Store, Ret }; +enum class Opcode { Add, Sub, Mul, Div, Mod, Neg, Alloca, Load, Store, Ret }; // User 是所有“会使用其他 Value 作为输入”的 IR 对象的抽象基类。 // 当前实现中只有 Instruction 继承自 User。 @@ -197,7 +197,14 @@ class BinaryInst : public Instruction { BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, Value* rhs, std::string name); Value* GetLhs() const; - Value* GetRhs() const; + Value* GetRhs() const; +}; + +class UnaryInst : public Instruction { + public: + UnaryInst(Opcode op, std::shared_ptr ty, Value* operand, + std::string name); + Value* GetUnaryOperand() const; }; class ReturnInst : public Instruction { @@ -303,6 +310,7 @@ class IRBuilder { BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name); BinaryInst* CreateSub(Value* lhs, Value* rhs, const std::string& name); BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name); + UnaryInst* CreateNeg(Value* operand, const std::string& name); AllocaInst* CreateAllocaI32(const std::string& name); LoadInst* CreateLoad(Value* ptr, const std::string& name); StoreInst* CreateStore(Value* val, Value* ptr); diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index 24d0b3b..2ed1c85 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -36,6 +36,7 @@ class IRGenImpl final : public SysYBaseVisitor { std::any visitLVal(SysYParser::LValContext* ctx) override; std::any visitAddExp(SysYParser::AddExpContext* ctx) override; std::any visitMulExp(SysYParser::MulExpContext* ctx) override; + std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override; private: enum class BlockFlow { diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 37861c8..54cc5d2 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -94,4 +94,14 @@ BinaryInst* IRBuilder::CreateMul(Value* lhs, Value* rhs, const std::string& name return CreateBinary(Opcode::Mul, lhs, rhs, name); } +UnaryInst* IRBuilder::CreateNeg(Value* operand, const std::string& name) { + if (!insert_block_) { + throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); + } + if (!operand) { + throw std::runtime_error(FormatError("ir", "IRBuilder::CreateNeg 缺少操作数")); + } + return insert_block_->Append(Opcode::Neg, Type::GetInt32Type(), operand, name); +} + } // namespace ir diff --git a/src/ir/IRPrinter.cpp b/src/ir/IRPrinter.cpp index 6d7f486..3716751 100644 --- a/src/ir/IRPrinter.cpp +++ b/src/ir/IRPrinter.cpp @@ -36,6 +36,8 @@ static const char* OpcodeToString(Opcode op) { return "sdiv"; case Opcode::Mod: return "srem"; + case Opcode::Neg: + return "neg"; case Opcode::Alloca: return "alloca"; case Opcode::Load: @@ -80,6 +82,14 @@ void IRPrinter::Print(const Module& module, std::ostream& os) { << ValueToString(bin->GetRhs()) << "\n"; break; } + case Opcode::Neg: { + auto* unary = static_cast(inst); + os << " " << unary->GetName() << " = " + << OpcodeToString(unary->GetOpcode()) << " " + << TypeToString(*unary->GetUnaryOperand()->GetType()) << " " + << ValueToString(unary->GetUnaryOperand()) << "\n"; + break; + } case Opcode::Alloca: { auto* alloca = static_cast(inst); os << " " << alloca->GetName() << " = alloca i32\n"; diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 5abab19..199b123 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -86,6 +86,29 @@ Value* BinaryInst::GetLhs() const { return GetOperand(0); } Value* BinaryInst::GetRhs() const { return GetOperand(1); } +UnaryInst::UnaryInst(Opcode op, std::shared_ptr ty, Value* operand, + std::string name) + : Instruction(op, std::move(ty), std::move(name)) { + if (op != Opcode::Neg) { + throw std::runtime_error(FormatError("ir", "UnaryInst 不支持的操作码")); + } + if (!operand) { + throw std::runtime_error(FormatError("ir", "UnaryInst 缺少操作数")); + } + if (!type_ || !operand->GetType()) { + throw std::runtime_error(FormatError("ir", "UnaryInst 缺少类型信息")); + } + if (type_->GetKind() != operand->GetType()->GetKind()) { + throw std::runtime_error(FormatError("ir", "UnaryInst 类型不匹配")); + } + if (!type_->IsInt32()) { + throw std::runtime_error(FormatError("ir", "UnaryInst 当前只支持 i32")); + } + AddOperand(operand); +} + +Value* UnaryInst::GetUnaryOperand() const { return GetOperand(0); } + ReturnInst::ReturnInst(std::shared_ptr void_ty, Value* val) : Instruction(Opcode::Ret, std::move(void_ty), "") { if (!val) { diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 7b25d4a..55c3cc2 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -132,6 +132,44 @@ std::any IRGenImpl::visitAddExp(SysYParser::AddExpContext* ctx) { builder_.CreateBinary(op, lhs, rhs, module_.GetContext().NextTemp())); } + +std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { + if (!ctx) { + throw std::runtime_error(FormatError("irgen", "非法一元表达式")); + } + + // 如果是 primaryExp 直接返回(unaryExp : primaryExp) + if (ctx->primaryExp()) { + return ctx->primaryExp()->accept(this); + } + + // 处理函数调用(unaryExp : ID LPAREN funcRParams? RPAREN) + // 当前暂不支持,留给后续扩展 + if (ctx->ID()) { + throw std::runtime_error(FormatError("irgen", "暂不支持函数调用")); + } + + // 处理一元运算符(unaryExp : addUnaryOp unaryExp) + if (ctx->addUnaryOp() && ctx->unaryExp()) { + ir::Value* operand = std::any_cast(ctx->unaryExp()->accept(this)); + + // 判断是正号还是负号 + if (ctx->addUnaryOp()->SUB()) { + // 负号:生成 sub 0, operand(LLVM IR 中没有 neg 指令) + ir::Value* zero = builder_.CreateConstInt(0); + return static_cast( + builder_.CreateSub(zero, operand, module_.GetContext().NextTemp())); + } else if (ctx->addUnaryOp()->ADD()) { + // 正号:直接返回操作数(+x 等价于 x) + return operand; + } else { + throw std::runtime_error(FormatError("irgen", "未知的一元运算符")); + } + } + + throw std::runtime_error(FormatError("irgen", "不支持的一元表达式类型")); +} + std::any IRGenImpl::visitMulExp(SysYParser::MulExpContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "非法乘除法表达式"));