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.

179 lines
5.8 KiB

#include "ir/IR.h"
#include <stdexcept>
namespace ir {
namespace {
void RequireInsertBlock(BasicBlock* bb) {
if (!bb) {
throw std::runtime_error("IRBuilder 未设置插入点");
}
}
std::shared_ptr<Type> InferLoadType(Value* ptr) {
if (!ptr || !ptr->GetType() || !ptr->GetType()->IsPointer()) {
throw std::runtime_error("CreateLoad 需要指针");
}
return ptr->GetType()->GetElementType();
}
std::shared_ptr<Type> InferGEPResultType(Value* base_ptr,
const std::vector<Value*>& indices) {
if (!base_ptr || !base_ptr->GetType() || !base_ptr->GetType()->IsPointer()) {
throw std::runtime_error("CreateGEP 需要指针基址");
}
auto current = base_ptr->GetType()->GetElementType();
for (size_t i = 0; i < indices.size(); ++i) {
auto* index = indices[i];
(void)index;
if (!current) {
throw std::runtime_error("CreateGEP 遇到空类型");
}
if (i == 0) {
continue;
}
if (current->IsArray()) {
current = current->GetElementType();
continue;
}
if (current->IsPointer()) {
current = current->GetElementType();
continue;
}
break;
}
return Type::GetPointerType(current);
}
} // namespace
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) { return ctx_.GetConstInt(v); }
ConstantFloat* IRBuilder::CreateConstFloat(float v) { return ctx_.GetConstFloat(v); }
ConstantValue* IRBuilder::CreateZero(std::shared_ptr<Type> type) {
if (!type) {
throw std::runtime_error("CreateZero 缺少类型");
}
if (type->IsInt1() || type->IsInt32()) {
return CreateConstInt(0);
}
if (type->IsFloat32()) {
return CreateConstFloat(0.0f);
}
return ctx_.CreateOwnedConstant<ConstantZero>(type);
}
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name) {
RequireInsertBlock(insert_block_);
if (!lhs || !rhs) {
throw std::runtime_error("CreateBinary 缺少操作数");
}
return insert_block_->Append<BinaryInst>(op, lhs->GetType(), lhs, rhs, name);
}
AllocaInst* IRBuilder::CreateAlloca(std::shared_ptr<Type> allocated_type,
const std::string& name) {
RequireInsertBlock(insert_block_);
auto* parent = insert_block_->GetParent();
if (!parent || !parent->GetEntry()) {
throw std::runtime_error("CreateAlloca 需要所在函数入口块");
}
return parent->GetEntry()->Append<AllocaInst>(std::move(allocated_type), name);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
return CreateAlloca(Type::GetInt32Type(), name);
}
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<LoadInst>(ptr, InferLoadType(ptr), name);
}
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<StoreInst>(val, ptr);
}
CompareInst* IRBuilder::CreateICmp(ICmpPred pred, Value* lhs, Value* rhs,
const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CompareInst>(pred, lhs, rhs, name);
}
CompareInst* IRBuilder::CreateFCmp(FCmpPred pred, Value* lhs, Value* rhs,
const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CompareInst>(pred, lhs, rhs, name);
}
BranchInst* IRBuilder::CreateBr(BasicBlock* target) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<BranchInst>(target);
}
CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_block,
BasicBlock* false_block) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CondBranchInst>(cond, true_block, false_block);
}
CallInst* IRBuilder::CreateCall(Function* callee, const std::vector<Value*>& args,
const std::string& name) {
RequireInsertBlock(insert_block_);
std::string actual_name = name;
if (callee && callee->GetReturnType()->IsVoid()) {
actual_name.clear();
}
return insert_block_->Append<CallInst>(callee, args, actual_name);
}
GetElementPtrInst* IRBuilder::CreateGEP(Value* base_ptr,
const std::vector<Value*>& indices,
const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<GetElementPtrInst>(
base_ptr, indices, InferGEPResultType(base_ptr, indices), name);
}
CastInst* IRBuilder::CreateSIToFP(Value* value, const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CastInst>(Opcode::SIToFP, value,
Type::GetFloatType(), name);
}
CastInst* IRBuilder::CreateFPToSI(Value* value, const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CastInst>(Opcode::FPToSI, value,
Type::GetInt32Type(), name);
}
CastInst* IRBuilder::CreateZExt(Value* value, std::shared_ptr<Type> dst_type,
const std::string& name) {
RequireInsertBlock(insert_block_);
return insert_block_->Append<CastInst>(Opcode::ZExt, value, std::move(dst_type),
name);
}
ReturnInst* IRBuilder::CreateRet(Value* value) {
RequireInsertBlock(insert_block_);
return value ? insert_block_->Append<ReturnInst>(value)
: insert_block_->Append<ReturnInst>();
}
ReturnInst* IRBuilder::CreateRetVoid() {
RequireInsertBlock(insert_block_);
return insert_block_->Append<ReturnInst>();
}
} // namespace ir