wip
[bigint-presentation-code.git] / register_allocator / src / fuzzing.rs
index 2091a50ae5182fc1e7f0a40fdd85ec8f0a524fcb..da4340199567dfcc66d6a815ba40b94b9de37f7a 100644 (file)
@@ -1,16 +1,22 @@
+use std::{collections::BTreeMap, num::NonZeroUsize};
+
 use crate::{
-    function::{Block, FnFields, SSAVal, SSAValDef},
-    index::{BlockIdx, SSAValIdx},
+    function::{Block, BlockTermInstKind, FnFields, Inst, InstKind, Operand, SSAVal, SSAValDef},
+    index::{BlockIdx, InstIdx, InstRange, SSAValIdx},
+    interned::{GlobalState, Intern},
     loc::Ty,
+    loc_set::LocSet,
 };
 use arbitrary::{Arbitrary, Error, Unstructured};
+use petgraph::algo::dominators;
 
-struct FnBuilder<'a, 'b> {
+struct FnBuilder<'a, 'b, 'g> {
+    global_state: &'g GlobalState,
     u: &'a mut Unstructured<'b>,
     func: FnFields,
 }
 
-impl FnBuilder<'_, '_> {
+impl FnBuilder<'_, '_, '_> {
     fn new_ssa_val(&mut self, ty: Ty, def: SSAValDef) -> SSAValIdx {
         let retval = SSAValIdx::new(self.func.ssa_vals.len());
         self.func.ssa_vals.push(SSAVal {
@@ -21,8 +27,29 @@ impl FnBuilder<'_, '_> {
         });
         retval
     }
+    fn new_inst_in_last_block(
+        &mut self,
+        kind: InstKind,
+        operands: Vec<Operand>,
+        clobbers: LocSet,
+    ) -> InstIdx {
+        let block = self.func.blocks.last_mut().expect("no block");
+        let inst_idx = block.insts.end;
+        assert_eq!(inst_idx.get(), self.func.insts.len());
+        block.insts.end = block.insts.end.next();
+        self.func.insts.push(Inst {
+            kind,
+            operands,
+            clobbers: clobbers.into_interned(self.global_state),
+        });
+        inst_idx
+    }
+    fn make_ssa_val_use(&mut self) -> Result<SSAValIdx, Error> {
+        todo!()
+    }
     fn run(&mut self) -> Result<(), Error> {
-        for block_idx in 0..self.u.int_in_range(1..=10)? {
+        let block_count = self.u.int_in_range(1..=10u16)?;
+        for block_idx in 0..block_count as usize {
             let block_idx = BlockIdx::new(block_idx);
             let mut params = Vec::new();
             for param_idx in 0..self.u.int_in_range(0..=10)? {
@@ -35,13 +62,73 @@ impl FnBuilder<'_, '_> {
                     },
                 ));
             }
-            let insts = todo!();
+            let end = InstIdx::new(self.func.insts.len());
             self.func.blocks.push(Block {
                 params,
-                insts,
+                insts: InstRange { start: end, end },
                 preds: Default::default(),
                 immediate_dominator: Default::default(),
             });
+            for _ in 0..self.u.int_in_range(0..=10)? {
+                self.new_inst_in_last_block(InstKind::Normal, vec![], self.u.arbitrary()?);
+            }
+            let mut succs_and_params = BTreeMap::default();
+            let succ_range = BlockIdx::ENTRY_BLOCK.get() as u16..=(block_count - 1);
+            if !succ_range.is_empty() {
+                for i in 0..self.u.int_in_range(0..=3usize)? {
+                    if i > succ_range.len() {
+                        break;
+                    }
+                    let succ = BlockIdx::new(self.u.int_in_range(succ_range)?.into());
+                    succs_and_params.insert(succ, vec![]);
+                }
+            }
+            let mut operands = vec![];
+            for _ in 0..self.u.int_in_range(0..=5)? {
+                operands.push(Operand {
+                    ssa_val: todo!(),
+                    kind_and_constraint: todo!(),
+                    stage: todo!(),
+                });
+            }
+            self.new_inst_in_last_block(
+                InstKind::BlockTerm(BlockTermInstKind { succs_and_params }),
+                operands,
+                self.u.arbitrary()?,
+            );
+        }
+        let dominators = dominators::simple_fast(&self.func, BlockIdx::ENTRY_BLOCK);
+        for block_idx in 0..self.func.blocks.len() {
+            let block_idx = BlockIdx::new(block_idx);
+            self.func.blocks[block_idx].immediate_dominator =
+                dominators.immediate_dominator(block_idx);
+            let term_idx = self
+                .func
+                .try_get_block_term_inst_idx(block_idx)
+                .expect("known to have block term inst");
+            let successors = self.func.insts[term_idx]
+                .kind
+                .block_term()
+                .expect("known to have block term inst")
+                .succs_and_params
+                .keys()
+                .copied();
+            for succ in successors {
+                self.func.blocks[succ].preds.insert(block_idx);
+            }
+            for inst_idx in self.func.blocks[block_idx].insts {
+                let inst = &mut self.func.insts[inst_idx];
+                match &mut inst.kind {
+                    InstKind::Normal => {
+                        let _;
+                        todo!()
+                    }
+                    InstKind::Copy(_) => unreachable!(),
+                    InstKind::BlockTerm(block_term_inst_kind) => {
+                        for (&succ, params) in &mut block_term_inst_kind.succs_and_params {}
+                    }
+                }
+            }
         }
         Ok(())
     }
@@ -49,16 +136,19 @@ impl FnBuilder<'_, '_> {
 
 impl<'a> Arbitrary<'a> for FnFields {
     fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> {
-        let mut builder = FnBuilder {
-            u,
-            func: Self {
-                ssa_vals: Vec::new(),
-                insts: Vec::new(),
-                blocks: Vec::new(),
-                start_inst_to_block_map: Default::default(),
-            },
-        };
-        builder.run()?;
-        Ok(builder.func)
+        GlobalState::get(|global_state| {
+            let mut builder = FnBuilder {
+                global_state,
+                u,
+                func: Self {
+                    ssa_vals: Vec::new(),
+                    insts: Vec::new(),
+                    blocks: Vec::new(),
+                    start_inst_to_block_map: Default::default(),
+                },
+            };
+            builder.run()?;
+            Ok(builder.func)
+        })
     }
 }