“IRGen部分实现:支持一元运算符(正负号)”

dyz
lc 1 week ago committed by olivame
parent 3366d20f9e
commit 7efc0b9ad4

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

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

@ -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<UnaryInst>(Opcode::Neg, Type::GetInt32Type(), operand, name);
}
} // namespace ir

@ -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<const UnaryInst*>(inst);
os << " " << unary->GetName() << " = "
<< OpcodeToString(unary->GetOpcode()) << " "
<< TypeToString(*unary->GetUnaryOperand()->GetType()) << " "
<< ValueToString(unary->GetUnaryOperand()) << "\n";
break;
}
case Opcode::Alloca: {
auto* alloca = static_cast<const AllocaInst*>(inst);
os << " " << alloca->GetName() << " = alloca i32\n";

@ -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<Type> 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<Type> void_ty, Value* val)
: Instruction(Opcode::Ret, std::move(void_ty), "") {
if (!val) {

@ -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<ir::Value*>(ctx->unaryExp()->accept(this));
// 判断是正号还是负号
if (ctx->addUnaryOp()->SUB()) {
// 负号:生成 sub 0, operandLLVM IR 中没有 neg 指令)
ir::Value* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(
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", "非法乘除法表达式"));

Loading…
Cancel
Save