Update rustfmt to 0.9.0.
This commit is contained in:
@@ -108,9 +108,12 @@ impl SubTest for TestBinEmit {
|
||||
for ebb in func.layout.ebbs() {
|
||||
for inst in func.layout.ebb_insts(ebb) {
|
||||
if !func.encodings[inst].is_legal() {
|
||||
if let Ok(enc) = isa.encode(&func.dfg,
|
||||
&func.dfg[inst],
|
||||
func.dfg.ctrl_typevar(inst)) {
|
||||
if let Ok(enc) = isa.encode(
|
||||
&func.dfg,
|
||||
&func.dfg[inst],
|
||||
func.dfg.ctrl_typevar(inst),
|
||||
)
|
||||
{
|
||||
func.encodings[inst] = enc;
|
||||
}
|
||||
}
|
||||
@@ -118,8 +121,9 @@ impl SubTest for TestBinEmit {
|
||||
}
|
||||
|
||||
// Relax branches and compute EBB offsets based on the encodings.
|
||||
let code_size = binemit::relax_branches(&mut func, isa)
|
||||
.map_err(|e| pretty_error(&func, context.isa, e))?;
|
||||
let code_size = binemit::relax_branches(&mut func, isa).map_err(|e| {
|
||||
pretty_error(&func, context.isa, e)
|
||||
})?;
|
||||
|
||||
// Collect all of the 'bin:' directives on instructions.
|
||||
let mut bins = HashMap::new();
|
||||
@@ -128,16 +132,20 @@ impl SubTest for TestBinEmit {
|
||||
match comment.entity {
|
||||
AnyEntity::Inst(inst) => {
|
||||
if let Some(prev) = bins.insert(inst, want) {
|
||||
return Err(format!("multiple 'bin:' directives on {}: '{}' and '{}'",
|
||||
func.dfg.display_inst(inst, isa),
|
||||
prev,
|
||||
want));
|
||||
return Err(format!(
|
||||
"multiple 'bin:' directives on {}: '{}' and '{}'",
|
||||
func.dfg.display_inst(inst, isa),
|
||||
prev,
|
||||
want
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(format!("'bin:' directive on non-inst {}: {}",
|
||||
comment.entity,
|
||||
comment.text))
|
||||
return Err(format!(
|
||||
"'bin:' directive on non-inst {}: {}",
|
||||
comment.entity,
|
||||
comment.text
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,10 +160,12 @@ impl SubTest for TestBinEmit {
|
||||
for ebb in func.layout.ebbs() {
|
||||
divert.clear();
|
||||
// Correct header offsets should have been computed by `relax_branches()`.
|
||||
assert_eq!(sink.offset,
|
||||
func.offsets[ebb],
|
||||
"Inconsistent {} header offset",
|
||||
ebb);
|
||||
assert_eq!(
|
||||
sink.offset,
|
||||
func.offsets[ebb],
|
||||
"Inconsistent {} header offset",
|
||||
ebb
|
||||
);
|
||||
for inst in func.layout.ebb_insts(ebb) {
|
||||
sink.text.clear();
|
||||
let enc = func.encodings[inst];
|
||||
@@ -166,34 +176,44 @@ impl SubTest for TestBinEmit {
|
||||
isa.emit_inst(&func, inst, &mut divert, &mut sink);
|
||||
let emitted = sink.offset - before;
|
||||
// Verify the encoding recipe sizes against the ISAs emit_inst implementation.
|
||||
assert_eq!(emitted,
|
||||
encinfo.bytes(enc),
|
||||
"Inconsistent size for [{}] {}",
|
||||
encinfo.display(enc),
|
||||
func.dfg.display_inst(inst, isa));
|
||||
assert_eq!(
|
||||
emitted,
|
||||
encinfo.bytes(enc),
|
||||
"Inconsistent size for [{}] {}",
|
||||
encinfo.display(enc),
|
||||
func.dfg.display_inst(inst, isa)
|
||||
);
|
||||
}
|
||||
|
||||
// Check against bin: directives.
|
||||
if let Some(want) = bins.remove(&inst) {
|
||||
if !enc.is_legal() {
|
||||
return Err(format!("{} can't be encoded: {}",
|
||||
inst,
|
||||
func.dfg.display_inst(inst, isa)));
|
||||
return Err(format!(
|
||||
"{} can't be encoded: {}",
|
||||
inst,
|
||||
func.dfg.display_inst(inst, isa)
|
||||
));
|
||||
}
|
||||
let have = sink.text.trim();
|
||||
if have != want {
|
||||
return Err(format!("Bad machine code for {}: {}\nWant: {}\nGot: {}",
|
||||
inst,
|
||||
func.dfg.display_inst(inst, isa),
|
||||
want,
|
||||
have));
|
||||
return Err(format!(
|
||||
"Bad machine code for {}: {}\nWant: {}\nGot: {}",
|
||||
inst,
|
||||
func.dfg.display_inst(inst, isa),
|
||||
want,
|
||||
have
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sink.offset != code_size {
|
||||
return Err(format!("Expected code size {}, got {}", code_size, sink.offset));
|
||||
return Err(format!(
|
||||
"Expected code size {}, got {}",
|
||||
code_size,
|
||||
sink.offset
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -41,22 +41,30 @@ impl SubTest for TestCompile {
|
||||
let mut comp_ctx = cretonne::Context::new();
|
||||
comp_ctx.func = func.into_owned();
|
||||
|
||||
let code_size = comp_ctx
|
||||
.compile(isa)
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
let code_size = comp_ctx.compile(isa).map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
|
||||
dbg!("Generated {} bytes of code:\n{}",
|
||||
code_size,
|
||||
comp_ctx.func.display(isa));
|
||||
dbg!(
|
||||
"Generated {} bytes of code:\n{}",
|
||||
code_size,
|
||||
comp_ctx.func.display(isa)
|
||||
);
|
||||
|
||||
// Finally verify that the returned code size matches the emitted bytes.
|
||||
let mut sink = SizeSink { offset: 0 };
|
||||
binemit::emit_function(&comp_ctx.func,
|
||||
|func, inst, div, sink| isa.emit_inst(func, inst, div, sink),
|
||||
&mut sink);
|
||||
binemit::emit_function(
|
||||
&comp_ctx.func,
|
||||
|func, inst, div, sink| isa.emit_inst(func, inst, div, sink),
|
||||
&mut sink,
|
||||
);
|
||||
|
||||
if sink.offset != code_size {
|
||||
return Err(format!("Expected code size {}, got {}", code_size, sink.offset));
|
||||
return Err(format!(
|
||||
"Expected code size {}, got {}",
|
||||
code_size,
|
||||
sink.offset
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -46,7 +46,9 @@ impl ConcurrentRunner {
|
||||
heartbeat_thread(reply_tx.clone());
|
||||
|
||||
let handles = (0..num_cpus::get())
|
||||
.map(|num| worker_thread(num, request_mutex.clone(), reply_tx.clone()))
|
||||
.map(|num| {
|
||||
worker_thread(num, request_mutex.clone(), reply_tx.clone())
|
||||
})
|
||||
.collect();
|
||||
|
||||
ConcurrentRunner {
|
||||
@@ -97,16 +99,17 @@ fn heartbeat_thread(replies: Sender<Reply>) -> thread::JoinHandle<()> {
|
||||
thread::Builder::new()
|
||||
.name("heartbeat".to_string())
|
||||
.spawn(move || while replies.send(Reply::Tick).is_ok() {
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
})
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Spawn a worker thread running tests.
|
||||
fn worker_thread(thread_num: usize,
|
||||
requests: Arc<Mutex<Receiver<Request>>>,
|
||||
replies: Sender<Reply>)
|
||||
-> thread::JoinHandle<()> {
|
||||
fn worker_thread(
|
||||
thread_num: usize,
|
||||
requests: Arc<Mutex<Receiver<Request>>>,
|
||||
replies: Sender<Reply>,
|
||||
) -> thread::JoinHandle<()> {
|
||||
thread::Builder::new()
|
||||
.name(format!("worker #{}", thread_num))
|
||||
.spawn(move || {
|
||||
|
||||
@@ -50,9 +50,11 @@ impl SubTest for TestDomtree {
|
||||
let inst = match comment.entity {
|
||||
AnyEntity::Inst(inst) => inst,
|
||||
_ => {
|
||||
return Err(format!("annotation on non-inst {}: {}",
|
||||
comment.entity,
|
||||
comment.text))
|
||||
return Err(format!(
|
||||
"annotation on non-inst {}: {}",
|
||||
comment.entity,
|
||||
comment.text
|
||||
))
|
||||
}
|
||||
};
|
||||
for src_ebb in tail.split_whitespace() {
|
||||
@@ -69,17 +71,21 @@ impl SubTest for TestDomtree {
|
||||
// Compare to computed domtree.
|
||||
match domtree.idom(ebb) {
|
||||
Some(got_inst) if got_inst != inst => {
|
||||
return Err(format!("mismatching idoms for {}:\n\
|
||||
return Err(format!(
|
||||
"mismatching idoms for {}:\n\
|
||||
want: {}, got: {}",
|
||||
src_ebb,
|
||||
inst,
|
||||
got_inst));
|
||||
src_ebb,
|
||||
inst,
|
||||
got_inst
|
||||
));
|
||||
}
|
||||
None => {
|
||||
return Err(format!("mismatching idoms for {}:\n\
|
||||
return Err(format!(
|
||||
"mismatching idoms for {}:\n\
|
||||
want: {}, got: unreachable",
|
||||
src_ebb,
|
||||
inst));
|
||||
src_ebb,
|
||||
inst
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -89,15 +95,17 @@ impl SubTest for TestDomtree {
|
||||
|
||||
// Now we know that everything in `expected` is consistent with `domtree`.
|
||||
// All other EBB's should be either unreachable or the entry block.
|
||||
for ebb in func.layout
|
||||
.ebbs()
|
||||
.skip(1)
|
||||
.filter(|ebb| !expected.contains_key(&ebb)) {
|
||||
for ebb in func.layout.ebbs().skip(1).filter(
|
||||
|ebb| !expected.contains_key(&ebb),
|
||||
)
|
||||
{
|
||||
if let Some(got_inst) = domtree.idom(ebb) {
|
||||
return Err(format!("mismatching idoms for renumbered {}:\n\
|
||||
return Err(format!(
|
||||
"mismatching idoms for renumbered {}:\n\
|
||||
want: unrechable, got: {}",
|
||||
ebb,
|
||||
got_inst));
|
||||
ebb,
|
||||
got_inst
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ impl SubTest for TestLegalizer {
|
||||
let isa = context.isa.expect("legalizer needs an ISA");
|
||||
|
||||
comp_ctx.flowgraph();
|
||||
comp_ctx
|
||||
.legalize(isa)
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
comp_ctx.legalize(isa).map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", &comp_ctx.func.display(Some(isa)))
|
||||
|
||||
@@ -39,13 +39,14 @@ impl SubTest for TestLICM {
|
||||
comp_ctx.func = func.into_owned();
|
||||
|
||||
comp_ctx.flowgraph();
|
||||
comp_ctx
|
||||
.licm()
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
comp_ctx.licm().map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", &comp_ctx.func)
|
||||
.map_err(|e| e.to_string())?;
|
||||
write!(&mut text, "{}", &comp_ctx.func).map_err(
|
||||
|e| e.to_string(),
|
||||
)?;
|
||||
run_filecheck(&text, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@ impl SubTest for TestRegalloc {
|
||||
|
||||
comp_ctx.flowgraph();
|
||||
// TODO: Should we have an option to skip legalization?
|
||||
comp_ctx
|
||||
.legalize(isa)
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
comp_ctx
|
||||
.regalloc(isa)
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
comp_ctx.legalize(isa).map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
comp_ctx.regalloc(isa).map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", &comp_ctx.func.display(Some(isa)))
|
||||
|
||||
@@ -41,11 +41,13 @@ impl Display for QueueEntry {
|
||||
let p = self.path.to_string_lossy();
|
||||
match self.state {
|
||||
State::Done(Ok(dur)) => {
|
||||
write!(f,
|
||||
"{}.{:03} {}",
|
||||
dur.as_secs(),
|
||||
dur.subsec_nanos() / 1000000,
|
||||
p)
|
||||
write!(
|
||||
f,
|
||||
"{}.{:03} {}",
|
||||
dur.as_secs(),
|
||||
dur.subsec_nanos() / 1000000,
|
||||
p
|
||||
)
|
||||
}
|
||||
State::Done(Err(ref e)) => write!(f, "FAIL {}: {}", p, e),
|
||||
_ => write!(f, "{}", p),
|
||||
@@ -104,11 +106,10 @@ 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 {
|
||||
path: file.into(),
|
||||
state: State::New,
|
||||
});
|
||||
self.tests.push(QueueEntry {
|
||||
path: file.into(),
|
||||
state: State::New,
|
||||
});
|
||||
}
|
||||
|
||||
/// Begin running tests concurrently.
|
||||
@@ -240,10 +241,12 @@ impl TestRunner {
|
||||
Reply::Tick => {
|
||||
self.ticks_since_progress += 1;
|
||||
if self.ticks_since_progress == TIMEOUT_SLOW {
|
||||
println!("STALLED for {} seconds with {}/{} tests finished",
|
||||
self.ticks_since_progress,
|
||||
self.reported_tests,
|
||||
self.tests.len());
|
||||
println!(
|
||||
"STALLED for {} seconds with {}/{} tests finished",
|
||||
self.ticks_since_progress,
|
||||
self.reported_tests,
|
||||
self.tests.len()
|
||||
);
|
||||
for jobid in self.reported_tests..self.tests.len() {
|
||||
if self.tests[jobid].state == State::Running {
|
||||
println!("slow: {}", self.tests[jobid]);
|
||||
@@ -251,8 +254,10 @@ impl TestRunner {
|
||||
}
|
||||
}
|
||||
if self.ticks_since_progress >= TIMEOUT_PANIC {
|
||||
panic!("worker threads stalled for {} seconds.",
|
||||
self.ticks_since_progress);
|
||||
panic!(
|
||||
"worker threads stalled for {} seconds.",
|
||||
self.ticks_since_progress
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,9 +283,9 @@ impl TestRunner {
|
||||
let mut times = self.tests
|
||||
.iter()
|
||||
.filter_map(|entry| match *entry {
|
||||
QueueEntry { state: State::Done(Ok(dur)), .. } => Some(dur),
|
||||
_ => None,
|
||||
})
|
||||
QueueEntry { state: State::Done(Ok(dur)), .. } => Some(dur),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Get me some real data, kid.
|
||||
@@ -304,12 +309,11 @@ impl TestRunner {
|
||||
return;
|
||||
}
|
||||
|
||||
for t in self.tests
|
||||
.iter()
|
||||
.filter(|entry| match **entry {
|
||||
QueueEntry { state: State::Done(Ok(dur)), .. } => dur > cut,
|
||||
_ => false,
|
||||
}) {
|
||||
for t in self.tests.iter().filter(|entry| match **entry {
|
||||
QueueEntry { state: State::Done(Ok(dur)), .. } => dur > cut,
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
println!("slow: {}", t)
|
||||
}
|
||||
|
||||
|
||||
@@ -76,10 +76,11 @@ pub fn run(path: &Path) -> TestResult {
|
||||
}
|
||||
|
||||
// Given a slice of tests, generate a vector of (test, flags, isa) tuples.
|
||||
fn test_tuples<'a>(tests: &'a [Box<SubTest>],
|
||||
isa_spec: &'a IsaSpec,
|
||||
no_isa_flags: &'a Flags)
|
||||
-> Result<Vec<(&'a SubTest, &'a Flags, Option<&'a TargetIsa>)>> {
|
||||
fn test_tuples<'a>(
|
||||
tests: &'a [Box<SubTest>],
|
||||
isa_spec: &'a IsaSpec,
|
||||
no_isa_flags: &'a Flags,
|
||||
) -> Result<Vec<(&'a SubTest, &'a Flags, Option<&'a TargetIsa>)>> {
|
||||
let mut out = Vec::new();
|
||||
for test in tests {
|
||||
if test.needs_isa() {
|
||||
@@ -104,10 +105,11 @@ fn test_tuples<'a>(tests: &'a [Box<SubTest>],
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn run_one_test<'a>(tuple: (&'a SubTest, &'a Flags, Option<&'a TargetIsa>),
|
||||
func: Cow<Function>,
|
||||
context: &mut Context<'a>)
|
||||
-> Result<()> {
|
||||
fn run_one_test<'a>(
|
||||
tuple: (&'a SubTest, &'a Flags, Option<&'a TargetIsa>),
|
||||
func: Cow<Function>,
|
||||
context: &mut Context<'a>,
|
||||
) -> Result<()> {
|
||||
let (test, flags, isa) = tuple;
|
||||
let name = format!("{}({})", test.name(), func.name);
|
||||
dbg!("Test: {} {}", name, isa.map(TargetIsa::name).unwrap_or("-"));
|
||||
@@ -117,11 +119,13 @@ fn run_one_test<'a>(tuple: (&'a SubTest, &'a Flags, Option<&'a TargetIsa>),
|
||||
|
||||
// Should we run the verifier before this test?
|
||||
if !context.verified && test.needs_verifier() {
|
||||
verify_function(&func, isa)
|
||||
.map_err(|e| pretty_verifier_error(&func, isa, e))?;
|
||||
verify_function(&func, isa).map_err(|e| {
|
||||
pretty_verifier_error(&func, isa, e)
|
||||
})?;
|
||||
context.verified = true;
|
||||
}
|
||||
|
||||
test.run(func, context)
|
||||
.map_err(|e| format!("{}: {}", name, e))
|
||||
test.run(func, context).map_err(
|
||||
|e| format!("{}: {}", name, e),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,13 +39,14 @@ impl SubTest for TestSimpleGVN {
|
||||
comp_ctx.func = func.into_owned();
|
||||
|
||||
comp_ctx.flowgraph();
|
||||
comp_ctx
|
||||
.simple_gvn()
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
comp_ctx.simple_gvn().map_err(|e| {
|
||||
pretty_error(&comp_ctx.func, context.isa, e)
|
||||
})?;
|
||||
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", &comp_ctx.func)
|
||||
.map_err(|e| e.to_string())?;
|
||||
write!(&mut text, "{}", &comp_ctx.func).map_err(
|
||||
|e| e.to_string(),
|
||||
)?;
|
||||
run_filecheck(&text, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,25 +66,25 @@ pub trait SubTest {
|
||||
/// match 'inst10'.
|
||||
impl<'a> filecheck::VariableMap for Context<'a> {
|
||||
fn lookup(&self, varname: &str) -> Option<FCValue> {
|
||||
self.details
|
||||
.map
|
||||
.lookup_str(varname)
|
||||
.map(|e| FCValue::Regex(format!(r"\b{}\b", e).into()))
|
||||
self.details.map.lookup_str(varname).map(|e| {
|
||||
FCValue::Regex(format!(r"\b{}\b", e).into())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 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))
|
||||
}
|
||||
}
|
||||
@@ -94,14 +94,14 @@ 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() {
|
||||
|
||||
@@ -65,9 +65,11 @@ impl SubTest for TestVerifier {
|
||||
if want_loc == got.location {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("correct error reported on {}, but wanted {}",
|
||||
got.location,
|
||||
want_loc))
|
||||
Err(format!(
|
||||
"correct error reported on {}, but wanted {}",
|
||||
got.location,
|
||||
want_loc
|
||||
))
|
||||
}
|
||||
}
|
||||
Some(_) => Err(format!("mismatching error: {}", got)),
|
||||
|
||||
Reference in New Issue
Block a user