1use alloc::{boxed::Box, format, rc::Rc};
2
3use super::*;
4use crate::{AttributeRef, any::AsAny, interner, traits::TraitInfo};
5
6pub trait OpRegistration: Op {
7 type Dialect: DialectRegistration;
8
9 fn dialect_name() -> interner::Symbol {
11 interner::Symbol::intern(<Self as OpRegistration>::Dialect::NAMESPACE)
12 }
13 fn name() -> interner::Symbol;
15 fn full_name() -> interner::Symbol {
17 interner::Symbol::intern(format!(
18 "{}.{}",
19 Self::dialect_name(),
20 <Self as OpRegistration>::name()
21 ))
22 }
23 fn traits() -> Box<[TraitInfo]>;
25 fn attrs() -> Box<[AttrInfo]>;
27 fn alloc_uninit(context: Rc<Context>) -> OperationRef;
29}
30
31pub trait BuildableOp<Args: core::marker::Tuple>: Op {
32 type Builder<'a, T>: FnOnce<Args, Output = Result<UnsafeIntrusiveEntityRef<Self>, crate::Report>>
33 + 'a
34 where
35 T: ?Sized + Builder + 'a;
36 fn builder<'b, B>(builder: &'b mut B, span: SourceSpan) -> Self::Builder<'b, B>
37 where
38 B: ?Sized + Builder + 'b;
39}
40
41pub trait Op: AsAny + OpVerifier {
42 fn name(&self) -> OperationName;
46 fn as_operation(&self) -> &Operation;
47 fn as_operation_mut(&mut self) -> &mut Operation;
48
49 fn print(&self, flags: &OpPrintingFlags) -> crate::formatter::Document {
50 use print::OpPrinter;
51
52 let op = self.as_operation();
53 let context = op.context_rc();
54 let mut printer = print::AsmPrinter::new(context, flags);
55 op.print(&mut printer);
56 printer.finish()
57 }
58
59 #[inline]
60 fn as_operation_ref(&self) -> OperationRef {
61 self.as_operation().as_operation_ref()
62 }
63 fn set_span(&mut self, span: SourceSpan) {
64 self.as_operation_mut().set_span(span);
65 }
66 fn parent(&self) -> Option<BlockRef> {
67 self.as_operation().parent()
68 }
69 fn parent_region(&self) -> Option<RegionRef> {
70 self.as_operation().parent_region()
71 }
72 fn parent_op(&self) -> Option<OperationRef> {
73 self.as_operation().parent_op()
74 }
75 fn num_regions(&self) -> usize {
76 self.as_operation().num_regions()
77 }
78 fn regions(&self) -> &RegionList {
79 self.as_operation().regions()
80 }
81 fn regions_mut(&mut self) -> &mut RegionList {
82 self.as_operation_mut().regions_mut()
83 }
84 fn region(&self, index: usize) -> EntityRef<'_, Region> {
85 self.as_operation().region(index)
86 }
87 fn region_mut(&mut self, index: usize) -> EntityMut<'_, Region> {
88 self.as_operation_mut().region_mut(index)
89 }
90 fn has_successors(&self) -> bool {
91 self.as_operation().has_successors()
92 }
93 fn num_successors(&self) -> usize {
94 self.as_operation().num_successors()
95 }
96 fn has_operands(&self) -> bool {
97 self.as_operation().has_operands()
98 }
99 fn num_operands(&self) -> usize {
100 self.as_operation().num_operands()
101 }
102 fn operands(&self) -> &OpOperandStorage {
103 self.as_operation().operands()
104 }
105 fn operands_mut(&mut self) -> &mut OpOperandStorage {
106 self.as_operation_mut().operands_mut()
107 }
108 fn has_results(&self) -> bool {
109 self.as_operation().has_results()
110 }
111 fn num_results(&self) -> usize {
112 self.as_operation().num_results()
113 }
114 fn results(&self) -> &OpResultStorage {
115 self.as_operation().results()
116 }
117 fn results_mut(&mut self) -> &mut OpResultStorage {
118 self.as_operation_mut().results_mut()
119 }
120 fn successors(&self) -> &OpSuccessorStorage {
121 self.as_operation().successors()
122 }
123 fn successors_mut(&mut self) -> &mut OpSuccessorStorage {
124 self.as_operation_mut().successors_mut()
125 }
126}
127
128impl Spanned for dyn Op {
129 fn span(&self) -> SourceSpan {
130 self.as_operation().span
131 }
132}
133
134pub trait OpExt {
135 fn get_attribute(&self, name: impl Into<interner::Symbol>) -> Option<AttributeRef>;
137
138 fn has_attribute(&self, name: impl Into<interner::Symbol>) -> bool;
140
141 fn set_attribute(&mut self, name: impl Into<interner::Symbol>, value: AttributeRef);
143
144 fn remove_attribute(&mut self, name: impl Into<interner::Symbol>);
146
147 fn nearest_parent_op<T: Op>(&self) -> Option<UnsafeIntrusiveEntityRef<T>>;
150}
151
152impl<T: ?Sized + Op> OpExt for T {
153 #[inline]
154 fn get_attribute(&self, name: impl Into<interner::Symbol>) -> Option<AttributeRef> {
155 self.as_operation().get_attribute(name)
156 }
157
158 #[inline]
159 fn has_attribute(&self, name: impl Into<interner::Symbol>) -> bool {
160 self.as_operation().has_attribute(name)
161 }
162
163 #[inline]
164 fn set_attribute(&mut self, name: impl Into<interner::Symbol>, value: AttributeRef) {
165 self.as_operation_mut().set_attribute(name, value);
166 }
167
168 #[inline]
169 fn remove_attribute(&mut self, name: impl Into<interner::Symbol>) {
170 self.as_operation_mut().remove_attribute(name);
171 }
172
173 #[inline]
174 fn nearest_parent_op<U: Op>(&self) -> Option<UnsafeIntrusiveEntityRef<U>> {
175 self.as_operation().nearest_parent_op()
176 }
177}