Keep EBB arguments in a ValueList.
This is the first step of the value list refactoring which will replace linked lists of values with value lists. - Keep a ValueList in the EbbData struct containing all the EBB arguments. - Change dfg.ebb_args() to return a slice instead of an iterator. This leaves us in a temporary hybrid state where we maintain both a linked list and a ValueList vector of the EBB arguments.
This commit is contained in:
@@ -222,6 +222,11 @@ impl<T: EntityRef> ListPool<T> {
|
||||
}
|
||||
|
||||
impl<T: EntityRef> EntityList<T> {
|
||||
/// 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
|
||||
|
||||
@@ -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::<Vec<_>>(), [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::<Vec<_>>(), [new1]);
|
||||
assert_eq!(dfg.ebb_args(ebb), &[new1]);
|
||||
|
||||
dfg.attach_ebb_arg(ebb, arg1);
|
||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [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::<Vec<_>>(), [new1, new2]);
|
||||
assert_eq!(dfg.ebb_args(ebb), &[new1, new2]);
|
||||
|
||||
dfg.attach_ebb_arg(ebb, arg1);
|
||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [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::<Vec<_>>(), [new1, new3, arg1]);
|
||||
assert_eq!(dfg.ebb_args(ebb), &[new1, new3, arg1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user