Update rustfmt to 0.9.0.
This commit is contained in:
@@ -89,7 +89,8 @@ impl<'f, IIB: InstInserterBase<'f>> InsertBuilder<'f, IIB> {
|
||||
///
|
||||
/// The `reuse` argument is expected to be an array of `Option<Value>`.
|
||||
pub fn with_results<Array>(self, reuse: Array) -> InsertReuseBuilder<'f, IIB, Array>
|
||||
where Array: AsRef<[Option<Value>]>
|
||||
where
|
||||
Array: AsRef<[Option<Value>]>,
|
||||
{
|
||||
InsertReuseBuilder {
|
||||
inserter: self.inserter,
|
||||
@@ -134,8 +135,9 @@ impl<'f, IIB: InstInserterBase<'f>> InstBuilderBase<'f> for InsertBuilder<'f, II
|
||||
|
||||
/// Builder that inserts a new instruction like `InsertBuilder`, but reusing result values.
|
||||
pub struct InsertReuseBuilder<'f, IIB, Array>
|
||||
where IIB: InstInserterBase<'f>,
|
||||
Array: AsRef<[Option<Value>]>
|
||||
where
|
||||
IIB: InstInserterBase<'f>,
|
||||
Array: AsRef<[Option<Value>]>,
|
||||
{
|
||||
inserter: IIB,
|
||||
reuse: Array,
|
||||
|
||||
@@ -89,17 +89,17 @@ impl Display for IntCC {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use self::IntCC::*;
|
||||
f.write_str(match *self {
|
||||
Equal => "eq",
|
||||
NotEqual => "ne",
|
||||
SignedGreaterThan => "sgt",
|
||||
SignedGreaterThanOrEqual => "sge",
|
||||
SignedLessThan => "slt",
|
||||
SignedLessThanOrEqual => "sle",
|
||||
UnsignedGreaterThan => "ugt",
|
||||
UnsignedGreaterThanOrEqual => "uge",
|
||||
UnsignedLessThan => "ult",
|
||||
UnsignedLessThanOrEqual => "ule",
|
||||
})
|
||||
Equal => "eq",
|
||||
NotEqual => "ne",
|
||||
SignedGreaterThan => "sgt",
|
||||
SignedGreaterThanOrEqual => "sge",
|
||||
SignedLessThan => "slt",
|
||||
SignedLessThanOrEqual => "sle",
|
||||
UnsignedGreaterThan => "ugt",
|
||||
UnsignedGreaterThanOrEqual => "uge",
|
||||
UnsignedLessThan => "ult",
|
||||
UnsignedLessThanOrEqual => "ule",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,21 +220,21 @@ impl Display for FloatCC {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use self::FloatCC::*;
|
||||
f.write_str(match *self {
|
||||
Ordered => "ord",
|
||||
Unordered => "uno",
|
||||
Equal => "eq",
|
||||
NotEqual => "ne",
|
||||
OrderedNotEqual => "one",
|
||||
UnorderedOrEqual => "ueq",
|
||||
LessThan => "lt",
|
||||
LessThanOrEqual => "le",
|
||||
GreaterThan => "gt",
|
||||
GreaterThanOrEqual => "ge",
|
||||
UnorderedOrLessThan => "ult",
|
||||
UnorderedOrLessThanOrEqual => "ule",
|
||||
UnorderedOrGreaterThan => "ugt",
|
||||
UnorderedOrGreaterThanOrEqual => "uge",
|
||||
})
|
||||
Ordered => "ord",
|
||||
Unordered => "uno",
|
||||
Equal => "eq",
|
||||
NotEqual => "ne",
|
||||
OrderedNotEqual => "one",
|
||||
UnorderedOrEqual => "ueq",
|
||||
LessThan => "lt",
|
||||
LessThanOrEqual => "le",
|
||||
GreaterThan => "gt",
|
||||
GreaterThanOrEqual => "ge",
|
||||
UnorderedOrLessThan => "ult",
|
||||
UnorderedOrLessThanOrEqual => "ule",
|
||||
UnorderedOrGreaterThan => "ugt",
|
||||
UnorderedOrGreaterThanOrEqual => "uge",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,16 +267,18 @@ impl FromStr for FloatCC {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
static INT_ALL: [IntCC; 10] = [IntCC::Equal,
|
||||
IntCC::NotEqual,
|
||||
IntCC::SignedLessThan,
|
||||
IntCC::SignedGreaterThanOrEqual,
|
||||
IntCC::SignedGreaterThan,
|
||||
IntCC::SignedLessThanOrEqual,
|
||||
IntCC::UnsignedLessThan,
|
||||
IntCC::UnsignedGreaterThanOrEqual,
|
||||
IntCC::UnsignedGreaterThan,
|
||||
IntCC::UnsignedLessThanOrEqual];
|
||||
static INT_ALL: [IntCC; 10] = [
|
||||
IntCC::Equal,
|
||||
IntCC::NotEqual,
|
||||
IntCC::SignedLessThan,
|
||||
IntCC::SignedGreaterThanOrEqual,
|
||||
IntCC::SignedGreaterThan,
|
||||
IntCC::SignedLessThanOrEqual,
|
||||
IntCC::UnsignedLessThan,
|
||||
IntCC::UnsignedGreaterThanOrEqual,
|
||||
IntCC::UnsignedGreaterThan,
|
||||
IntCC::UnsignedLessThanOrEqual,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn int_inverse() {
|
||||
@@ -306,20 +308,22 @@ mod tests {
|
||||
assert_eq!("bogus".parse::<IntCC>(), Err(()));
|
||||
}
|
||||
|
||||
static FLOAT_ALL: [FloatCC; 14] = [FloatCC::Ordered,
|
||||
FloatCC::Unordered,
|
||||
FloatCC::Equal,
|
||||
FloatCC::NotEqual,
|
||||
FloatCC::OrderedNotEqual,
|
||||
FloatCC::UnorderedOrEqual,
|
||||
FloatCC::LessThan,
|
||||
FloatCC::LessThanOrEqual,
|
||||
FloatCC::GreaterThan,
|
||||
FloatCC::GreaterThanOrEqual,
|
||||
FloatCC::UnorderedOrLessThan,
|
||||
FloatCC::UnorderedOrLessThanOrEqual,
|
||||
FloatCC::UnorderedOrGreaterThan,
|
||||
FloatCC::UnorderedOrGreaterThanOrEqual];
|
||||
static FLOAT_ALL: [FloatCC; 14] = [
|
||||
FloatCC::Ordered,
|
||||
FloatCC::Unordered,
|
||||
FloatCC::Equal,
|
||||
FloatCC::NotEqual,
|
||||
FloatCC::OrderedNotEqual,
|
||||
FloatCC::UnorderedOrEqual,
|
||||
FloatCC::LessThan,
|
||||
FloatCC::LessThanOrEqual,
|
||||
FloatCC::GreaterThan,
|
||||
FloatCC::GreaterThanOrEqual,
|
||||
FloatCC::UnorderedOrLessThan,
|
||||
FloatCC::UnorderedOrLessThanOrEqual,
|
||||
FloatCC::UnorderedOrGreaterThan,
|
||||
FloatCC::UnorderedOrGreaterThanOrEqual,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn float_inverse() {
|
||||
|
||||
@@ -153,17 +153,21 @@ impl DataFlowGraph {
|
||||
pub fn value_def(&self, v: Value) -> ValueDef {
|
||||
match self.values[v] {
|
||||
ValueData::Inst { inst, num, .. } => {
|
||||
assert_eq!(Some(v),
|
||||
self.results[inst].get(num as usize, &self.value_lists),
|
||||
"Dangling result value {}: {}",
|
||||
v,
|
||||
self.display_inst(inst, None));
|
||||
assert_eq!(
|
||||
Some(v),
|
||||
self.results[inst].get(num as usize, &self.value_lists),
|
||||
"Dangling result value {}: {}",
|
||||
v,
|
||||
self.display_inst(inst, None)
|
||||
);
|
||||
ValueDef::Res(inst, num as usize)
|
||||
}
|
||||
ValueData::Arg { ebb, num, .. } => {
|
||||
assert_eq!(Some(v),
|
||||
self.ebbs[ebb].args.get(num as usize, &self.value_lists),
|
||||
"Dangling EBB argument value");
|
||||
assert_eq!(
|
||||
Some(v),
|
||||
self.ebbs[ebb].args.get(num as usize, &self.value_lists),
|
||||
"Dangling EBB argument value"
|
||||
);
|
||||
ValueDef::Arg(ebb, num as usize)
|
||||
}
|
||||
ValueData::Alias { original, .. } => {
|
||||
@@ -247,19 +251,23 @@ impl DataFlowGraph {
|
||||
// Try to create short alias chains by finding the original source value.
|
||||
// This also avoids the creation of loops.
|
||||
let original = self.resolve_aliases(src);
|
||||
assert_ne!(dest,
|
||||
original,
|
||||
"Aliasing {} to {} would create a loop",
|
||||
dest,
|
||||
src);
|
||||
assert_ne!(
|
||||
dest,
|
||||
original,
|
||||
"Aliasing {} to {} would create a loop",
|
||||
dest,
|
||||
src
|
||||
);
|
||||
let ty = self.value_type(original);
|
||||
assert_eq!(self.value_type(dest),
|
||||
ty,
|
||||
"Aliasing {} to {} would change its type {} to {}",
|
||||
dest,
|
||||
src,
|
||||
self.value_type(dest),
|
||||
ty);
|
||||
assert_eq!(
|
||||
self.value_type(dest),
|
||||
ty,
|
||||
"Aliasing {} to {} would change its type {} to {}",
|
||||
dest,
|
||||
src,
|
||||
self.value_type(dest),
|
||||
ty
|
||||
);
|
||||
|
||||
self.values[dest] = ValueData::Alias { ty, original };
|
||||
}
|
||||
@@ -274,29 +282,36 @@ impl DataFlowGraph {
|
||||
/// cleared, so it likely needs to be removed from the graph.
|
||||
///
|
||||
pub fn replace_with_aliases(&mut self, dest_inst: Inst, src_inst: Inst) {
|
||||
debug_assert_ne!(dest_inst,
|
||||
src_inst,
|
||||
"Replacing {} with itself would create a loop",
|
||||
dest_inst);
|
||||
debug_assert_eq!(self.results[dest_inst].len(&self.value_lists),
|
||||
self.results[src_inst].len(&self.value_lists),
|
||||
"Replacing {} with {} would produce a different number of results.",
|
||||
dest_inst,
|
||||
src_inst);
|
||||
debug_assert_ne!(
|
||||
dest_inst,
|
||||
src_inst,
|
||||
"Replacing {} with itself would create a loop",
|
||||
dest_inst
|
||||
);
|
||||
debug_assert_eq!(
|
||||
self.results[dest_inst].len(&self.value_lists),
|
||||
self.results[src_inst].len(&self.value_lists),
|
||||
"Replacing {} with {} would produce a different number of results.",
|
||||
dest_inst,
|
||||
src_inst
|
||||
);
|
||||
|
||||
for (&dest, &src) in self.results[dest_inst]
|
||||
.as_slice(&self.value_lists)
|
||||
.iter()
|
||||
.zip(self.results[src_inst].as_slice(&self.value_lists)) {
|
||||
.as_slice(&self.value_lists)
|
||||
.iter()
|
||||
.zip(self.results[src_inst].as_slice(&self.value_lists))
|
||||
{
|
||||
let original = src;
|
||||
let ty = self.value_type(original);
|
||||
assert_eq!(self.value_type(dest),
|
||||
ty,
|
||||
"Aliasing {} to {} would change its type {} to {}",
|
||||
dest,
|
||||
src,
|
||||
self.value_type(dest),
|
||||
ty);
|
||||
assert_eq!(
|
||||
self.value_type(dest),
|
||||
ty,
|
||||
"Aliasing {} to {} would change its type {} to {}",
|
||||
dest,
|
||||
src,
|
||||
self.value_type(dest),
|
||||
ty
|
||||
);
|
||||
|
||||
self.values[dest] = ValueData::Alias { ty, original };
|
||||
}
|
||||
@@ -371,10 +386,11 @@ impl DataFlowGraph {
|
||||
}
|
||||
|
||||
/// Returns an object that displays `inst`.
|
||||
pub fn display_inst<'a, I: Into<Option<&'a TargetIsa>>>(&'a self,
|
||||
inst: Inst,
|
||||
isa: I)
|
||||
-> DisplayInst<'a> {
|
||||
pub fn display_inst<'a, I: Into<Option<&'a TargetIsa>>>(
|
||||
&'a self,
|
||||
inst: Inst,
|
||||
isa: I,
|
||||
) -> DisplayInst<'a> {
|
||||
DisplayInst(self, isa.into(), inst)
|
||||
}
|
||||
|
||||
@@ -433,12 +449,14 @@ impl DataFlowGraph {
|
||||
/// Create a new set of result values for `inst` using `ctrl_typevar` to determine the result
|
||||
/// types. Any values provided by `reuse` will be reused. When `reuse` is exhausted or when it
|
||||
/// produces `None`, a new value is created.
|
||||
pub fn make_inst_results_reusing<I>(&mut self,
|
||||
inst: Inst,
|
||||
ctrl_typevar: Type,
|
||||
reuse: I)
|
||||
-> usize
|
||||
where I: Iterator<Item = Option<Value>>
|
||||
pub fn make_inst_results_reusing<I>(
|
||||
&mut self,
|
||||
inst: Inst,
|
||||
ctrl_typevar: Type,
|
||||
reuse: I,
|
||||
) -> usize
|
||||
where
|
||||
I: Iterator<Item = Option<Value>>,
|
||||
{
|
||||
let mut reuse = reuse.fuse();
|
||||
let constraints = self.insts[inst].opcode().constraints();
|
||||
@@ -478,9 +496,10 @@ impl DataFlowGraph {
|
||||
}
|
||||
|
||||
/// Create an `InsertBuilder` that will insert an instruction at the cursor's current position.
|
||||
pub fn ins<'c, 'fc: 'c, 'fd>(&'fd mut self,
|
||||
at: &'c mut Cursor<'fc>)
|
||||
-> InsertBuilder<'fd, LayoutCursorInserter<'c, 'fc, 'fd>> {
|
||||
pub fn ins<'c, 'fc: 'c, 'fd>(
|
||||
&'fd mut self,
|
||||
at: &'c mut Cursor<'fc>,
|
||||
) -> InsertBuilder<'fd, LayoutCursorInserter<'c, 'fc, 'fd>> {
|
||||
InsertBuilder::new(LayoutCursorInserter::new(at, self))
|
||||
}
|
||||
|
||||
@@ -537,20 +556,24 @@ impl DataFlowGraph {
|
||||
_ => panic!("{} is not an instruction result value", old_value),
|
||||
};
|
||||
let new_value = self.make_value(ValueData::Inst {
|
||||
ty: new_type,
|
||||
num,
|
||||
inst,
|
||||
});
|
||||
ty: new_type,
|
||||
num,
|
||||
inst,
|
||||
});
|
||||
let num = num as usize;
|
||||
let attached = mem::replace(self.results[inst]
|
||||
.get_mut(num, &mut self.value_lists)
|
||||
.expect("Replacing detached result"),
|
||||
new_value);
|
||||
assert_eq!(attached,
|
||||
old_value,
|
||||
"{} wasn't detached from {}",
|
||||
old_value,
|
||||
self.display_inst(inst, None));
|
||||
let attached = mem::replace(
|
||||
self.results[inst]
|
||||
.get_mut(num, &mut self.value_lists)
|
||||
.expect("Replacing detached result"),
|
||||
new_value,
|
||||
);
|
||||
assert_eq!(
|
||||
attached,
|
||||
old_value,
|
||||
"{} wasn't detached from {}",
|
||||
old_value,
|
||||
self.display_inst(inst, None)
|
||||
);
|
||||
new_value
|
||||
}
|
||||
|
||||
@@ -560,19 +583,19 @@ impl DataFlowGraph {
|
||||
let num = self.results[inst].push(res, &mut self.value_lists);
|
||||
assert!(num <= u16::MAX as usize, "Too many result values");
|
||||
self.make_value(ValueData::Inst {
|
||||
ty,
|
||||
inst,
|
||||
num: num as u16,
|
||||
})
|
||||
ty,
|
||||
inst,
|
||||
num: num as u16,
|
||||
})
|
||||
}
|
||||
|
||||
/// Append a new value argument to an instruction.
|
||||
///
|
||||
/// Panics if the instruction doesn't support arguments.
|
||||
pub fn append_inst_arg(&mut self, inst: Inst, new_arg: Value) {
|
||||
let mut branch_values = self.insts[inst]
|
||||
.take_value_list()
|
||||
.expect("the instruction doesn't have value arguments");
|
||||
let mut branch_values = self.insts[inst].take_value_list().expect(
|
||||
"the instruction doesn't have value arguments",
|
||||
);
|
||||
branch_values.push(new_arg, &mut self.value_lists);
|
||||
self.insts[inst].put_value_list(branch_values)
|
||||
}
|
||||
@@ -581,9 +604,9 @@ impl DataFlowGraph {
|
||||
///
|
||||
/// This function panics if the instruction doesn't have any result.
|
||||
pub fn first_result(&self, inst: Inst) -> Value {
|
||||
self.results[inst]
|
||||
.first(&self.value_lists)
|
||||
.expect("Instruction has no results")
|
||||
self.results[inst].first(&self.value_lists).expect(
|
||||
"Instruction has no results",
|
||||
)
|
||||
}
|
||||
|
||||
/// Test if `inst` has any result values currently.
|
||||
@@ -613,11 +636,12 @@ impl DataFlowGraph {
|
||||
/// called first.
|
||||
///
|
||||
/// Returns `None` if asked about a result index that is too large.
|
||||
pub fn compute_result_type(&self,
|
||||
inst: Inst,
|
||||
result_idx: usize,
|
||||
ctrl_typevar: Type)
|
||||
-> Option<Type> {
|
||||
pub fn compute_result_type(
|
||||
&self,
|
||||
inst: Inst,
|
||||
result_idx: usize,
|
||||
ctrl_typevar: Type,
|
||||
) -> Option<Type> {
|
||||
let constraints = self.insts[inst].opcode().constraints();
|
||||
let fixed_results = constraints.fixed_results();
|
||||
|
||||
@@ -626,13 +650,12 @@ impl DataFlowGraph {
|
||||
}
|
||||
|
||||
// Not a fixed result, try to extract a return type from the call signature.
|
||||
self.call_signature(inst)
|
||||
.and_then(|sigref| {
|
||||
self.signatures[sigref]
|
||||
.return_types
|
||||
.get(result_idx - fixed_results)
|
||||
.map(|&arg| arg.value_type)
|
||||
})
|
||||
self.call_signature(inst).and_then(|sigref| {
|
||||
self.signatures[sigref]
|
||||
.return_types
|
||||
.get(result_idx - fixed_results)
|
||||
.map(|&arg| arg.value_type)
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the controlling type variable, or `VOID` if `inst` isn't polymorphic.
|
||||
@@ -644,8 +667,9 @@ impl DataFlowGraph {
|
||||
} else if constraints.requires_typevar_operand() {
|
||||
// Not all instruction formats have a designated operand, but in that case
|
||||
// `requires_typevar_operand()` should never be true.
|
||||
self.value_type(self[inst].typevar_operand(&self.value_lists)
|
||||
.expect("Instruction format doesn't have a designated operand, bad opcode."))
|
||||
self.value_type(self[inst].typevar_operand(&self.value_lists).expect(
|
||||
"Instruction format doesn't have a designated operand, bad opcode.",
|
||||
))
|
||||
} else {
|
||||
self.value_type(self.first_result(inst))
|
||||
}
|
||||
@@ -691,10 +715,10 @@ impl DataFlowGraph {
|
||||
let num = self.ebbs[ebb].args.push(arg, &mut self.value_lists);
|
||||
assert!(num <= u16::MAX as usize, "Too many arguments to EBB");
|
||||
self.make_value(ValueData::Arg {
|
||||
ty,
|
||||
num: num as u16,
|
||||
ebb,
|
||||
})
|
||||
ty,
|
||||
num: num as u16,
|
||||
ebb,
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes `val` from `ebb`'s argument by swapping it with the last argument of `ebb`.
|
||||
@@ -712,9 +736,10 @@ impl DataFlowGraph {
|
||||
} else {
|
||||
panic!("{} must be an EBB argument", val);
|
||||
};
|
||||
self.ebbs[ebb]
|
||||
.args
|
||||
.swap_remove(num as usize, &mut self.value_lists);
|
||||
self.ebbs[ebb].args.swap_remove(
|
||||
num as usize,
|
||||
&mut self.value_lists,
|
||||
);
|
||||
if let Some(last_arg_val) = self.ebbs[ebb].args.get(num as usize, &self.value_lists) {
|
||||
// We update the position of the old last arg.
|
||||
if let ValueData::Arg { num: ref mut old_num, .. } = self.values[last_arg_val] {
|
||||
@@ -734,23 +759,26 @@ impl DataFlowGraph {
|
||||
} else {
|
||||
panic!("{} must be an EBB argument", val);
|
||||
};
|
||||
self.ebbs[ebb]
|
||||
.args
|
||||
.remove(num as usize, &mut self.value_lists);
|
||||
self.ebbs[ebb].args.remove(
|
||||
num as usize,
|
||||
&mut self.value_lists,
|
||||
);
|
||||
for index in num..(self.ebb_args(ebb).len() as u16) {
|
||||
match self.values[self.ebbs[ebb]
|
||||
.args
|
||||
.get(index as usize, &self.value_lists)
|
||||
.unwrap()] {
|
||||
.args
|
||||
.get(index as usize, &self.value_lists)
|
||||
.unwrap()] {
|
||||
ValueData::Arg { ref mut num, .. } => {
|
||||
*num -= 1;
|
||||
}
|
||||
_ => {
|
||||
panic!("{} must be an EBB argument",
|
||||
self.ebbs[ebb]
|
||||
.args
|
||||
.get(index as usize, &self.value_lists)
|
||||
.unwrap())
|
||||
panic!(
|
||||
"{} must be an EBB argument",
|
||||
self.ebbs[ebb]
|
||||
.args
|
||||
.get(index as usize, &self.value_lists)
|
||||
.unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -791,10 +819,10 @@ impl DataFlowGraph {
|
||||
panic!("{} must be an EBB argument", old_arg);
|
||||
};
|
||||
let new_arg = self.make_value(ValueData::Arg {
|
||||
ty: new_type,
|
||||
num,
|
||||
ebb,
|
||||
});
|
||||
ty: new_type,
|
||||
num,
|
||||
ebb,
|
||||
});
|
||||
|
||||
self.ebbs[ebb].args.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
|
||||
new_arg
|
||||
|
||||
@@ -218,7 +218,9 @@ mod tests {
|
||||
use std::mem;
|
||||
use packed_option::PackedOption;
|
||||
// This is the whole point of `PackedOption`.
|
||||
assert_eq!(mem::size_of::<Value>(),
|
||||
mem::size_of::<PackedOption<Value>>());
|
||||
assert_eq!(
|
||||
mem::size_of::<Value>(),
|
||||
mem::size_of::<PackedOption<Value>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +55,11 @@ impl Signature {
|
||||
let bytes = self.argument_types
|
||||
.iter()
|
||||
.filter_map(|arg| match arg.location {
|
||||
ArgumentLoc::Stack(offset) if offset >= 0 => {
|
||||
Some(offset as u32 + arg.value_type.bytes())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
ArgumentLoc::Stack(offset) if offset >= 0 => {
|
||||
Some(offset as u32 + arg.value_type.bytes())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.fold(0, cmp::max);
|
||||
self.argument_bytes = Some(bytes);
|
||||
}
|
||||
@@ -73,10 +73,11 @@ impl Signature {
|
||||
/// Wrapper type capable of displaying a `Signature` with correct register names.
|
||||
pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>);
|
||||
|
||||
fn write_list(f: &mut fmt::Formatter,
|
||||
args: &[ArgumentType],
|
||||
regs: Option<&RegInfo>)
|
||||
-> fmt::Result {
|
||||
fn write_list(
|
||||
f: &mut fmt::Formatter,
|
||||
args: &[ArgumentType],
|
||||
regs: Option<&RegInfo>,
|
||||
) -> fmt::Result {
|
||||
match args.split_first() {
|
||||
None => {}
|
||||
Some((first, rest)) => {
|
||||
@@ -310,9 +311,9 @@ impl fmt::Display for CallConv {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::CallConv::*;
|
||||
f.write_str(match *self {
|
||||
Native => "native",
|
||||
SpiderWASM => "spiderwasm",
|
||||
})
|
||||
Native => "native",
|
||||
SpiderWASM => "spiderwasm",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,12 +347,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn argument_purpose() {
|
||||
let all_purpose = [ArgumentPurpose::Normal,
|
||||
ArgumentPurpose::StructReturn,
|
||||
ArgumentPurpose::Link,
|
||||
ArgumentPurpose::FramePointer,
|
||||
ArgumentPurpose::CalleeSaved,
|
||||
ArgumentPurpose::VMContext];
|
||||
let all_purpose = [
|
||||
ArgumentPurpose::Normal,
|
||||
ArgumentPurpose::StructReturn,
|
||||
ArgumentPurpose::Link,
|
||||
ArgumentPurpose::FramePointer,
|
||||
ArgumentPurpose::CalleeSaved,
|
||||
ArgumentPurpose::VMContext,
|
||||
];
|
||||
for (&e, &n) in all_purpose.iter().zip(PURPOSE_NAMES.iter()) {
|
||||
assert_eq!(e.to_string(), n);
|
||||
assert_eq!(Ok(e), n.parse());
|
||||
@@ -373,8 +376,9 @@ mod tests {
|
||||
assert_eq!(sig.to_string(), "(i32) spiderwasm");
|
||||
sig.return_types.push(ArgumentType::new(F32));
|
||||
assert_eq!(sig.to_string(), "(i32) -> f32 spiderwasm");
|
||||
sig.argument_types
|
||||
.push(ArgumentType::new(I32.by(4).unwrap()));
|
||||
sig.argument_types.push(
|
||||
ArgumentType::new(I32.by(4).unwrap()),
|
||||
);
|
||||
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 spiderwasm");
|
||||
sig.return_types.push(ArgumentType::new(B8));
|
||||
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 spiderwasm");
|
||||
@@ -391,7 +395,9 @@ mod tests {
|
||||
assert_eq!(sig.argument_bytes, Some(28));
|
||||
|
||||
// Writing ABI-annotated signatures.
|
||||
assert_eq!(sig.to_string(),
|
||||
"(i32 [24], i32x4 [8]) -> f32, b8 spiderwasm");
|
||||
assert_eq!(
|
||||
sig.to_string(),
|
||||
"(i32 [24], i32x4 [8]) -> f32, b8 spiderwasm"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ impl FunctionName {
|
||||
/// assert_eq!(name.to_string(), "#0a0908");
|
||||
/// ```
|
||||
pub fn new<T>(v: T) -> FunctionName
|
||||
where T: Into<Vec<u8>>
|
||||
where
|
||||
T: Into<Vec<u8>>,
|
||||
{
|
||||
let vec = v.into();
|
||||
if vec.len() <= NAME_LENGTH_THRESHOLD {
|
||||
@@ -39,9 +40,9 @@ impl FunctionName {
|
||||
bytes[i] = byte;
|
||||
}
|
||||
FunctionName(NameRepr::Short {
|
||||
length: vec.len() as u8,
|
||||
bytes: bytes,
|
||||
})
|
||||
length: vec.len() as u8,
|
||||
bytes: bytes,
|
||||
})
|
||||
} else {
|
||||
FunctionName(NameRepr::Long(vec))
|
||||
}
|
||||
@@ -114,11 +115,17 @@ mod tests {
|
||||
assert_eq!(FunctionName::new("x").to_string(), "%x");
|
||||
assert_eq!(FunctionName::new("x_1").to_string(), "%x_1");
|
||||
assert_eq!(FunctionName::new(" ").to_string(), "#20");
|
||||
assert_eq!(FunctionName::new("кретон").to_string(),
|
||||
"#d0bad180d0b5d182d0bed0bd");
|
||||
assert_eq!(FunctionName::new("印花棉布").to_string(),
|
||||
"#e58db0e88ab1e6a389e5b883");
|
||||
assert_eq!(FunctionName::new(vec![0, 1, 2, 3, 4, 5]).to_string(),
|
||||
"#000102030405");
|
||||
assert_eq!(
|
||||
FunctionName::new("кретон").to_string(),
|
||||
"#d0bad180d0b5d182d0bed0bd"
|
||||
);
|
||||
assert_eq!(
|
||||
FunctionName::new("印花棉布").to_string(),
|
||||
"#e58db0e88ab1e6a389e5b883"
|
||||
);
|
||||
assert_eq!(
|
||||
FunctionName::new(vec![0, 1, 2, 3, 4, 5]).to_string(),
|
||||
"#000102030405"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ pub enum HeapStyle {
|
||||
impl fmt::Display for HeapData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match self.style {
|
||||
HeapStyle::Dynamic { .. } => "dynamic",
|
||||
HeapStyle::Static { .. } => "static",
|
||||
})?;
|
||||
HeapStyle::Dynamic { .. } => "dynamic",
|
||||
HeapStyle::Static { .. } => "static",
|
||||
})?;
|
||||
|
||||
match self.base {
|
||||
HeapBase::ReservedReg => write!(f, " reserved_reg")?,
|
||||
|
||||
@@ -192,10 +192,10 @@ impl FromStr for Uimm32 {
|
||||
// Parse a decimal or hexadecimal `Uimm32`, formatted as above.
|
||||
fn from_str(s: &str) -> Result<Uimm32, &'static str> {
|
||||
parse_i64(s).and_then(|x| if 0 <= x && x <= u32::MAX as i64 {
|
||||
Ok(Uimm32(x as u32))
|
||||
} else {
|
||||
Err("Uimm32 out of range")
|
||||
})
|
||||
Ok(Uimm32(x as u32))
|
||||
} else {
|
||||
Err("Uimm32 out of range")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,10 +260,10 @@ impl FromStr for Offset32 {
|
||||
return Err("Offset must begin with sign");
|
||||
}
|
||||
parse_i64(s).and_then(|x| if i32::MIN as i64 <= x && x <= i32::MAX as i64 {
|
||||
Ok(Offset32::new(x as i32))
|
||||
} else {
|
||||
Err("Offset out of range")
|
||||
})
|
||||
Ok(Offset32::new(x as i32))
|
||||
} else {
|
||||
Err("Offset out of range")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,10 +325,10 @@ impl FromStr for Uoffset32 {
|
||||
return Err("Unsigned offset must begin with '+' sign");
|
||||
}
|
||||
parse_i64(s).and_then(|x| if 0 <= x && x <= u32::MAX as i64 {
|
||||
Ok(Uoffset32::new(x as u32))
|
||||
} else {
|
||||
Err("Offset out of range")
|
||||
})
|
||||
Ok(Uoffset32::new(x as u32))
|
||||
} else {
|
||||
Err("Offset out of range")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,20 +458,20 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result<u64, &'static str> {
|
||||
if s2.starts_with("NaN:0x") {
|
||||
// Quiet NaN with payload.
|
||||
return match u64::from_str_radix(&s2[6..], 16) {
|
||||
Ok(payload) if payload < quiet_bit => {
|
||||
Ok(sign_bit | max_e_bits | quiet_bit | payload)
|
||||
}
|
||||
_ => Err("Invalid NaN payload"),
|
||||
};
|
||||
Ok(payload) if payload < quiet_bit => {
|
||||
Ok(sign_bit | max_e_bits | quiet_bit | payload)
|
||||
}
|
||||
_ => Err("Invalid NaN payload"),
|
||||
};
|
||||
}
|
||||
if s2.starts_with("sNaN:0x") {
|
||||
// Signaling NaN with payload.
|
||||
return match u64::from_str_radix(&s2[7..], 16) {
|
||||
Ok(payload) if 0 < payload && payload < quiet_bit => {
|
||||
Ok(sign_bit | max_e_bits | payload)
|
||||
}
|
||||
_ => Err("Invalid sNaN payload"),
|
||||
};
|
||||
Ok(payload) if 0 < payload && payload < quiet_bit => {
|
||||
Ok(sign_bit | max_e_bits | payload)
|
||||
}
|
||||
_ => Err("Invalid sNaN payload"),
|
||||
};
|
||||
}
|
||||
|
||||
return Err("Float must be hexadecimal");
|
||||
@@ -662,7 +662,8 @@ mod tests {
|
||||
|
||||
// Verify that `text` can be parsed as a `T` into a value that displays as `want`.
|
||||
fn parse_ok<T: FromStr + Display>(text: &str, want: &str)
|
||||
where <T as FromStr>::Err: Display
|
||||
where
|
||||
<T as FromStr>::Err: Display,
|
||||
{
|
||||
match text.parse::<T>() {
|
||||
Err(s) => panic!("\"{}\".parse() error: {}", text, s),
|
||||
@@ -672,7 +673,8 @@ mod tests {
|
||||
|
||||
// Verify that `text` fails to parse as `T` with the error `msg`.
|
||||
fn parse_err<T: FromStr + Display>(text: &str, msg: &str)
|
||||
where <T as FromStr>::Err: Display
|
||||
where
|
||||
<T as FromStr>::Err: Display,
|
||||
{
|
||||
match text.parse::<T>() {
|
||||
Err(s) => assert_eq!(s.to_string(), msg),
|
||||
@@ -781,18 +783,26 @@ mod tests {
|
||||
assert_eq!(Ieee32::with_float(1.0).to_string(), "0x1.000000p0");
|
||||
assert_eq!(Ieee32::with_float(1.5).to_string(), "0x1.800000p0");
|
||||
assert_eq!(Ieee32::with_float(0.5).to_string(), "0x1.000000p-1");
|
||||
assert_eq!(Ieee32::with_float(f32::EPSILON).to_string(),
|
||||
"0x1.000000p-23");
|
||||
assert_eq!(
|
||||
Ieee32::with_float(f32::EPSILON).to_string(),
|
||||
"0x1.000000p-23"
|
||||
);
|
||||
assert_eq!(Ieee32::with_float(f32::MIN).to_string(), "-0x1.fffffep127");
|
||||
assert_eq!(Ieee32::with_float(f32::MAX).to_string(), "0x1.fffffep127");
|
||||
// Smallest positive normal number.
|
||||
assert_eq!(Ieee32::with_float(f32::MIN_POSITIVE).to_string(),
|
||||
"0x1.000000p-126");
|
||||
assert_eq!(
|
||||
Ieee32::with_float(f32::MIN_POSITIVE).to_string(),
|
||||
"0x1.000000p-126"
|
||||
);
|
||||
// Subnormals.
|
||||
assert_eq!(Ieee32::with_float(f32::MIN_POSITIVE / 2.0).to_string(),
|
||||
"0x0.800000p-126");
|
||||
assert_eq!(Ieee32::with_float(f32::MIN_POSITIVE * f32::EPSILON).to_string(),
|
||||
"0x0.000002p-126");
|
||||
assert_eq!(
|
||||
Ieee32::with_float(f32::MIN_POSITIVE / 2.0).to_string(),
|
||||
"0x0.800000p-126"
|
||||
);
|
||||
assert_eq!(
|
||||
Ieee32::with_float(f32::MIN_POSITIVE * f32::EPSILON).to_string(),
|
||||
"0x0.000002p-126"
|
||||
);
|
||||
assert_eq!(Ieee32::with_float(f32::INFINITY).to_string(), "+Inf");
|
||||
assert_eq!(Ieee32::with_float(f32::NEG_INFINITY).to_string(), "-Inf");
|
||||
assert_eq!(Ieee32::with_float(f32::NAN).to_string(), "+NaN");
|
||||
@@ -883,32 +893,48 @@ mod tests {
|
||||
assert_eq!(Ieee64::with_float(1.0).to_string(), "0x1.0000000000000p0");
|
||||
assert_eq!(Ieee64::with_float(1.5).to_string(), "0x1.8000000000000p0");
|
||||
assert_eq!(Ieee64::with_float(0.5).to_string(), "0x1.0000000000000p-1");
|
||||
assert_eq!(Ieee64::with_float(f64::EPSILON).to_string(),
|
||||
"0x1.0000000000000p-52");
|
||||
assert_eq!(Ieee64::with_float(f64::MIN).to_string(),
|
||||
"-0x1.fffffffffffffp1023");
|
||||
assert_eq!(Ieee64::with_float(f64::MAX).to_string(),
|
||||
"0x1.fffffffffffffp1023");
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::EPSILON).to_string(),
|
||||
"0x1.0000000000000p-52"
|
||||
);
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::MIN).to_string(),
|
||||
"-0x1.fffffffffffffp1023"
|
||||
);
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::MAX).to_string(),
|
||||
"0x1.fffffffffffffp1023"
|
||||
);
|
||||
// Smallest positive normal number.
|
||||
assert_eq!(Ieee64::with_float(f64::MIN_POSITIVE).to_string(),
|
||||
"0x1.0000000000000p-1022");
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::MIN_POSITIVE).to_string(),
|
||||
"0x1.0000000000000p-1022"
|
||||
);
|
||||
// Subnormals.
|
||||
assert_eq!(Ieee64::with_float(f64::MIN_POSITIVE / 2.0).to_string(),
|
||||
"0x0.8000000000000p-1022");
|
||||
assert_eq!(Ieee64::with_float(f64::MIN_POSITIVE * f64::EPSILON).to_string(),
|
||||
"0x0.0000000000001p-1022");
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::MIN_POSITIVE / 2.0).to_string(),
|
||||
"0x0.8000000000000p-1022"
|
||||
);
|
||||
assert_eq!(
|
||||
Ieee64::with_float(f64::MIN_POSITIVE * f64::EPSILON).to_string(),
|
||||
"0x0.0000000000001p-1022"
|
||||
);
|
||||
assert_eq!(Ieee64::with_float(f64::INFINITY).to_string(), "+Inf");
|
||||
assert_eq!(Ieee64::with_float(f64::NEG_INFINITY).to_string(), "-Inf");
|
||||
assert_eq!(Ieee64::with_float(f64::NAN).to_string(), "+NaN");
|
||||
assert_eq!(Ieee64::with_float(-f64::NAN).to_string(), "-NaN");
|
||||
// Construct some qNaNs with payloads.
|
||||
assert_eq!(Ieee64(0x7ff8000000000001).to_string(), "+NaN:0x1");
|
||||
assert_eq!(Ieee64(0x7ffc000000000001).to_string(),
|
||||
"+NaN:0x4000000000001");
|
||||
assert_eq!(
|
||||
Ieee64(0x7ffc000000000001).to_string(),
|
||||
"+NaN:0x4000000000001"
|
||||
);
|
||||
// Signaling NaNs.
|
||||
assert_eq!(Ieee64(0x7ff0000000000001).to_string(), "+sNaN:0x1");
|
||||
assert_eq!(Ieee64(0x7ff4000000000001).to_string(),
|
||||
"+sNaN:0x4000000000001");
|
||||
assert_eq!(
|
||||
Ieee64(0x7ff4000000000001).to_string(),
|
||||
"+sNaN:0x4000000000001"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -481,7 +481,8 @@ impl OpcodeConstraints {
|
||||
pub fn result_type(self, n: usize, ctrl_type: Type) -> Type {
|
||||
assert!(n < self.fixed_results(), "Invalid result index");
|
||||
if let ResolvedConstraint::Bound(t) =
|
||||
OPERAND_CONSTRAINTS[self.constraint_offset() + n].resolve(ctrl_type) {
|
||||
OPERAND_CONSTRAINTS[self.constraint_offset() + n].resolve(ctrl_type)
|
||||
{
|
||||
t
|
||||
} else {
|
||||
panic!("Result constraints can't be free");
|
||||
@@ -494,8 +495,10 @@ impl OpcodeConstraints {
|
||||
/// Unlike results, it is possible for some input values to vary freely within a specific
|
||||
/// `ValueTypeSet`. This is represented with the `ArgumentConstraint::Free` variant.
|
||||
pub fn value_argument_constraint(self, n: usize, ctrl_type: Type) -> ResolvedConstraint {
|
||||
assert!(n < self.fixed_value_arguments(),
|
||||
"Invalid value argument index");
|
||||
assert!(
|
||||
n < self.fixed_value_arguments(),
|
||||
"Invalid value argument index"
|
||||
);
|
||||
let offset = self.constraint_offset() + self.fixed_results();
|
||||
OPERAND_CONSTRAINTS[offset + n].resolve(ctrl_type)
|
||||
}
|
||||
@@ -613,14 +616,14 @@ impl OperandConstraint {
|
||||
AsBool => Bound(ctrl_type.as_bool()),
|
||||
HalfWidth => Bound(ctrl_type.half_width().expect("invalid type for half_width")),
|
||||
DoubleWidth => {
|
||||
Bound(ctrl_type
|
||||
.double_width()
|
||||
.expect("invalid type for double_width"))
|
||||
Bound(ctrl_type.double_width().expect(
|
||||
"invalid type for double_width",
|
||||
))
|
||||
}
|
||||
HalfVector => {
|
||||
Bound(ctrl_type
|
||||
.half_vector()
|
||||
.expect("invalid type for half_vector"))
|
||||
Bound(ctrl_type.half_vector().expect(
|
||||
"invalid type for half_vector",
|
||||
))
|
||||
}
|
||||
DoubleVector => Bound(ctrl_type.by(2).expect("invalid type for double_vector")),
|
||||
}
|
||||
@@ -688,10 +691,14 @@ mod tests {
|
||||
assert_eq!(a.fixed_value_arguments(), 2);
|
||||
assert_eq!(a.result_type(0, types::I32), types::I32);
|
||||
assert_eq!(a.result_type(0, types::I8), types::I8);
|
||||
assert_eq!(a.value_argument_constraint(0, types::I32),
|
||||
ResolvedConstraint::Bound(types::I32));
|
||||
assert_eq!(a.value_argument_constraint(1, types::I32),
|
||||
ResolvedConstraint::Bound(types::I32));
|
||||
assert_eq!(
|
||||
a.value_argument_constraint(0, types::I32),
|
||||
ResolvedConstraint::Bound(types::I32)
|
||||
);
|
||||
assert_eq!(
|
||||
a.value_argument_constraint(1, types::I32),
|
||||
ResolvedConstraint::Bound(types::I32)
|
||||
);
|
||||
|
||||
let b = Opcode::Bitcast.constraints();
|
||||
assert!(!b.use_typevar_operand());
|
||||
|
||||
@@ -71,9 +71,9 @@ impl JumpTableData {
|
||||
|
||||
/// Checks if any of the entries branch to `ebb`.
|
||||
pub fn branches_to(&self, ebb: Ebb) -> bool {
|
||||
self.table
|
||||
.iter()
|
||||
.any(|target_ebb| target_ebb.expand() == Some(ebb))
|
||||
self.table.iter().any(|target_ebb| {
|
||||
target_ebb.expand() == Some(ebb)
|
||||
})
|
||||
}
|
||||
|
||||
/// Access the whole table as a mutable slice.
|
||||
@@ -148,8 +148,10 @@ mod tests {
|
||||
jt.set_entry(0, e2);
|
||||
jt.set_entry(10, e1);
|
||||
|
||||
assert_eq!(jt.to_string(),
|
||||
"jump_table ebb2, 0, 0, 0, 0, 0, 0, 0, 0, 0, ebb1");
|
||||
assert_eq!(
|
||||
jt.to_string(),
|
||||
"jump_table ebb2, 0, 0, 0, 0, 0, 0, 0, 0, 0, ebb1"
|
||||
);
|
||||
|
||||
let v: Vec<(usize, Ebb)> = jt.entries().collect();
|
||||
assert_eq!(v, [(0, e2), (10, e1)]);
|
||||
|
||||
@@ -96,8 +96,9 @@ fn test_midpoint() {
|
||||
|
||||
impl ProgramOrder for Layout {
|
||||
fn cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
|
||||
where A: Into<ExpandedProgramPoint>,
|
||||
B: Into<ExpandedProgramPoint>
|
||||
where
|
||||
A: Into<ExpandedProgramPoint>,
|
||||
B: Into<ExpandedProgramPoint>,
|
||||
{
|
||||
let a_seq = self.seq(a);
|
||||
let b_seq = self.seq(b);
|
||||
@@ -166,8 +167,9 @@ impl Layout {
|
||||
/// Assign a valid sequence number to `inst` such that the numbers are still monotonic. This may
|
||||
/// require renumbering.
|
||||
fn assign_inst_seq(&mut self, inst: Inst) {
|
||||
let ebb = self.inst_ebb(inst)
|
||||
.expect("inst must be inserted before assigning an seq");
|
||||
let ebb = self.inst_ebb(inst).expect(
|
||||
"inst must be inserted before assigning an seq",
|
||||
);
|
||||
|
||||
// Get the sequence number immediately before `inst`.
|
||||
let prev_seq = match self.insts[inst].prev.expand() {
|
||||
@@ -283,8 +285,10 @@ impl Layout {
|
||||
|
||||
/// Insert `ebb` as the last EBB in the layout.
|
||||
pub fn append_ebb(&mut self, ebb: Ebb) {
|
||||
assert!(!self.is_ebb_inserted(ebb),
|
||||
"Cannot append EBB that is already in the layout");
|
||||
assert!(
|
||||
!self.is_ebb_inserted(ebb),
|
||||
"Cannot append EBB that is already in the layout"
|
||||
);
|
||||
{
|
||||
let node = &mut self.ebbs[ebb];
|
||||
assert!(node.first_inst.is_none() && node.last_inst.is_none());
|
||||
@@ -302,10 +306,14 @@ impl Layout {
|
||||
|
||||
/// Insert `ebb` in the layout before the existing EBB `before`.
|
||||
pub fn insert_ebb(&mut self, ebb: Ebb, before: Ebb) {
|
||||
assert!(!self.is_ebb_inserted(ebb),
|
||||
"Cannot insert EBB that is already in the layout");
|
||||
assert!(self.is_ebb_inserted(before),
|
||||
"EBB Insertion point not in the layout");
|
||||
assert!(
|
||||
!self.is_ebb_inserted(ebb),
|
||||
"Cannot insert EBB that is already in the layout"
|
||||
);
|
||||
assert!(
|
||||
self.is_ebb_inserted(before),
|
||||
"EBB Insertion point not in the layout"
|
||||
);
|
||||
let after = self.ebbs[before].prev;
|
||||
{
|
||||
let node = &mut self.ebbs[ebb];
|
||||
@@ -322,10 +330,14 @@ impl Layout {
|
||||
|
||||
/// Insert `ebb` in the layout *after* the existing EBB `after`.
|
||||
pub fn insert_ebb_after(&mut self, ebb: Ebb, after: Ebb) {
|
||||
assert!(!self.is_ebb_inserted(ebb),
|
||||
"Cannot insert EBB that is already in the layout");
|
||||
assert!(self.is_ebb_inserted(after),
|
||||
"EBB Insertion point not in the layout");
|
||||
assert!(
|
||||
!self.is_ebb_inserted(ebb),
|
||||
"Cannot insert EBB that is already in the layout"
|
||||
);
|
||||
assert!(
|
||||
self.is_ebb_inserted(after),
|
||||
"EBB Insertion point not in the layout"
|
||||
);
|
||||
let before = self.ebbs[after].next;
|
||||
{
|
||||
let node = &mut self.ebbs[ebb];
|
||||
@@ -411,7 +423,8 @@ impl Layout {
|
||||
|
||||
/// Get the EBB containing the program point `pp`. Panic if `pp` is not in the layout.
|
||||
pub fn pp_ebb<PP>(&self, pp: PP) -> Ebb
|
||||
where PP: Into<ExpandedProgramPoint>
|
||||
where
|
||||
PP: Into<ExpandedProgramPoint>,
|
||||
{
|
||||
match pp.into() {
|
||||
ExpandedProgramPoint::Ebb(ebb) => ebb,
|
||||
@@ -424,8 +437,10 @@ impl Layout {
|
||||
/// Append `inst` to the end of `ebb`.
|
||||
pub fn append_inst(&mut self, inst: Inst, ebb: Ebb) {
|
||||
assert_eq!(self.inst_ebb(inst), None);
|
||||
assert!(self.is_ebb_inserted(ebb),
|
||||
"Cannot append instructions to EBB not in layout");
|
||||
assert!(
|
||||
self.is_ebb_inserted(ebb),
|
||||
"Cannot append instructions to EBB not in layout"
|
||||
);
|
||||
{
|
||||
let ebb_node = &mut self.ebbs[ebb];
|
||||
{
|
||||
@@ -457,8 +472,9 @@ impl Layout {
|
||||
/// Insert `inst` before the instruction `before` in the same EBB.
|
||||
pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
|
||||
assert_eq!(self.inst_ebb(inst), None);
|
||||
let ebb = self.inst_ebb(before)
|
||||
.expect("Instruction before insertion point not in the layout");
|
||||
let ebb = self.inst_ebb(before).expect(
|
||||
"Instruction before insertion point not in the layout",
|
||||
);
|
||||
let after = self.insts[before].prev;
|
||||
{
|
||||
let inst_node = &mut self.insts[inst];
|
||||
@@ -531,8 +547,9 @@ impl Layout {
|
||||
/// i4
|
||||
/// ```
|
||||
pub fn split_ebb(&mut self, new_ebb: Ebb, before: Inst) {
|
||||
let old_ebb = self.inst_ebb(before)
|
||||
.expect("The `before` instruction must be in the layout");
|
||||
let old_ebb = self.inst_ebb(before).expect(
|
||||
"The `before` instruction must be in the layout",
|
||||
);
|
||||
assert!(!self.is_ebb_inserted(new_ebb));
|
||||
|
||||
// Insert new_ebb after old_ebb.
|
||||
@@ -683,7 +700,8 @@ pub trait CursorBase {
|
||||
/// }
|
||||
/// ```
|
||||
fn at_inst(mut self, inst: Inst) -> Self
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_inst(inst);
|
||||
self
|
||||
@@ -703,7 +721,8 @@ pub trait CursorBase {
|
||||
/// }
|
||||
/// ```
|
||||
fn at_first_inst(mut self, ebb: Ebb) -> Self
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.goto_first_inst(ebb);
|
||||
self
|
||||
@@ -783,9 +802,9 @@ pub trait CursorBase {
|
||||
self.layout().first_ebb
|
||||
};
|
||||
self.set_position(match next {
|
||||
Some(ebb) => CursorPosition::Before(ebb),
|
||||
None => CursorPosition::Nowhere,
|
||||
});
|
||||
Some(ebb) => CursorPosition::Before(ebb),
|
||||
None => CursorPosition::Nowhere,
|
||||
});
|
||||
next
|
||||
}
|
||||
|
||||
@@ -816,9 +835,9 @@ pub trait CursorBase {
|
||||
self.layout().last_ebb
|
||||
};
|
||||
self.set_position(match prev {
|
||||
Some(ebb) => CursorPosition::After(ebb),
|
||||
None => CursorPosition::Nowhere,
|
||||
});
|
||||
Some(ebb) => CursorPosition::After(ebb),
|
||||
None => CursorPosition::Nowhere,
|
||||
});
|
||||
prev
|
||||
}
|
||||
|
||||
@@ -872,9 +891,9 @@ pub trait CursorBase {
|
||||
self.set_position(At(next));
|
||||
Some(next)
|
||||
} else {
|
||||
let pos = After(self.layout()
|
||||
.inst_ebb(inst)
|
||||
.expect("current instruction removed?"));
|
||||
let pos = After(self.layout().inst_ebb(inst).expect(
|
||||
"current instruction removed?",
|
||||
));
|
||||
self.set_position(pos);
|
||||
None
|
||||
}
|
||||
@@ -925,9 +944,9 @@ pub trait CursorBase {
|
||||
self.set_position(At(prev));
|
||||
Some(prev)
|
||||
} else {
|
||||
let pos = Before(self.layout()
|
||||
.inst_ebb(inst)
|
||||
.expect("current instruction removed?"));
|
||||
let pos = Before(self.layout().inst_ebb(inst).expect(
|
||||
"current instruction removed?",
|
||||
));
|
||||
self.set_position(pos);
|
||||
None
|
||||
}
|
||||
@@ -1057,9 +1076,10 @@ pub struct LayoutCursorInserter<'c, 'fc: 'c, 'fd> {
|
||||
|
||||
impl<'c, 'fc: 'c, 'fd> LayoutCursorInserter<'c, 'fc, 'fd> {
|
||||
/// Create a new inserter. Don't use this, use `dfg.ins(pos)`.
|
||||
pub fn new(pos: &'c mut Cursor<'fc>,
|
||||
dfg: &'fd mut DataFlowGraph)
|
||||
-> LayoutCursorInserter<'c, 'fc, 'fd> {
|
||||
pub fn new(
|
||||
pos: &'c mut Cursor<'fc>,
|
||||
dfg: &'fd mut DataFlowGraph,
|
||||
) -> LayoutCursorInserter<'c, 'fc, 'fd> {
|
||||
LayoutCursorInserter { pos, dfg }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,9 @@ pub trait ProgramOrder {
|
||||
/// directly. Depending on the implementation, there is a good chance performance will be
|
||||
/// improved for those cases where the type of either argument is known statically.
|
||||
fn cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
|
||||
where A: Into<ExpandedProgramPoint>,
|
||||
B: Into<ExpandedProgramPoint>;
|
||||
where
|
||||
A: Into<ExpandedProgramPoint>,
|
||||
B: Into<ExpandedProgramPoint>;
|
||||
|
||||
/// Is the range from `inst` to `ebb` just the gap between consecutive EBBs?
|
||||
///
|
||||
|
||||
@@ -65,11 +65,11 @@ impl fmt::Display for StackSlotKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::StackSlotKind::*;
|
||||
f.write_str(match *self {
|
||||
Local => "local",
|
||||
SpillSlot => "spill_slot",
|
||||
IncomingArg => "incoming_arg",
|
||||
OutgoingArg => "outgoing_arg",
|
||||
})
|
||||
Local => "local",
|
||||
SpillSlot => "spill_slot",
|
||||
IncomingArg => "incoming_arg",
|
||||
OutgoingArg => "outgoing_arg",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,9 +228,9 @@ impl StackSlots {
|
||||
let size = ty.bytes();
|
||||
|
||||
// Look for an existing outgoing stack slot with the same offset and size.
|
||||
let inspos = match self.outgoing
|
||||
.binary_search_by_key(&(offset, size),
|
||||
|&ss| (self[ss].offset, self[ss].size)) {
|
||||
let inspos = match self.outgoing.binary_search_by_key(&(offset, size), |&ss| {
|
||||
(self[ss].offset, self[ss].size)
|
||||
}) {
|
||||
Ok(idx) => return self.outgoing[idx],
|
||||
Err(idx) => idx,
|
||||
};
|
||||
@@ -255,10 +255,14 @@ mod tests {
|
||||
fn stack_slot() {
|
||||
let mut func = Function::new();
|
||||
|
||||
let ss0 = func.stack_slots
|
||||
.push(StackSlotData::new(StackSlotKind::IncomingArg, 4));
|
||||
let ss1 = func.stack_slots
|
||||
.push(StackSlotData::new(StackSlotKind::SpillSlot, 8));
|
||||
let ss0 = func.stack_slots.push(StackSlotData::new(
|
||||
StackSlotKind::IncomingArg,
|
||||
4,
|
||||
));
|
||||
let ss1 = func.stack_slots.push(StackSlotData::new(
|
||||
StackSlotKind::SpillSlot,
|
||||
8,
|
||||
));
|
||||
assert_eq!(ss0.to_string(), "ss0");
|
||||
assert_eq!(ss1.to_string(), "ss1");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user