Cranelift: Add .wat to assembly test support and generate Wasm load/store tests for all ISAs (#5439)

* cranelift-filetest: Add the ability to test `.wat` to assembly

* Make the load/store test case generator script use `.wat` tests

And generate tests that exercise both Wasm-to-CLIF lowering and Wasm all the way
to assembly.

* Remove old versions of generated load/store tests

* Add new generated load/store tests

* Fix filename reference in script
This commit is contained in:
Nick Fitzgerald
2022-12-14 13:13:43 -08:00
committed by GitHub
parent 9dc4f1a83c
commit be710df237
502 changed files with 34040 additions and 760 deletions

View File

@@ -127,7 +127,7 @@ impl TestRunner {
// This recursive search tries to minimize statting in a directory hierarchy containing
// mostly test cases.
//
// - Directory entries with a "clif" extension are presumed to be test case files.
// - Directory entries with a "clif" or "wat" extension are presumed to be test case files.
// - Directory entries with no extension are presumed to be subdirectories.
// - Anything else is ignored.
//
@@ -160,7 +160,7 @@ impl TestRunner {
// Recognize directories and tests by extension.
// Yes, this means we ignore directories with '.' in their name.
match path.extension().and_then(OsStr::to_str) {
Some("clif") => self.push_test(path),
Some("clif" | "wat") => self.push_test(path),
Some(_) => {}
None => self.push_dir(path),
}

View File

@@ -29,25 +29,41 @@ pub fn run(path: &Path, wat: &str) -> Result<()> {
.validate()
.context("test configuration is malformed")?;
let wasm = wat::parse_str(wat).context("failed to parse the test WAT")?;
wasmparser::validate(&wasm).context("test WAT failed to validate")?;
let parsed = cranelift_reader::parse_sets_and_triple(&config.settings, &config.target)
.context("invalid ISA target or Cranelift settings")?;
let fisa = parsed.as_fisa();
let flags_or_isa = parsed.as_fisa();
ensure!(
fisa.isa.is_some(),
flags_or_isa.isa.is_some(),
"Running `.wat` tests requires specifying an ISA"
);
let isa = flags_or_isa.isa.unwrap();
let mut env = ModuleEnv::new(fisa.isa.as_ref().unwrap().frontend_config(), config);
let mut env = ModuleEnv::new(isa, config.clone());
let wasm = wat::parse_str(wat).context("failed to parse the test WAT")?;
let mut validator = wasmparser::Validator::new_with_features(
cranelift_wasm::ModuleEnvironment::wasm_features(&env),
);
validator
.validate_all(&wasm)
.context("test WAT failed to validate")?;
cranelift_wasm::translate_module(&wasm, &mut env)
.context("failed to translate the test case into CLIF")?;
let mut actual = String::new();
for (_index, func) in env.inner.info.function_bodies.iter() {
writeln!(&mut actual, "{}", func.display()).unwrap();
if config.compile {
let mut ctx = cranelift_codegen::Context::for_function(func.clone());
ctx.set_disasm(true);
let code = ctx
.compile(isa)
.map_err(|e| crate::pretty_anyhow_error(&e.func, e.inner))?;
writeln!(&mut actual, "function {}:", func.name).unwrap();
writeln!(&mut actual, "{}", code.disasm.as_ref().unwrap()).unwrap();
} else {
writeln!(&mut actual, "{}", func.display()).unwrap();
}
}
let actual = actual.trim();
log::debug!("=== actual ===\n{actual}");

View File

@@ -15,6 +15,9 @@ pub struct TestConfig {
#[serde(default)]
pub target: String,
#[serde(default)]
pub compile: bool,
#[serde(default)]
pub settings: Vec<String>,

View File

@@ -7,7 +7,10 @@ use std::collections::{BTreeMap, HashSet};
use super::config::TestConfig;
use cranelift::prelude::EntityRef;
use cranelift_codegen::{ir, isa::TargetFrontendConfig};
use cranelift_codegen::{
ir,
isa::{TargetFrontendConfig, TargetIsa},
};
use cranelift_wasm::{
DummyEnvironment, FuncEnvironment, FuncIndex, ModuleEnvironment, TargetEnvironment,
};
@@ -15,12 +18,19 @@ use cranelift_wasm::{
pub struct ModuleEnv {
pub inner: DummyEnvironment,
pub config: TestConfig,
pub heap_access_spectre_mitigation: bool,
}
impl ModuleEnv {
pub fn new(frontend_config: TargetFrontendConfig, config: TestConfig) -> Self {
let inner = DummyEnvironment::new(frontend_config, config.debug_info);
Self { inner, config }
pub fn new(target_isa: &dyn TargetIsa, config: TestConfig) -> Self {
let inner = DummyEnvironment::new(target_isa.frontend_config(), config.debug_info);
Self {
inner,
config,
heap_access_spectre_mitigation: target_isa
.flags()
.enable_heap_access_spectre_mitigation(),
}
}
}
@@ -67,6 +77,14 @@ impl<'data> ModuleEnvironment<'data> for ModuleEnv {
Ok(())
}
fn wasm_features(&self) -> wasmparser::WasmFeatures {
wasmparser::WasmFeatures {
memory64: true,
multi_memory: true,
..self.inner.wasm_features()
}
}
// ================================================================
// ====== Everything below here is delegated to `self.inner` ======
// ================================================================