Files
wasmtime/cranelift/filetests/src/test_verifier.rs
Ryan Hunt 832666c45e Mass rename Ebb and relatives to Block (#1365)
* Manually rename BasicBlock to BlockPredecessor

BasicBlock is a pair of (Ebb, Inst) that is used to represent the
basic block subcomponent of an Ebb that is a predecessor to an Ebb.

Eventually we will be able to remove this struct, but for now it
makes sense to give it a non-conflicting name so that we can start
to transition Ebb to represent a basic block.

I have not updated any comments that refer to BasicBlock, as
eventually we will remove BlockPredecessor and replace with Block,
which is a basic block, so the comments will become correct.

* Manually rename SSABuilder block types to avoid conflict

SSABuilder has its own Block and BlockData types. These along with
associated identifier will cause conflicts in a later commit, so
they are renamed to be more verbose here.

* Automatically rename 'Ebb' to 'Block' in *.rs

* Automatically rename 'EBB' to 'block' in *.rs

* Automatically rename 'ebb' to 'block' in *.rs

* Automatically rename 'extended basic block' to 'basic block' in *.rs

* Automatically rename 'an basic block' to 'a basic block' in *.rs

* Manually update comment for `Block`

`Block`'s wikipedia article required an update.

* Automatically rename 'an `Block`' to 'a `Block`' in *.rs

* Automatically rename 'extended_basic_block' to 'basic_block' in *.rs

* Automatically rename 'ebb' to 'block' in *.clif

* Manually rename clif constant that contains 'ebb' as substring to avoid conflict

* Automatically rename filecheck uses of 'EBB' to 'BB'

'regex: EBB' -> 'regex: BB'
'$EBB' -> '$BB'

* Automatically rename 'EBB' 'Ebb' to 'block' in *.clif

* Automatically rename 'an block' to 'a block' in *.clif

* Fix broken testcase when function name length increases

Test function names are limited to 16 characters. This causes
the new longer name to be truncated and fail a filecheck test. An
outdated comment was also fixed.
2020-02-07 10:46:47 -06:00

95 lines
2.9 KiB
Rust

//! Test command for checking the IR verifier.
//!
//! The `test verifier` test command looks for annotations on instructions like this:
//!
//! ```clif
//! jump block3 ; error: jump to non-existent block
//! ```
//!
//! This annotation means that the verifier is expected to given an error for the jump instruction
//! containing the substring "jump to non-existent block".
use crate::match_directive::match_directive;
use crate::subtest::{Context, SubTest, SubtestResult};
use cranelift_codegen::ir::Function;
use cranelift_codegen::verify_function;
use cranelift_reader::TestCommand;
use std::borrow::{Borrow, Cow};
use std::fmt::Write;
struct TestVerifier;
pub fn subtest(parsed: &TestCommand) -> SubtestResult<Box<dyn SubTest>> {
assert_eq!(parsed.command, "verifier");
if !parsed.options.is_empty() {
Err(format!("No options allowed on {}", parsed))
} else {
Ok(Box::new(TestVerifier))
}
}
impl SubTest for TestVerifier {
fn name(&self) -> &'static str {
"verifier"
}
fn needs_verifier(&self) -> bool {
// Running the verifier before this test would defeat its purpose.
false
}
fn run(&self, func: Cow<Function>, context: &Context) -> SubtestResult<()> {
let func = func.borrow();
// Scan source annotations for "error:" directives.
let mut expected = Vec::new();
for comment in &context.details.comments {
if let Some(tail) = match_directive(comment.text, "error:") {
expected.push((comment.entity, tail));
}
}
match verify_function(func, context.flags_or_isa()) {
Ok(()) if expected.is_empty() => Ok(()),
Ok(()) => Err(format!("passed, but expected errors: {:?}", expected)),
Err(ref errors) if expected.is_empty() => {
Err(format!("expected no error, but got:\n{}", errors))
}
Err(errors) => {
let mut errors = errors.0;
let mut msg = String::new();
// For each expected error, find a suitable match.
for expect in expected {
let pos = errors
.iter()
.position(|err| err.location == expect.0 && err.message.contains(expect.1));
match pos {
None => {
writeln!(msg, " expected error {}: {}", expect.0, expect.1).unwrap();
}
Some(pos) => {
errors.swap_remove(pos);
}
}
}
// Report remaining errors.
for err in errors {
writeln!(msg, "unexpected error {}", err).unwrap();
}
if msg.is_empty() {
Ok(())
} else {
Err(msg)
}
}
}
}
}