225 lines
7.7 KiB
C++
225 lines
7.7 KiB
C++
// IR 构建工具:
|
|
// - 管理插入点(当前基本块/位置)
|
|
// - 提供创建各类指令的便捷接口,降低 IRGen 复杂度
|
|
|
|
#include "ir/IR.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
#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(float v) {
|
|
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
|
|
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"));
|
|
}
|
|
return insert_block_->Append<BinaryInst>(op, lhs->GetType(), lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::Add, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateSub(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::Sub, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateMul(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::Mul, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateDiv(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::Div, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateMod(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::Mod, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateFAdd(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::FAdd, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateFSub(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::FSub, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateFMul(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::FMul, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateFDiv(Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
return CreateBinary(Opcode::FDiv, lhs, rhs, name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateICmp(Opcode op, Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<BinaryInst>(op, Type::GetInt32Type(), lhs, rhs,
|
|
name);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateFCmp(Opcode op, Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<BinaryInst>(op, Type::GetInt32Type(), lhs, rhs,
|
|
name);
|
|
}
|
|
|
|
AllocaInst* IRBuilder::CreateAlloca(std::shared_ptr<Type> ty,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<AllocaInst>(ty, name);
|
|
}
|
|
|
|
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
|
|
return CreateAlloca(Type::GetPtrInt32Type(), name);
|
|
}
|
|
|
|
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"));
|
|
}
|
|
std::shared_ptr<Type> val_ty;
|
|
if (ptr->GetType()->IsPtrInt32()) {
|
|
val_ty = Type::GetInt32Type();
|
|
} else if (ptr->GetType()->IsPtrFloat()) {
|
|
val_ty = Type::GetFloatType();
|
|
} else {
|
|
throw std::runtime_error(FormatError("ir", "LoadInst 不支持的指针类型"));
|
|
}
|
|
return insert_block_->Append<LoadInst>(val_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);
|
|
}
|
|
|
|
ReturnInst* IRBuilder::CreateRet(Value* v) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
|
|
}
|
|
|
|
BranchInst* IRBuilder::CreateBr(BasicBlock* dest) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<BranchInst>(dest);
|
|
}
|
|
|
|
BranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* if_true,
|
|
BasicBlock* if_false) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<BranchInst>(cond, if_true, if_false);
|
|
}
|
|
|
|
CallInst* IRBuilder::CreateCall(Function* func, const std::vector<Value*>& args,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<CallInst>(func, args, name);
|
|
}
|
|
|
|
GetElementPtrInst* IRBuilder::CreateGEP(std::shared_ptr<Type> ptr_ty, Value* ptr,
|
|
const std::vector<Value*>& indices,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<GetElementPtrInst>(ptr_ty, ptr, indices, name);
|
|
}
|
|
|
|
CastInst* IRBuilder::CreateZExt(Value* val, std::shared_ptr<Type> ty,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<CastInst>(Opcode::ZExt, ty, val, name);
|
|
}
|
|
|
|
CastInst* IRBuilder::CreateSIToFP(Value* val, std::shared_ptr<Type> ty,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<CastInst>(Opcode::SIToFP, ty, val, name);
|
|
}
|
|
|
|
CastInst* IRBuilder::CreateFPToSI(Value* val, std::shared_ptr<Type> ty,
|
|
const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<CastInst>(Opcode::FPToSI, ty, val, name);
|
|
}
|
|
|
|
PhiInst* IRBuilder::CreatePhi(std::shared_ptr<Type> ty, const std::string& name) {
|
|
if (!insert_block_) {
|
|
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
|
|
}
|
|
return insert_block_->Append<PhiInst>(ty, name);
|
|
}
|
|
|
|
} // namespace ir
|