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> {
|
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.
|
/// Returns `true` if the list has a length of 0.
|
||||||
pub fn is_empty(&self) -> bool {
|
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
|
// 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.
|
//! 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::entities::ExpandedValue;
|
||||||
use ir::instructions::{Opcode, InstructionData, CallInfo};
|
use ir::instructions::{Opcode, InstructionData, CallInfo};
|
||||||
use ir::extfunc::ExtFuncData;
|
use ir::extfunc::ExtFuncData;
|
||||||
@@ -687,17 +687,7 @@ impl DataFlowGraph {
|
|||||||
|
|
||||||
/// Get the number of arguments on `ebb`.
|
/// Get the number of arguments on `ebb`.
|
||||||
pub fn num_ebb_args(&self, ebb: Ebb) -> usize {
|
pub fn num_ebb_args(&self, ebb: Ebb) -> usize {
|
||||||
match self.ebbs[ebb].last_arg.expand() {
|
self.ebbs[ebb].args.len(&self.value_lists)
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append an argument with type `ty` to `ebb`.
|
/// Append an argument with type `ty` to `ebb`.
|
||||||
@@ -712,12 +702,9 @@ impl DataFlowGraph {
|
|||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate through the arguments to an EBB.
|
/// Get the arguments to an EBB.
|
||||||
pub fn ebb_args(&self, ebb: Ebb) -> Values {
|
pub fn ebb_args(&self, ebb: Ebb) -> &[Value] {
|
||||||
Values {
|
self.ebbs[ebb].args.as_slice(&self.value_lists)
|
||||||
dfg: self,
|
|
||||||
cur: self.ebbs[ebb].first_arg.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace an EBB argument with a new value of type `ty`.
|
/// Replace an EBB argument with a new value of type `ty`.
|
||||||
@@ -752,6 +739,8 @@ impl DataFlowGraph {
|
|||||||
old_data);
|
old_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.ebbs[ebb].args.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
|
||||||
|
|
||||||
// Now fix up the linked lists.
|
// Now fix up the linked lists.
|
||||||
if self.ebbs[ebb].last_arg.expand() == Some(old_arg) {
|
if self.ebbs[ebb].last_arg.expand() == Some(old_arg) {
|
||||||
self.ebbs[ebb].last_arg = new_arg.into();
|
self.ebbs[ebb].last_arg = new_arg.into();
|
||||||
@@ -804,6 +793,7 @@ impl DataFlowGraph {
|
|||||||
let first = self.ebbs[ebb].first_arg.into();
|
let first = self.ebbs[ebb].first_arg.into();
|
||||||
self.ebbs[ebb].first_arg = None.into();
|
self.ebbs[ebb].first_arg = None.into();
|
||||||
self.ebbs[ebb].last_arg = None.into();
|
self.ebbs[ebb].last_arg = None.into();
|
||||||
|
self.ebbs[ebb].args.clear(&mut self.value_lists);
|
||||||
first
|
first
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,6 +805,7 @@ impl DataFlowGraph {
|
|||||||
///
|
///
|
||||||
/// In almost all cases, you should be using `append_ebb_arg()` instead of this method.
|
/// 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) {
|
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()) {
|
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.
|
// If last_argument is `None`, we're adding the first EBB argument.
|
||||||
None => {
|
None => {
|
||||||
@@ -861,6 +852,9 @@ impl DataFlowGraph {
|
|||||||
// match the function arguments.
|
// match the function arguments.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct EbbData {
|
struct EbbData {
|
||||||
|
// List of arguments to this EBB.
|
||||||
|
args: ValueList,
|
||||||
|
|
||||||
// First argument to this EBB, or `None` if the block has no arguments.
|
// 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`
|
// The arguments are all `ValueData::Argument` entries that form a linked list from `first_arg`
|
||||||
@@ -874,6 +868,7 @@ struct EbbData {
|
|||||||
impl EbbData {
|
impl EbbData {
|
||||||
fn new() -> EbbData {
|
fn new() -> EbbData {
|
||||||
EbbData {
|
EbbData {
|
||||||
|
args: ValueList::new(),
|
||||||
first_arg: None.into(),
|
first_arg: None.into(),
|
||||||
last_arg: None.into(),
|
last_arg: None.into(),
|
||||||
}
|
}
|
||||||
@@ -966,28 +961,20 @@ mod tests {
|
|||||||
let ebb = dfg.make_ebb();
|
let ebb = dfg.make_ebb();
|
||||||
assert_eq!(ebb.to_string(), "ebb0");
|
assert_eq!(ebb.to_string(), "ebb0");
|
||||||
assert_eq!(dfg.num_ebb_args(ebb), 0);
|
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.detach_ebb_args(ebb), None);
|
||||||
assert_eq!(dfg.num_ebb_args(ebb), 0);
|
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);
|
let arg1 = dfg.append_ebb_arg(ebb, types::F32);
|
||||||
assert_eq!(arg1.to_string(), "vx0");
|
assert_eq!(arg1.to_string(), "vx0");
|
||||||
assert_eq!(dfg.num_ebb_args(ebb), 1);
|
assert_eq!(dfg.num_ebb_args(ebb), 1);
|
||||||
{
|
assert_eq!(dfg.ebb_args(ebb), &[arg1]);
|
||||||
let mut args1 = dfg.ebb_args(ebb);
|
|
||||||
assert_eq!(args1.next(), Some(arg1));
|
|
||||||
assert_eq!(args1.next(), None);
|
|
||||||
}
|
|
||||||
let arg2 = dfg.append_ebb_arg(ebb, types::I16);
|
let arg2 = dfg.append_ebb_arg(ebb, types::I16);
|
||||||
assert_eq!(arg2.to_string(), "vx1");
|
assert_eq!(arg2.to_string(), "vx1");
|
||||||
assert_eq!(dfg.num_ebb_args(ebb), 2);
|
assert_eq!(dfg.num_ebb_args(ebb), 2);
|
||||||
{
|
assert_eq!(dfg.ebb_args(ebb), &[arg1, arg2]);
|
||||||
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.value_def(arg1), ValueDef::Arg(ebb, 0));
|
assert_eq!(dfg.value_def(arg1), ValueDef::Arg(ebb, 0));
|
||||||
assert_eq!(dfg.value_def(arg2), ValueDef::Arg(ebb, 1));
|
assert_eq!(dfg.value_def(arg2), ValueDef::Arg(ebb, 1));
|
||||||
@@ -997,7 +984,7 @@ mod tests {
|
|||||||
// Swap the two EBB arguments.
|
// Swap the two EBB arguments.
|
||||||
let take1 = dfg.detach_ebb_args(ebb).unwrap();
|
let take1 = dfg.detach_ebb_args(ebb).unwrap();
|
||||||
assert_eq!(dfg.num_ebb_args(ebb), 0);
|
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();
|
let take2 = dfg.next_ebb_arg(take1).unwrap();
|
||||||
assert_eq!(take1, arg1);
|
assert_eq!(take1, arg1);
|
||||||
assert_eq!(take2, arg2);
|
assert_eq!(take2, arg2);
|
||||||
@@ -1005,7 +992,7 @@ mod tests {
|
|||||||
dfg.attach_ebb_arg(ebb, take2);
|
dfg.attach_ebb_arg(ebb, take2);
|
||||||
let arg3 = dfg.append_ebb_arg(ebb, types::I32);
|
let arg3 = dfg.append_ebb_arg(ebb, types::I32);
|
||||||
dfg.attach_ebb_arg(ebb, take1);
|
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]
|
#[test]
|
||||||
@@ -1018,24 +1005,24 @@ mod tests {
|
|||||||
let new1 = dfg.replace_ebb_arg(arg1, types::I64);
|
let new1 = dfg.replace_ebb_arg(arg1, types::I64);
|
||||||
assert_eq!(dfg.value_type(arg1), types::F32);
|
assert_eq!(dfg.value_type(arg1), types::F32);
|
||||||
assert_eq!(dfg.value_type(new1), types::I64);
|
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);
|
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);
|
let new2 = dfg.replace_ebb_arg(arg1, types::I8);
|
||||||
assert_eq!(dfg.value_type(arg1), types::F32);
|
assert_eq!(dfg.value_type(arg1), types::F32);
|
||||||
assert_eq!(dfg.value_type(new2), types::I8);
|
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);
|
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);
|
let new3 = dfg.replace_ebb_arg(new2, types::I16);
|
||||||
assert_eq!(dfg.value_type(new1), types::I64);
|
assert_eq!(dfg.value_type(new1), types::I64);
|
||||||
assert_eq!(dfg.value_type(new2), types::I8);
|
assert_eq!(dfg.value_type(new2), types::I8);
|
||||||
assert_eq!(dfg.value_type(new3), types::I16);
|
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]
|
#[test]
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ impl LiveValueTracker {
|
|||||||
|
|
||||||
// Now add all the live arguments to `ebb`.
|
// Now add all the live arguments to `ebb`.
|
||||||
let first_arg = self.live.values.len();
|
let first_arg = self.live.values.len();
|
||||||
for value in dfg.ebb_args(ebb) {
|
for &value in dfg.ebb_args(ebb) {
|
||||||
let lr = liveness
|
let lr = liveness
|
||||||
.get(value)
|
.get(value)
|
||||||
.expect("EBB argument value has no live range");
|
.expect("EBB argument value has no live range");
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ impl<'a> Verifier<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Arguments belong to the correct ebb.
|
// 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) {
|
match self.func.dfg.value_def(arg) {
|
||||||
ValueDef::Arg(arg_ebb, _) => {
|
ValueDef::Arg(arg_ebb, _) => {
|
||||||
if ebb != arg_ebb {
|
if ebb != arg_ebb {
|
||||||
@@ -405,7 +405,7 @@ impl<'a> Verifier<'a> {
|
|||||||
return err!(ebb, "entry block arguments must match function signature");
|
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);
|
let arg_type = self.func.dfg.value_type(arg);
|
||||||
if arg_type != expected_types[i].value_type {
|
if arg_type != expected_types[i].value_type {
|
||||||
return err!(ebb,
|
return err!(ebb,
|
||||||
@@ -510,7 +510,8 @@ impl<'a> Verifier<'a> {
|
|||||||
let iter = self.func
|
let iter = self.func
|
||||||
.dfg
|
.dfg
|
||||||
.ebb_args(ebb)
|
.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)?;
|
self.typecheck_variable_args_iterator(inst, iter)?;
|
||||||
}
|
}
|
||||||
BranchInfo::Table(table) => {
|
BranchInfo::Table(table) => {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
|
|||||||
write!(w, " ")?;
|
write!(w, " ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut args = func.dfg.ebb_args(ebb);
|
let mut args = func.dfg.ebb_args(ebb).iter().cloned();
|
||||||
match args.next() {
|
match args.next() {
|
||||||
None => return writeln!(w, "{}:", ebb),
|
None => return writeln!(w, "{}:", ebb),
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
|
|||||||
@@ -1895,13 +1895,12 @@ mod tests {
|
|||||||
let mut ebbs = func.layout.ebbs();
|
let mut ebbs = func.layout.ebbs();
|
||||||
|
|
||||||
let ebb0 = ebbs.next().unwrap();
|
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 ebb4 = ebbs.next().unwrap();
|
||||||
let mut ebb4_args = func.dfg.ebb_args(ebb4);
|
let ebb4_args = func.dfg.ebb_args(ebb4);
|
||||||
let arg0 = ebb4_args.next().unwrap();
|
assert_eq!(ebb4_args.len(), 1);
|
||||||
assert_eq!(func.dfg.value_type(arg0), types::I32);
|
assert_eq!(func.dfg.value_type(ebb4_args[0]), types::I32);
|
||||||
assert_eq!(ebb4_args.next(), None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user