You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/src/ir/IRBuilder.cpp

213 lines
7.7 KiB

// IR 构建工具:
// - 管理插入点(当前基本块/位置)
// - 提供创建各类指令的便捷接口,降低 IRGen 复杂度
#include "include/ir/IR.h"
#include <stdexcept>
#include "include/utils/Log.h"
namespace ir {
IRBuilder::IRBuilder(Context& ctx, BasicBlock* bb)
: ctx_(ctx), insert_block_(bb) {}
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insert_block_ = bb; }
BasicBlock* IRBuilder::GetInsertBlock() const { return insert_block_; }
ConstantInt* IRBuilder::CreateConstInt(int v) {
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
return ctx_.GetConstInt(v);
}
ConstantFloat* IRBuilder::CreateConstFloat(double v) { return ctx_.GetConstFloat(v); }
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateBinary 缺少 lhs"));
}
if (!rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateBinary 缺少 rhs"));
}
auto result_ty = lhs->GetType();
if (op == Opcode::Eq || op == Opcode::Ne || op == Opcode::Lt ||
op == Opcode::Le || op == Opcode::Gt || op == Opcode::Ge) {
result_ty = Type::GetInt1Type();
}
return insert_block_->Append<BinaryInst>(op, result_ty, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateICmp(Opcode op, Value* lhs, Value* rhs,
const std::string& name) {
if (op != Opcode::Eq && op != Opcode::Ne && op != Opcode::Lt &&
op != Opcode::Le && op != Opcode::Gt && op != Opcode::Ge) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateICmp 仅支持比较操作码"));
}
return CreateBinary(op, lhs, rhs, name);
}
CastInst* IRBuilder::CreateSIToFP(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::CreateSIToFP 缺少操作数"));
}
return insert_block_->Append<CastInst>(Opcode::SIToFP, Type::GetFloat32Type(),
operand, name);
}
CastInst* IRBuilder::CreateFPToSI(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::CreateFPToSI 缺少操作数"));
}
return insert_block_->Append<CastInst>(Opcode::FPToSI, Type::GetInt32Type(),
operand, name);
}
CastInst* IRBuilder::CreateZExt(Value* operand, std::shared_ptr<Type> target_ty,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!operand) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateZExt 缺少操作数"));
}
return insert_block_->Append<CastInst>(Opcode::ZExt, target_ty, operand, name);
}
AllocaInst* IRBuilder::CreateAlloca(std::shared_ptr<Type> elem_ty,
const std::string& name, Value* count) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<AllocaInst>(std::move(elem_ty), name, count);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name,
Value* count) {
return CreateAlloca(Type::GetInt32Type(), name, count);
}
AllocaInst* IRBuilder::CreateAllocaF32(const std::string& name,
Value* count) {
return CreateAlloca(Type::GetFloat32Type(), name, count);
}
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!ptr) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateLoad 缺少 ptr"));
}
if (!ptr->GetType() ||
(!ptr->GetType()->IsPtrInt32() && !ptr->GetType()->IsPtrFloat32())) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateLoad 仅支持 i32*/float*"));
}
auto value_ty = ptr->GetType()->IsPtrFloat32() ? Type::GetFloat32Type()
: Type::GetInt32Type();
return insert_block_->Append<LoadInst>(value_ty, ptr, name);
}
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!val) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateStore 缺少 val"));
}
if (!ptr) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateStore 缺少 ptr"));
}
return insert_block_->Append<StoreInst>(Type::GetVoidType(), val, ptr);
}
GetElementPtrInst* IRBuilder::CreateGEP(Value* base_ptr, Value* index,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!base_ptr || !index) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateGEP 缺少操作数"));
}
if (!base_ptr->GetType() ||
(!base_ptr->GetType()->IsPtrInt32() && !base_ptr->GetType()->IsPtrFloat32())) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateGEP 基址必须是 i32*/float*"));
}
auto ptr_ty = base_ptr->GetType()->IsPtrFloat32() ? Type::GetPtrFloat32Type()
: Type::GetPtrInt32Type();
return insert_block_->Append<GetElementPtrInst>(ptr_ty, base_ptr, index, name);
}
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 缺少被调函数"));
}
return insert_block_->Append<CallInst>(callee->GetType(), callee, args, name);
}
BranchInst* IRBuilder::CreateBr(BasicBlock* target) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!target) {
throw std::runtime_error(FormatError("ir", "IRBuilder::CreateBr 缺少目标块"));
}
return insert_block_->Append<BranchInst>(Type::GetVoidType(), target);
}
CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_bb,
BasicBlock* false_bb) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!cond || !true_bb || !false_bb) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCondBr 缺少操作数"));
}
return insert_block_->Append<CondBranchInst>(Type::GetVoidType(), cond,
true_bb, false_bb);
}
ReturnInst* IRBuilder::CreateRet(Value* v) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
}
ReturnInst* IRBuilder::CreateRetVoid() {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), nullptr);
}
} // namespace ir