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.

284 lines
12 KiB

#include "ir/IR.h"
#include <stdexcept>
#include <string>
#include "utils/Log.h"
namespace ir {
// ─── User ─────────────────────────────────────────────────────────────────────
User::User(std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)) {}
size_t User::GetNumOperands() const { return operands_.size(); }
Value* User::GetOperand(size_t index) const {
if (index >= operands_.size()) {
throw std::out_of_range("User operand index out of range");
}
return operands_[index];
}
void User::SetOperand(size_t index, Value* value) {
if (index >= operands_.size()) {
throw std::out_of_range("User operand index out of range");
}
auto* old = operands_[index];
if (old == value) return;
if (old) old->RemoveUse(this, index);
operands_[index] = value;
if (value) value->AddUse(this, index);
}
void User::AddOperand(Value* value) {
size_t idx = operands_.size();
operands_.push_back(value);
if (value) value->AddUse(this, idx);
}
// ─── Instruction ──────────────────────────────────────────────────────────────
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
: User(std::move(ty), std::move(name)), opcode_(op) {}
Opcode Instruction::GetOpcode() const { return opcode_; }
bool Instruction::IsTerminator() const {
return opcode_ == Opcode::Ret || opcode_ == Opcode::Br ||
opcode_ == Opcode::CondBr;
}
BasicBlock* Instruction::GetParent() const { return parent_; }
void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; }
// ─── BinaryInst ───────────────────────────────────────────────────────────────
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
Value* rhs, std::string name)
: Instruction(op, std::move(ty), std::move(name)) {
if (op != Opcode::Add && op != Opcode::Sub && op != Opcode::Mul &&
op != Opcode::Div && op != Opcode::Mod && op != Opcode::FAdd &&
op != Opcode::FSub && op != Opcode::FMul && op != Opcode::FDiv) {
throw std::runtime_error(
FormatError("ir", "BinaryInst: 不支持的操作码"));
}
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数"));
}
AddOperand(lhs);
AddOperand(rhs);
}
Value* BinaryInst::GetLhs() const { return GetOperand(0); }
Value* BinaryInst::GetRhs() const { return GetOperand(1); }
// ─── ICmpInst ─────────────────────────────────────────────────────────────────
ICmpInst::ICmpInst(ICmpPredicate pred, Value* lhs, Value* rhs, std::string name)
: Instruction(Opcode::ICmp, Type::GetInt1Type(), std::move(name)),
pred_(pred) {
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "ICmpInst 缺少操作数"));
}
AddOperand(lhs);
AddOperand(rhs);
}
Value* ICmpInst::GetLhs() const { return GetOperand(0); }
Value* ICmpInst::GetRhs() const { return GetOperand(1); }
// ─── FCmpInst ─────────────────────────────────────────────────────────────────
FCmpInst::FCmpInst(FCmpPredicate pred, Value* lhs, Value* rhs, std::string name)
: Instruction(Opcode::FCmp, Type::GetInt1Type(), std::move(name)),
pred_(pred) {
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "FCmpInst 缺少操作数"));
}
AddOperand(lhs);
AddOperand(rhs);
}
Value* FCmpInst::GetLhs() const { return GetOperand(0); }
Value* FCmpInst::GetRhs() const { return GetOperand(1); }
// ─── BrInst ───────────────────────────────────────────────────────────────────
BrInst::BrInst(BasicBlock* target)
: Instruction(Opcode::Br, Type::GetVoidType(), "") {
if (!target) {
throw std::runtime_error(FormatError("ir", "BrInst 缺少目标"));
}
AddOperand(target);
}
BasicBlock* BrInst::GetTarget() const {
return static_cast<BasicBlock*>(GetOperand(0));
}
// ─── CondBrInst ───────────────────────────────────────────────────────────────
CondBrInst::CondBrInst(Value* cond, BasicBlock* true_bb, BasicBlock* false_bb)
: Instruction(Opcode::CondBr, Type::GetVoidType(), "") {
if (!cond || !true_bb || !false_bb) {
throw std::runtime_error(FormatError("ir", "CondBrInst 缺少操作数"));
}
AddOperand(cond);
AddOperand(true_bb);
AddOperand(false_bb);
}
Value* CondBrInst::GetCond() const { return GetOperand(0); }
BasicBlock* CondBrInst::GetTrueBB() const {
return static_cast<BasicBlock*>(GetOperand(1));
}
BasicBlock* CondBrInst::GetFalseBB() const {
return static_cast<BasicBlock*>(GetOperand(2));
}
// ─── CallInst ─────────────────────────────────────────────────────────────────
CallInst::CallInst(Function* callee, std::vector<Value*> args, std::string name)
: Instruction(Opcode::Call,
callee ? callee->GetType() : Type::GetVoidType(),
std::move(name)),
callee_(callee) {
if (!callee) {
throw std::runtime_error(FormatError("ir", "CallInst: callee 为空"));
}
callee_name_ = callee->GetName();
for (auto* arg : args) {
AddOperand(arg);
}
}
CallInst::CallInst(std::string callee_name, std::shared_ptr<Type> ret_type,
std::vector<Value*> args, std::string name)
: Instruction(Opcode::Call, std::move(ret_type), std::move(name)),
callee_(nullptr),
callee_name_(std::move(callee_name)) {
for (auto* arg : args) {
AddOperand(arg);
}
}
// ─── ZExtInst ─────────────────────────────────────────────────────────────────
ZExtInst::ZExtInst(Value* val, std::string name)
: Instruction(Opcode::ZExt, Type::GetInt32Type(), std::move(name)) {
if (!val) {
throw std::runtime_error(FormatError("ir", "ZExtInst 缺少操作数"));
}
AddOperand(val);
}
Value* ZExtInst::GetSrc() const { return GetOperand(0); }
// ─── SIToFPInst ───────────────────────────────────────────────────────────────
SIToFPInst::SIToFPInst(Value* val, std::string name)
: Instruction(Opcode::SIToFP, Type::GetFloat32Type(), std::move(name)) {
if (!val) {
throw std::runtime_error(FormatError("ir", "SIToFPInst 缺少操作数"));
}
AddOperand(val);
}
Value* SIToFPInst::GetSrc() const { return GetOperand(0); }
// ─── FPToSIInst ───────────────────────────────────────────────────────────────
FPToSIInst::FPToSIInst(Value* val, std::string name)
: Instruction(Opcode::FPToSI, Type::GetInt32Type(), std::move(name)) {
if (!val) {
throw std::runtime_error(FormatError("ir", "FPToSIInst 缺少操作数"));
}
AddOperand(val);
}
Value* FPToSIInst::GetSrc() const { return GetOperand(0); }
// ─── ReturnInst ───────────────────────────────────────────────────────────────
ReturnInst::ReturnInst(Value* val)
: Instruction(Opcode::Ret, Type::GetVoidType(), "") {
if (val) {
AddOperand(val);
}
}
ReturnInst::ReturnInst()
: Instruction(Opcode::Ret, Type::GetVoidType(), "") {}
Value* ReturnInst::GetValue() const {
return HasValue() ? GetOperand(0) : nullptr;
}
// ─── AllocaInst ───────────────────────────────────────────────────────────────
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)),
num_elements_(1) {
if (!type_->IsPtrInt32() && !type_->IsPtrFloat32()) {
throw std::runtime_error(FormatError("ir", "AllocaInst 只支持 i32* 和 f32*"));
}
}
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, int num_elements,
std::string name)
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)),
num_elements_(num_elements) {
if (!type_->IsPtrInt32() && !type_->IsPtrFloat32()) {
throw std::runtime_error(FormatError("ir", "AllocaInst 只支持 i32* 和 f32*"));
}
}
// ─── GepInst ──────────────────────────────────────────────────────────────────
GepInst::GepInst(Value* base_ptr, Value* index, std::string name)
: Instruction(Opcode::Gep,
(base_ptr && base_ptr->GetType()->IsPtrFloat32())
? Type::GetPtrFloat32Type()
: Type::GetPtrInt32Type(),
std::move(name)) {
if (!base_ptr || !index) {
throw std::runtime_error(FormatError("ir", "GepInst 缺少操作数"));
}
AddOperand(base_ptr);
AddOperand(index);
}
Value* GepInst::GetBasePtr() const { return GetOperand(0); }
Value* GepInst::GetIndex() const { return GetOperand(1); }
// ─── LoadInst ─────────────────────────────────────────────────────────────────
LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name)
: Instruction(Opcode::Load, std::move(val_ty), std::move(name)) {
if (!ptr) {
throw std::runtime_error(FormatError("ir", "LoadInst 缺少 ptr"));
}
AddOperand(ptr);
}
Value* LoadInst::GetPtr() const { return GetOperand(0); }
// ─── StoreInst ────────────────────────────────────────────────────────────────
StoreInst::StoreInst(Value* val, Value* ptr)
: Instruction(Opcode::Store, Type::GetVoidType(), "") {
if (!val || !ptr) {
throw std::runtime_error(FormatError("ir", "StoreInst 缺少操作数"));
}
AddOperand(val);
AddOperand(ptr);
}
Value* StoreInst::GetValue() const { return GetOperand(0); }
Value* StoreInst::GetPtr() const { return GetOperand(1); }
// ─── GlobalValue (占位) ────────────────────────────────────────────────────────
GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
: User(std::move(ty), std::move(name)) {}
// ─── GlobalVariable ────────────────────────────────────────────────────────────
GlobalVariable::GlobalVariable(std::string name, bool is_const, int init_val,
int num_elements, bool is_array_decl,
bool is_float)
: Value(is_float ? Type::GetPtrFloat32Type() : Type::GetPtrInt32Type(),
std::move(name)),
is_const_(is_const),
is_float_(is_float),
init_val_(init_val),
init_val_f_(0.0f),
num_elements_(num_elements),
is_array_decl_(is_array_decl) {}
} // namespace ir