1 //! Data flow graph tracking Instructions, Values, and blocks.
2 
3 use crate::entity::{self, PrimaryMap, SecondaryMap};
4 use crate::ir;
5 use crate::ir::builder::ReplaceBuilder;
6 use crate::ir::dynamic_type::{DynamicTypeData, DynamicTypes};
7 use crate::ir::instructions::{CallInfo, InstructionData};
8 use crate::ir::pcc::Fact;
9 use crate::ir::{
10     types, Block, BlockCall, ConstantData, ConstantPool, DynamicType, ExtFuncData, FuncRef,
11     Immediate, Inst, JumpTables, RelSourceLoc, SigRef, Signature, Type, Value,
12     ValueLabelAssignments, ValueList, ValueListPool,
13 };
14 use crate::packed_option::ReservedValue;
15 use crate::write::write_operands;
16 use core::fmt;
17 use core::iter;
18 use core::mem;
19 use core::ops::{Index, IndexMut};
20 use core::u16;
21 
22 use alloc::collections::BTreeMap;
23 #[cfg(feature = "enable-serde")]
24 use serde_derive::{Deserialize, Serialize};
25 use smallvec::SmallVec;
26 
27 /// Storage for instructions within the DFG.
28 #[derive(Clone, PartialEq, Hash)]
29 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
30 pub struct Insts(PrimaryMap<Inst, InstructionData>);
31 
32 /// Allow immutable access to instructions via indexing.
33 impl Index<Inst> for Insts {
34     type Output = InstructionData;
35 
36     fn index(&self, inst: Inst) -> &InstructionData {
37         self.0.index(inst)
38     }
39 }
40 
41 /// Allow mutable access to instructions via indexing.
42 impl IndexMut<Inst> for Insts {
43     fn index_mut(&mut self, inst: Inst) -> &mut InstructionData {
44         self.0.index_mut(inst)
45     }
46 }
47 
48 /// Storage for basic blocks within the DFG.
49 #[derive(Clone, PartialEq, Hash)]
50 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
51 pub struct Blocks(PrimaryMap<Block, BlockData>);
52 
53 impl Blocks {
54     /// Create a new basic block.
55     pub fn add(&mut self) -> Block {
56         self.0.push(BlockData::new())
57     }
58 
59     /// Get the total number of basic blocks created in this function, whether they are
60     /// currently inserted in the layout or not.
61     ///
62     /// This is intended for use with `SecondaryMap::with_capacity`.
63     pub fn len(&self) -> usize {
64         self.0.len()
65     }
66 
67     /// Returns `true` if the given block reference is valid.
68     pub fn is_valid(&self, block: Block) -> bool {
69         self.0.is_valid(block)
70     }
71 }
72 
73 impl Index<Block> for Blocks {
74     type Output = BlockData;
75 
76     fn index(&self, block: Block) -> &BlockData {
77         &self.0[block]
78     }
79 }
80 
81 impl IndexMut<Block> for Blocks {
82     fn index_mut(&mut self, block: Block) -> &mut BlockData {
83         &mut self.0[block]
84     }
85 }
86 
87 /// A data flow graph defines all instructions and basic blocks in a function as well as
88 /// the data flow dependencies between them. The DFG also tracks values which can be either
89 /// instruction results or block parameters.
90 ///
91 /// The layout of blocks in the function and of instructions in each block is recorded by the
92 /// `Layout` data structure which forms the other half of the function representation.
93 ///
94 #[derive(Clone, PartialEq, Hash)]
95 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
96 pub struct DataFlowGraph {
97     /// Data about all of the instructions in the function, including opcodes and operands.
98     /// The instructions in this map are not in program order. That is tracked by `Layout`, along
99     /// with the block containing each instruction.
100     pub insts: Insts,
101 
102     /// List of result values for each instruction.
103     ///
104     /// This map gets resized automatically by `make_inst()` so it is always in sync with the
105     /// primary `insts` map.
106     results: SecondaryMap<Inst, ValueList>,
107 
108     /// basic blocks in the function and their parameters.
109     ///
110     /// This map is not in program order. That is handled by `Layout`, and so is the sequence of
111     /// instructions contained in each block.
112     pub blocks: Blocks,
113 
114     /// Dynamic types created.
115     pub dynamic_types: DynamicTypes,
116 
117     /// Memory pool of value lists.
118     ///
119     /// The `ValueList` references into this pool appear in many places:
120     ///
121     /// - Instructions in `insts` that don't have room for their entire argument list inline.
122     /// - Instruction result values in `results`.
123     /// - block parameters in `blocks`.
124     pub value_lists: ValueListPool,
125 
126     /// Primary value table with entries for all values.
127     values: PrimaryMap<Value, ValueDataPacked>,
128 
129     /// Facts: proof-carrying-code assertions about values.
130     pub facts: SecondaryMap<Value, Option<Fact>>,
131 
132     /// Function signature table. These signatures are referenced by indirect call instructions as
133     /// well as the external function references.
134     pub signatures: PrimaryMap<SigRef, Signature>,
135 
136     /// External function references. These are functions that can be called directly.
137     pub ext_funcs: PrimaryMap<FuncRef, ExtFuncData>,
138 
139     /// Saves Value labels.
140     pub values_labels: Option<BTreeMap<Value, ValueLabelAssignments>>,
141 
142     /// Constants used within the function.
143     pub constants: ConstantPool,
144 
145     /// Stores large immediates that otherwise will not fit on InstructionData.
146     pub immediates: PrimaryMap<Immediate, ConstantData>,
147 
148     /// Jump tables used in this function.
149     pub jump_tables: JumpTables,
150 }
151 
152 impl DataFlowGraph {
153     /// Create a new empty `DataFlowGraph`.
154     pub fn new() -> Self {
155         Self {
156             insts: Insts(PrimaryMap::new()),
157             results: SecondaryMap::new(),
158             blocks: Blocks(PrimaryMap::new()),
159             dynamic_types: DynamicTypes::new(),
160             value_lists: ValueListPool::new(),
161             values: PrimaryMap::new(),
162             facts: SecondaryMap::new(),
163             signatures: PrimaryMap::new(),
164             ext_funcs: PrimaryMap::new(),
165             values_labels: None,
166             constants: ConstantPool::new(),
167             immediates: PrimaryMap::new(),
168             jump_tables: JumpTables::new(),
169         }
170     }
171 
172     /// Clear everything.
173     pub fn clear(&mut self) {
174         self.insts.0.clear();
175         self.results.clear();
176         self.blocks.0.clear();
177         self.dynamic_types.clear();
178         self.value_lists.clear();
179         self.values.clear();
180         self.signatures.clear();
181         self.ext_funcs.clear();
182         self.values_labels = None;
183         self.constants.clear();
184         self.immediates.clear();
185         self.jump_tables.clear();
186         self.facts.clear();
187     }
188 
189     /// Get the total number of instructions created in this function, whether they are currently
190     /// inserted in the layout or not.
191     ///
192     /// This is intended for use with `SecondaryMap::with_capacity`.
193     pub fn num_insts(&self) -> usize {
194         self.insts.0.len()
195     }
196 
197     /// Returns `true` if the given instruction reference is valid.
198     pub fn inst_is_valid(&self, inst: Inst) -> bool {
199         self.insts.0.is_valid(inst)
200     }
201 
202     /// Get the total number of basic blocks created in this function, whether they are
203     /// currently inserted in the layout or not.
204     ///
205     /// This is intended for use with `SecondaryMap::with_capacity`.
206     pub fn num_blocks(&self) -> usize {
207         self.blocks.len()
208     }
209 
210     /// Returns `true` if the given block reference is valid.
211     pub fn block_is_valid(&self, block: Block) -> bool {
212         self.blocks.is_valid(block)
213     }
214 
215     /// Make a BlockCall, bundling together the block and its arguments.
216     pub fn block_call(&mut self, block: Block, args: &[Value]) -> BlockCall {
217         BlockCall::new(block, args, &mut self.value_lists)
218     }
219 
220     /// Get the total number of values.
221     pub fn num_values(&self) -> usize {
222         self.values.len()
223     }
224 
225     /// Get an iterator over all values and their definitions.
226     pub fn values_and_defs(&self) -> impl Iterator<Item = (Value, ValueDef)> + '_ {
227         self.values().map(|value| (value, self.value_def(value)))
228     }
229 
230     /// Starts collection of debug information.
231     pub fn collect_debug_info(&mut self) {
232         if self.values_labels.is_none() {
233             self.values_labels = Some(Default::default());
234         }
235     }
236 
237     /// Inserts a `ValueLabelAssignments::Alias` for `to_alias` if debug info
238     /// collection is enabled.
239     pub fn add_value_label_alias(&mut self, to_alias: Value, from: RelSourceLoc, value: Value) {
240         if let Some(values_labels) = self.values_labels.as_mut() {
241             values_labels.insert(to_alias, ir::ValueLabelAssignments::Alias { from, value });
242         }
243     }
244 }
245 
246 /// Resolve value aliases.
247 ///
248 /// Find the original SSA value that `value` aliases, or None if an
249 /// alias cycle is detected.
250 fn maybe_resolve_aliases(
251     values: &PrimaryMap<Value, ValueDataPacked>,
252     value: Value,
253 ) -> Option<Value> {
254     let mut v = value;
255 
256     // Note that values may be empty here.
257     for _ in 0..=values.len() {
258         if let ValueData::Alias { original, .. } = ValueData::from(values[v]) {
259             v = original;
260         } else {
261             return Some(v);
262         }
263     }
264 
265     None
266 }
267 
268 /// Resolve value aliases.
269 ///
270 /// Find the original SSA value that `value` aliases.
271 fn resolve_aliases(values: &PrimaryMap<Value, ValueDataPacked>, value: Value) -> Value {
272     if let Some(v) = maybe_resolve_aliases(values, value) {
273         v
274     } else {
275         panic!("Value alias loop detected for {}", value);
276     }
277 }
278 
279 /// Iterator over all Values in a DFG.
280 pub struct Values<'a> {
281     inner: entity::Iter<'a, Value, ValueDataPacked>,
282 }
283 
284 /// Check for non-values.
285 fn valid_valuedata(data: ValueDataPacked) -> bool {
286     let data = ValueData::from(data);
287     if let ValueData::Alias {
288         ty: types::INVALID,
289         original,
290     } = ValueData::from(data)
291     {
292         if original == Value::reserved_value() {
293             return false;
294         }
295     }
296     true
297 }
298 
299 impl<'a> Iterator for Values<'a> {
300     type Item = Value;
301 
302     fn next(&mut self) -> Option<Self::Item> {
303         self.inner
304             .by_ref()
305             .find(|kv| valid_valuedata(*kv.1))
306             .map(|kv| kv.0)
307     }
308 }
309 
310 /// Handling values.
311 ///
312 /// Values are either block parameters or instruction results.
313 impl DataFlowGraph {
314     /// Allocate an extended value entry.
315     fn make_value(&mut self, data: ValueData) -> Value {
316         self.values.push(data.into())
317     }
318 
319     /// Get an iterator over all values.
320     pub fn values<'a>(&'a self) -> Values {
321         Values {
322             inner: self.values.iter(),
323         }
324     }
325 
326     /// Check if a value reference is valid.
327     pub fn value_is_valid(&self, v: Value) -> bool {
328         self.values.is_valid(v)
329     }
330 
331     /// Check whether a value is valid and not an alias.
332     pub fn value_is_real(&self, value: Value) -> bool {
333         // Deleted or unused values are also stored as aliases so this excludes
334         // those as well.
335         self.value_is_valid(value) && !matches!(self.values[value].into(), ValueData::Alias { .. })
336     }
337 
338     /// Get the type of a value.
339     pub fn value_type(&self, v: Value) -> Type {
340         self.values[v].ty()
341     }
342 
343     /// Get the definition of a value.
344     ///
345     /// This is either the instruction that defined it or the Block that has the value as an
346     /// parameter.
347     pub fn value_def(&self, v: Value) -> ValueDef {
348         match ValueData::from(self.values[v]) {
349             ValueData::Inst { inst, num, .. } => ValueDef::Result(inst, num as usize),
350             ValueData::Param { block, num, .. } => ValueDef::Param(block, num as usize),
351             ValueData::Alias { original, .. } => {
352                 // Make sure we only recurse one level. `resolve_aliases` has safeguards to
353                 // detect alias loops without overrunning the stack.
354                 self.value_def(self.resolve_aliases(original))
355             }
356             ValueData::Union { x, y, .. } => ValueDef::Union(x, y),
357         }
358     }
359 
360     /// Determine if `v` is an attached instruction result / block parameter.
361     ///
362     /// An attached value can't be attached to something else without first being detached.
363     ///
364     /// Value aliases are not considered to be attached to anything. Use `resolve_aliases()` to
365     /// determine if the original aliased value is attached.
366     pub fn value_is_attached(&self, v: Value) -> bool {
367         use self::ValueData::*;
368         match ValueData::from(self.values[v]) {
369             Inst { inst, num, .. } => Some(&v) == self.inst_results(inst).get(num as usize),
370             Param { block, num, .. } => Some(&v) == self.block_params(block).get(num as usize),
371             Alias { .. } => false,
372             Union { .. } => false,
373         }
374     }
375 
376     /// Resolve value aliases.
377     ///
378     /// Find the original SSA value that `value` aliases.
379     pub fn resolve_aliases(&self, value: Value) -> Value {
380         resolve_aliases(&self.values, value)
381     }
382 
383     /// Replace all uses of value aliases with their resolved values, and delete
384     /// the aliases.
385     pub fn resolve_all_aliases(&mut self) {
386         let invalid_value = ValueDataPacked::from(ValueData::Alias {
387             ty: types::INVALID,
388             original: Value::reserved_value(),
389         });
390 
391         // Rewrite each chain of aliases. Update every alias along the chain
392         // into an alias directly to the final value. Due to updating every
393         // alias that it looks at, this loop runs in time linear in the number
394         // of values.
395         for mut src in self.values.keys() {
396             let value_data = self.values[src];
397             if value_data == invalid_value {
398                 continue;
399             }
400             if let ValueData::Alias { mut original, .. } = value_data.into() {
401                 // We don't use the type after this, we just need some place to
402                 // store the resolved aliases temporarily.
403                 let resolved = ValueDataPacked::from(ValueData::Alias {
404                     ty: types::INVALID,
405                     original: resolve_aliases(&self.values, original),
406                 });
407                 // Walk the chain again, splatting the new alias everywhere.
408                 // resolve_aliases panics if there's an alias cycle, so we don't
409                 // need to guard against cycles here.
410                 loop {
411                     self.values[src] = resolved;
412                     src = original;
413                     if let ValueData::Alias { original: next, .. } = self.values[src].into() {
414                         original = next;
415                     } else {
416                         break;
417                     }
418                 }
419             }
420         }
421 
422         // Now aliases don't point to other aliases, so we can replace any use
423         // of an alias with the final value in constant time.
424 
425         // Rewrite InstructionData in `self.insts`.
426         for inst in self.insts.0.values_mut() {
427             inst.map_values(&mut self.value_lists, &mut self.jump_tables, |arg| {
428                 if let ValueData::Alias { original, .. } = self.values[arg].into() {
429                     original
430                 } else {
431                     arg
432                 }
433             });
434         }
435 
436         // - `results` and block-params in `blocks` are not aliases, by
437         //   definition.
438         // - `dynamic_types` has no values.
439         // - `value_lists` can only be accessed via references from elsewhere.
440         // - `values` only has value references in aliases (which we've
441         //   removed), and unions (but the egraph pass ensures there are no
442         //   aliases before creating unions).
443 
444         // Merge `facts` from any alias onto the aliased value. Note that if
445         // there was a chain of aliases, at this point every alias that was in
446         // the chain points to the same final value, so their facts will all be
447         // merged together.
448         for value in self.facts.keys() {
449             if let ValueData::Alias { original, .. } = self.values[value].into() {
450                 if let Some(new_fact) = self.facts[value].take() {
451                     match &mut self.facts[original] {
452                         Some(old_fact) => *old_fact = Fact::intersect(old_fact, &new_fact),
453                         old_fact => *old_fact = Some(new_fact),
454                     }
455                 }
456             }
457         }
458 
459         // - `signatures` and `ext_funcs` have no values.
460 
461         if let Some(values_labels) = &mut self.values_labels {
462             // Debug info is best-effort. If any is attached to value aliases,
463             // just discard it.
464             values_labels.retain(|&k, _| !matches!(self.values[k].into(), ValueData::Alias { .. }));
465 
466             // If debug-info says a value should have the same labels as another
467             // value, then make sure that target is not a value alias.
468             for value_label in values_labels.values_mut() {
469                 if let ValueLabelAssignments::Alias { value, .. } = value_label {
470                     if let ValueData::Alias { original, .. } = self.values[*value].into() {
471                         *value = original;
472                     }
473                 }
474             }
475         }
476 
477         // - `constants` and `immediates` have no values.
478         // - `jump_tables` is updated together with instruction-data above.
479 
480         // Delete all aliases now that there are no uses left.
481         for value in self.values.values_mut() {
482             if let ValueData::Alias { .. } = ValueData::from(*value) {
483                 *value = invalid_value;
484             }
485         }
486     }
487 
488     /// Turn a value into an alias of another.
489     ///
490     /// Change the `dest` value to behave as an alias of `src`. This means that all uses of `dest`
491     /// will behave as if they used that value `src`.
492     ///
493     /// The `dest` value can't be attached to an instruction or block.
494     pub fn change_to_alias(&mut self, dest: Value, src: Value) {
495         debug_assert!(!self.value_is_attached(dest));
496         // Try to create short alias chains by finding the original source value.
497         // This also avoids the creation of loops.
498         let original = self.resolve_aliases(src);
499         debug_assert_ne!(
500             dest, original,
501             "Aliasing {} to {} would create a loop",
502             dest, src
503         );
504         let ty = self.value_type(original);
505         debug_assert_eq!(
506             self.value_type(dest),
507             ty,
508             "Aliasing {} to {} would change its type {} to {}",
509             dest,
510             src,
511             self.value_type(dest),
512             ty
513         );
514         debug_assert_ne!(ty, types::INVALID);
515 
516         self.values[dest] = ValueData::Alias { ty, original }.into();
517     }
518 
519     /// Replace the results of one instruction with aliases to the results of another.
520     ///
521     /// Change all the results of `dest_inst` to behave as aliases of
522     /// corresponding results of `src_inst`, as if calling change_to_alias for
523     /// each.
524     ///
525     /// After calling this instruction, `dest_inst` will have had its results
526     /// cleared, so it likely needs to be removed from the graph.
527     ///
528     pub fn replace_with_aliases(&mut self, dest_inst: Inst, original_inst: Inst) {
529         debug_assert_ne!(
530             dest_inst, original_inst,
531             "Replacing {} with itself would create a loop",
532             dest_inst
533         );
534 
535         let dest_results = self.results[dest_inst].as_slice(&self.value_lists);
536         let original_results = self.results[original_inst].as_slice(&self.value_lists);
537 
538         debug_assert_eq!(
539             dest_results.len(),
540             original_results.len(),
541             "Replacing {} with {} would produce a different number of results.",
542             dest_inst,
543             original_inst
544         );
545 
546         for (&dest, &original) in dest_results.iter().zip(original_results) {
547             let ty = self.value_type(original);
548             debug_assert_eq!(
549                 self.value_type(dest),
550                 ty,
551                 "Aliasing {} to {} would change its type {} to {}",
552                 dest,
553                 original,
554                 self.value_type(dest),
555                 ty
556             );
557             debug_assert_ne!(ty, types::INVALID);
558 
559             self.values[dest] = ValueData::Alias { ty, original }.into();
560         }
561 
562         self.clear_results(dest_inst);
563     }
564 }
565 
566 /// Where did a value come from?
567 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
568 pub enum ValueDef {
569     /// Value is the n'th result of an instruction.
570     Result(Inst, usize),
571     /// Value is the n'th parameter to a block.
572     Param(Block, usize),
573     /// Value is a union of two other values.
574     Union(Value, Value),
575 }
576 
577 impl ValueDef {
578     /// Unwrap the instruction where the value was defined, or panic.
579     pub fn unwrap_inst(&self) -> Inst {
580         self.inst().expect("Value is not an instruction result")
581     }
582 
583     /// Get the instruction where the value was defined, if any.
584     pub fn inst(&self) -> Option<Inst> {
585         match *self {
586             Self::Result(inst, _) => Some(inst),
587             _ => None,
588         }
589     }
590 
591     /// Unwrap the block there the parameter is defined, or panic.
592     pub fn unwrap_block(&self) -> Block {
593         match *self {
594             Self::Param(block, _) => block,
595             _ => panic!("Value is not a block parameter"),
596         }
597     }
598 
599     /// Get the number component of this definition.
600     ///
601     /// When multiple values are defined at the same program point, this indicates the index of
602     /// this value.
603     pub fn num(self) -> usize {
604         match self {
605             Self::Result(_, n) | Self::Param(_, n) => n,
606             Self::Union(_, _) => 0,
607         }
608     }
609 }
610 
611 /// Internal table storage for extended values.
612 #[derive(Clone, Debug, PartialEq, Hash)]
613 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
614 enum ValueData {
615     /// Value is defined by an instruction.
616     Inst { ty: Type, num: u16, inst: Inst },
617 
618     /// Value is a block parameter.
619     Param { ty: Type, num: u16, block: Block },
620 
621     /// Value is an alias of another value.
622     /// An alias value can't be linked as an instruction result or block parameter. It is used as a
623     /// placeholder when the original instruction or block has been rewritten or modified.
624     Alias { ty: Type, original: Value },
625 
626     /// Union is a "fork" in representation: the value can be
627     /// represented as either of the values named here. This is used
628     /// for aegraph (acyclic egraph) representation in the DFG.
629     Union { ty: Type, x: Value, y: Value },
630 }
631 
632 /// Bit-packed version of ValueData, for efficiency.
633 ///
634 /// Layout:
635 ///
636 /// ```plain
637 ///        | tag:2 |  type:14        |    x:24       | y:24          |
638 ///
639 /// Inst       00     ty               inst output     inst index
640 /// Param      01     ty               blockparam num  block index
641 /// Alias      10     ty               0               value index
642 /// Union      11     ty               first value     second value
643 /// ```
644 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
645 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
646 struct ValueDataPacked(u64);
647 
648 /// Encodes a value in 0..2^32 into 0..2^n, where n is less than 32
649 /// (and is implied by `mask`), by translating 2^32-1 (0xffffffff)
650 /// into 2^n-1 and panic'ing on 2^n..2^32-1.
651 fn encode_narrow_field(x: u32, bits: u8) -> u32 {
652     let max = (1 << bits) - 1;
653     if x == 0xffff_ffff {
654         max
655     } else {
656         debug_assert!(
657             x < max,
658             "{x} does not fit into {bits} bits (must be less than {max} to \
659              allow for a 0xffffffff sentinal)"
660         );
661         x
662     }
663 }
664 
665 /// The inverse of the above `encode_narrow_field`: unpacks 2^n-1 into
666 /// 2^32-1.
667 fn decode_narrow_field(x: u32, bits: u8) -> u32 {
668     if x == (1 << bits) - 1 {
669         0xffff_ffff
670     } else {
671         x
672     }
673 }
674 
675 impl ValueDataPacked {
676     const Y_SHIFT: u8 = 0;
677     const Y_BITS: u8 = 24;
678     const X_SHIFT: u8 = Self::Y_SHIFT + Self::Y_BITS;
679     const X_BITS: u8 = 24;
680     const TYPE_SHIFT: u8 = Self::X_SHIFT + Self::X_BITS;
681     const TYPE_BITS: u8 = 14;
682     const TAG_SHIFT: u8 = Self::TYPE_SHIFT + Self::TYPE_BITS;
683     const TAG_BITS: u8 = 2;
684 
685     const TAG_INST: u64 = 0;
686     const TAG_PARAM: u64 = 1;
687     const TAG_ALIAS: u64 = 2;
688     const TAG_UNION: u64 = 3;
689 
690     fn make(tag: u64, ty: Type, x: u32, y: u32) -> ValueDataPacked {
691         debug_assert!(tag < (1 << Self::TAG_BITS));
692         debug_assert!(ty.repr() < (1 << Self::TYPE_BITS));
693 
694         let x = encode_narrow_field(x, Self::X_BITS);
695         let y = encode_narrow_field(y, Self::Y_BITS);
696 
697         ValueDataPacked(
698             (tag << Self::TAG_SHIFT)
699                 | ((ty.repr() as u64) << Self::TYPE_SHIFT)
700                 | ((x as u64) << Self::X_SHIFT)
701                 | ((y as u64) << Self::Y_SHIFT),
702         )
703     }
704 
705     #[inline(always)]
706     fn field(self, shift: u8, bits: u8) -> u64 {
707         (self.0 >> shift) & ((1 << bits) - 1)
708     }
709 
710     #[inline(always)]
711     fn ty(self) -> Type {
712         let ty = self.field(ValueDataPacked::TYPE_SHIFT, ValueDataPacked::TYPE_BITS) as u16;
713         Type::from_repr(ty)
714     }
715 
716     #[inline(always)]
717     fn set_type(&mut self, ty: Type) {
718         self.0 &= !(((1 << Self::TYPE_BITS) - 1) << Self::TYPE_SHIFT);
719         self.0 |= (ty.repr() as u64) << Self::TYPE_SHIFT;
720     }
721 }
722 
723 impl From<ValueData> for ValueDataPacked {
724     fn from(data: ValueData) -> Self {
725         match data {
726             ValueData::Inst { ty, num, inst } => {
727                 Self::make(Self::TAG_INST, ty, num.into(), inst.as_bits())
728             }
729             ValueData::Param { ty, num, block } => {
730                 Self::make(Self::TAG_PARAM, ty, num.into(), block.as_bits())
731             }
732             ValueData::Alias { ty, original } => {
733                 Self::make(Self::TAG_ALIAS, ty, 0, original.as_bits())
734             }
735             ValueData::Union { ty, x, y } => {
736                 Self::make(Self::TAG_UNION, ty, x.as_bits(), y.as_bits())
737             }
738         }
739     }
740 }
741 
742 impl From<ValueDataPacked> for ValueData {
743     fn from(data: ValueDataPacked) -> Self {
744         let tag = data.field(ValueDataPacked::TAG_SHIFT, ValueDataPacked::TAG_BITS);
745         let ty = u16::try_from(data.field(ValueDataPacked::TYPE_SHIFT, ValueDataPacked::TYPE_BITS))
746             .expect("Mask should ensure result fits in a u16");
747         let x = u32::try_from(data.field(ValueDataPacked::X_SHIFT, ValueDataPacked::X_BITS))
748             .expect("Mask should ensure result fits in a u32");
749         let y = u32::try_from(data.field(ValueDataPacked::Y_SHIFT, ValueDataPacked::Y_BITS))
750             .expect("Mask should ensure result fits in a u32");
751 
752         let ty = Type::from_repr(ty);
753         match tag {
754             ValueDataPacked::TAG_INST => ValueData::Inst {
755                 ty,
756                 num: u16::try_from(x).expect("Inst result num should fit in u16"),
757                 inst: Inst::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)),
758             },
759             ValueDataPacked::TAG_PARAM => ValueData::Param {
760                 ty,
761                 num: u16::try_from(x).expect("Blockparam index should fit in u16"),
762                 block: Block::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)),
763             },
764             ValueDataPacked::TAG_ALIAS => ValueData::Alias {
765                 ty,
766                 original: Value::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)),
767             },
768             ValueDataPacked::TAG_UNION => ValueData::Union {
769                 ty,
770                 x: Value::from_bits(decode_narrow_field(x, ValueDataPacked::X_BITS)),
771                 y: Value::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)),
772             },
773             _ => panic!("Invalid tag {} in ValueDataPacked 0x{:x}", tag, data.0),
774         }
775     }
776 }
777 
778 /// Instructions.
779 ///
780 impl DataFlowGraph {
781     /// Create a new instruction.
782     ///
783     /// The type of the first result is indicated by `data.ty`. If the
784     /// instruction produces multiple results, also call
785     /// `make_inst_results` to allocate value table entries. (It is
786     /// always safe to call `make_inst_results`, regardless of how
787     /// many results the instruction has.)
788     pub fn make_inst(&mut self, data: InstructionData) -> Inst {
789         let n = self.num_insts() + 1;
790         self.results.resize(n);
791         self.insts.0.push(data)
792     }
793 
794     /// Declares a dynamic vector type
795     pub fn make_dynamic_ty(&mut self, data: DynamicTypeData) -> DynamicType {
796         self.dynamic_types.push(data)
797     }
798 
799     /// Returns an object that displays `inst`.
800     pub fn display_inst<'a>(&'a self, inst: Inst) -> DisplayInst<'a> {
801         DisplayInst(self, inst)
802     }
803 
804     /// Returns an object that displays the given `value`'s defining instruction.
805     ///
806     /// Panics if the value is not defined by an instruction (i.e. it is a basic
807     /// block argument).
808     pub fn display_value_inst(&self, value: Value) -> DisplayInst<'_> {
809         match self.value_def(value) {
810             ir::ValueDef::Result(inst, _) => self.display_inst(inst),
811             ir::ValueDef::Param(_, _) => panic!("value is not defined by an instruction"),
812             ir::ValueDef::Union(_, _) => panic!("value is a union of two other values"),
813         }
814     }
815 
816     /// Construct a read-only visitor context for the values of this instruction.
817     pub fn inst_values<'dfg>(
818         &'dfg self,
819         inst: Inst,
820     ) -> impl DoubleEndedIterator<Item = Value> + 'dfg {
821         self.inst_args(inst)
822             .iter()
823             .chain(
824                 self.insts[inst]
825                     .branch_destination(&self.jump_tables)
826                     .into_iter()
827                     .flat_map(|branch| branch.args_slice(&self.value_lists).iter()),
828             )
829             .copied()
830     }
831 
832     /// Map a function over the values of the instruction.
833     pub fn map_inst_values<F>(&mut self, inst: Inst, body: F)
834     where
835         F: FnMut(Value) -> Value,
836     {
837         self.insts[inst].map_values(&mut self.value_lists, &mut self.jump_tables, body);
838     }
839 
840     /// Overwrite the instruction's value references with values from the iterator.
841     /// NOTE: the iterator provided is expected to yield at least as many values as the instruction
842     /// currently has.
843     pub fn overwrite_inst_values<I>(&mut self, inst: Inst, mut values: I)
844     where
845         I: Iterator<Item = Value>,
846     {
847         self.insts[inst].map_values(&mut self.value_lists, &mut self.jump_tables, |_| {
848             values.next().unwrap()
849         });
850     }
851 
852     /// Get all value arguments on `inst` as a slice.
853     pub fn inst_args(&self, inst: Inst) -> &[Value] {
854         self.insts[inst].arguments(&self.value_lists)
855     }
856 
857     /// Get all value arguments on `inst` as a mutable slice.
858     pub fn inst_args_mut(&mut self, inst: Inst) -> &mut [Value] {
859         self.insts[inst].arguments_mut(&mut self.value_lists)
860     }
861 
862     /// Get the fixed value arguments on `inst` as a slice.
863     pub fn inst_fixed_args(&self, inst: Inst) -> &[Value] {
864         let num_fixed_args = self.insts[inst]
865             .opcode()
866             .constraints()
867             .num_fixed_value_arguments();
868         &self.inst_args(inst)[..num_fixed_args]
869     }
870 
871     /// Get the fixed value arguments on `inst` as a mutable slice.
872     pub fn inst_fixed_args_mut(&mut self, inst: Inst) -> &mut [Value] {
873         let num_fixed_args = self.insts[inst]
874             .opcode()
875             .constraints()
876             .num_fixed_value_arguments();
877         &mut self.inst_args_mut(inst)[..num_fixed_args]
878     }
879 
880     /// Get the variable value arguments on `inst` as a slice.
881     pub fn inst_variable_args(&self, inst: Inst) -> &[Value] {
882         let num_fixed_args = self.insts[inst]
883             .opcode()
884             .constraints()
885             .num_fixed_value_arguments();
886         &self.inst_args(inst)[num_fixed_args..]
887     }
888 
889     /// Get the variable value arguments on `inst` as a mutable slice.
890     pub fn inst_variable_args_mut(&mut self, inst: Inst) -> &mut [Value] {
891         let num_fixed_args = self.insts[inst]
892             .opcode()
893             .constraints()
894             .num_fixed_value_arguments();
895         &mut self.inst_args_mut(inst)[num_fixed_args..]
896     }
897 
898     /// Create result values for an instruction that produces multiple results.
899     ///
900     /// Instructions that produce no result values only need to be created with `make_inst`,
901     /// otherwise call `make_inst_results` to allocate value table entries for the results.
902     ///
903     /// The result value types are determined from the instruction's value type constraints and the
904     /// provided `ctrl_typevar` type for polymorphic instructions. For non-polymorphic
905     /// instructions, `ctrl_typevar` is ignored, and `INVALID` can be used.
906     ///
907     /// The type of the first result value is also set, even if it was already set in the
908     /// `InstructionData` passed to `make_inst`. If this function is called with a single-result
909     /// instruction, that is the only effect.
910     pub fn make_inst_results(&mut self, inst: Inst, ctrl_typevar: Type) -> usize {
911         self.make_inst_results_reusing(inst, ctrl_typevar, iter::empty())
912     }
913 
914     /// Create result values for `inst`, reusing the provided detached values.
915     ///
916     /// Create a new set of result values for `inst` using `ctrl_typevar` to determine the result
917     /// types. Any values provided by `reuse` will be reused. When `reuse` is exhausted or when it
918     /// produces `None`, a new value is created.
919     pub fn make_inst_results_reusing<I>(
920         &mut self,
921         inst: Inst,
922         ctrl_typevar: Type,
923         reuse: I,
924     ) -> usize
925     where
926         I: Iterator<Item = Option<Value>>,
927     {
928         self.clear_results(inst);
929 
930         let mut reuse = reuse.fuse();
931         let result_tys: SmallVec<[_; 16]> = self.inst_result_types(inst, ctrl_typevar).collect();
932 
933         for (expected, &ty) in result_tys.iter().enumerate() {
934             let num = u16::try_from(expected).expect("Result value index should fit in u16");
935             let value_data = ValueData::Inst { ty, num, inst };
936             let v = if let Some(Some(v)) = reuse.next() {
937                 debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
938                 debug_assert!(!self.value_is_attached(v));
939                 self.values[v] = value_data.into();
940                 v
941             } else {
942                 self.make_value(value_data)
943             };
944             let actual = self.results[inst].push(v, &mut self.value_lists);
945             debug_assert_eq!(expected, actual);
946         }
947 
948         result_tys.len()
949     }
950 
951     /// Create a `ReplaceBuilder` that will replace `inst` with a new instruction in place.
952     pub fn replace(&mut self, inst: Inst) -> ReplaceBuilder {
953         ReplaceBuilder::new(self, inst)
954     }
955 
956     /// Clear the list of result values from `inst`.
957     ///
958     /// This leaves `inst` without any result values. New result values can be created by calling
959     /// `make_inst_results` or by using a `replace(inst)` builder.
960     pub fn clear_results(&mut self, inst: Inst) {
961         self.results[inst].clear(&mut self.value_lists)
962     }
963 
964     /// Replace an instruction result with a new value of type `new_type`.
965     ///
966     /// The `old_value` must be an attached instruction result.
967     ///
968     /// The old value is left detached, so it should probably be changed into something else.
969     ///
970     /// Returns the new value.
971     pub fn replace_result(&mut self, old_value: Value, new_type: Type) -> Value {
972         let (num, inst) = match ValueData::from(self.values[old_value]) {
973             ValueData::Inst { num, inst, .. } => (num, inst),
974             _ => panic!("{} is not an instruction result value", old_value),
975         };
976         let new_value = self.make_value(ValueData::Inst {
977             ty: new_type,
978             num,
979             inst,
980         });
981         let num = num as usize;
982         let attached = mem::replace(
983             self.results[inst]
984                 .get_mut(num, &mut self.value_lists)
985                 .expect("Replacing detached result"),
986             new_value,
987         );
988         debug_assert_eq!(
989             attached,
990             old_value,
991             "{} wasn't detached from {}",
992             old_value,
993             self.display_inst(inst)
994         );
995         new_value
996     }
997 
998     /// Clone an instruction, attaching new result `Value`s and
999     /// returning them.
1000     pub fn clone_inst(&mut self, inst: Inst) -> Inst {
1001         // First, add a clone of the InstructionData.
1002         let inst_data = self.insts[inst].clone();
1003         // If the `inst_data` has a reference to a ValueList, clone it
1004         // as well, because we can't share these (otherwise mutating
1005         // one would affect the other).
1006         let inst_data = inst_data.deep_clone(&mut self.value_lists);
1007         let new_inst = self.make_inst(inst_data);
1008         // Get the controlling type variable.
1009         let ctrl_typevar = self.ctrl_typevar(inst);
1010         // Create new result values.
1011         let num_results = self.make_inst_results(new_inst, ctrl_typevar);
1012         // Copy over PCC facts, if any.
1013         for i in 0..num_results {
1014             let old_result = self.inst_results(inst)[i];
1015             let new_result = self.inst_results(new_inst)[i];
1016             self.facts[new_result] = self.facts[old_result].clone();
1017         }
1018         new_inst
1019     }
1020 
1021     /// Get the first result of an instruction.
1022     ///
1023     /// This function panics if the instruction doesn't have any result.
1024     pub fn first_result(&self, inst: Inst) -> Value {
1025         self.results[inst]
1026             .first(&self.value_lists)
1027             .expect("Instruction has no results")
1028     }
1029 
1030     /// Test if `inst` has any result values currently.
1031     pub fn has_results(&self, inst: Inst) -> bool {
1032         !self.results[inst].is_empty()
1033     }
1034 
1035     /// Return all the results of an instruction.
1036     pub fn inst_results(&self, inst: Inst) -> &[Value] {
1037         self.results[inst].as_slice(&self.value_lists)
1038     }
1039 
1040     /// Return all the results of an instruction as ValueList.
1041     pub fn inst_results_list(&self, inst: Inst) -> ValueList {
1042         self.results[inst]
1043     }
1044 
1045     /// Create a union of two values.
1046     pub fn union(&mut self, x: Value, y: Value) -> Value {
1047         // Get the type.
1048         let ty = self.value_type(x);
1049         debug_assert_eq!(ty, self.value_type(y));
1050         self.make_value(ValueData::Union { ty, x, y })
1051     }
1052 
1053     /// Get the call signature of a direct or indirect call instruction.
1054     /// Returns `None` if `inst` is not a call instruction.
1055     pub fn call_signature(&self, inst: Inst) -> Option<SigRef> {
1056         match self.insts[inst].analyze_call(&self.value_lists) {
1057             CallInfo::NotACall => None,
1058             CallInfo::Direct(f, _) => Some(self.ext_funcs[f].signature),
1059             CallInfo::Indirect(s, _) => Some(s),
1060         }
1061     }
1062 
1063     /// Like `call_signature` but returns none for tail call instructions.
1064     fn non_tail_call_signature(&self, inst: Inst) -> Option<SigRef> {
1065         let sig = self.call_signature(inst)?;
1066         match self.insts[inst].opcode() {
1067             ir::Opcode::ReturnCall | ir::Opcode::ReturnCallIndirect => None,
1068             _ => Some(sig),
1069         }
1070     }
1071 
1072     // Only for use by the verifier. Everyone else should just use
1073     // `dfg.inst_results(inst).len()`.
1074     pub(crate) fn num_expected_results_for_verifier(&self, inst: Inst) -> usize {
1075         match self.non_tail_call_signature(inst) {
1076             Some(sig) => self.signatures[sig].returns.len(),
1077             None => {
1078                 let constraints = self.insts[inst].opcode().constraints();
1079                 constraints.num_fixed_results()
1080             }
1081         }
1082     }
1083 
1084     /// Get the result types of the given instruction.
1085     pub fn inst_result_types<'a>(
1086         &'a self,
1087         inst: Inst,
1088         ctrl_typevar: Type,
1089     ) -> impl iter::ExactSizeIterator<Item = Type> + 'a {
1090         return match self.non_tail_call_signature(inst) {
1091             Some(sig) => InstResultTypes::Signature(self, sig, 0),
1092             None => {
1093                 let constraints = self.insts[inst].opcode().constraints();
1094                 InstResultTypes::Constraints(constraints, ctrl_typevar, 0)
1095             }
1096         };
1097 
1098         enum InstResultTypes<'a> {
1099             Signature(&'a DataFlowGraph, SigRef, usize),
1100             Constraints(ir::instructions::OpcodeConstraints, Type, usize),
1101         }
1102 
1103         impl Iterator for InstResultTypes<'_> {
1104             type Item = Type;
1105 
1106             fn next(&mut self) -> Option<Type> {
1107                 match self {
1108                     InstResultTypes::Signature(dfg, sig, i) => {
1109                         let param = dfg.signatures[*sig].returns.get(*i)?;
1110                         *i += 1;
1111                         Some(param.value_type)
1112                     }
1113                     InstResultTypes::Constraints(constraints, ctrl_ty, i) => {
1114                         if *i < constraints.num_fixed_results() {
1115                             let ty = constraints.result_type(*i, *ctrl_ty);
1116                             *i += 1;
1117                             Some(ty)
1118                         } else {
1119                             None
1120                         }
1121                     }
1122                 }
1123             }
1124 
1125             fn size_hint(&self) -> (usize, Option<usize>) {
1126                 let len = match self {
1127                     InstResultTypes::Signature(dfg, sig, i) => {
1128                         dfg.signatures[*sig].returns.len() - *i
1129                     }
1130                     InstResultTypes::Constraints(constraints, _, i) => {
1131                         constraints.num_fixed_results() - *i
1132                     }
1133                 };
1134                 (len, Some(len))
1135             }
1136         }
1137 
1138         impl ExactSizeIterator for InstResultTypes<'_> {}
1139     }
1140 
1141     /// Compute the type of an instruction result from opcode constraints and call signatures.
1142     ///
1143     /// This computes the same sequence of result types that `make_inst_results()` above would
1144     /// assign to the created result values, but it does not depend on `make_inst_results()` being
1145     /// called first.
1146     ///
1147     /// Returns `None` if asked about a result index that is too large.
1148     pub fn compute_result_type(
1149         &self,
1150         inst: Inst,
1151         result_idx: usize,
1152         ctrl_typevar: Type,
1153     ) -> Option<Type> {
1154         self.inst_result_types(inst, ctrl_typevar).nth(result_idx)
1155     }
1156 
1157     /// Get the controlling type variable, or `INVALID` if `inst` isn't polymorphic.
1158     pub fn ctrl_typevar(&self, inst: Inst) -> Type {
1159         let constraints = self.insts[inst].opcode().constraints();
1160 
1161         if !constraints.is_polymorphic() {
1162             types::INVALID
1163         } else if constraints.requires_typevar_operand() {
1164             // Not all instruction formats have a designated operand, but in that case
1165             // `requires_typevar_operand()` should never be true.
1166             self.value_type(
1167                 self.insts[inst]
1168                     .typevar_operand(&self.value_lists)
1169                     .unwrap_or_else(|| {
1170                         panic!(
1171                             "Instruction format for {:?} doesn't have a designated operand",
1172                             self.insts[inst]
1173                         )
1174                     }),
1175             )
1176         } else {
1177             self.value_type(self.first_result(inst))
1178         }
1179     }
1180 }
1181 
1182 /// basic blocks.
1183 impl DataFlowGraph {
1184     /// Create a new basic block.
1185     pub fn make_block(&mut self) -> Block {
1186         self.blocks.add()
1187     }
1188 
1189     /// Get the number of parameters on `block`.
1190     pub fn num_block_params(&self, block: Block) -> usize {
1191         self.blocks[block].params(&self.value_lists).len()
1192     }
1193 
1194     /// Get the parameters on `block`.
1195     pub fn block_params(&self, block: Block) -> &[Value] {
1196         self.blocks[block].params(&self.value_lists)
1197     }
1198 
1199     /// Get the types of the parameters on `block`.
1200     pub fn block_param_types(&self, block: Block) -> impl Iterator<Item = Type> + '_ {
1201         self.block_params(block).iter().map(|&v| self.value_type(v))
1202     }
1203 
1204     /// Append a parameter with type `ty` to `block`.
1205     pub fn append_block_param(&mut self, block: Block, ty: Type) -> Value {
1206         let param = self.values.next_key();
1207         let num = self.blocks[block].params.push(param, &mut self.value_lists);
1208         debug_assert!(num <= u16::MAX as usize, "Too many parameters on block");
1209         self.make_value(ValueData::Param {
1210             ty,
1211             num: num as u16,
1212             block,
1213         })
1214     }
1215 
1216     /// Removes `val` from `block`'s parameters by swapping it with the last parameter on `block`.
1217     /// Returns the position of `val` before removal.
1218     ///
1219     /// *Important*: to ensure O(1) deletion, this method swaps the removed parameter with the
1220     /// last `block` parameter. This can disrupt all the branch instructions jumping to this
1221     /// `block` for which you have to change the branch argument order if necessary.
1222     ///
1223     /// Panics if `val` is not a block parameter.
1224     pub fn swap_remove_block_param(&mut self, val: Value) -> usize {
1225         let (block, num) =
1226             if let ValueData::Param { num, block, .. } = ValueData::from(self.values[val]) {
1227                 (block, num)
1228             } else {
1229                 panic!("{} must be a block parameter", val);
1230             };
1231         self.blocks[block]
1232             .params
1233             .swap_remove(num as usize, &mut self.value_lists);
1234         if let Some(last_arg_val) = self.blocks[block]
1235             .params
1236             .get(num as usize, &self.value_lists)
1237         {
1238             // We update the position of the old last arg.
1239             let mut last_arg_data = ValueData::from(self.values[last_arg_val]);
1240             if let ValueData::Param {
1241                 num: ref mut old_num,
1242                 ..
1243             } = &mut last_arg_data
1244             {
1245                 *old_num = num;
1246                 self.values[last_arg_val] = last_arg_data.into();
1247             } else {
1248                 panic!("{} should be a Block parameter", last_arg_val);
1249             }
1250         }
1251         num as usize
1252     }
1253 
1254     /// Removes `val` from `block`'s parameters by a standard linear time list removal which
1255     /// preserves ordering. Also updates the values' data.
1256     pub fn remove_block_param(&mut self, val: Value) {
1257         let (block, num) =
1258             if let ValueData::Param { num, block, .. } = ValueData::from(self.values[val]) {
1259                 (block, num)
1260             } else {
1261                 panic!("{} must be a block parameter", val);
1262             };
1263         self.blocks[block]
1264             .params
1265             .remove(num as usize, &mut self.value_lists);
1266         for index in num..(self.num_block_params(block) as u16) {
1267             let packed = &mut self.values[self.blocks[block]
1268                 .params
1269                 .get(index as usize, &self.value_lists)
1270                 .unwrap()];
1271             let mut data = ValueData::from(*packed);
1272             match &mut data {
1273                 ValueData::Param { ref mut num, .. } => {
1274                     *num -= 1;
1275                     *packed = data.into();
1276                 }
1277                 _ => panic!(
1278                     "{} must be a block parameter",
1279                     self.blocks[block]
1280                         .params
1281                         .get(index as usize, &self.value_lists)
1282                         .unwrap()
1283                 ),
1284             }
1285         }
1286     }
1287 
1288     /// Append an existing value to `block`'s parameters.
1289     ///
1290     /// The appended value can't already be attached to something else.
1291     ///
1292     /// In almost all cases, you should be using `append_block_param()` instead of this method.
1293     pub fn attach_block_param(&mut self, block: Block, param: Value) {
1294         debug_assert!(!self.value_is_attached(param));
1295         let num = self.blocks[block].params.push(param, &mut self.value_lists);
1296         debug_assert!(num <= u16::MAX as usize, "Too many parameters on block");
1297         let ty = self.value_type(param);
1298         self.values[param] = ValueData::Param {
1299             ty,
1300             num: num as u16,
1301             block,
1302         }
1303         .into();
1304     }
1305 
1306     /// Replace a block parameter with a new value of type `ty`.
1307     ///
1308     /// The `old_value` must be an attached block parameter. It is removed from its place in the list
1309     /// of parameters and replaced by a new value of type `new_type`. The new value gets the same
1310     /// position in the list, and other parameters are not disturbed.
1311     ///
1312     /// The old value is left detached, so it should probably be changed into something else.
1313     ///
1314     /// Returns the new value.
1315     pub fn replace_block_param(&mut self, old_value: Value, new_type: Type) -> Value {
1316         // Create new value identical to the old one except for the type.
1317         let (block, num) =
1318             if let ValueData::Param { num, block, .. } = ValueData::from(self.values[old_value]) {
1319                 (block, num)
1320             } else {
1321                 panic!("{} must be a block parameter", old_value);
1322             };
1323         let new_arg = self.make_value(ValueData::Param {
1324             ty: new_type,
1325             num,
1326             block,
1327         });
1328 
1329         self.blocks[block]
1330             .params
1331             .as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
1332         new_arg
1333     }
1334 
1335     /// Detach all the parameters from `block` and return them as a `ValueList`.
1336     ///
1337     /// This is a quite low-level operation. Sensible things to do with the detached block parameters
1338     /// is to put them back on the same block with `attach_block_param()` or change them into aliases
1339     /// with `change_to_alias()`.
1340     pub fn detach_block_params(&mut self, block: Block) -> ValueList {
1341         self.blocks[block].params.take()
1342     }
1343 
1344     /// Merge the facts for two values. If both values have facts and
1345     /// they differ, both values get a special "conflict" fact that is
1346     /// never satisfied.
1347     pub fn merge_facts(&mut self, a: Value, b: Value) {
1348         let a = self.resolve_aliases(a);
1349         let b = self.resolve_aliases(b);
1350         match (&self.facts[a], &self.facts[b]) {
1351             (Some(a), Some(b)) if a == b => { /* nothing */ }
1352             (None, None) => { /* nothing */ }
1353             (Some(a), None) => {
1354                 self.facts[b] = Some(a.clone());
1355             }
1356             (None, Some(b)) => {
1357                 self.facts[a] = Some(b.clone());
1358             }
1359             (Some(a_fact), Some(b_fact)) => {
1360                 assert_eq!(self.value_type(a), self.value_type(b));
1361                 let merged = Fact::intersect(a_fact, b_fact);
1362                 crate::trace!(
1363                     "facts merge on {} and {}: {:?}, {:?} -> {:?}",
1364                     a,
1365                     b,
1366                     a_fact,
1367                     b_fact,
1368                     merged,
1369                 );
1370                 self.facts[a] = Some(merged.clone());
1371                 self.facts[b] = Some(merged);
1372             }
1373         }
1374     }
1375 }
1376 
1377 /// Contents of a basic block.
1378 ///
1379 /// Parameters on a basic block are values that dominate everything in the block. All
1380 /// branches to this block must provide matching arguments, and the arguments to the entry block must
1381 /// match the function arguments.
1382 #[derive(Clone, PartialEq, Hash)]
1383 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1384 pub struct BlockData {
1385     /// List of parameters to this block.
1386     params: ValueList,
1387 }
1388 
1389 impl BlockData {
1390     fn new() -> Self {
1391         Self {
1392             params: ValueList::new(),
1393         }
1394     }
1395 
1396     /// Get the parameters on `block`.
1397     pub fn params<'a>(&self, pool: &'a ValueListPool) -> &'a [Value] {
1398         self.params.as_slice(pool)
1399     }
1400 }
1401 
1402 /// Object that can display an instruction.
1403 pub struct DisplayInst<'a>(&'a DataFlowGraph, Inst);
1404 
1405 impl<'a> fmt::Display for DisplayInst<'a> {
1406     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1407         let dfg = self.0;
1408         let inst = self.1;
1409 
1410         if let Some((first, rest)) = dfg.inst_results(inst).split_first() {
1411             write!(f, "{}", first)?;
1412             for v in rest {
1413                 write!(f, ", {}", v)?;
1414             }
1415             write!(f, " = ")?;
1416         }
1417 
1418         let typevar = dfg.ctrl_typevar(inst);
1419         if typevar.is_invalid() {
1420             write!(f, "{}", dfg.insts[inst].opcode())?;
1421         } else {
1422             write!(f, "{}.{}", dfg.insts[inst].opcode(), typevar)?;
1423         }
1424         write_operands(f, dfg, inst)
1425     }
1426 }
1427 
1428 /// Parser routines. These routines should not be used outside the parser.
1429 impl DataFlowGraph {
1430     /// Set the type of a value. This is only for use in the parser, which needs
1431     /// to create invalid values for index padding which may be reassigned later.
1432     #[cold]
1433     fn set_value_type_for_parser(&mut self, v: Value, t: Type) {
1434         assert_eq!(
1435             self.value_type(v),
1436             types::INVALID,
1437             "this function is only for assigning types to previously invalid values"
1438         );
1439         self.values[v].set_type(t);
1440     }
1441 
1442     /// Check that the given concrete `Type` has been defined in the function.
1443     pub fn check_dynamic_type(&mut self, ty: Type) -> Option<Type> {
1444         debug_assert!(ty.is_dynamic_vector());
1445         if self
1446             .dynamic_types
1447             .values()
1448             .any(|dyn_ty_data| dyn_ty_data.concrete().unwrap() == ty)
1449         {
1450             Some(ty)
1451         } else {
1452             None
1453         }
1454     }
1455 
1456     /// Create result values for `inst`, reusing the provided detached values.
1457     /// This is similar to `make_inst_results_reusing` except it's only for use
1458     /// in the parser, which needs to reuse previously invalid values.
1459     #[cold]
1460     pub fn make_inst_results_for_parser(
1461         &mut self,
1462         inst: Inst,
1463         ctrl_typevar: Type,
1464         reuse: &[Value],
1465     ) -> usize {
1466         let mut reuse_iter = reuse.iter().copied();
1467         let result_tys: SmallVec<[_; 16]> = self.inst_result_types(inst, ctrl_typevar).collect();
1468         for ty in result_tys {
1469             if ty.is_dynamic_vector() {
1470                 self.check_dynamic_type(ty)
1471                     .unwrap_or_else(|| panic!("Use of undeclared dynamic type: {}", ty));
1472             }
1473             if let Some(v) = reuse_iter.next() {
1474                 self.set_value_type_for_parser(v, ty);
1475             }
1476         }
1477 
1478         self.make_inst_results_reusing(inst, ctrl_typevar, reuse.iter().map(|x| Some(*x)))
1479     }
1480 
1481     /// Similar to `append_block_param`, append a parameter with type `ty` to
1482     /// `block`, but using value `val`. This is only for use by the parser to
1483     /// create parameters with specific values.
1484     #[cold]
1485     pub fn append_block_param_for_parser(&mut self, block: Block, ty: Type, val: Value) {
1486         let num = self.blocks[block].params.push(val, &mut self.value_lists);
1487         assert!(num <= u16::MAX as usize, "Too many parameters on block");
1488         self.values[val] = ValueData::Param {
1489             ty,
1490             num: num as u16,
1491             block,
1492         }
1493         .into();
1494     }
1495 
1496     /// Create a new value alias. This is only for use by the parser to create
1497     /// aliases with specific values, and the printer for testing.
1498     #[cold]
1499     pub fn make_value_alias_for_serialization(&mut self, src: Value, dest: Value) {
1500         assert_ne!(src, Value::reserved_value());
1501         assert_ne!(dest, Value::reserved_value());
1502 
1503         let ty = if self.values.is_valid(src) {
1504             self.value_type(src)
1505         } else {
1506             // As a special case, if we can't resolve the aliasee yet, use INVALID
1507             // temporarily. It will be resolved later in parsing.
1508             types::INVALID
1509         };
1510         let data = ValueData::Alias { ty, original: src };
1511         self.values[dest] = data.into();
1512     }
1513 
1514     /// If `v` is already defined as an alias, return its destination value.
1515     /// Otherwise return None. This allows the parser to coalesce identical
1516     /// alias definitions, and the printer to identify an alias's immediate target.
1517     #[cold]
1518     pub fn value_alias_dest_for_serialization(&self, v: Value) -> Option<Value> {
1519         if let ValueData::Alias { original, .. } = ValueData::from(self.values[v]) {
1520             Some(original)
1521         } else {
1522             None
1523         }
1524     }
1525 
1526     /// Compute the type of an alias. This is only for use in the parser.
1527     /// Returns false if an alias cycle was encountered.
1528     #[cold]
1529     pub fn set_alias_type_for_parser(&mut self, v: Value) -> bool {
1530         if let Some(resolved) = maybe_resolve_aliases(&self.values, v) {
1531             let old_ty = self.value_type(v);
1532             let new_ty = self.value_type(resolved);
1533             if old_ty == types::INVALID {
1534                 self.set_value_type_for_parser(v, new_ty);
1535             } else {
1536                 assert_eq!(old_ty, new_ty);
1537             }
1538             true
1539         } else {
1540             false
1541         }
1542     }
1543 
1544     /// Create an invalid value, to pad the index space. This is only for use by
1545     /// the parser to pad out the value index space.
1546     #[cold]
1547     pub fn make_invalid_value_for_parser(&mut self) {
1548         let data = ValueData::Alias {
1549             ty: types::INVALID,
1550             original: Value::reserved_value(),
1551         };
1552         self.make_value(data);
1553     }
1554 
1555     /// Check if a value reference is valid, while being aware of aliases which
1556     /// may be unresolved while parsing.
1557     #[cold]
1558     pub fn value_is_valid_for_parser(&self, v: Value) -> bool {
1559         if !self.value_is_valid(v) {
1560             return false;
1561         }
1562         if let ValueData::Alias { ty, .. } = ValueData::from(self.values[v]) {
1563             ty != types::INVALID
1564         } else {
1565             true
1566         }
1567     }
1568 }
1569 
1570 #[cfg(test)]
1571 mod tests {
1572     use super::*;
1573     use crate::cursor::{Cursor, FuncCursor};
1574     use crate::ir::{Function, Opcode, TrapCode};
1575     use alloc::string::ToString;
1576 
1577     #[test]
1578     fn make_inst() {
1579         let mut dfg = DataFlowGraph::new();
1580 
1581         let idata = InstructionData::UnaryImm {
1582             opcode: Opcode::Iconst,
1583             imm: 0.into(),
1584         };
1585         let inst = dfg.make_inst(idata);
1586 
1587         dfg.make_inst_results(inst, types::I32);
1588         assert_eq!(inst.to_string(), "inst0");
1589         assert_eq!(dfg.display_inst(inst).to_string(), "v0 = iconst.i32 0");
1590 
1591         // Immutable reference resolution.
1592         {
1593             let immdfg = &dfg;
1594             let ins = &immdfg.insts[inst];
1595             assert_eq!(ins.opcode(), Opcode::Iconst);
1596         }
1597 
1598         // Results.
1599         let val = dfg.first_result(inst);
1600         assert_eq!(dfg.inst_results(inst), &[val]);
1601 
1602         assert_eq!(dfg.value_def(val), ValueDef::Result(inst, 0));
1603         assert_eq!(dfg.value_type(val), types::I32);
1604 
1605         // Replacing results.
1606         assert!(dfg.value_is_attached(val));
1607         let v2 = dfg.replace_result(val, types::F64);
1608         assert!(!dfg.value_is_attached(val));
1609         assert!(dfg.value_is_attached(v2));
1610         assert_eq!(dfg.inst_results(inst), &[v2]);
1611         assert_eq!(dfg.value_def(v2), ValueDef::Result(inst, 0));
1612         assert_eq!(dfg.value_type(v2), types::F64);
1613     }
1614 
1615     #[test]
1616     fn no_results() {
1617         let mut dfg = DataFlowGraph::new();
1618 
1619         let idata = InstructionData::Trap {
1620             opcode: Opcode::Trap,
1621             code: TrapCode::User(0),
1622         };
1623         let inst = dfg.make_inst(idata);
1624         assert_eq!(dfg.display_inst(inst).to_string(), "trap user0");
1625 
1626         // Result slice should be empty.
1627         assert_eq!(dfg.inst_results(inst), &[]);
1628     }
1629 
1630     #[test]
1631     fn block() {
1632         let mut dfg = DataFlowGraph::new();
1633 
1634         let block = dfg.make_block();
1635         assert_eq!(block.to_string(), "block0");
1636         assert_eq!(dfg.num_block_params(block), 0);
1637         assert_eq!(dfg.block_params(block), &[]);
1638         assert!(dfg.detach_block_params(block).is_empty());
1639         assert_eq!(dfg.num_block_params(block), 0);
1640         assert_eq!(dfg.block_params(block), &[]);
1641 
1642         let arg1 = dfg.append_block_param(block, types::F32);
1643         assert_eq!(arg1.to_string(), "v0");
1644         assert_eq!(dfg.num_block_params(block), 1);
1645         assert_eq!(dfg.block_params(block), &[arg1]);
1646 
1647         let arg2 = dfg.append_block_param(block, types::I16);
1648         assert_eq!(arg2.to_string(), "v1");
1649         assert_eq!(dfg.num_block_params(block), 2);
1650         assert_eq!(dfg.block_params(block), &[arg1, arg2]);
1651 
1652         assert_eq!(dfg.value_def(arg1), ValueDef::Param(block, 0));
1653         assert_eq!(dfg.value_def(arg2), ValueDef::Param(block, 1));
1654         assert_eq!(dfg.value_type(arg1), types::F32);
1655         assert_eq!(dfg.value_type(arg2), types::I16);
1656 
1657         // Swap the two block parameters.
1658         let vlist = dfg.detach_block_params(block);
1659         assert_eq!(dfg.num_block_params(block), 0);
1660         assert_eq!(dfg.block_params(block), &[]);
1661         assert_eq!(vlist.as_slice(&dfg.value_lists), &[arg1, arg2]);
1662         dfg.attach_block_param(block, arg2);
1663         let arg3 = dfg.append_block_param(block, types::I32);
1664         dfg.attach_block_param(block, arg1);
1665         assert_eq!(dfg.block_params(block), &[arg2, arg3, arg1]);
1666     }
1667 
1668     #[test]
1669     fn replace_block_params() {
1670         let mut dfg = DataFlowGraph::new();
1671 
1672         let block = dfg.make_block();
1673         let arg1 = dfg.append_block_param(block, types::F32);
1674 
1675         let new1 = dfg.replace_block_param(arg1, types::I64);
1676         assert_eq!(dfg.value_type(arg1), types::F32);
1677         assert_eq!(dfg.value_type(new1), types::I64);
1678         assert_eq!(dfg.block_params(block), &[new1]);
1679 
1680         dfg.attach_block_param(block, arg1);
1681         assert_eq!(dfg.block_params(block), &[new1, arg1]);
1682 
1683         let new2 = dfg.replace_block_param(arg1, types::I8);
1684         assert_eq!(dfg.value_type(arg1), types::F32);
1685         assert_eq!(dfg.value_type(new2), types::I8);
1686         assert_eq!(dfg.block_params(block), &[new1, new2]);
1687 
1688         dfg.attach_block_param(block, arg1);
1689         assert_eq!(dfg.block_params(block), &[new1, new2, arg1]);
1690 
1691         let new3 = dfg.replace_block_param(new2, types::I16);
1692         assert_eq!(dfg.value_type(new1), types::I64);
1693         assert_eq!(dfg.value_type(new2), types::I8);
1694         assert_eq!(dfg.value_type(new3), types::I16);
1695         assert_eq!(dfg.block_params(block), &[new1, new3, arg1]);
1696     }
1697 
1698     #[test]
1699     fn swap_remove_block_params() {
1700         let mut dfg = DataFlowGraph::new();
1701 
1702         let block = dfg.make_block();
1703         let arg1 = dfg.append_block_param(block, types::F32);
1704         let arg2 = dfg.append_block_param(block, types::F32);
1705         let arg3 = dfg.append_block_param(block, types::F32);
1706         assert_eq!(dfg.block_params(block), &[arg1, arg2, arg3]);
1707 
1708         dfg.swap_remove_block_param(arg1);
1709         assert_eq!(dfg.value_is_attached(arg1), false);
1710         assert_eq!(dfg.value_is_attached(arg2), true);
1711         assert_eq!(dfg.value_is_attached(arg3), true);
1712         assert_eq!(dfg.block_params(block), &[arg3, arg2]);
1713         dfg.swap_remove_block_param(arg2);
1714         assert_eq!(dfg.value_is_attached(arg2), false);
1715         assert_eq!(dfg.value_is_attached(arg3), true);
1716         assert_eq!(dfg.block_params(block), &[arg3]);
1717         dfg.swap_remove_block_param(arg3);
1718         assert_eq!(dfg.value_is_attached(arg3), false);
1719         assert_eq!(dfg.block_params(block), &[]);
1720     }
1721 
1722     #[test]
1723     fn aliases() {
1724         use crate::ir::condcodes::IntCC;
1725         use crate::ir::InstBuilder;
1726 
1727         let mut func = Function::new();
1728         let block0 = func.dfg.make_block();
1729         let mut pos = FuncCursor::new(&mut func);
1730         pos.insert_block(block0);
1731 
1732         // Build a little test program.
1733         let v1 = pos.ins().iconst(types::I32, 42);
1734 
1735         // Make sure we can resolve value aliases even when values is empty.
1736         assert_eq!(pos.func.dfg.resolve_aliases(v1), v1);
1737 
1738         let arg0 = pos.func.dfg.append_block_param(block0, types::I32);
1739         let (s, c) = pos.ins().uadd_overflow(v1, arg0);
1740         let iadd = match pos.func.dfg.value_def(s) {
1741             ValueDef::Result(i, 0) => i,
1742             _ => panic!(),
1743         };
1744 
1745         // Remove `c` from the result list.
1746         pos.func.stencil.dfg.results[iadd].remove(1, &mut pos.func.stencil.dfg.value_lists);
1747 
1748         // Replace `uadd_overflow` with a normal `iadd` and an `icmp`.
1749         pos.func.dfg.replace(iadd).iadd(v1, arg0);
1750         let c2 = pos.ins().icmp(IntCC::Equal, s, v1);
1751         pos.func.dfg.change_to_alias(c, c2);
1752 
1753         assert_eq!(pos.func.dfg.resolve_aliases(c2), c2);
1754         assert_eq!(pos.func.dfg.resolve_aliases(c), c2);
1755     }
1756 
1757     #[test]
1758     fn cloning() {
1759         use crate::ir::InstBuilder;
1760 
1761         let mut func = Function::new();
1762         let mut sig = Signature::new(crate::isa::CallConv::SystemV);
1763         sig.params.push(ir::AbiParam::new(types::I32));
1764         let sig = func.import_signature(sig);
1765         let block0 = func.dfg.make_block();
1766         let mut pos = FuncCursor::new(&mut func);
1767         pos.insert_block(block0);
1768         let v1 = pos.ins().iconst(types::I32, 0);
1769         let v2 = pos.ins().iconst(types::I32, 1);
1770         let call_inst = pos.ins().call_indirect(sig, v1, &[v1]);
1771         let func = pos.func;
1772 
1773         let call_inst_dup = func.dfg.clone_inst(call_inst);
1774         func.dfg.inst_args_mut(call_inst)[0] = v2;
1775         assert_eq!(v1, func.dfg.inst_args(call_inst_dup)[0]);
1776     }
1777 }
1778