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.
111 lines
3.4 KiB
111 lines
3.4 KiB
// IR 构建工具:
|
|
// - 管理插入点(当前基本块/位置)
|
|
// - 提供创建各类指令的便捷接口,降低 IRGen 复杂度
|
|
|
|
#include "ir/IR.h"
|
|
#include <stdexcept>
|
|
|
|
namespace ir {
|
|
namespace {
|
|
|
|
bool IsArithmeticType(const std::shared_ptr<Type>& ty) {
|
|
return ty && ty->kind() == Type::Kind::Int32;
|
|
}
|
|
|
|
bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
|
|
return ty && ty->kind() == Type::Kind::PtrInt32;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
IRBuilder::IRBuilder(BasicBlock* bb) : insertBlock_(bb) {}
|
|
|
|
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
|
|
|
|
BasicBlock* IRBuilder::GetInsertBlock() const { return insertBlock_; }
|
|
|
|
ConstantInt* IRBuilder::CreateConstInt(int v) {
|
|
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
|
|
return DefaultContext().GetConstInt(v);
|
|
}
|
|
|
|
BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
|
|
const std::string& name) {
|
|
if (!insertBlock_) {
|
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
|
}
|
|
if (!lhs) {
|
|
throw std::runtime_error("IRBuilder::CreateBinary 缺少 lhs");
|
|
}
|
|
if (!rhs) {
|
|
throw std::runtime_error("IRBuilder::CreateBinary 缺少 rhs");
|
|
}
|
|
if (op != Opcode::Add) {
|
|
throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 Add");
|
|
}
|
|
if (!lhs->type() || !rhs->type() ||
|
|
lhs->type()->kind() != rhs->type()->kind()) {
|
|
throw std::runtime_error("IRBuilder::CreateBinary 操作数类型不匹配");
|
|
}
|
|
if (!IsArithmeticType(lhs->type())) {
|
|
throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 i32 二元运算");
|
|
}
|
|
return insertBlock_->Append<BinaryInst>(op, lhs->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 (!insertBlock_) {
|
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
|
}
|
|
return insertBlock_->Append<AllocaInst>(name);
|
|
}
|
|
|
|
LoadInst* IRBuilder::CreateLoad(Value* ptr, const std::string& name) {
|
|
if (!insertBlock_) {
|
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
|
}
|
|
if (!ptr) {
|
|
throw std::runtime_error("IRBuilder::CreateLoad 缺少 ptr");
|
|
}
|
|
if (!IsPtrInt32Type(ptr->type())) {
|
|
throw std::runtime_error("IRBuilder::CreateLoad 当前只支持从 i32* 加载");
|
|
}
|
|
return insertBlock_->Append<LoadInst>(ptr, name);
|
|
}
|
|
|
|
StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
|
|
if (!insertBlock_) {
|
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
|
}
|
|
if (!val) {
|
|
throw std::runtime_error("IRBuilder::CreateStore 缺少 val");
|
|
}
|
|
if (!ptr) {
|
|
throw std::runtime_error("IRBuilder::CreateStore 缺少 ptr");
|
|
}
|
|
if (!IsArithmeticType(val->type())) {
|
|
throw std::runtime_error("IRBuilder::CreateStore 当前只支持存储 i32");
|
|
}
|
|
if (!IsPtrInt32Type(ptr->type())) {
|
|
throw std::runtime_error("IRBuilder::CreateStore 当前只支持写入 i32*");
|
|
}
|
|
return insertBlock_->Append<StoreInst>(val, ptr);
|
|
}
|
|
|
|
ReturnInst* IRBuilder::CreateRet(Value* v) {
|
|
if (!insertBlock_) {
|
|
throw std::runtime_error("IRBuilder 未设置插入点");
|
|
}
|
|
if (!v) {
|
|
throw std::runtime_error("IRBuilder::CreateRet 缺少返回值");
|
|
}
|
|
return insertBlock_->Append<ReturnInst>(v);
|
|
}
|
|
|
|
} // namespace ir
|