Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/filetests/src/test_compile.rs
1691 views
1
//! Test command for testing the code generator pipeline
2
//!
3
//! The `compile` test command runs each function through the full code generator pipeline
4
5
use crate::subtest::{Context, SubTest, check_precise_output, run_filecheck};
6
use anyhow::Result;
7
use cranelift_codegen::ir;
8
use cranelift_reader::{TestCommand, TestOption};
9
use log::info;
10
use std::borrow::Cow;
11
12
struct TestCompile {
13
/// Flag indicating that the text expectation, comments after the function,
14
/// must be a precise 100% match on the compiled output of the function.
15
/// This test assertion is also automatically-update-able to allow tweaking
16
/// the code generator and easily updating all affected tests.
17
precise_output: bool,
18
/// Flag indicating that we expect compilation to fail, not succeed.
19
expect_fail: bool,
20
}
21
22
pub fn subtest(parsed: &TestCommand) -> Result<Box<dyn SubTest>> {
23
assert_eq!(parsed.command, "compile");
24
let mut test = TestCompile {
25
precise_output: false,
26
expect_fail: false,
27
};
28
for option in parsed.options.iter() {
29
match option {
30
TestOption::Flag("precise-output") => test.precise_output = true,
31
TestOption::Flag("expect-fail") => test.expect_fail = true,
32
_ => anyhow::bail!("unknown option on {}", parsed),
33
}
34
}
35
Ok(Box::new(test))
36
}
37
38
impl SubTest for TestCompile {
39
fn name(&self) -> &'static str {
40
"compile"
41
}
42
43
fn is_mutating(&self) -> bool {
44
true
45
}
46
47
fn needs_isa(&self) -> bool {
48
true
49
}
50
51
fn run(&self, func: Cow<ir::Function>, context: &Context) -> Result<()> {
52
let isa = context.isa.expect("compile needs an ISA");
53
let params = func.params.clone();
54
let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned());
55
56
// With `MachBackend`s, we need to explicitly request disassembly results.
57
comp_ctx.set_disasm(true);
58
59
let compiled_code = comp_ctx.compile(isa, &mut Default::default());
60
61
let compiled_code = if self.expect_fail {
62
if compiled_code.is_ok() {
63
anyhow::bail!("Expected compilation failure but compilation succeeded");
64
}
65
return Ok(());
66
} else {
67
compiled_code.map_err(|e| crate::pretty_anyhow_error(&e.func, e.inner))?
68
};
69
let total_size = compiled_code.code_info().total_size;
70
71
let vcode = compiled_code.vcode.as_ref().unwrap();
72
73
info!("Generated {total_size} bytes of code:\n{vcode}");
74
75
if self.precise_output {
76
let dis = match isa.triple().architecture {
77
target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 => {
78
// Disable hexdumps/offsets to reduce the churn in these
79
// tests as instructions are encoded differently and/or
80
// their immediates change.
81
let mut disas =
82
pulley_interpreter::disas::Disassembler::new(compiled_code.buffer.data());
83
disas.hexdump(false).offsets(false);
84
pulley_interpreter::decode::Decoder::decode_all(&mut disas)?;
85
disas.disas().to_string()
86
}
87
_ => {
88
let cs = isa
89
.to_capstone()
90
.map_err(|e| anyhow::format_err!("{}", e))?;
91
compiled_code.disassemble(Some(&params), &cs)?
92
}
93
};
94
95
let actual = Vec::from_iter(
96
std::iter::once("VCode:")
97
.chain(compiled_code.vcode.as_ref().unwrap().lines())
98
.chain(["", "Disassembled:"])
99
.chain(dis.lines()),
100
);
101
102
check_precise_output(&actual, context)
103
} else {
104
run_filecheck(&vcode, context)
105
}
106
}
107
}
108
109