mod inst_builder;
pub use inst_builder::InstBuilder;
use crate::{Block, BlockData, IRType, Inst, Value, Variable, function::Function};
#[derive(Default)]
pub struct IRBuilder {
function: Option<Function>,
current_block: Option<Block>,
next_val_id: u32,
next_var_id: u32,
next_block_id: u32,
}
impl IRBuilder {
pub fn new() -> Self {
Self {
function: Some(Function::default()),
..Default::default()
}
}
pub fn start_new_func(&mut self) {
self.function = Some(Function::default())
}
fn gen_block_id(&mut self) -> Block {
let id = Block(self.next_block_id);
self.next_block_id += 1;
id
}
fn is_val_type(&self, val: Value, ty: IRType) -> bool {
self.function.as_ref().unwrap().is_val_type(val, ty)
}
pub fn get_val_type(&self, val: Value) -> IRType {
self.function.as_ref().unwrap().get_val_type(val)
}
fn create_val(&mut self, ty: IRType) -> Value {
let val = Value(self.next_val_id);
self.next_val_id += 1;
self.function.as_mut().unwrap().values.insert(val, ty);
val
}
pub fn get_var_type(&self, var: Variable) -> IRType {
self.function.as_ref().unwrap().get_var_type(var)
}
pub fn create_var(&mut self, ty: IRType) -> Variable {
let var = Variable(self.next_var_id);
self.next_var_id += 1;
self.function.as_mut().unwrap().variables.insert(var, ty);
var
}
pub fn create_block(&mut self, param_types: &[IRType]) -> Block {
let block = self.gen_block_id();
let params = param_types
.iter()
.map(|ty| self.create_val(*ty))
.collect::<Vec<_>>();
let block_data = BlockData {
params,
insts: Vec::new(),
};
self.function
.as_mut()
.unwrap()
.blocks
.insert(block, block_data);
block
}
pub fn switch_to_block(&mut self, block: Block) {
self.current_block = Some(block);
}
pub fn get_block_params(&self, block: Block) -> &[Value] {
self.function
.as_ref()
.unwrap()
.get_block(&block)
.unwrap()
.params
.as_slice()
}
pub fn set_entry_block(&mut self, block: Block) {
self.function.as_mut().unwrap().entry_block = Some(block);
}
fn push_inst(&mut self, inst: Inst) {
if let Some(target_block) = self
.current_block
.as_ref()
.and_then(|block| self.function.as_mut().unwrap().get_block_mut(block))
{
target_block.insts.push(inst);
}
}
pub fn finalize_func(&mut self) -> Function {
self.function.take().unwrap()
}
}