mod value_like;
pub use self::value_like::ValueLike;
use super::{block::BlockArgument, operation::OperationResult, Type};
use crate::{utility::print_callback, Context};
use mlir_sys::{mlirValueEqual, mlirValuePrint, MlirValue};
use std::{
ffi::c_void,
fmt::{self, Debug, Display, Formatter},
marker::PhantomData,
};
#[derive(Clone, Copy)]
pub struct Value<'c, 'a> {
raw: MlirValue,
_context: PhantomData<&'c Context>,
_parent: PhantomData<&'a ()>,
}
impl<'c, 'a> Value<'c, 'a> {
pub unsafe fn from_raw(value: MlirValue) -> Self {
Self {
raw: value,
_context: Default::default(),
_parent: Default::default(),
}
}
}
impl<'c, 'a> ValueLike<'c> for Value<'c, 'a> {
fn to_raw(&self) -> MlirValue {
self.raw
}
}
impl<'c, 'a> PartialEq for Value<'c, 'a> {
fn eq(&self, other: &Self) -> bool {
unsafe { mlirValueEqual(self.raw, other.raw) }
}
}
impl<'c, 'a> Eq for Value<'c, 'a> {}
impl<'c, 'a> Display for Value<'c, 'a> {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
let mut data = (formatter, Ok(()));
unsafe {
mlirValuePrint(
self.raw,
Some(print_callback),
&mut data as *mut _ as *mut c_void,
);
}
data.1
}
}
impl<'c, 'a> Debug for Value<'c, 'a> {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
writeln!(formatter, "Value(")?;
Display::fmt(self, formatter)?;
write!(formatter, ")")
}
}
from_borrowed_subtypes!(Value, BlockArgument, OperationResult);
#[cfg(test)]
mod tests {
use super::*;
use crate::{
ir::{operation::OperationBuilder, Attribute, Block, Identifier, Location},
test::create_test_context,
Context,
};
#[test]
fn r#type() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
assert_eq!(operation.result(0).unwrap().r#type(), index_type);
}
#[test]
fn is_operation_result() {
let context = create_test_context();
let location = Location::unknown(&context);
let r#type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[r#type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
assert!(operation.result(0).unwrap().is_operation_result());
}
#[test]
fn is_block_argument() {
let context = create_test_context();
let r#type = Type::index(&context);
let block = Block::new(&[(r#type, Location::unknown(&context))]);
assert!(block.argument(0).unwrap().is_block_argument());
}
#[test]
fn dump() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let value = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
value.result(0).unwrap().dump();
}
#[test]
fn equal() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
let result = Value::from(operation.result(0).unwrap());
assert_eq!(result, result);
}
#[test]
fn not_equal() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = || {
OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap()
};
assert_ne!(
Value::from(operation().result(0).unwrap()),
operation().result(0).unwrap().into()
);
}
#[test]
fn display_with_unregistered_dialect() {
let context = Context::new();
context.set_allow_unregistered_dialects(true);
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
assert_eq!(
operation.result(0).unwrap().to_string(),
"%0 = \"arith.constant\"() {value = 0 : index} : () -> index\n"
);
}
#[test]
fn display_with_registered_dialect() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
assert_eq!(
operation.result(0).unwrap().to_string(),
"%c0 = arith.constant 0 : index\n"
);
}
#[test]
fn debug() {
let context = create_test_context();
let location = Location::unknown(&context);
let index_type = Type::index(&context);
let operation = OperationBuilder::new("arith.constant", location)
.add_results(&[index_type])
.add_attributes(&[(
Identifier::new(&context, "value"),
Attribute::parse(&context, "0 : index").unwrap(),
)])
.build()
.unwrap();
assert_eq!(
format!("{:?}", Value::from(operation.result(0).unwrap())),
"Value(\n%c0 = arith.constant 0 : index\n)"
);
}
}