use crate::ir::Op;
use std::fmt::Debug;
use std::fmt::Display;
use std::sync::Arc;
use std::sync::RwLock;
#[derive(Clone, Debug)]
pub struct Type {
name: String,
}
impl Type {
pub fn new(name: String) -> Self {
Type { name }
}
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Debug)]
pub struct BlockArgument {
name: String,
typ: Type,
}
impl BlockArgument {
pub fn new(name: String, typ: Type) -> Self {
BlockArgument { name, typ }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: &str) {
self.name = name.to_string();
}
}
impl Display for BlockArgument {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} : {}", self.name, self.typ)
}
}
pub struct OpResult {
name: String,
typ: Type,
defining_op: Option<Arc<RwLock<dyn Op>>>,
}
impl OpResult {
pub fn new(name: String, typ: Type, defining_op: Option<Arc<RwLock<dyn Op>>>) -> Self {
OpResult {
name,
typ,
defining_op,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn typ(&self) -> Type {
self.typ.clone()
}
pub fn defining_op(&self) -> Arc<RwLock<dyn Op>> {
if self.defining_op.is_none() {
panic!("Defining op not set for {}", self.name);
}
self.defining_op.clone().unwrap()
}
pub fn set_name(&mut self, name: &str) {
self.name = name.to_string();
}
pub fn set_typ(&mut self, typ: Type) {
self.typ = typ;
}
pub fn set_defining_op(&mut self, op: Option<Arc<RwLock<dyn Op>>>) {
self.defining_op = op;
}
}
impl Default for OpResult {
fn default() -> Self {
Self {
name: "Undefined name".to_string(),
typ: Type::new("Unset type".to_string()),
defining_op: None,
}
}
}
pub enum Users {
HasNoOpResults,
OpOperands(Vec<Arc<RwLock<OpOperand>>>),
}
impl Users {
pub fn len(&self) -> usize {
match self {
Users::HasNoOpResults => 0,
Users::OpOperands(users) => users.len(),
}
}
}
pub enum Value {
BlockArgument(BlockArgument),
OpResult(OpResult),
}
impl Value {
pub fn name(&self) -> &str {
match self {
Value::BlockArgument(arg) => &arg.name,
Value::OpResult(result) => &result.name,
}
}
pub fn set_defining_op(&mut self, op: Option<Arc<RwLock<dyn Op>>>) {
match self {
Value::BlockArgument(_) => panic!("Cannot set defining op for BlockArgument"),
Value::OpResult(op_res) => op_res.set_defining_op(op),
}
}
pub fn set_name(&mut self, name: &str) {
match self {
Value::BlockArgument(arg) => arg.set_name(name),
Value::OpResult(result) => result.set_name(name),
}
}
fn op_result_users(&self, op_res: &OpResult) -> Vec<Arc<RwLock<OpOperand>>> {
let op = op_res.defining_op();
let op = op.try_read().unwrap();
let parent = {
let operation = op.operation();
let operation = operation.try_read().unwrap();
let parent = operation.parent();
parent.unwrap()
};
let block = parent.try_read().unwrap();
let index = block.index_of(op.operation().clone());
let index = index.unwrap();
let ops = block.ops();
let ops = ops.try_read().unwrap();
let mut out = Vec::new();
for i in index..ops.len() {
let op = ops[i].try_read().unwrap();
let operation = op.operation();
let operation = operation.try_read().unwrap();
let operands = operation.operands();
let operands = operands.try_read().unwrap();
for operand in operands.iter() {
let operand_clone = operand.clone();
let operand_clone = operand_clone.try_read().unwrap();
let value = operand_clone.value();
let value = value.try_read().unwrap();
if std::ptr::eq(&*value as *const Value, self as *const Value) {
out.push(operand.clone());
}
}
}
out
}
pub fn users(&self) -> Users {
match self {
Value::BlockArgument(_) => Users::HasNoOpResults,
Value::OpResult(op_res) => Users::OpOperands(self.op_result_users(op_res)),
}
}
pub fn rename(&mut self, new_name: &str) {
self.set_name(new_name);
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::BlockArgument(arg) => write!(f, "{} : {}", arg.name, arg.typ.name),
Value::OpResult(result) => write!(f, "{}", result.name),
}
}
}
pub struct OpOperand {
pub value: Arc<RwLock<Value>>,
}
impl OpOperand {
pub fn new(value: Arc<RwLock<Value>>) -> Self {
OpOperand { value }
}
pub fn name(&self) -> String {
let value = self.value.try_read().unwrap();
value.name().to_string()
}
pub fn value(&self) -> Arc<RwLock<Value>> {
self.value.clone()
}
pub fn defining_op(&self) -> Option<Arc<RwLock<dyn Op>>> {
let value = self.value();
let value = &*value.read().unwrap();
match value {
Value::BlockArgument(_) => None,
Value::OpResult(op_res) => Some(op_res.defining_op()),
}
}
}
impl Display for OpOperand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}