use crate::ir::entities::{BasicBlock, Function, Value, ValueData, ValueKind};
use crate::ir::types::Type;
use std::fmt;
#[derive(Clone, Debug)]
pub struct Integer {
value: i32,
}
impl Integer {
pub(in crate::ir) fn new_data(value: i32) -> ValueData {
ValueData::new(Type::get_i32(), ValueKind::Integer(Self { value }))
}
pub fn value(&self) -> i32 {
self.value
}
pub fn value_mut(&mut self) -> &mut i32 {
&mut self.value
}
}
#[derive(Clone, Debug)]
pub struct ZeroInit;
impl ZeroInit {
pub(in crate::ir) fn new_data(ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::ZeroInit(Self))
}
}
#[derive(Clone, Debug)]
pub struct Undef;
impl Undef {
pub(in crate::ir) fn new_data(ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::Undef(Self))
}
}
#[derive(Clone, Debug)]
pub struct Aggregate {
elems: Vec<Value>,
}
impl Aggregate {
pub(in crate::ir) fn new_data(elems: Vec<Value>, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::Aggregate(Self { elems }))
}
pub fn elems(&self) -> &[Value] {
&self.elems
}
pub fn elems_mut(&mut self) -> &mut Vec<Value> {
&mut self.elems
}
}
#[derive(Clone, Debug)]
pub struct FuncArgRef {
index: usize,
}
impl FuncArgRef {
pub(in crate::ir) fn new_data(index: usize, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::FuncArgRef(Self { index }))
}
pub fn index(&self) -> usize {
self.index
}
pub fn index_mut(&mut self) -> &mut usize {
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct BlockArgRef {
index: usize,
}
impl BlockArgRef {
pub(in crate::ir) fn new_data(index: usize, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::BlockArgRef(Self { index }))
}
pub fn index(&self) -> usize {
self.index
}
pub fn index_mut(&mut self) -> &mut usize {
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct Alloc;
impl Alloc {
pub(in crate::ir) fn new_data(ty: Type) -> ValueData {
assert!(!ty.is_unit(), "`ty` can not be unit");
ValueData::new(ty, ValueKind::Alloc(Self))
}
}
#[derive(Clone, Debug)]
pub struct GlobalAlloc {
init: Value,
}
impl GlobalAlloc {
pub(in crate::ir) fn new_data(init: Value, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::GlobalAlloc(Self { init }))
}
pub fn init(&self) -> Value {
self.init
}
pub fn init_mut(&mut self) -> &mut Value {
&mut self.init
}
}
#[derive(Clone, Debug)]
pub struct Load {
src: Value,
}
impl Load {
pub(in crate::ir) fn new_data(src: Value, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::Load(Self { src }))
}
pub fn src(&self) -> Value {
self.src
}
pub fn src_mut(&mut self) -> &mut Value {
&mut self.src
}
}
#[derive(Clone, Debug)]
pub struct Store {
value: Value,
dest: Value,
}
impl Store {
pub(in crate::ir) fn new_data(value: Value, dest: Value) -> ValueData {
ValueData::new(Type::get_unit(), ValueKind::Store(Self { value, dest }))
}
pub fn value(&self) -> Value {
self.value
}
pub fn value_mut(&mut self) -> &mut Value {
&mut self.value
}
pub fn dest(&self) -> Value {
self.dest
}
pub fn dest_mut(&mut self) -> &mut Value {
&mut self.dest
}
}
#[derive(Clone, Debug)]
pub struct GetPtr {
src: Value,
index: Value,
}
impl GetPtr {
pub(in crate::ir) fn new_data(src: Value, index: Value, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::GetPtr(Self { src, index }))
}
pub fn src(&self) -> Value {
self.src
}
pub fn src_mut(&mut self) -> &mut Value {
&mut self.src
}
pub fn index(&self) -> Value {
self.index
}
pub fn index_mut(&mut self) -> &mut Value {
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct GetElemPtr {
src: Value,
index: Value,
}
impl GetElemPtr {
pub(in crate::ir) fn new_data(src: Value, index: Value, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::GetElemPtr(Self { src, index }))
}
pub fn src(&self) -> Value {
self.src
}
pub fn src_mut(&mut self) -> &mut Value {
&mut self.src
}
pub fn index(&self) -> Value {
self.index
}
pub fn index_mut(&mut self) -> &mut Value {
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct Binary {
op: BinaryOp,
lhs: Value,
rhs: Value,
}
impl Binary {
pub(in crate::ir) fn new_data(op: BinaryOp, lhs: Value, rhs: Value, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::Binary(Self { op, lhs, rhs }))
}
pub fn op(&self) -> BinaryOp {
self.op
}
pub fn op_mut(&mut self) -> &mut BinaryOp {
&mut self.op
}
pub fn lhs(&self) -> Value {
self.lhs
}
pub fn lhs_mut(&mut self) -> &mut Value {
&mut self.lhs
}
pub fn rhs(&self) -> Value {
self.rhs
}
pub fn rhs_mut(&mut self) -> &mut Value {
&mut self.rhs
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BinaryOp {
NotEq,
Eq,
Gt,
Lt,
Ge,
Le,
Add,
Sub,
Mul,
Div,
Mod,
And,
Or,
Xor,
Shl,
Shr,
Sar,
}
impl fmt::Display for BinaryOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
BinaryOp::NotEq => f.write_str("ne"),
BinaryOp::Eq => f.write_str("eq"),
BinaryOp::Gt => f.write_str("gt"),
BinaryOp::Lt => f.write_str("lt"),
BinaryOp::Ge => f.write_str("ge"),
BinaryOp::Le => f.write_str("le"),
BinaryOp::Add => f.write_str("add"),
BinaryOp::Sub => f.write_str("sub"),
BinaryOp::Mul => f.write_str("mul"),
BinaryOp::Div => f.write_str("div"),
BinaryOp::Mod => f.write_str("mod"),
BinaryOp::And => f.write_str("and"),
BinaryOp::Or => f.write_str("or"),
BinaryOp::Xor => f.write_str("xor"),
BinaryOp::Shl => f.write_str("shl"),
BinaryOp::Shr => f.write_str("shr"),
BinaryOp::Sar => f.write_str("sar"),
}
}
}
#[derive(Clone, Debug)]
pub struct Branch {
cond: Value,
true_bb: BasicBlock,
false_bb: BasicBlock,
true_args: Vec<Value>,
false_args: Vec<Value>,
}
impl Branch {
pub(in crate::ir) fn new_data(
cond: Value,
true_bb: BasicBlock,
false_bb: BasicBlock,
) -> ValueData {
ValueData::new(
Type::get_unit(),
ValueKind::Branch(Self {
cond,
true_bb,
false_bb,
true_args: Vec::new(),
false_args: Vec::new(),
}),
)
}
pub(in crate::ir) fn with_args(
cond: Value,
true_bb: BasicBlock,
false_bb: BasicBlock,
true_args: Vec<Value>,
false_args: Vec<Value>,
) -> ValueData {
ValueData::new(
Type::get_unit(),
ValueKind::Branch(Self {
cond,
true_bb,
false_bb,
true_args,
false_args,
}),
)
}
pub fn cond(&self) -> Value {
self.cond
}
pub fn cond_mut(&mut self) -> &mut Value {
&mut self.cond
}
pub fn true_bb(&self) -> BasicBlock {
self.true_bb
}
pub fn true_bb_mut(&mut self) -> &mut BasicBlock {
&mut self.true_bb
}
pub fn false_bb(&self) -> BasicBlock {
self.false_bb
}
pub fn false_bb_mut(&mut self) -> &mut BasicBlock {
&mut self.false_bb
}
pub fn true_args(&self) -> &[Value] {
&self.true_args
}
pub fn true_args_mut(&mut self) -> &mut Vec<Value> {
&mut self.true_args
}
pub fn false_args(&self) -> &[Value] {
&self.false_args
}
pub fn false_args_mut(&mut self) -> &mut Vec<Value> {
&mut self.false_args
}
}
#[derive(Clone, Debug)]
pub struct Jump {
target: BasicBlock,
args: Vec<Value>,
}
impl Jump {
pub(in crate::ir) fn new_data(target: BasicBlock) -> ValueData {
ValueData::new(
Type::get_unit(),
ValueKind::Jump(Self {
target,
args: Vec::new(),
}),
)
}
pub(in crate::ir) fn with_args(target: BasicBlock, args: Vec<Value>) -> ValueData {
ValueData::new(Type::get_unit(), ValueKind::Jump(Self { target, args }))
}
pub fn target(&self) -> BasicBlock {
self.target
}
pub fn target_mut(&mut self) -> &mut BasicBlock {
&mut self.target
}
pub fn args(&self) -> &[Value] {
&self.args
}
pub fn args_mut(&mut self) -> &mut Vec<Value> {
&mut self.args
}
}
#[derive(Clone, Debug)]
pub struct Call {
callee: Function,
args: Vec<Value>,
}
impl Call {
pub(in crate::ir) fn new_data(callee: Function, args: Vec<Value>, ty: Type) -> ValueData {
ValueData::new(ty, ValueKind::Call(Self { callee, args }))
}
pub fn callee(&self) -> Function {
self.callee
}
pub fn callee_mut(&mut self) -> &mut Function {
&mut self.callee
}
pub fn args(&self) -> &[Value] {
&self.args
}
pub fn args_mut(&mut self) -> &mut Vec<Value> {
&mut self.args
}
}
#[derive(Clone, Debug)]
pub struct Return {
value: Option<Value>,
}
impl Return {
pub(in crate::ir) fn new_data(value: Option<Value>) -> ValueData {
ValueData::new(Type::get_unit(), ValueKind::Return(Self { value }))
}
pub fn value(&self) -> Option<Value> {
self.value
}
pub fn value_mut(&mut self) -> &mut Option<Value> {
&mut self.value
}
}