1use crate::ir;
7use crate::ir::instructions::InstructionFormat;
8use crate::ir::types;
9use crate::ir::{DataFlowGraph, InstructionData};
10use crate::ir::{Inst, Opcode, Type, Value};
11
12pub trait InstBuilderBase<'f>: Sized {
21 fn data_flow_graph(&self) -> &DataFlowGraph;
24 fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph;
27
28 fn build(self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph);
33}
34
35include!(concat!(env!("OUT_DIR"), "/inst_builder.rs"));
40
41impl<'f, T: InstBuilderBase<'f>> InstBuilder<'f> for T {}
43
44pub trait InstInserterBase<'f>: Sized {
52 fn data_flow_graph(&self) -> &DataFlowGraph;
54
55 fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph;
57
58 fn insert_built_inst(self, inst: Inst) -> &'f mut DataFlowGraph;
60}
61
62use core::marker::PhantomData;
63
64pub struct InsertBuilder<'f, IIB: InstInserterBase<'f>> {
70 inserter: IIB,
71 unused: PhantomData<&'f u32>,
72}
73
74impl<'f, IIB: InstInserterBase<'f>> InsertBuilder<'f, IIB> {
75 pub fn new(inserter: IIB) -> Self {
78 Self {
79 inserter,
80 unused: PhantomData,
81 }
82 }
83
84 pub fn with_results<Array>(self, reuse: Array) -> InsertReuseBuilder<'f, IIB, Array>
92 where
93 Array: AsRef<[Option<Value>]>,
94 {
95 InsertReuseBuilder {
96 inserter: self.inserter,
97 reuse,
98 unused: PhantomData,
99 }
100 }
101
102 pub fn with_result(self, v: Value) -> InsertReuseBuilder<'f, IIB, [Option<Value>; 1]> {
110 self.with_results([Some(v)])
113 }
114}
115
116impl<'f, IIB: InstInserterBase<'f>> InstBuilderBase<'f> for InsertBuilder<'f, IIB> {
117 fn data_flow_graph(&self) -> &DataFlowGraph {
118 self.inserter.data_flow_graph()
119 }
120
121 fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph {
122 self.inserter.data_flow_graph_mut()
123 }
124
125 fn build(mut self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph) {
126 let inst;
127 {
128 let dfg = self.inserter.data_flow_graph_mut();
129 inst = dfg.make_inst(data);
130 dfg.make_inst_results(inst, ctrl_typevar);
131 }
132 (inst, self.inserter.insert_built_inst(inst))
133 }
134}
135
136pub struct InsertReuseBuilder<'f, IIB, Array>
138where
139 IIB: InstInserterBase<'f>,
140 Array: AsRef<[Option<Value>]>,
141{
142 inserter: IIB,
143 reuse: Array,
144 unused: PhantomData<&'f u32>,
145}
146
147impl<'f, IIB, Array> InstBuilderBase<'f> for InsertReuseBuilder<'f, IIB, Array>
148where
149 IIB: InstInserterBase<'f>,
150 Array: AsRef<[Option<Value>]>,
151{
152 fn data_flow_graph(&self) -> &DataFlowGraph {
153 self.inserter.data_flow_graph()
154 }
155
156 fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph {
157 self.inserter.data_flow_graph_mut()
158 }
159
160 fn build(mut self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph) {
161 let inst;
162 {
163 let dfg = self.inserter.data_flow_graph_mut();
164 inst = dfg.make_inst(data);
165 let ru = self.reuse.as_ref().iter().cloned();
167 dfg.make_inst_results_reusing(inst, ctrl_typevar, ru);
168 }
169 (inst, self.inserter.insert_built_inst(inst))
170 }
171}
172
173pub struct ReplaceBuilder<'f> {
182 dfg: &'f mut DataFlowGraph,
183 inst: Inst,
184}
185
186impl<'f> ReplaceBuilder<'f> {
187 pub fn new(dfg: &'f mut DataFlowGraph, inst: Inst) -> Self {
189 Self { dfg, inst }
190 }
191}
192
193impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
194 fn data_flow_graph(&self) -> &DataFlowGraph {
195 self.dfg
196 }
197
198 fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph {
199 self.dfg
200 }
201
202 fn build(self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph) {
203 self.dfg.insts[self.inst] = data;
205
206 if !self.dfg.has_results(self.inst) {
207 self.dfg.make_inst_results(self.inst, ctrl_typevar);
210 }
211
212 (self.inst, self.dfg)
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use crate::cursor::{Cursor, FuncCursor};
219 use crate::ir::condcodes::*;
220 use crate::ir::types::*;
221 use crate::ir::{Function, InstBuilder, ValueDef};
222
223 #[test]
224 fn types() {
225 let mut func = Function::new();
226 let block0 = func.dfg.make_block();
227 let arg0 = func.dfg.append_block_param(block0, I32);
228 let mut pos = FuncCursor::new(&mut func);
229 pos.insert_block(block0);
230
231 let v0 = pos.ins().iconst(I32, 3);
233 assert_eq!(pos.func.dfg.value_type(v0), I32);
234
235 let v1 = pos.ins().iadd(arg0, v0);
237 assert_eq!(pos.func.dfg.value_type(v1), I32);
238
239 let cmp = pos.ins().icmp(IntCC::Equal, arg0, v0);
241 assert_eq!(pos.func.dfg.value_type(cmp), I8);
242 }
243
244 #[test]
245 fn reuse_results() {
246 let mut func = Function::new();
247 let block0 = func.dfg.make_block();
248 let arg0 = func.dfg.append_block_param(block0, I32);
249 let mut pos = FuncCursor::new(&mut func);
250 pos.insert_block(block0);
251
252 let v0 = pos.ins().iadd_imm(arg0, 17);
253 assert_eq!(pos.func.dfg.value_type(v0), I32);
254 let iadd = pos.prev_inst().unwrap();
255 assert_eq!(pos.func.dfg.value_def(v0), ValueDef::Result(iadd, 0));
256
257 pos.func.dfg.clear_results(iadd);
259 let v0b = pos.ins().with_result(v0).iconst(I32, 3);
260 assert_eq!(v0, v0b);
261 assert_eq!(pos.current_inst(), Some(iadd));
262 let iconst = pos.prev_inst().unwrap();
263 assert!(iadd != iconst);
264 assert_eq!(pos.func.dfg.value_def(v0), ValueDef::Result(iconst, 0));
265 }
266
267 #[test]
268 #[should_panic]
269 #[cfg(debug_assertions)]
270 fn panics_when_inserting_wrong_opcode() {
271 use crate::ir::{Opcode, TrapCode};
272
273 let mut func = Function::new();
274 let block0 = func.dfg.make_block();
275 let mut pos = FuncCursor::new(&mut func);
276 pos.insert_block(block0);
277
278 pos.ins()
280 .Trap(Opcode::Return, I32, TrapCode::BAD_CONVERSION_TO_INTEGER);
281 }
282}