use crate::{impl_table_key, ty::Type};
mod cfg;
mod dfg;
mod entity;
mod function;
mod inst;
mod layout;
mod module;
pub mod prelude;
mod process;
mod sig;
mod unit;
pub use self::cfg::*;
pub use self::dfg::*;
pub use self::entity::*;
pub use self::function::*;
pub use self::inst::*;
pub use self::layout::*;
pub use self::module::*;
pub use self::process::*;
pub use self::sig::*;
pub use self::unit::*;
#[derive(Clone, Copy)]
enum FunctionInsertPos {
None,
Append(Block),
Prepend(Block),
After(Inst),
Before(Inst),
}
impl FunctionInsertPos {
fn add_inst(&mut self, inst: Inst, layout: &mut FunctionLayout) {
use FunctionInsertPos::*;
match *self {
None => panic!("no block selected to insert instruction"),
Append(bb) => layout.append_inst(inst, bb),
Prepend(bb) => {
layout.prepend_inst(inst, bb);
*self = After(inst);
}
After(other) => {
layout.insert_inst_after(inst, other);
*self = After(inst);
}
Before(other) => layout.insert_inst_before(inst, other),
}
}
fn remove_inst(&mut self, inst: Inst, layout: &FunctionLayout) {
use FunctionInsertPos::*;
match *self {
After(i) if i == inst => {
*self = layout
.next_inst(i)
.map(Before)
.unwrap_or(Append(layout.inst_block(i).unwrap()))
}
Before(i) if i == inst => {
*self = layout
.prev_inst(i)
.map(After)
.unwrap_or(Prepend(layout.inst_block(i).unwrap()))
}
_ => (),
}
}
}
#[derive(Clone, Copy)]
enum EntityInsertPos {
Append,
Prepend,
After(Inst),
Before(Inst),
}
impl EntityInsertPos {
fn add_inst(&mut self, inst: Inst, layout: &mut InstLayout) {
use EntityInsertPos::*;
match *self {
Append => layout.append_inst(inst),
Prepend => {
layout.prepend_inst(inst);
*self = After(inst);
}
After(other) => {
layout.insert_inst_after(inst, other);
*self = After(inst);
}
Before(other) => layout.insert_inst_before(inst, other),
}
}
fn remove_inst(&mut self, inst: Inst, layout: &InstLayout) {
use EntityInsertPos::*;
match *self {
After(i) if i == inst => *self = layout.next_inst(i).map(Before).unwrap_or(Append),
Before(i) if i == inst => *self = layout.prev_inst(i).map(After).unwrap_or(Prepend),
_ => (),
}
}
}
impl_table_key! {
struct Inst(u32) as "i";
struct Value(u32) as "v";
struct Block(u32) as "bb";
struct Arg(u32) as "arg";
struct ExtUnit(u32) as "ext";
}
impl Value {
fn invalid() -> Self {
Value(std::u32::MAX)
}
pub fn is_invalid(&self) -> bool {
self.0 == std::u32::MAX
}
}
impl Block {
fn invalid() -> Self {
Block(std::u32::MAX)
}
pub fn is_invalid(&self) -> bool {
self.0 == std::u32::MAX
}
}
#[derive(Debug, Serialize, Deserialize)]
pub enum ValueData {
Inst { ty: Type, inst: Inst },
Arg { ty: Type, arg: Arg },
Placeholder { ty: Type },
}
impl ValueData {
pub fn is_placeholder(&self) -> bool {
match self {
ValueData::Placeholder { .. } => true,
_ => false,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlockData {
pub name: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtUnitData {
pub name: UnitName,
pub sig: Signature,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AnyObject {
Inst(Inst),
Value(Value),
Block(Block),
Arg(Arg),
}
impl From<Inst> for AnyObject {
fn from(x: Inst) -> Self {
AnyObject::Inst(x)
}
}
impl From<Value> for AnyObject {
fn from(x: Value) -> Self {
AnyObject::Value(x)
}
}
impl From<Block> for AnyObject {
fn from(x: Block) -> Self {
AnyObject::Block(x)
}
}
impl From<Arg> for AnyObject {
fn from(x: Arg) -> Self {
AnyObject::Arg(x)
}
}
impl std::fmt::Display for AnyObject {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
AnyObject::Inst(x) => write!(f, "{}", x),
AnyObject::Value(x) => write!(f, "{}", x),
AnyObject::Block(x) => write!(f, "{}", x),
AnyObject::Arg(x) => write!(f, "{}", x),
}
}
}
impl Value {
pub fn dump(self, dfg: &DataFlowGraph) -> ValueDumper {
ValueDumper(self, dfg)
}
}
pub struct ValueDumper<'a>(Value, &'a DataFlowGraph);
impl std::fmt::Display for ValueDumper<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.0.is_invalid() {
write!(f, "%<invalid>")
} else if let Some(name) = self.1.get_name(self.0) {
write!(f, "%{}", name)
} else if let Some(index) = self.1.get_anonymous_hint(self.0) {
write!(f, "%{}", index)
} else {
write!(f, "%{}", self.0)
}
}
}
impl Block {
pub fn dump(self, cfg: &ControlFlowGraph) -> BlockDumper {
BlockDumper(self, cfg)
}
}
pub struct BlockDumper<'a>(Block, &'a ControlFlowGraph);
impl std::fmt::Display for BlockDumper<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.0.is_invalid() {
write!(f, "%<invalid>")
} else if let Some(name) = self.1.get_name(self.0) {
write!(f, "%{}", name)
} else if let Some(index) = self.1.get_anonymous_hint(self.0) {
write!(f, "%{}", index)
} else {
write!(f, "%{}", self.0)
}
}
}