diff --git a/lib/cretonne/src/entity_list.rs b/lib/cretonne/src/entity_list.rs index 0b90265470..d6f0e49119 100644 --- a/lib/cretonne/src/entity_list.rs +++ b/lib/cretonne/src/entity_list.rs @@ -222,6 +222,11 @@ impl ListPool { } impl EntityList { + /// Create a new empty list. + pub fn new() -> Self { + Default::default() + } + /// Returns `true` if the list has a length of 0. pub fn is_empty(&self) -> bool { // 0 is a magic value for the empty list. Any list in the pool array must have a positive diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 22ce7a116d..ffa842e5a5 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -1,6 +1,6 @@ //! Data flow graph tracking Instructions, Values, and EBBs. -use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueListPool}; +use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueListPool}; use ir::entities::ExpandedValue; use ir::instructions::{Opcode, InstructionData, CallInfo}; use ir::extfunc::ExtFuncData; @@ -687,17 +687,7 @@ impl DataFlowGraph { /// Get the number of arguments on `ebb`. pub fn num_ebb_args(&self, ebb: Ebb) -> usize { - match self.ebbs[ebb].last_arg.expand() { - None => 0, - Some(last_arg) => { - if let ExpandedValue::Table(idx) = last_arg.expand() { - if let ValueData::Arg { num, .. } = self.extended_values[idx] { - return num as usize + 1; - } - } - panic!("inconsistent value table entry for EBB argument"); - } - } + self.ebbs[ebb].args.len(&self.value_lists) } /// Append an argument with type `ty` to `ebb`. @@ -712,12 +702,9 @@ impl DataFlowGraph { val } - /// Iterate through the arguments to an EBB. - pub fn ebb_args(&self, ebb: Ebb) -> Values { - Values { - dfg: self, - cur: self.ebbs[ebb].first_arg.into(), - } + /// Get the arguments to an EBB. + pub fn ebb_args(&self, ebb: Ebb) -> &[Value] { + self.ebbs[ebb].args.as_slice(&self.value_lists) } /// Replace an EBB argument with a new value of type `ty`. @@ -752,6 +739,8 @@ impl DataFlowGraph { old_data); }; + self.ebbs[ebb].args.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg; + // Now fix up the linked lists. if self.ebbs[ebb].last_arg.expand() == Some(old_arg) { self.ebbs[ebb].last_arg = new_arg.into(); @@ -804,6 +793,7 @@ impl DataFlowGraph { let first = self.ebbs[ebb].first_arg.into(); self.ebbs[ebb].first_arg = None.into(); self.ebbs[ebb].last_arg = None.into(); + self.ebbs[ebb].args.clear(&mut self.value_lists); first } @@ -815,6 +805,7 @@ impl DataFlowGraph { /// /// In almost all cases, you should be using `append_ebb_arg()` instead of this method. pub fn attach_ebb_arg(&mut self, ebb: Ebb, arg: Value) { + self.ebbs[ebb].args.push(arg, &mut self.value_lists); let arg_num = match self.ebbs[ebb].last_arg.map(|v| v.expand()) { // If last_argument is `None`, we're adding the first EBB argument. None => { @@ -861,6 +852,9 @@ impl DataFlowGraph { // match the function arguments. #[derive(Clone)] struct EbbData { + // List of arguments to this EBB. + args: ValueList, + // First argument to this EBB, or `None` if the block has no arguments. // // The arguments are all `ValueData::Argument` entries that form a linked list from `first_arg` @@ -874,6 +868,7 @@ struct EbbData { impl EbbData { fn new() -> EbbData { EbbData { + args: ValueList::new(), first_arg: None.into(), last_arg: None.into(), } @@ -966,28 +961,20 @@ mod tests { let ebb = dfg.make_ebb(); assert_eq!(ebb.to_string(), "ebb0"); assert_eq!(dfg.num_ebb_args(ebb), 0); - assert_eq!(dfg.ebb_args(ebb).next(), None); + assert_eq!(dfg.ebb_args(ebb), &[]); assert_eq!(dfg.detach_ebb_args(ebb), None); assert_eq!(dfg.num_ebb_args(ebb), 0); - assert_eq!(dfg.ebb_args(ebb).next(), None); + assert_eq!(dfg.ebb_args(ebb), &[]); let arg1 = dfg.append_ebb_arg(ebb, types::F32); assert_eq!(arg1.to_string(), "vx0"); assert_eq!(dfg.num_ebb_args(ebb), 1); - { - let mut args1 = dfg.ebb_args(ebb); - assert_eq!(args1.next(), Some(arg1)); - assert_eq!(args1.next(), None); - } + assert_eq!(dfg.ebb_args(ebb), &[arg1]); + let arg2 = dfg.append_ebb_arg(ebb, types::I16); assert_eq!(arg2.to_string(), "vx1"); assert_eq!(dfg.num_ebb_args(ebb), 2); - { - let mut args2 = dfg.ebb_args(ebb); - assert_eq!(args2.next(), Some(arg1)); - assert_eq!(args2.next(), Some(arg2)); - assert_eq!(args2.next(), None); - } + assert_eq!(dfg.ebb_args(ebb), &[arg1, arg2]); assert_eq!(dfg.value_def(arg1), ValueDef::Arg(ebb, 0)); assert_eq!(dfg.value_def(arg2), ValueDef::Arg(ebb, 1)); @@ -997,7 +984,7 @@ mod tests { // Swap the two EBB arguments. let take1 = dfg.detach_ebb_args(ebb).unwrap(); assert_eq!(dfg.num_ebb_args(ebb), 0); - assert_eq!(dfg.ebb_args(ebb).next(), None); + assert_eq!(dfg.ebb_args(ebb), &[]); let take2 = dfg.next_ebb_arg(take1).unwrap(); assert_eq!(take1, arg1); assert_eq!(take2, arg2); @@ -1005,7 +992,7 @@ mod tests { dfg.attach_ebb_arg(ebb, take2); let arg3 = dfg.append_ebb_arg(ebb, types::I32); dfg.attach_ebb_arg(ebb, take1); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [take2, arg3, take1]); + assert_eq!(dfg.ebb_args(ebb), &[take2, arg3, take1]); } #[test] @@ -1018,24 +1005,24 @@ mod tests { let new1 = dfg.replace_ebb_arg(arg1, types::I64); assert_eq!(dfg.value_type(arg1), types::F32); assert_eq!(dfg.value_type(new1), types::I64); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [new1]); + assert_eq!(dfg.ebb_args(ebb), &[new1]); dfg.attach_ebb_arg(ebb, arg1); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [new1, arg1]); + assert_eq!(dfg.ebb_args(ebb), &[new1, arg1]); let new2 = dfg.replace_ebb_arg(arg1, types::I8); assert_eq!(dfg.value_type(arg1), types::F32); assert_eq!(dfg.value_type(new2), types::I8); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [new1, new2]); + assert_eq!(dfg.ebb_args(ebb), &[new1, new2]); dfg.attach_ebb_arg(ebb, arg1); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [new1, new2, arg1]); + assert_eq!(dfg.ebb_args(ebb), &[new1, new2, arg1]); let new3 = dfg.replace_ebb_arg(new2, types::I16); assert_eq!(dfg.value_type(new1), types::I64); assert_eq!(dfg.value_type(new2), types::I8); assert_eq!(dfg.value_type(new3), types::I16); - assert_eq!(dfg.ebb_args(ebb).collect::>(), [new1, new3, arg1]); + assert_eq!(dfg.ebb_args(ebb), &[new1, new3, arg1]); } #[test] diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index 75b18ef019..458fe14e26 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -182,7 +182,7 @@ impl LiveValueTracker { // Now add all the live arguments to `ebb`. let first_arg = self.live.values.len(); - for value in dfg.ebb_args(ebb) { + for &value in dfg.ebb_args(ebb) { let lr = liveness .get(value) .expect("EBB argument value has no live range"); diff --git a/lib/cretonne/src/verifier.rs b/lib/cretonne/src/verifier.rs index e6dbf4c86d..371ada0440 100644 --- a/lib/cretonne/src/verifier.rs +++ b/lib/cretonne/src/verifier.rs @@ -151,7 +151,7 @@ impl<'a> Verifier<'a> { } // Arguments belong to the correct ebb. - for arg in self.func.dfg.ebb_args(ebb) { + for &arg in self.func.dfg.ebb_args(ebb) { match self.func.dfg.value_def(arg) { ValueDef::Arg(arg_ebb, _) => { if ebb != arg_ebb { @@ -405,7 +405,7 @@ impl<'a> Verifier<'a> { return err!(ebb, "entry block arguments must match function signature"); } - for (i, arg) in self.func.dfg.ebb_args(ebb).enumerate() { + for (i, &arg) in self.func.dfg.ebb_args(ebb).iter().enumerate() { let arg_type = self.func.dfg.value_type(arg); if arg_type != expected_types[i].value_type { return err!(ebb, @@ -510,7 +510,8 @@ impl<'a> Verifier<'a> { let iter = self.func .dfg .ebb_args(ebb) - .map(|v| self.func.dfg.value_type(v)); + .iter() + .map(|&v| self.func.dfg.value_type(v)); self.typecheck_variable_args_iterator(inst, iter)?; } BranchInfo::Table(table) => { diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index bc9299d796..09a4410f43 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -95,7 +95,7 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result { write!(w, " ")?; } - let mut args = func.dfg.ebb_args(ebb); + let mut args = func.dfg.ebb_args(ebb).iter().cloned(); match args.next() { None => return writeln!(w, "{}:", ebb), Some(arg) => { diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index a0e1f71719..a0302a1a30 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -1895,13 +1895,12 @@ mod tests { let mut ebbs = func.layout.ebbs(); let ebb0 = ebbs.next().unwrap(); - assert_eq!(func.dfg.ebb_args(ebb0).next(), None); + assert_eq!(func.dfg.ebb_args(ebb0), &[]); let ebb4 = ebbs.next().unwrap(); - let mut ebb4_args = func.dfg.ebb_args(ebb4); - let arg0 = ebb4_args.next().unwrap(); - assert_eq!(func.dfg.value_type(arg0), types::I32); - assert_eq!(ebb4_args.next(), None); + let ebb4_args = func.dfg.ebb_args(ebb4); + assert_eq!(ebb4_args.len(), 1); + assert_eq!(func.dfg.value_type(ebb4_args[0]), types::I32); } #[test]