#include "ir/IR.h" #include namespace ir { namespace { void RequireInsertBlock(BasicBlock* bb) { if (!bb) { throw std::runtime_error("IRBuilder 未设置插入点"); } } std::shared_ptr InferLoadType(Value* ptr) { if (!ptr || !ptr->GetType() || !ptr->GetType()->IsPointer()) { throw std::runtime_error("CreateLoad 需要指针"); } return ptr->GetType()->GetElementType(); } std::shared_ptr InferGEPResultType(Value* base_ptr, const std::vector& 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) { 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(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(op, lhs->GetType(), lhs, rhs, name); } AllocaInst* IRBuilder::CreateAlloca(std::shared_ptr 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(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(ptr, InferLoadType(ptr), name); } StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) { RequireInsertBlock(insert_block_); return insert_block_->Append(val, ptr); } CompareInst* IRBuilder::CreateICmp(ICmpPred pred, Value* lhs, Value* rhs, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append(pred, lhs, rhs, name); } CompareInst* IRBuilder::CreateFCmp(FCmpPred pred, Value* lhs, Value* rhs, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append(pred, lhs, rhs, name); } BranchInst* IRBuilder::CreateBr(BasicBlock* target) { RequireInsertBlock(insert_block_); return insert_block_->Append(target); } CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_block, BasicBlock* false_block) { RequireInsertBlock(insert_block_); return insert_block_->Append(cond, true_block, false_block); } CallInst* IRBuilder::CreateCall(Function* callee, const std::vector& 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(callee, args, actual_name); } GetElementPtrInst* IRBuilder::CreateGEP(Value* base_ptr, const std::vector& indices, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append( base_ptr, indices, InferGEPResultType(base_ptr, indices), name); } CastInst* IRBuilder::CreateSIToFP(Value* value, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append(Opcode::SIToFP, value, Type::GetFloatType(), name); } CastInst* IRBuilder::CreateFPToSI(Value* value, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append(Opcode::FPToSI, value, Type::GetInt32Type(), name); } CastInst* IRBuilder::CreateZExt(Value* value, std::shared_ptr dst_type, const std::string& name) { RequireInsertBlock(insert_block_); return insert_block_->Append(Opcode::ZExt, value, std::move(dst_type), name); } ReturnInst* IRBuilder::CreateRet(Value* value) { RequireInsertBlock(insert_block_); return value ? insert_block_->Append(value) : insert_block_->Append(); } ReturnInst* IRBuilder::CreateRetVoid() { RequireInsertBlock(insert_block_); return insert_block_->Append(); } } // namespace ir