|
|
// 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
|