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:
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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}");
|
||||
|
||||
@@ -15,6 +15,9 @@ pub struct TestConfig {
|
||||
#[serde(default)]
|
||||
pub target: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub compile: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub settings: Vec<String>,
|
||||
|
||||
|
||||
@@ -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` ======
|
||||
// ================================================================
|
||||
|
||||
Reference in New Issue
Block a user