// IR 构建工具：
// - 管理插入点（当前基本块/位置）
// - 提供创建各类指令的便捷接口，降低 IRGen 复杂度

#include "ir/IR.h"

#include <stdexcept>
#include <cstring>
#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);
}

// IRBuilder 方法实现
ConstantFloat* IRBuilder::CreateConstFloat(float v) {
  return ctx_.GetConstFloat(v);
}

ConstantArray* IRBuilder::CreateConstArray(std::shared_ptr<ArrayType> ty, 
                                            std::vector<ConstantValue*> elements) {
  return ctx_.GetConstArray(ty, std::move(elements));
}

ConstantZero* IRBuilder::CreateZeroConstant(std::shared_ptr<Type> ty) {
  return ctx_.GetZeroConstant(ty);
}


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"));
  }
  
  // 检查操作码是否为有效的二元操作符
  switch (op) {
    case Opcode::Add:
    case Opcode::Sub:
    case Opcode::Mul:
    case Opcode::Div:
    case Opcode::Mod:
    case Opcode::And:
    case Opcode::Or:
    // 添加浮点操作码
    case Opcode::FAdd:
    case Opcode::FSub:
    case Opcode::FMul:
    case Opcode::FDiv:
      // 有效的二元操作符
      break;
    case Opcode::Not:
      // Not是一元操作符，不应该在BinaryInst中
      throw std::runtime_error(FormatError("ir", "Not是一元操作符，应使用其他指令"));
    default:
      throw std::runtime_error(FormatError("ir", "BinaryInst 不支持的操作码"));
  }
  
  // 确定结果类型
  std::shared_ptr<Type> result_type;
  
  // 检查操作数类型是否相同
  if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind()) {
    throw std::runtime_error(
        FormatError("ir", "CreateBinary 操作数类型不匹配"));
  }
  
  // 检查是否为浮点操作
  bool is_float_op = (op == Opcode::FAdd || op == Opcode::FSub || 
                     op == Opcode::FMul || op == Opcode::FDiv);
  
  if (is_float_op) {
    // 浮点操作要求操作数是浮点类型
    if (!lhs->GetType()->IsFloat()) {
      throw std::runtime_error(
          FormatError("ir", "浮点运算要求操作数为浮点类型"));
    }
    result_type = lhs->GetType();
  } else {
    bool is_logical = (op == Opcode::And || op == Opcode::Or);
    
    if (is_logical) {
      // 逻辑运算的结果是 int32（布尔值）
      result_type = Type::GetInt32Type();
    } else {
      // 算术运算的结果类型与操作数相同
      result_type = lhs->GetType();
    }
    
    // 检查操作数类型是否支持
    if (!lhs->GetType()->IsInt32() && !lhs->GetType()->IsFloat()) {
      throw std::runtime_error(
          FormatError("ir", "CreateBinary 只支持 int32 和 float 类型"));
    }
  }
  
  return insert_block_->Append<BinaryInst>(op, result_type, lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
                                 const std::string& name) {
  return CreateBinary(Opcode::Add, lhs, rhs, name);
}

AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  return insert_block_->Append<AllocaInst>(Type::GetPtrInt32Type(), name);
}

AllocaInst* IRBuilder::CreateAllocaFloat(const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  return insert_block_->Append<AllocaInst>(Type::GetPtrFloatType(), 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"));
  }
  auto ptr_ty = ptr->GetType();
  std::shared_ptr<Type> elem_ty;
  
  if (ptr_ty->IsPtrInt32()) {
    elem_ty = Type::GetInt32Type();
  } else if (ptr_ty->IsPtrFloat()) {
    elem_ty = Type::GetFloatType();
  } else if (ptr_ty->IsPtrInt1()) {
    elem_ty = Type::GetInt1Type();
  } else if (ptr_ty->IsArray()) {
    // 数组类型的指针，元素类型是数组元素类型
    auto* array_ty = dynamic_cast<ArrayType*>(ptr_ty.get());
    if (array_ty) {
      elem_ty = array_ty->GetElementType();
    } else {
      throw std::runtime_error(FormatError("ir", "不支持的指针类型"));
    }
  } else {
    // 尝试其他指针类型
    throw std::runtime_error(FormatError("ir", "不支持的指针类型"));
  }
  
  return insert_block_->Append<LoadInst>(elem_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"));
  }
  
  // 检查类型兼容性
  auto ptr_ty = ptr->GetType();
  auto val_ty = val->GetType();
  
  if (ptr_ty->IsPtrInt32()) {
    if (!val_ty->IsInt32()) {
      throw std::runtime_error(FormatError("ir", "存储类型不匹配：期望 int32"));
    }
  } else if (ptr_ty->IsPtrFloat()) {
    if (!val_ty->IsFloat()) {
      throw std::runtime_error(FormatError("ir", "存储类型不匹配：期望 float"));
    }
  } else if (ptr_ty->IsArray()) {
    // 数组存储：检查元素类型
    auto* array_ty = dynamic_cast<ArrayType*>(ptr_ty.get());
    if (array_ty) {
      auto elem_ty = array_ty->GetElementType();
      if (elem_ty->IsInt32() && !val_ty->IsInt32()) {
        throw std::runtime_error(FormatError("ir", "数组元素类型不匹配：期望 int32"));
      } else if (elem_ty->IsFloat() && !val_ty->IsFloat()) {
        throw std::runtime_error(FormatError("ir", "数组元素类型不匹配：期望 float"));
      }
    }
  }
  
  return insert_block_->Append<StoreInst>(Type::GetVoidType(), val, ptr);
}

ReturnInst* IRBuilder::CreateRet(Value* v) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!v) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateRet 缺少返回值"));
  }
  return insert_block_->Append<ReturnInst>(Type::GetVoidType(), v);
}

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 缺少 target"));
  }
  return insert_block_->Append<BranchInst>(Type::GetVoidType(), target);
}

BranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_target, 
                                    BasicBlock* false_target) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!cond) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateCondBr 缺少 cond"));
  }
  if (!true_target) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateCondBr 缺少 true_target"));
  }
  if (!false_target) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateCondBr 缺少 false_target"));
  }
  return insert_block_->Append<BranchInst>(Type::GetVoidType(), cond, true_target, false_target);
}

// 创建整数相等比较
IcmpInst* IRBuilder::CreateICmpEQ(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpEQ 缺少操作数"));
  }
  // 检查类型必须一致
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::EQ, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建整数不等比较
IcmpInst* IRBuilder::CreateICmpNE(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpNE 缺少操作数"));
  }
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::NE, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建整数小于比较
IcmpInst* IRBuilder::CreateICmpLT(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpLT 缺少操作数"));
  }
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::LT, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建整数小于等于比较
IcmpInst* IRBuilder::CreateICmpLE(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpLE 缺少操作数"));
  }
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::LE, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建整数大于比较
IcmpInst* IRBuilder::CreateICmpGT(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpGT 缺少操作数"));
  }
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::GT, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建整数大于等于比较
IcmpInst* IRBuilder::CreateICmpGE(Value* lhs, Value* rhs, 
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!lhs || !rhs) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateICmpGE 缺少操作数"));
  }
  if (lhs->GetType() != rhs->GetType()) {
    throw std::runtime_error(
        FormatError("ir", "比较操作数类型不匹配"));
  }
  return insert_block_->Append<IcmpInst>(IcmpInst::Predicate::GE, lhs, rhs,
                                         Type::GetInt1Type(), name);
}

// 创建零扩展指令
ZExtInst* IRBuilder::CreateZExt(Value* value, std::shared_ptr<Type> target_ty,
                                const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!value) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateZExt 缺少 value"));
  }
  if (!target_ty) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateZExt 缺少 target_ty"));
  }
  
  auto src_ty = value->GetType();
  // 类型检查：源类型应该是较小的整数类型
  if (!src_ty->IsInt1() && !src_ty->IsInt32()) {
    throw std::runtime_error(
        FormatError("ir", "ZExt 源类型必须是整数类型"));
  }
  // 目标类型应该是较大的整数类型
  if (!target_ty->IsInt32()) {
    throw std::runtime_error(
        FormatError("ir", "ZExt 目标类型必须是整数类型"));
  }
  
  return insert_block_->Append<ZExtInst>(value, target_ty, name);
}

// 创建截断指令
TruncInst* IRBuilder::CreateTrunc(Value* value, std::shared_ptr<Type> target_ty,
                                  const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!value) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateTrunc 缺少 value"));
  }
  if (!target_ty) {
    throw std::runtime_error(
        FormatError("ir", "IRBuilder::CreateTrunc 缺少 target_ty"));
  }
  
  auto src_ty = value->GetType();
  // 类型检查：源类型应该是较大的整数类型
  if (!src_ty->IsInt32()) {
    throw std::runtime_error(
        FormatError("ir", "Trunc 源类型必须是整数类型"));
  }
  // 目标类型应该是较小的整数类型
  if (!target_ty->IsInt1() && !target_ty->IsInt32()) {
    throw std::runtime_error(
        FormatError("ir", "Trunc 目标类型必须是整数类型"));
  }
  
  return insert_block_->Append<TruncInst>(value, target_ty, name);
}

// 便捷方法：i1 转 i32
ZExtInst* IRBuilder::CreateZExtI1ToI32(Value* value, const std::string& name) {
  return CreateZExt(value, Type::GetInt32Type(), name);
}

// 便捷方法：i32 转 i1
TruncInst* IRBuilder::CreateTruncI32ToI1(Value* value, const std::string& name) {
  return CreateTrunc(value, Type::GetInt1Type(), name);
}

BinaryInst* IRBuilder::CreateDiv(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::CreateDiv 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateDiv 缺少 rhs"));
  }
  return insert_block_->Append<BinaryInst>(Opcode::Div, lhs->GetType(), lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateMod(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::CreateMod 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMod 缺少 rhs"));
  }
  return insert_block_->Append<BinaryInst>(Opcode::Mod, lhs->GetType(), lhs, rhs, name);
}


BinaryInst* IRBuilder::CreateAnd(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::CreateAnd 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateAnd 缺少 rhs"));
  }
  return insert_block_->Append<BinaryInst>(Opcode::And, Type::GetInt32Type(), lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateOr(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::CreateOr 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateOr 缺少 rhs"));
  }
  return insert_block_->Append<BinaryInst>(Opcode::Or, Type::GetInt32Type(), lhs, rhs, name);
}

IcmpInst* IRBuilder::CreateNot(Value* val, const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!val) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateNot 缺少 operand"));
  }
  auto zero = CreateConstInt(0);
  return CreateICmpEQ(val, zero, name);
}

GEPInst* IRBuilder::CreateGEP(Value* base, 
                              const std::vector<Value*>& indices,
                              const std::string& name) {
  if (!insert_block_) {
    throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
  }
  if (!base) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateGEP 缺少 base"));
  }
  
  // 检查所有索引
  for (size_t i = 0; i < indices.size(); ++i) {
    if (!indices[i]) {
      throw std::runtime_error(
          FormatError("ir", "IRBuilder::CreateGEP 索引 " + std::to_string(i) + " 为空"));
    }
  }
  
  // GEP返回指针类型，假设与base类型相同
  return insert_block_->Append<GEPInst>(base->GetType(), base, indices, name);
}


BinaryInst* IRBuilder::CreateMul(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::CreateMul 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateMul 缺少 rhs"));
  }
  return CreateBinary(Opcode::Mul, lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateSub(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::CreateSub 缺少 lhs"));
  }
  if (!rhs) {
    throw std::runtime_error(FormatError("ir", "IRBuilder::CreateSub 缺少 rhs"));
  }
  return CreateBinary(Opcode::Sub, lhs, rhs, name);
}

// 注意：当前 CreateCall 仅支持直接调用 Function，且不支持变长参数列表等复杂特性。
// 创建函数调用指令的实现,被调用的函数,参数列表，返回值临时变量名
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 缺少 callee"));
  }
  auto func_ty = std::static_pointer_cast<FunctionType>(callee->GetType());
  auto ret_ty = func_ty->GetReturnType();
  return insert_block_->Append<CallInst>(ret_ty, callee, args, name);
}


BinaryInst* IRBuilder::CreateFAdd(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<BinaryInst>(Opcode::FAdd, lhs->GetType(), lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateFSub(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<BinaryInst>(Opcode::FSub, lhs->GetType(), lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateFMul(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<BinaryInst>(Opcode::FMul, lhs->GetType(), lhs, rhs, name);
}

BinaryInst* IRBuilder::CreateFDiv(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<BinaryInst>(Opcode::FDiv, lhs->GetType(), lhs, rhs, name);
}

// 浮点比较
FcmpInst* IRBuilder::CreateFCmpOEQ(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::OEQ, lhs, rhs, Type::GetInt1Type(), name);
}

FcmpInst* IRBuilder::CreateFCmpONE(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::ONE, lhs, rhs, Type::GetInt1Type(), name);
}

FcmpInst* IRBuilder::CreateFCmpOLT(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::OLT, lhs, rhs, Type::GetInt1Type(), name);
}

FcmpInst* IRBuilder::CreateFCmpOLE(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::OLE, lhs, rhs, Type::GetInt1Type(), name);
}

FcmpInst* IRBuilder::CreateFCmpOGT(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::OGT, lhs, rhs, Type::GetInt1Type(), name);
}

FcmpInst* IRBuilder::CreateFCmpOGE(Value* lhs, Value* rhs, const std::string& name) {
  return insert_block_->Append<FcmpInst>(
      FcmpInst::Predicate::OGE, lhs, rhs, Type::GetInt1Type(), name);
}

// 类型转换
SIToFPInst* IRBuilder::CreateSIToFP(Value* value, std::shared_ptr<Type> target_ty,
                                   const std::string& name) {
  return insert_block_->Append<SIToFPInst>(value, target_ty, name);
}

FPToSIInst* IRBuilder::CreateFPToSI(Value* value, std::shared_ptr<Type> target_ty,
                                   const std::string& name) {
  return insert_block_->Append<FPToSIInst>(value, target_ty, name);
}

}  // namespace ir
