rustfmt 0.8.1

This commit is contained in:
Jakob Stoklund Olesen
2017-04-05 09:00:11 -07:00
parent e641c97670
commit 1984c96f7c
38 changed files with 497 additions and 334 deletions

View File

@@ -51,7 +51,11 @@ pub type CommandResult = Result<(), String>;
fn cton_util() -> CommandResult {
// Parse comand line arguments.
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.help(true).version(Some(format!("Cretonne {}", VERSION))).decode())
.and_then(|d| {
d.help(true)
.version(Some(format!("Cretonne {}", VERSION)))
.decode()
})
.unwrap_or_else(|e| e.exit());
// Find the sub-command to execute.

View File

@@ -119,7 +119,8 @@ fn worker_thread(thread_num: usize,
// Tell them we're starting this job.
// The receiver should always be present for this as long as we have jobs.
replies.send(Reply::Starting {
replies
.send(Reply::Starting {
jobid: jobid,
thread_num: thread_num,
})
@@ -141,7 +142,8 @@ fn worker_thread(thread_num: usize,
dbg!("FAIL: {}", msg);
}
replies.send(Reply::Done {
replies
.send(Reply::Done {
jobid: jobid,
result: result,
})

View File

@@ -41,7 +41,8 @@ impl SubTest for TestLegalizer {
comp_ctx.flowgraph();
comp_ctx.legalize(isa);
comp_ctx.verify(isa).map_err(|e| pretty_verifier_error(&comp_ctx.func, e))?;
comp_ctx.verify(isa)
.map_err(|e| pretty_verifier_error(&comp_ctx.func, e))?;
let mut text = String::new();
write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string())?;

View File

@@ -47,7 +47,8 @@ impl SubTest for TestRegalloc {
// TODO: Should we have an option to skip legalization?
comp_ctx.legalize(isa);
comp_ctx.regalloc(isa);
comp_ctx.verify(isa).map_err(|e| pretty_verifier_error(&comp_ctx.func, e))?;
comp_ctx.verify(isa)
.map_err(|e| pretty_verifier_error(&comp_ctx.func, e))?;
let mut text = String::new();
write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string())?;

View File

@@ -104,7 +104,8 @@ impl TestRunner {
///
/// Any problems reading `file` as a test case file will be reported as a test failure.
pub fn push_test<P: Into<PathBuf>>(&mut self, file: P) {
self.tests.push(QueueEntry {
self.tests
.push(QueueEntry {
path: file.into(),
state: State::New,
});
@@ -206,7 +207,9 @@ impl TestRunner {
}
// Check for any asynchronous replies without blocking.
while let Some(reply) = self.threads.as_mut().and_then(ConcurrentRunner::try_get) {
while let Some(reply) = self.threads
.as_mut()
.and_then(ConcurrentRunner::try_get) {
self.handle_reply(reply);
}
}
@@ -303,10 +306,10 @@ impl TestRunner {
return;
}
for t in self.tests.iter().filter(|entry| match **entry {
QueueEntry { state: State::Done(Ok(dur)), .. } => {
dur > cut
}
for t in self.tests
.iter()
.filter(|entry| match **entry {
QueueEntry { state: State::Done(Ok(dur)), .. } => dur > cut,
_ => false,
}) {
println!("slow: {}", t)

View File

@@ -120,5 +120,6 @@ fn run_one_test<'a>(tuple: (&'a SubTest, &'a Flags, Option<&'a TargetIsa>),
context.verified = true;
}
test.run(func, context).map_err(|e| format!("{}: {}", name, e))
test.run(func, context)
.map_err(|e| format!("{}: {}", name, e))
}

View File

@@ -76,11 +76,13 @@ impl<'a> filecheck::VariableMap for Context<'a> {
/// Run filecheck on `text`, using directives extracted from `context`.
pub fn run_filecheck(text: &str, context: &Context) -> Result<()> {
let checker = build_filechecker(context)?;
if checker.check(&text, context).map_err(|e| format!("filecheck: {}", e))? {
if checker.check(&text, context)
.map_err(|e| format!("filecheck: {}", e))? {
Ok(())
} else {
// Filecheck mismatch. Emit an explanation as output.
let (_, explain) = checker.explain(&text, context).map_err(|e| format!("explain: {}", e))?;
let (_, explain) = checker.explain(&text, context)
.map_err(|e| format!("explain: {}", e))?;
Err(format!("filecheck failed:\n{}{}", checker, explain))
}
}
@@ -90,10 +92,12 @@ pub fn build_filechecker(context: &Context) -> Result<Checker> {
let mut builder = CheckerBuilder::new();
// Preamble comments apply to all functions.
for comment in context.preamble_comments {
builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e))?;
builder.directive(comment.text)
.map_err(|e| format!("filecheck: {}", e))?;
}
for comment in &context.details.comments {
builder.directive(comment.text).map_err(|e| format!("filecheck: {}", e))?;
builder.directive(comment.text)
.map_err(|e| format!("filecheck: {}", e))?;
}
let checker = builder.finish();
if checker.is_empty() {

View File

@@ -18,10 +18,12 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
}
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer).map_err(|e| format!("stdin: {}", e))?;
io::stdin().read_to_string(&mut buffer)
.map_err(|e| format!("stdin: {}", e))?;
if verbose {
let (success, explain) = checker.explain(&buffer, NO_VARIABLES).map_err(|e| e.to_string())?;
let (success, explain) = checker.explain(&buffer, NO_VARIABLES)
.map_err(|e| e.to_string())?;
print!("{}", explain);
if success {
println!("OK");
@@ -29,10 +31,12 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
} else {
Err("Check failed".to_string())
}
} else if checker.check(&buffer, NO_VARIABLES).map_err(|e| e.to_string())? {
} else if checker.check(&buffer, NO_VARIABLES)
.map_err(|e| e.to_string())? {
Ok(())
} else {
let (_, explain) = checker.explain(&buffer, NO_VARIABLES).map_err(|e| e.to_string())?;
let (_, explain) = checker.explain(&buffer, NO_VARIABLES)
.map_err(|e| e.to_string())?;
print!("{}", explain);
Err("Check failed".to_string())
}
@@ -41,6 +45,7 @@ pub fn run(files: Vec<String>, verbose: bool) -> CommandResult {
fn read_checkfile(filename: &str) -> Result<Checker, String> {
let buffer = read_to_string(&filename).map_err(|e| format!("{}: {}", filename, e))?;
let mut builder = CheckerBuilder::new();
builder.text(&buffer).map_err(|e| format!("{}: {}", filename, e))?;
builder.text(&buffer)
.map_err(|e| format!("{}: {}", filename, e))?;
Ok(builder.finish())
}

View File

@@ -30,7 +30,7 @@ function banner() {
# rustfmt is installed.
#
# This version should always be bumped to the newest version available.
RUSTFMT_VERSION="0.8.0"
RUSTFMT_VERSION="0.8.1"
if cargo install --list | grep -q "^rustfmt v$RUSTFMT_VERSION"; then
banner "Rust formatting"

View File

@@ -9,7 +9,10 @@ use self::cton_reader::parse_functions;
fn test_reverse_postorder_traversal(function_source: &str, ebb_order: Vec<u32>) {
let func = &parse_functions(function_source).unwrap()[0];
let cfg = ControlFlowGraph::with_function(&func);
let ebbs = ebb_order.iter().map(|n| Ebb::with_number(*n).unwrap()).collect::<Vec<Ebb>>();
let ebbs = ebb_order
.iter()
.map(|n| Ebb::with_number(*n).unwrap())
.collect::<Vec<Ebb>>();
let mut postorder_ebbs = cfg.postorder_ebbs();
let mut postorder_map = EntityMap::with_capacity(postorder_ebbs.len());

View File

@@ -108,7 +108,10 @@ pub fn legalize_args<AA: ArgAssigner>(args: &mut Vec<ArgumentType>, aa: &mut AA)
}
// Split this argument into two smaller ones. Then revisit both.
ArgAction::Convert(conv) => {
let new_arg = ArgumentType { value_type: conv.apply(arg.value_type), ..arg };
let new_arg = ArgumentType {
value_type: conv.apply(arg.value_type),
..arg
};
args[argno].value_type = new_arg.value_type;
if conv.is_split() {
args.insert(argno + 1, new_arg);

View File

@@ -69,6 +69,7 @@ impl Context {
/// Run the register allocator.
pub fn regalloc(&mut self, isa: &TargetIsa) {
self.regalloc.run(isa, &mut self.func, &self.cfg, &self.domtree);
self.regalloc
.run(isa, &mut self.func, &self.cfg, &self.domtree);
}
}

View File

@@ -88,7 +88,8 @@ impl DominatorTree {
// Run a finger up the dominator tree from b until we see a.
// Do nothing if b is unreachable.
while rpo_a < self.nodes[ebb_b].rpo_number {
b = self.idom(ebb_b).expect("Shouldn't meet unreachable here.");
b = self.idom(ebb_b)
.expect("Shouldn't meet unreachable here.");
ebb_b = layout.inst_ebb(b).expect("Dominator got removed.");
}
@@ -209,8 +210,9 @@ impl DominatorTree {
.filter(|&(ebb, _)| self.is_reachable(ebb));
// The RPO must visit at least one predecessor before this node.
let mut idom =
reachable_preds.next().expect("EBB node must have one reachable predecessor");
let mut idom = reachable_preds
.next()
.expect("EBB node must have one reachable predecessor");
for pred in reachable_preds {
idom = self.common_dominator(idom, pred, layout);

View File

@@ -135,7 +135,9 @@ impl<T: EntityRef> ListPool<T> {
// The `wrapping_sub` handles the special case 0, which is the empty list. This way, the
// cost of the bounds check that we have to pay anyway is co-opted to handle the special
// case of the empty list.
self.data.get(idx.wrapping_sub(1)).map(|len| len.index())
self.data
.get(idx.wrapping_sub(1))
.map(|len| len.index())
}
/// Allocate a storage block with a size given by `sclass`.

View File

@@ -65,10 +65,7 @@ impl<'c, 'fc, 'fd> InsertBuilder<'c, 'fc, 'fd> {
pub fn new(dfg: &'fd mut DataFlowGraph,
pos: &'c mut Cursor<'fc>)
-> InsertBuilder<'c, 'fc, 'fd> {
InsertBuilder {
dfg: dfg,
pos: pos,
}
InsertBuilder { dfg: dfg, pos: pos }
}
}
@@ -182,8 +179,9 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
// Normally, make_inst_results() would also set the first result type, but we're not
// going to call that, so set it manually.
*self.dfg[self.inst].first_type_mut() =
self.dfg.compute_result_type(self.inst, 0, ctrl_typevar).unwrap_or_default();
*self.dfg[self.inst].first_type_mut() = self.dfg
.compute_result_type(self.inst, 0, ctrl_typevar)
.unwrap_or_default();
}
(self.inst, self.dfg)

View File

@@ -356,25 +356,37 @@ impl DataFlowGraph {
/// Get the fixed value arguments on `inst` as a slice.
pub fn inst_fixed_args(&self, inst: Inst) -> &[Value] {
let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
let fixed_args = self[inst]
.opcode()
.constraints()
.fixed_value_arguments();
&self.inst_args(inst)[..fixed_args]
}
/// Get the fixed value arguments on `inst` as a mutable slice.
pub fn inst_fixed_args_mut(&mut self, inst: Inst) -> &mut [Value] {
let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
let fixed_args = self[inst]
.opcode()
.constraints()
.fixed_value_arguments();
&mut self.inst_args_mut(inst)[..fixed_args]
}
/// Get the variable value arguments on `inst` as a slice.
pub fn inst_variable_args(&self, inst: Inst) -> &[Value] {
let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
let fixed_args = self[inst]
.opcode()
.constraints()
.fixed_value_arguments();
&self.inst_args(inst)[fixed_args..]
}
/// Get the variable value arguments on `inst` as a mutable slice.
pub fn inst_variable_args_mut(&mut self, inst: Inst) -> &mut [Value] {
let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
let fixed_args = self[inst]
.opcode()
.constraints()
.fixed_value_arguments();
&mut self.inst_args_mut(inst)[fixed_args..]
}
@@ -505,7 +517,12 @@ impl DataFlowGraph {
(inst, 1)
}
ExpandedValue::Table(idx) => {
if let ValueData::Inst { num, inst, ref mut next, .. } = self.extended_values[idx] {
if let ValueData::Inst {
num,
inst,
ref mut next,
..
} = self.extended_values[idx] {
assert!(next.is_none(), "last_res is not the last result");
*next = res.into();
assert!(num < u16::MAX, "Too many arguments to EBB");
@@ -518,8 +535,12 @@ impl DataFlowGraph {
// Now update `res` itself.
if let ExpandedValue::Table(idx) = res.expand() {
if let ValueData::Inst { ref mut num, ref mut inst, ref mut next, .. } =
self.extended_values[idx] {
if let ValueData::Inst {
ref mut num,
ref mut inst,
ref mut next,
..
} = self.extended_values[idx] {
*num = res_num;
*inst = res_inst;
*next = None.into();
@@ -565,7 +586,8 @@ impl DataFlowGraph {
///
/// Returns the new `Inst` reference where the original instruction has been moved.
pub fn redefine_first_value(&mut self, pos: &mut Cursor) -> Inst {
let orig = pos.current_inst().expect("Cursor must point at an instruction");
let orig = pos.current_inst()
.expect("Cursor must point at an instruction");
let data = self[orig].clone();
// After cloning, any secondary values are attached to both copies. Don't do that, we only
// want them on the new clone.
@@ -630,7 +652,8 @@ impl DataFlowGraph {
}
// Not a fixed result, try to extract a return type from the call signature.
self.call_signature(inst).and_then(|sigref| {
self.call_signature(inst)
.and_then(|sigref| {
self.signatures[sigref]
.return_types
.get(result_idx - fixed_results)
@@ -815,8 +838,12 @@ impl DataFlowGraph {
// Now update `arg` itself.
let arg_ebb = ebb;
if let ExpandedValue::Table(idx) = arg.expand() {
if let ValueData::Arg { ref mut num, ebb, ref mut next, .. } =
self.extended_values[idx] {
if let ValueData::Arg {
ref mut num,
ebb,
ref mut next,
..
} = self.extended_values[idx] {
*num = arg_num;
*next = None.into();
assert_eq!(arg_ebb, ebb, "{} should already belong to EBB", arg);

View File

@@ -286,14 +286,18 @@ mod tests {
assert_eq!(Value::table_with_number(1).unwrap().to_string(), "vx1");
assert_eq!(Value::direct_with_number(u32::MAX / 2), None);
assert_eq!(match Value::direct_with_number(u32::MAX / 2 - 1).unwrap().expand() {
assert_eq!(match Value::direct_with_number(u32::MAX / 2 - 1)
.unwrap()
.expand() {
ExpandedValue::Direct(i) => i.index() as u32,
_ => u32::MAX,
},
u32::MAX / 2 - 1);
assert_eq!(Value::table_with_number(u32::MAX / 2), None);
assert_eq!(match Value::table_with_number(u32::MAX / 2 - 1).unwrap().expand() {
assert_eq!(match Value::table_with_number(u32::MAX / 2 - 1)
.unwrap()
.expand() {
ExpandedValue::Table(i) => i as u32,
_ => u32::MAX,
},

View File

@@ -221,7 +221,8 @@ mod tests {
assert_eq!(sig.to_string(), "(i32)");
sig.return_types.push(ArgumentType::new(F32));
assert_eq!(sig.to_string(), "(i32) -> f32");
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");
sig.return_types.push(ArgumentType::new(B8));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8");

View File

@@ -304,15 +304,21 @@ impl InstructionData {
/// here.
pub fn analyze_branch<'a>(&'a self, pool: &'a ValueListPool) -> BranchInfo<'a> {
match self {
&InstructionData::Jump { destination, ref args, .. } => {
BranchInfo::SingleDest(destination, &args.as_slice(pool))
}
&InstructionData::Branch { destination, ref args, .. } => {
BranchInfo::SingleDest(destination, &args.as_slice(pool)[1..])
}
&InstructionData::BranchIcmp { destination, ref args, .. } => {
BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..])
}
&InstructionData::Jump {
destination,
ref args,
..
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)),
&InstructionData::Branch {
destination,
ref args,
..
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[1..]),
&InstructionData::BranchIcmp {
destination,
ref args,
..
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..]),
&InstructionData::BranchTable { table, .. } => BranchInfo::Table(table),
_ => BranchInfo::NotABranch,
}
@@ -601,9 +607,21 @@ impl OperandConstraint {
Same => Bound(ctrl_type),
LaneOf => Bound(ctrl_type.lane_type()),
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")),
HalfVector => Bound(ctrl_type.half_vector().expect("invalid type for half_vector")),
HalfWidth => {
Bound(ctrl_type
.half_width()
.expect("invalid type for half_width"))
}
DoubleWidth => {
Bound(ctrl_type
.double_width()
.expect("invalid type for double_width"))
}
HalfVector => {
Bound(ctrl_type
.half_vector()
.expect("invalid type for half_vector"))
}
DoubleVector => Bound(ctrl_type.by(2).expect("invalid type for double_vector")),
}
}

View File

@@ -66,15 +66,14 @@ impl JumpTableData {
///
/// This returns an iterator that skips any empty slots in the table.
pub fn entries<'a>(&'a self) -> Entries {
Entries(self.table
.iter()
.cloned()
.enumerate())
Entries(self.table.iter().cloned().enumerate())
}
/// 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.
@@ -109,10 +108,7 @@ impl Display for JumpTableData {
Some(first) => write!(fmt, "jump_table {}", first)?,
}
for dest in self.table
.iter()
.skip(1)
.map(|e| e.expand()) {
for dest in self.table.iter().skip(1).map(|e| e.expand()) {
match dest {
None => write!(fmt, ", 0")?,
Some(ebb) => write!(fmt, ", {}", ebb)?,

View File

@@ -125,7 +125,10 @@ impl Layout {
/// Get the last sequence number in `ebb`.
fn last_ebb_seq(&self, ebb: Ebb) -> SequenceNumber {
// Get the seq of the last instruction if it exists, otherwise use the EBB header seq.
self.ebbs[ebb].last_inst.map(|inst| self.insts[inst].seq).unwrap_or(self.ebbs[ebb].seq)
self.ebbs[ebb]
.last_inst
.map(|inst| self.insts[inst].seq)
.unwrap_or(self.ebbs[ebb].seq)
}
/// Assign a valid sequence number to `ebb` such that the numbers are still monotonic. This may
@@ -134,7 +137,10 @@ impl Layout {
assert!(self.is_ebb_inserted(ebb));
// Get the sequence number immediately before `ebb`, or 0.
let prev_seq = self.ebbs[ebb].prev.map(|prev_ebb| self.last_ebb_seq(prev_ebb)).unwrap_or(0);
let prev_seq = self.ebbs[ebb]
.prev
.map(|prev_ebb| self.last_ebb_seq(prev_ebb))
.unwrap_or(0);
// Get the sequence number immediately following `ebb`.
let next_seq = if let Some(inst) = self.ebbs[ebb].first_inst.expand() {
@@ -159,7 +165,8 @@ 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() {
@@ -436,8 +443,8 @@ 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 = self.insts.ensure(inst);
@@ -485,8 +492,8 @@ 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.
@@ -786,8 +793,9 @@ impl<'f> Cursor<'f> {
self.pos = At(next);
Some(next)
} else {
self.pos =
After(self.layout.inst_ebb(inst).expect("current instruction removed?"));
self.pos = After(self.layout
.inst_ebb(inst)
.expect("current instruction removed?"));
None
}
}
@@ -837,8 +845,9 @@ impl<'f> Cursor<'f> {
self.pos = At(prev);
Some(prev)
} else {
self.pos =
Before(self.layout.inst_ebb(inst).expect("current instruction removed?"));
self.pos = Before(self.layout
.inst_ebb(inst)
.expect("current instruction removed?"));
None
}
}

View File

@@ -348,12 +348,7 @@ mod tests {
assert_eq!(big.bits(), 64 * 256);
assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
assert_eq!(B1.by(2)
.unwrap()
.half_vector()
.unwrap()
.to_string(),
"b1");
assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
assert_eq!(I32.half_vector(), None);
assert_eq!(VOID.half_vector(), None);
@@ -383,12 +378,7 @@ mod tests {
assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
assert_eq!(B8.by(1).unwrap().to_string(), "b8");
assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
assert_eq!(B32.by(4)
.unwrap()
.by(2)
.unwrap()
.to_string(),
"b32x8");
assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");

View File

@@ -235,7 +235,11 @@ fn put_sb<CS: CodeSink + ?Sized>(bits: u16, rs1: RegUnit, rs2: RegUnit, sink: &m
}
fn recipe_sb<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::BranchIcmp { destination, ref args, .. } = func.dfg[inst] {
if let InstructionData::BranchIcmp {
destination,
ref args,
..
} = func.dfg[inst] {
let args = &args.as_slice(&func.dfg.value_lists)[0..2];
sink.reloc_ebb(RelocKind::Branch.into(), destination);
put_sb(func.encodings[inst].bits(),
@@ -248,7 +252,11 @@ fn recipe_sb<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS)
}
fn recipe_sbzero<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::Branch { destination, ref args, .. } = func.dfg[inst] {
if let InstructionData::Branch {
destination,
ref args,
..
} = func.dfg[inst] {
let args = &args.as_slice(&func.dfg.value_lists)[0..1];
sink.reloc_ebb(RelocKind::Branch.into(), destination);
put_sb(func.encodings[inst].bits(),

View File

@@ -107,7 +107,8 @@ fn legalize_inst_results<ResType>(dfg: &mut DataFlowGraph,
-> Inst
where ResType: FnMut(&DataFlowGraph, usize) -> ArgumentType
{
let mut call = pos.current_inst().expect("Cursor must point to a call instruction");
let mut call = pos.current_inst()
.expect("Cursor must point to a call instruction");
// We theoretically allow for call instructions that return a number of fixed results before
// the call return values. In practice, it doesn't happen.
@@ -364,10 +365,13 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
mut get_abi_type: ArgType)
where ArgType: FnMut(&DataFlowGraph, usize) -> ArgumentType
{
let inst = pos.current_inst().expect("Cursor must point to a call instruction");
let inst = pos.current_inst()
.expect("Cursor must point to a call instruction");
// Lift the value list out of the call instruction so we modify it.
let mut vlist = dfg[inst].take_value_list().expect("Call must have a value list");
let mut vlist = dfg[inst]
.take_value_list()
.expect("Call must have a value list");
// The value list contains all arguments to the instruction, including the callee on an
// indirect call which isn't part of the call arguments that must match the ABI signature.
@@ -405,7 +409,9 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
let mut abi_arg = 0;
for old_arg in 0..have_args {
let old_value = vlist.get(old_arg_offset + old_arg, &dfg.value_lists).unwrap();
let old_value = vlist
.get(old_arg_offset + old_arg, &dfg.value_lists)
.unwrap();
let mut put_arg = |dfg: &mut DataFlowGraph, arg| {
let abi_type = get_abi_type(dfg, abi_arg);
if dfg.value_type(arg) == abi_type.value_type {
@@ -435,7 +441,8 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
///
/// Returns `true` if any instructions were inserted.
pub fn handle_call_abi(dfg: &mut DataFlowGraph, cfg: &ControlFlowGraph, pos: &mut Cursor) -> bool {
let mut inst = pos.current_inst().expect("Cursor must point to a call instruction");
let mut inst = pos.current_inst()
.expect("Cursor must point to a call instruction");
// Start by checking if the argument types already match the signature.
let sig_ref = match check_call_signature(dfg, inst) {
@@ -475,7 +482,8 @@ pub fn handle_return_abi(dfg: &mut DataFlowGraph,
pos: &mut Cursor,
sig: &Signature)
-> bool {
let inst = pos.current_inst().expect("Cursor must point to a return instruction");
let inst = pos.current_inst()
.expect("Cursor must point to a return instruction");
// Check if the returned types already match the signature.
if check_return_signature(dfg, inst, sig) {

View File

@@ -125,7 +125,9 @@ fn split_any(dfg: &mut DataFlowGraph,
"Predecessor not a branch: {}",
dfg.display_inst(inst));
let fixed_args = branch_opc.constraints().fixed_value_arguments();
let mut args = dfg[inst].take_value_list().expect("Branches must have value lists.");
let mut args = dfg[inst]
.take_value_list()
.expect("Branches must have value lists.");
let num_args = args.len(&dfg.value_lists);
// Get the old value passed to the EBB argument we're repairing.
let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists)
@@ -142,12 +144,14 @@ fn split_any(dfg: &mut DataFlowGraph,
let (lo, hi) = split_value(dfg, pos, old_arg, repair.concat, &mut repairs);
// The `lo` part replaces the original argument.
*args.get_mut(fixed_args + repair.num, &mut dfg.value_lists).unwrap() = lo;
*args.get_mut(fixed_args + repair.num, &mut dfg.value_lists)
.unwrap() = lo;
// The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
// same EBB, there could be multiple arguments missing.
if num_args > fixed_args + repair.hi_num {
*args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists).unwrap() = hi;
*args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists)
.unwrap() = hi;
} else {
// We need to append one or more arguments. If we're adding more than one argument,
// there must be pending repairs on the stack that will fill in the correct values

View File

@@ -35,10 +35,7 @@ mod tests {
fn check(x: &[u32], want: &[u32]) {
assert_eq!(x.len(), want.len());
let want_count = want.iter()
.cloned()
.filter(|&x| x % 10 == 0)
.count();
let want_count = want.iter().cloned().filter(|&x| x % 10 == 0).count();
let mut v = Vec::new();
v.extend(x.iter().cloned());
let count = partition_slice(&mut v[..], |&x| x % 10 == 0);

View File

@@ -232,7 +232,9 @@ impl<'a> Context<'a> {
if let Affinity::Reg(rc_index) = lv.affinity {
let regclass = self.reginfo.rc(rc_index);
// TODO: Fall back to a top-level super-class. Sub-classes are only hints.
let regunit = regs.iter(regclass).next().expect("Out of registers for arguments");
let regunit = regs.iter(regclass)
.next()
.expect("Out of registers for arguments");
regs.take(regclass, regunit);
*locations.ensure(lv.value) = ValueLoc::Reg(regunit);
}

View File

@@ -52,6 +52,7 @@ impl Context {
// TODO: Second pass: Spilling.
// Third pass: Reload and coloring.
self.coloring.run(isa, func, domtree, &mut self.liveness, &mut self.tracker);
self.coloring
.run(isa, func, domtree, &mut self.liveness, &mut self.tracker);
}
}

View File

@@ -68,7 +68,8 @@ impl LiveValueVec {
/// Add a new live value to `values`.
fn push(&mut self, value: Value, endpoint: Inst, affinity: Affinity) {
self.values.push(LiveValue {
self.values
.push(LiveValue {
value: value,
endpoint: endpoint,
affinity: affinity,
@@ -163,11 +164,14 @@ impl LiveValueTracker {
// If the immediate dominator exits, we must have a stored list for it. This is a
// requirement to the order EBBs are visited: All dominators must have been processed
// before the current EBB.
let idom_live_list =
self.idom_sets.get(&idom).expect("No stored live set for dominator");
let idom_live_list = self.idom_sets
.get(&idom)
.expect("No stored live set for dominator");
// Get just the values that are live-in to `ebb`.
for &value in idom_live_list.as_slice(&self.idom_pool) {
let lr = liveness.get(value).expect("Immediate dominator value has no live range");
let lr = liveness
.get(value)
.expect("Immediate dominator value has no live range");
// Check if this value is live-in here.
if let Some(endpoint) = lr.livein_local_end(ebb, program_order) {
@@ -179,7 +183,9 @@ impl LiveValueTracker {
// Now add all the live arguments to `ebb`.
let first_arg = self.live.values.len();
for value in dfg.ebb_args(ebb) {
let lr = liveness.get(value).expect("EBB argument value has no live range");
let lr = liveness
.get(value)
.expect("EBB argument value has no live range");
assert_eq!(lr.def(), ebb.into());
match lr.def_local_end().into() {
ExpandedProgramPoint::Inst(endpoint) => {
@@ -259,13 +265,12 @@ impl LiveValueTracker {
/// Save the current set of live values so it is associated with `idom`.
fn save_idom_live_set(&mut self, idom: Inst) {
let values = self.live
.values
.iter()
.map(|lv| lv.value);
let values = self.live.values.iter().map(|lv| lv.value);
let pool = &mut self.idom_pool;
// If there already is a set saved for `idom`, just keep it.
self.idom_sets.entry(idom).or_insert_with(|| {
self.idom_sets
.entry(idom)
.or_insert_with(|| {
let mut list = ValueList::default();
list.extend(values, pool);
list

View File

@@ -205,7 +205,8 @@ fn get_or_create<'a>(lrset: &'a mut LiveRangeSet,
def = inst.into();
// Initialize the affinity from the defining instruction's result constraints.
// Don't do this for call return values which are always tied to a single register.
affinity = recipe_constraints.get(func.encodings[inst].recipe())
affinity = recipe_constraints
.get(func.encodings[inst].recipe())
.and_then(|rc| rc.outs.get(rnum))
.map(Affinity::new)
.unwrap_or_default();
@@ -315,7 +316,8 @@ impl Liveness {
let recipe = func.encodings[inst].recipe();
// Iterator of constraints, one per value operand.
// TODO: Should we fail here if the instruction doesn't have a valid encoding?
let mut operand_constraints = recipe_constraints.get(recipe)
let mut operand_constraints = recipe_constraints
.get(recipe)
.map(|c| c.ins)
.unwrap_or(&[])
.iter();

View File

@@ -221,7 +221,9 @@ impl LiveRange {
/// Return `Ok(n)` if `liveins[n]` already contains `ebb`.
/// Otherwise, return `Err(n)` with the index where such an interval should be inserted.
fn find_ebb_interval<PO: ProgramOrder>(&self, ebb: Ebb, order: &PO) -> Result<usize, usize> {
self.liveins.binary_search_by(|intv| order.cmp(intv.begin, ebb)).or_else(|n| {
self.liveins
.binary_search_by(|intv| order.cmp(intv.begin, ebb))
.or_else(|n| {
// The interval at `n-1` may cover `ebb`.
if n > 0 && order.cmp(self.liveins[n - 1].end, ebb) == Ordering::Greater {
Ok(n - 1)
@@ -307,7 +309,8 @@ impl LiveRange {
}
// Cannot coalesce; insert new interval
(false, false) => {
self.liveins.insert(n,
self.liveins
.insert(n,
Interval {
begin: ebb,
end: to,
@@ -361,7 +364,9 @@ impl LiveRange {
/// answer, but it is also possible that an even later program point is returned. So don't
/// depend on the returned `Inst` to belong to `ebb`.
pub fn livein_local_end<PO: ProgramOrder>(&self, ebb: Ebb, order: &PO) -> Option<Inst> {
self.find_ebb_interval(ebb, order).ok().map(|n| self.liveins[n].end)
self.find_ebb_interval(ebb, order)
.ok()
.map(|n| self.liveins[n].end)
}
}

View File

@@ -177,8 +177,9 @@ impl<'a> Verifier<'a> {
let fixed_results = inst_data.opcode().constraints().fixed_results();
// var_results is 0 if we aren't a call instruction
let var_results =
dfg.call_signature(inst).map(|sig| dfg.signatures[sig].return_types.len()).unwrap_or(0);
let var_results = dfg.call_signature(inst)
.map(|sig| dfg.signatures[sig].return_types.len())
.unwrap_or(0);
let total_results = fixed_results + var_results;
if total_results == 0 {
@@ -218,9 +219,21 @@ impl<'a> Verifier<'a> {
&MultiAry { ref args, .. } => {
self.verify_value_list(inst, args)?;
}
&Jump { destination, ref args, .. } |
&Branch { destination, ref args, .. } |
&BranchIcmp { destination, ref args, .. } => {
&Jump {
destination,
ref args,
..
} |
&Branch {
destination,
ref args,
..
} |
&BranchIcmp {
destination,
ref args,
..
} => {
self.verify_ebb(inst, destination)?;
self.verify_value_list(inst, args)?;
}
@@ -265,10 +278,7 @@ impl<'a> Verifier<'a> {
}
fn verify_sig_ref(&self, inst: Inst, s: SigRef) -> Result<()> {
if !self.func
.dfg
.signatures
.is_valid(s) {
if !self.func.dfg.signatures.is_valid(s) {
err!(inst, "invalid signature reference {}", s)
} else {
Ok(())
@@ -276,10 +286,7 @@ impl<'a> Verifier<'a> {
}
fn verify_func_ref(&self, inst: Inst, f: FuncRef) -> Result<()> {
if !self.func
.dfg
.ext_funcs
.is_valid(f) {
if !self.func.dfg.ext_funcs.is_valid(f) {
err!(inst, "invalid function reference {}", f)
} else {
Ok(())
@@ -326,7 +333,8 @@ impl<'a> Verifier<'a> {
def_inst);
}
// Defining instruction dominates the instruction that uses the value.
if !self.domtree.dominates(def_inst, loc_inst, &self.func.layout) {
if !self.domtree
.dominates(def_inst, loc_inst, &self.func.layout) {
return err!(loc_inst, "uses value from non-dominating {}", def_inst);
}
}
@@ -343,7 +351,8 @@ impl<'a> Verifier<'a> {
ebb);
}
// The defining EBB dominates the instruction using this value.
if !self.domtree.ebb_dominates(ebb, loc_inst, &self.func.layout) {
if !self.domtree
.ebb_dominates(ebb, loc_inst, &self.func.layout) {
return err!(loc_inst, "uses value arg from non-dominating {}", ebb);
}
}
@@ -378,10 +387,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).enumerate() {
let arg_type = self.func.dfg.value_type(arg);
if arg_type != expected_types[i].value_type {
return err!(ebb,
@@ -452,11 +458,7 @@ impl<'a> Verifier<'a> {
fn typecheck_fixed_args(&self, inst: Inst, ctrl_type: Type) -> Result<()> {
let constraints = self.func.dfg[inst].opcode().constraints();
for (i, &arg) in self.func
.dfg
.inst_fixed_args(inst)
.iter()
.enumerate() {
for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() {
let arg_type = self.func.dfg.value_type(arg);
match constraints.value_argument_constraint(i, ctrl_type) {
ResolvedConstraint::Bound(expected_type) => {
@@ -510,13 +512,17 @@ impl<'a> Verifier<'a> {
match self.func.dfg[inst].analyze_call(&self.func.dfg.value_lists) {
CallInfo::Direct(func_ref, _) => {
let sig_ref = self.func.dfg.ext_funcs[func_ref].signature;
let arg_types =
self.func.dfg.signatures[sig_ref].argument_types.iter().map(|a| a.value_type);
let arg_types = self.func.dfg.signatures[sig_ref]
.argument_types
.iter()
.map(|a| a.value_type);
self.typecheck_variable_args_iterator(inst, arg_types)?;
}
CallInfo::Indirect(sig_ref, _) => {
let arg_types =
self.func.dfg.signatures[sig_ref].argument_types.iter().map(|a| a.value_type);
let arg_types = self.func.dfg.signatures[sig_ref]
.argument_types
.iter()
.map(|a| a.value_type);
self.typecheck_variable_args_iterator(inst, arg_types)?;
}
CallInfo::NotACall => {}
@@ -673,7 +679,8 @@ mod tests {
let mut func = Function::new();
let ebb0 = func.dfg.make_ebb();
func.layout.append_ebb(ebb0);
let nullary_with_bad_opcode = func.dfg.make_inst(InstructionData::Nullary {
let nullary_with_bad_opcode = func.dfg
.make_inst(InstructionData::Nullary {
opcode: Opcode::Jump,
ty: types::VOID,
});

View File

@@ -262,7 +262,11 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
IntCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
IntCompareImm { cond, arg, imm, .. } => write!(w, " {}, {}, {}", cond, arg, imm),
FloatCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
Jump { destination, ref args, .. } => {
Jump {
destination,
ref args,
..
} => {
if args.is_empty() {
write!(w, " {}", destination)
} else {
@@ -272,7 +276,11 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
DisplayValues(args.as_slice(pool)))
}
}
Branch { destination, ref args, .. } => {
Branch {
destination,
ref args,
..
} => {
let args = args.as_slice(pool);
write!(w, " {}, {}", args[0], destination)?;
if args.len() > 1 {
@@ -280,7 +288,12 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
}
Ok(())
}
BranchIcmp { cond, destination, ref args, .. } => {
BranchIcmp {
cond,
destination,
ref args,
..
} => {
let args = args.as_slice(pool);
write!(w, " {}, {}, {}, {}", cond, args[0], args[1], destination)?;
if args.len() > 2 {

View File

@@ -183,7 +183,9 @@ impl Checker {
continue;
}
Directive::Regex(ref var, ref rx) => {
state.vars.insert(var.clone(),
state
.vars
.insert(var.clone(),
VarDef {
value: Value::Regex(Cow::Borrowed(rx)),
offset: 0,
@@ -208,10 +210,14 @@ impl Checker {
state.recorder.directive(not_idx);
if let Some((s, e)) = rx.find(&text[not_begin..match_begin]) {
// Matched `not:` pattern.
state.recorder.matched_not(rx.as_str(), (not_begin + s, not_begin + e));
state
.recorder
.matched_not(rx.as_str(), (not_begin + s, not_begin + e));
return Ok(false);
} else {
state.recorder.missed_not(rx.as_str(), (not_begin, match_begin));
state
.recorder
.missed_not(rx.as_str(), (not_begin, match_begin));
}
}
}
@@ -410,9 +416,11 @@ mod tests {
Ok(true));
assert_eq!(b.directive("regex: X = tommy").map_err(e2s),
Err("expected '=' after variable 'X' in regex: X = tommy".to_string()));
assert_eq!(b.directive("[arm]not: patt $x $(y) here").map_err(e2s),
assert_eq!(b.directive("[arm]not: patt $x $(y) here")
.map_err(e2s),
Ok(true));
assert_eq!(b.directive("[x86]sameln: $x $(y=[^]]*) there").map_err(e2s),
assert_eq!(b.directive("[x86]sameln: $x $(y=[^]]*) there")
.map_err(e2s),
Ok(true));
// Windows line ending sneaking in.
assert_eq!(b.directive("regex: Y=foo\r").map_err(e2s), Ok(true));

View File

@@ -119,7 +119,8 @@ impl<'a> Display for Explainer<'a> {
m.regex)?;
// Emit any variable definitions.
if let Ok(found) = self.vardefs.binary_search_by_key(&m.directive, |v| v.directive) {
if let Ok(found) = self.vardefs
.binary_search_by_key(&m.directive, |v| v.directive) {
let mut first = found;
while first > 0 && self.vardefs[first - 1].directive == m.directive {
first -= 1;
@@ -147,7 +148,8 @@ impl<'a> Recorder for Explainer<'a> {
}
fn matched_check(&mut self, regex: &str, matched: MatchRange) {
self.matches.push(Match {
self.matches
.push(Match {
directive: self.directive,
is_match: true,
is_not: false,
@@ -157,7 +159,8 @@ impl<'a> Recorder for Explainer<'a> {
}
fn matched_not(&mut self, regex: &str, matched: MatchRange) {
self.matches.push(Match {
self.matches
.push(Match {
directive: self.directive,
is_match: true,
is_not: true,
@@ -167,7 +170,8 @@ impl<'a> Recorder for Explainer<'a> {
}
fn missed_check(&mut self, regex: &str, searched: MatchRange) {
self.matches.push(Match {
self.matches
.push(Match {
directive: self.directive,
is_match: false,
is_not: false,
@@ -177,7 +181,8 @@ impl<'a> Recorder for Explainer<'a> {
}
fn missed_not(&mut self, regex: &str, searched: MatchRange) {
self.matches.push(Match {
self.matches
.push(Match {
directive: self.directive,
is_match: false,
is_not: true,
@@ -187,7 +192,8 @@ impl<'a> Recorder for Explainer<'a> {
}
fn defined_var(&mut self, varname: &str, value: &str) {
self.vardefs.push(VarDef {
self.vardefs
.push(VarDef {
directive: self.directive,
varname: varname.to_owned(),
value: value.to_owned(),

View File

@@ -107,7 +107,8 @@ impl<'a> Context<'a> {
// Get the index of a recipe name if it exists.
fn find_recipe_index(&self, recipe_name: &str) -> Option<u16> {
if let Some(unique_isa) = self.unique_isa {
unique_isa.recipe_names()
unique_isa
.recipe_names()
.iter()
.position(|&name| name == recipe_name)
.map(|idx| idx as u16)
@@ -118,17 +119,14 @@ impl<'a> Context<'a> {
// Allocate a new stack slot and add a mapping number -> StackSlot.
fn add_ss(&mut self, number: u32, data: StackSlotData, loc: &Location) -> Result<()> {
self.map.def_ss(number, self.function.stack_slots.push(data), loc)
self.map
.def_ss(number, self.function.stack_slots.push(data), loc)
}
// Allocate a new signature and add a mapping number -> SigRef.
fn add_sig(&mut self, number: u32, data: Signature, loc: &Location) -> Result<()> {
self.map.def_sig(number,
self.function
.dfg
.signatures
.push(data),
loc)
self.map
.def_sig(number, self.function.dfg.signatures.push(data), loc)
}
// Resolve a reference to a signature.
@@ -141,12 +139,8 @@ impl<'a> Context<'a> {
// Allocate a new external function and add a mapping number -> FuncRef.
fn add_fn(&mut self, number: u32, data: ExtFuncData, loc: &Location) -> Result<()> {
self.map.def_fn(number,
self.function
.dfg
.ext_funcs
.push(data),
loc)
self.map
.def_fn(number, self.function.dfg.ext_funcs.push(data), loc)
}
// Resolve a reference to a function.
@@ -159,7 +153,8 @@ impl<'a> Context<'a> {
// Allocate a new jump table and add a mapping number -> JumpTable.
fn add_jt(&mut self, number: u32, data: JumpTableData, loc: &Location) -> Result<()> {
self.map.def_jt(number, self.function.jump_tables.push(data), loc)
self.map
.def_jt(number, self.function.jump_tables.push(data), loc)
}
// Resolve a reference to a jump table.
@@ -238,19 +233,34 @@ impl<'a> Context<'a> {
}
InstructionData::MultiAry { ref mut args, .. } => {
self.map.rewrite_values(args.as_mut_slice(value_lists), loc)?;
self.map
.rewrite_values(args.as_mut_slice(value_lists), loc)?;
}
InstructionData::Jump { ref mut destination, ref mut args, .. } |
InstructionData::Branch { ref mut destination, ref mut args, .. } |
InstructionData::BranchIcmp { ref mut destination, ref mut args, .. } => {
InstructionData::Jump {
ref mut destination,
ref mut args,
..
} |
InstructionData::Branch {
ref mut destination,
ref mut args,
..
} |
InstructionData::BranchIcmp {
ref mut destination,
ref mut args,
..
} => {
self.map.rewrite_ebb(destination, loc)?;
self.map.rewrite_values(args.as_mut_slice(value_lists), loc)?;
self.map
.rewrite_values(args.as_mut_slice(value_lists), loc)?;
}
InstructionData::Call { ref mut args, .. } |
InstructionData::IndirectCall { ref mut args, .. } => {
self.map.rewrite_values(args.as_mut_slice(value_lists), loc)?;
self.map
.rewrite_values(args.as_mut_slice(value_lists), loc)?;
}
}
}
@@ -307,7 +317,8 @@ impl<'a> Parser<'a> {
Token::Comment(text) => {
// Gather comments, associate them with `comment_entity`.
if let Some(entity) = self.comment_entity {
self.comments.push(Comment {
self.comments
.push(Comment {
entity: entity,
text: text,
});
@@ -464,7 +475,8 @@ impl<'a> Parser<'a> {
self.consume();
// Lexer just gives us raw text that looks like an integer.
// Parse it as a u8 to check for overflow and other issues.
text.parse().map_err(|_| self.error("expected u8 decimal immediate"))
text.parse()
.map_err(|_| self.error("expected u8 decimal immediate"))
} else {
err!(self.loc, err_msg)
}
@@ -477,7 +489,8 @@ impl<'a> Parser<'a> {
self.consume();
// Lexer just gives us raw text that looks like an integer.
// Parse it as a u32 to check for overflow and other issues.
text.parse().map_err(|_| self.error("expected u32 decimal immediate"))
text.parse()
.map_err(|_| self.error("expected u32 decimal immediate"))
} else {
err!(self.loc, err_msg)
}
@@ -714,7 +727,9 @@ impl<'a> Parser<'a> {
sig.return_types = self.parse_argument_list(unique_isa)?;
}
if sig.argument_types.iter().all(|a| a.location.is_assigned()) {
if sig.argument_types
.iter()
.all(|a| a.location.is_assigned()) {
sig.compute_argument_bytes();
}
@@ -816,35 +831,23 @@ impl<'a> Parser<'a> {
match self.token() {
Some(Token::StackSlot(..)) => {
self.gather_comments(ctx.function.stack_slots.next_key());
self.parse_stack_slot_decl().and_then(|(num, dat)| {
ctx.add_ss(num, dat, &self.loc)
})
self.parse_stack_slot_decl()
.and_then(|(num, dat)| ctx.add_ss(num, dat, &self.loc))
}
Some(Token::SigRef(..)) => {
self.gather_comments(ctx.function
.dfg
.signatures
.next_key());
self.parse_signature_decl(ctx.unique_isa).and_then(|(num, dat)| {
ctx.add_sig(num,
dat,
&self.loc)
})
self.gather_comments(ctx.function.dfg.signatures.next_key());
self.parse_signature_decl(ctx.unique_isa)
.and_then(|(num, dat)| ctx.add_sig(num, dat, &self.loc))
}
Some(Token::FuncRef(..)) => {
self.gather_comments(ctx.function
.dfg
.ext_funcs
.next_key());
self.parse_function_decl(ctx).and_then(|(num, dat)| {
ctx.add_fn(num, dat, &self.loc)
})
self.gather_comments(ctx.function.dfg.ext_funcs.next_key());
self.parse_function_decl(ctx)
.and_then(|(num, dat)| ctx.add_fn(num, dat, &self.loc))
}
Some(Token::JumpTable(..)) => {
self.gather_comments(ctx.function.jump_tables.next_key());
self.parse_jump_table_decl().and_then(|(num, dat)| {
ctx.add_jt(num, dat, &self.loc)
})
self.parse_jump_table_decl()
.and_then(|(num, dat)| ctx.add_jt(num, dat, &self.loc))
}
// More to come..
_ => return Ok(()),
@@ -861,7 +864,8 @@ impl<'a> Parser<'a> {
self.match_identifier("stack_slot", "expected 'stack_slot'")?;
// stack-slot-decl ::= StackSlot(ss) "=" "stack_slot" * Bytes {"," stack-slot-flag}
let bytes: i64 = self.match_imm64("expected byte-size in stack_slot decl")?.into();
let bytes: i64 = self.match_imm64("expected byte-size in stack_slot decl")?
.into();
if bytes < 0 {
return err!(self.loc, "negative stack slot size");
}
@@ -903,11 +907,10 @@ impl<'a> Parser<'a> {
let data = match self.token() {
Some(Token::Identifier("function")) => {
let (loc, name, sig) = self.parse_function_spec(ctx.unique_isa)?;
let sigref = ctx.function
.dfg
.signatures
.push(sig);
ctx.map.def_entity(sigref.into(), &loc).expect("duplicate SigRef entities created");
let sigref = ctx.function.dfg.signatures.push(sig);
ctx.map
.def_entity(sigref.into(), &loc)
.expect("duplicate SigRef entities created");
ExtFuncData {
name: name,
signature: sigref,
@@ -1224,7 +1227,9 @@ impl<'a> Parser<'a> {
let inst = ctx.function.dfg.make_inst(inst_data);
let num_results = ctx.function.dfg.make_inst_results(inst, ctrl_typevar);
ctx.function.layout.append_inst(inst, ebb);
ctx.map.def_entity(inst.into(), &opcode_loc).expect("duplicate inst references created");
ctx.map
.def_entity(inst.into(), &opcode_loc)
.expect("duplicate inst references created");
if let Some(encoding) = encoding {
*ctx.function.encodings.ensure(inst) = encoding;
@@ -1282,16 +1287,19 @@ impl<'a> Parser<'a> {
inst_data: &InstructionData)
-> Result<Type> {
let constraints = opcode.constraints();
let ctrl_type = match explicit_ctrl_type {
let ctrl_type =
match explicit_ctrl_type {
Some(t) => t,
None => {
if constraints.use_typevar_operand() {
// This is an opcode that supports type inference, AND there was no explicit
// type specified. Look up `ctrl_value` to see if it was defined already.
// TBD: If it is defined in another block, the type should have been specified
// explicitly. It is unfortunate that the correctness of IL depends on the
// layout of the blocks.
let ctrl_src_value = inst_data.typevar_operand(&ctx.function.dfg.value_lists)
// This is an opcode that supports type inference, AND there was no
// explicit type specified. Look up `ctrl_value` to see if it was defined
// already.
// TBD: If it is defined in another block, the type should have been
// specified explicitly. It is unfortunate that the correctness of IL
// depends on the layout of the blocks.
let ctrl_src_value = inst_data
.typevar_operand(&ctx.function.dfg.value_lists)
.expect("Constraints <-> Format inconsistency");
ctx.function.dfg.value_type(match ctx.map.get_value(ctrl_src_value) {
Some(v) => v,
@@ -1309,8 +1317,8 @@ impl<'a> Parser<'a> {
}
})
} else if constraints.is_polymorphic() {
// This opcode does not support type inference, so the explicit type variable
// is required.
// This opcode does not support type inference, so the explicit type
// variable is required.
return err!(self.loc,
"type variable required for polymorphic opcode, e.g. '{}.{}'",
opcode,
@@ -1629,7 +1637,8 @@ impl<'a> Parser<'a> {
InstructionFormat::BranchTable => {
let arg = self.match_value("expected SSA value operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let table = self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))?;
let table = self.match_jt()
.and_then(|num| ctx.get_jt(num, &self.loc))?;
InstructionData::BranchTable {
opcode: opcode,
ty: VOID,
@@ -1679,7 +1688,8 @@ mod tests {
assert_eq!(v4.to_string(), "v0");
let vx3 = details.map.lookup_str("vx3").unwrap();
assert_eq!(vx3.to_string(), "vx0");
let aliased_to = func.dfg.resolve_aliases(Value::table_with_number(0).unwrap());
let aliased_to = func.dfg
.resolve_aliases(Value::table_with_number(0).unwrap());
assert_eq!(aliased_to.to_string(), "v0");
}
@@ -1696,11 +1706,20 @@ mod tests {
"(i8 uext inreg, f32, f64) -> i32 sext, f64");
// `void` is not recognized as a type by the lexer. It should not appear in files.
assert_eq!(Parser::new("() -> void").parse_signature(None).unwrap_err().to_string(),
assert_eq!(Parser::new("() -> void")
.parse_signature(None)
.unwrap_err()
.to_string(),
"1: expected argument type");
assert_eq!(Parser::new("i8 -> i8").parse_signature(None).unwrap_err().to_string(),
assert_eq!(Parser::new("i8 -> i8")
.parse_signature(None)
.unwrap_err()
.to_string(),
"1: expected function signature: ( args... )");
assert_eq!(Parser::new("(i8 -> i8").parse_signature(None).unwrap_err().to_string(),
assert_eq!(Parser::new("(i8 -> i8")
.parse_signature(None)
.unwrap_err()
.to_string(),
"1: expected ')' after function arguments");
}

View File

@@ -40,7 +40,10 @@ impl<'a> TestCommand<'a> {
let cmd = parts.next().unwrap_or("");
TestCommand {
command: cmd,
options: parts.filter(|s| !s.is_empty()).map(TestOption::new).collect(),
options: parts
.filter(|s| !s.is_empty())
.map(TestOption::new)
.collect(),
}
}
}