Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/filetests/src/test_verifier.rs
1691 views
1
//! Test command for checking the IR verifier.
2
//!
3
//! The `test verifier` test command looks for annotations on instructions like this:
4
//!
5
//! ```clif
6
//! jump block3 ; error: jump to non-existent block
7
//! ```
8
//!
9
//! This annotation means that the verifier is expected to given an error for the jump instruction
10
//! containing the substring "jump to non-existent block".
11
12
use crate::match_directive::match_directive;
13
use crate::subtest::{Context, SubTest};
14
use cranelift_codegen::ir::Function;
15
use cranelift_codegen::verify_function;
16
use cranelift_reader::TestCommand;
17
use std::borrow::{Borrow, Cow};
18
use std::fmt::Write;
19
20
struct TestVerifier;
21
22
pub fn subtest(parsed: &TestCommand) -> anyhow::Result<Box<dyn SubTest>> {
23
assert_eq!(parsed.command, "verifier");
24
if !parsed.options.is_empty() {
25
anyhow::bail!("No options allowed on {}", parsed);
26
}
27
Ok(Box::new(TestVerifier))
28
}
29
30
impl SubTest for TestVerifier {
31
fn name(&self) -> &'static str {
32
"verifier"
33
}
34
35
fn needs_verifier(&self) -> bool {
36
// Running the verifier before this test would defeat its purpose.
37
false
38
}
39
40
fn run(&self, func: Cow<Function>, context: &Context) -> anyhow::Result<()> {
41
let func = func.borrow();
42
43
// Scan source annotations for "error:" directives.
44
let mut expected = Vec::new();
45
46
for comment in &context.details.comments {
47
if let Some(tail) = match_directive(comment.text, "error:") {
48
expected.push((comment.entity, tail));
49
}
50
}
51
52
match verify_function(func, context.flags_or_isa()) {
53
Ok(()) if expected.is_empty() => Ok(()),
54
Ok(()) => anyhow::bail!("passed, but expected errors: {:?}", expected),
55
56
Err(ref errors) if expected.is_empty() => {
57
anyhow::bail!("expected no error, but got:\n{}", errors);
58
}
59
60
Err(errors) => {
61
let mut errors = errors.0;
62
let mut msg = String::new();
63
64
// For each expected error, find a suitable match.
65
for expect in expected {
66
let pos = errors
67
.iter()
68
.position(|err| err.location == expect.0 && err.message.contains(expect.1));
69
70
match pos {
71
None => {
72
writeln!(msg, " expected error {}: {}", expect.0, expect.1).unwrap();
73
}
74
Some(pos) => {
75
errors.swap_remove(pos);
76
}
77
}
78
}
79
80
// Report remaining errors.
81
for err in errors {
82
writeln!(msg, "unexpected error {err}").unwrap();
83
}
84
85
if msg.is_empty() {
86
Ok(())
87
} else {
88
anyhow::bail!("{}", msg);
89
}
90
}
91
}
92
}
93
}
94
95