melior/ir/attribute/
dense_elements.rs1use super::{Attribute, AttributeLike};
2use crate::{
3 ir::{Type, TypeLike},
4 Error,
5};
6use mlir_sys::{
7 mlirDenseElementsAttrGet, mlirDenseElementsAttrGetInt32Value,
8 mlirDenseElementsAttrGetInt64Value, mlirElementsAttrGetNumElements, MlirAttribute,
9};
10
11#[derive(Clone, Copy)]
13pub struct DenseElementsAttribute<'c> {
14 attribute: Attribute<'c>,
15}
16
17impl<'c> DenseElementsAttribute<'c> {
18 pub fn new(r#type: Type<'c>, values: &[Attribute<'c>]) -> Result<Self, Error> {
20 if r#type.is_shaped() {
21 Ok(unsafe {
22 Self::from_raw(mlirDenseElementsAttrGet(
23 r#type.to_raw(),
24 values.len() as isize,
25 values.as_ptr() as *const _ as *const _,
26 ))
27 })
28 } else {
29 Err(Error::TypeExpected("shaped", r#type.to_string()))
30 }
31 }
32
33 pub fn len(&self) -> usize {
35 (unsafe { mlirElementsAttrGetNumElements(self.attribute.to_raw()) }) as usize
36 }
37
38 pub fn is_empty(&self) -> bool {
40 self.len() == 0
41 }
42
43 pub fn i32_element(&self, index: usize) -> Result<i32, Error> {
46 if !self.is_dense_int_elements() {
47 Err(Error::ElementExpected {
48 r#type: "integer",
49 value: self.to_string(),
50 })
51 } else if index < self.len() {
52 Ok(unsafe {
53 mlirDenseElementsAttrGetInt32Value(self.attribute.to_raw(), index as isize)
54 })
55 } else {
56 Err(Error::PositionOutOfBounds {
57 name: "dense element",
58 value: self.to_string(),
59 index,
60 })
61 }
62 }
63
64 pub fn i64_element(&self, index: usize) -> Result<i64, Error> {
66 if !self.is_dense_int_elements() {
67 Err(Error::ElementExpected {
68 r#type: "integer",
69 value: self.to_string(),
70 })
71 } else if index < self.len() {
72 Ok(unsafe {
73 mlirDenseElementsAttrGetInt64Value(self.attribute.to_raw(), index as isize)
74 })
75 } else {
76 Err(Error::PositionOutOfBounds {
77 name: "dense element",
78 value: self.to_string(),
79 index,
80 })
81 }
82 }
83}
84
85attribute_traits!(DenseElementsAttribute, is_dense_elements, "dense elements");
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::{
91 ir::{
92 attribute::IntegerAttribute,
93 r#type::{IntegerType, MemRefType},
94 },
95 test::create_test_context,
96 };
97
98 #[test]
99 fn i32_element() {
100 let context = create_test_context();
101 let integer_type = IntegerType::new(&context, 32).into();
102 let attribute = DenseElementsAttribute::new(
103 MemRefType::new(integer_type, &[3], None, None).into(),
104 &[IntegerAttribute::new(integer_type, 42).into()],
105 )
106 .unwrap();
107
108 assert_eq!(attribute.i32_element(0), Ok(42));
109 assert_eq!(attribute.i32_element(1), Ok(42));
110 assert_eq!(attribute.i32_element(2), Ok(42));
111 assert_eq!(
112 attribute.i32_element(3),
113 Err(Error::PositionOutOfBounds {
114 name: "dense element",
115 value: attribute.to_string(),
116 index: 3,
117 })
118 );
119 }
120
121 #[test]
122 fn i64_element() {
123 let context = create_test_context();
124 let integer_type = IntegerType::new(&context, 64).into();
125 let attribute = DenseElementsAttribute::new(
126 MemRefType::new(integer_type, &[3], None, None).into(),
127 &[IntegerAttribute::new(integer_type, 42).into()],
128 )
129 .unwrap();
130
131 assert_eq!(attribute.i64_element(0), Ok(42));
132 assert_eq!(attribute.i64_element(1), Ok(42));
133 assert_eq!(attribute.i64_element(2), Ok(42));
134 assert_eq!(
135 attribute.i64_element(3),
136 Err(Error::PositionOutOfBounds {
137 name: "dense element",
138 value: attribute.to_string(),
139 index: 3,
140 })
141 );
142 }
143
144 #[test]
145 fn len() {
146 let context = create_test_context();
147 let integer_type = IntegerType::new(&context, 64).into();
148 let attribute = DenseElementsAttribute::new(
149 MemRefType::new(integer_type, &[3], None, None).into(),
150 &[IntegerAttribute::new(integer_type, 0).into()],
151 )
152 .unwrap();
153
154 assert_eq!(attribute.len(), 3);
155 }
156}