use super::{BlockArgument, BlockRef, TypeLike};
use crate::{
Error,
ir::{Location, Operation, OperationRef, RegionRef, Type, Value, operation::OperationRefMut},
};
use core::fmt::Display;
use mlir_sys::{
MlirBlock, mlirBlockAddArgument, mlirBlockAppendOwnedOperation, mlirBlockEraseArgument,
mlirBlockGetArgument, mlirBlockGetFirstOperation, mlirBlockGetNextInRegion,
mlirBlockGetNumArguments, mlirBlockGetNumPredecessors, mlirBlockGetNumSuccessors,
mlirBlockGetParentOperation, mlirBlockGetParentRegion, mlirBlockGetPredecessor,
mlirBlockGetSuccessor, mlirBlockGetTerminator, mlirBlockInsertArgument,
mlirBlockInsertOwnedOperation, mlirBlockInsertOwnedOperationAfter,
mlirBlockInsertOwnedOperationBefore,
};
pub trait BlockLike<'c, 'a>: Display + 'a {
fn to_raw(&self) -> MlirBlock;
fn argument(&self, index: usize) -> Result<BlockArgument<'c, 'a>, Error> {
unsafe {
if index < self.argument_count() {
Ok(BlockArgument::from_raw(mlirBlockGetArgument(
self.to_raw(),
index as isize,
)))
} else {
Err(Error::PositionOutOfBounds {
name: "block argument",
value: self.to_string(),
index,
})
}
}
}
fn argument_count(&self) -> usize {
unsafe { mlirBlockGetNumArguments(self.to_raw()) as usize }
}
fn first_operation(&self) -> Option<OperationRef<'c, 'a>> {
unsafe { OperationRef::from_option_raw(mlirBlockGetFirstOperation(self.to_raw())) }
}
fn first_operation_mut(&self) -> Option<OperationRefMut<'c, 'a>> {
unsafe { OperationRefMut::from_option_raw(mlirBlockGetFirstOperation(self.to_raw())) }
}
fn terminator(&self) -> Option<OperationRef<'c, 'a>> {
unsafe { OperationRef::from_option_raw(mlirBlockGetTerminator(self.to_raw())) }
}
fn terminator_mut(&self) -> Option<OperationRefMut<'c, 'a>> {
unsafe { OperationRefMut::from_option_raw(mlirBlockGetTerminator(self.to_raw())) }
}
fn parent_region(&self) -> Option<RegionRef<'c, 'a>> {
unsafe { RegionRef::from_option_raw(mlirBlockGetParentRegion(self.to_raw())) }
}
fn parent_operation(&self) -> Option<OperationRef<'c, 'a>> {
unsafe { OperationRef::from_option_raw(mlirBlockGetParentOperation(self.to_raw())) }
}
fn add_argument(&self, r#type: Type<'c>, location: Location<'c>) -> Value<'c, 'a> {
unsafe {
Value::from_raw(mlirBlockAddArgument(
self.to_raw(),
r#type.to_raw(),
location.to_raw(),
))
}
}
fn append_operation(&self, operation: Operation<'c>) -> OperationRef<'c, 'a> {
unsafe {
let operation = operation.into_raw();
mlirBlockAppendOwnedOperation(self.to_raw(), operation);
OperationRef::from_raw(operation)
}
}
fn insert_operation(&self, position: usize, operation: Operation<'c>) -> OperationRef<'c, 'a> {
unsafe {
let operation = operation.into_raw();
mlirBlockInsertOwnedOperation(self.to_raw(), position as isize, operation);
OperationRef::from_raw(operation)
}
}
fn insert_operation_after(
&self,
one: OperationRef<'c, 'a>,
other: Operation<'c>,
) -> OperationRef<'c, 'a> {
unsafe {
let other = other.into_raw();
mlirBlockInsertOwnedOperationAfter(self.to_raw(), one.to_raw(), other);
OperationRef::from_raw(other)
}
}
fn insert_operation_before(
&self,
one: OperationRef<'c, 'a>,
other: Operation<'c>,
) -> OperationRef<'c, 'a> {
unsafe {
let other = other.into_raw();
mlirBlockInsertOwnedOperationBefore(self.to_raw(), one.to_raw(), other);
OperationRef::from_raw(other)
}
}
fn insert_argument(
&self,
index: usize,
r#type: Type<'c>,
location: Location<'c>,
) -> Value<'c, 'a> {
unsafe {
Value::from_raw(mlirBlockInsertArgument(
self.to_raw(),
index as isize,
r#type.to_raw(),
location.to_raw(),
))
}
}
unsafe fn erase_argument(&self, index: usize) {
unsafe { mlirBlockEraseArgument(self.to_raw(), index as u32) }
}
fn successor_count(&self) -> usize {
unsafe { mlirBlockGetNumSuccessors(self.to_raw()) as usize }
}
fn successor(&self, index: usize) -> Result<BlockRef<'c, 'a>, Error> {
if index < self.successor_count() {
Ok(unsafe { BlockRef::from_raw(mlirBlockGetSuccessor(self.to_raw(), index as isize)) })
} else {
Err(Error::PositionOutOfBounds {
name: "block successor",
value: self.to_string(),
index,
})
}
}
fn predecessor_count(&self) -> usize {
unsafe { mlirBlockGetNumPredecessors(self.to_raw()) as usize }
}
fn predecessor(&self, index: usize) -> Result<BlockRef<'c, 'a>, Error> {
if index < self.predecessor_count() {
Ok(unsafe {
BlockRef::from_raw(mlirBlockGetPredecessor(self.to_raw(), index as isize))
})
} else {
Err(Error::PositionOutOfBounds {
name: "block predecessor",
value: self.to_string(),
index,
})
}
}
fn next_in_region(&self) -> Option<BlockRef<'c, 'a>> {
unsafe { BlockRef::from_option_raw(mlirBlockGetNextInRegion(self.to_raw())) }
}
}