forked from NUDT-compiler/nudt-compiler-cpp
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.
213 lines
7.7 KiB
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
|