Skip to content

Commit 48f4621

Browse files
authored
Run the full test suite on 32-bit platforms (bytecodealliance#9837)
* Run the full test suite on 32-bit platforms This commit switches to running the full test suite in its entirety (`./ci/run-tests.sh`) on 32-bit platforms in CI in addition to 64-bit platforms. This notably adds i686 and armv7 as architectures that are tested in CI. Lots of little fixes here and there were applied to a number of tests. Many tests just don't run on 32-bit platforms or a platform without Cranelift support, and they've been annotated as such where necessary. Other tests were adjusted to run on all platforms a few minor bug fixes are here as well. prtest:full * Fix clippy warning * Get wasm code working by default on 32-bit Don't require the `pulley` feature opt-in on 32-bit platforms to get wasm code running. * Fix dead code warning * Fix build on armv7 * Fix test assertion on armv7 * Review comments * Update how tests are skipped * Change how Pulley is defaulted Default to pulley in `build.rs` rather than in `Cargo.toml` to make it easier to write down the condition and comment what's happening. This means that the `pulley-interpreter` crate and pulley support in Cranelift is always compiled in now and cannot be removed. This should hopefully be ok though as the `pulley-interpreter` crate is still conditionally used (meaning it can get GC'd) and the code-size of Cranelift is not as important as the runtime itself. * pulley: Save/restore callee-save state on traps * Fewer clippy warnings about casts * Use wrapping_add in `g32_addr`, fixing arm test
1 parent ba950f2 commit 48f4621

File tree

35 files changed

+445
-287
lines changed

35 files changed

+445
-287
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ wasmtime-test-macros = { path = "crates/test-macros" }
124124
pulley-interpreter = { workspace = true, features = ["disas"] }
125125
wasmtime-wast-util = { path = 'crates/wast-util' }
126126
wasm-encoder = { workspace = true }
127+
cranelift-native = { workspace = true }
127128

128129
[target.'cfg(windows)'.dev-dependencies]
129130
windows-sys = { workspace = true, features = ["Win32_System_Memory"] }

ci/build-test-matrix.js

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,6 @@ const FAST_MATRIX = [
3030
},
3131
];
3232

33-
// Returns whether the given package supports a 32-bit architecture, used when
34-
// testing on i686 and armv7 below.
35-
function supports32Bit(pkg) {
36-
if (pkg.indexOf("pulley") !== -1)
37-
return true;
38-
39-
return pkg == 'wasmtime-fiber' || pkg == 'wasmtime';
40-
}
41-
4233
// This is the full, unsharded, and unfiltered matrix of what we test on
4334
// CI. This includes a number of platforms and a number of cross-compiled
4435
// targets that are emulated with QEMU. This must be kept tightly in sync with
@@ -138,15 +129,13 @@ const FULL_MATRIX = [
138129
},
139130
{
140131
"name": "Tests on i686-unknown-linux-gnu",
141-
"32-bit": true,
142132
"os": ubuntu,
143133
"target": "i686-unknown-linux-gnu",
144134
"gcc_package": "gcc-i686-linux-gnu",
145135
"gcc": "i686-linux-gnu-gcc",
146136
},
147137
{
148138
"name": "Tests on armv7-unknown-linux-gnueabihf",
149-
"32-bit": true,
150139
"os": ubuntu,
151140
"target": "armv7-unknown-linux-gnueabihf",
152141
"gcc_package": "gcc-arm-linux-gnueabihf",
@@ -230,29 +219,6 @@ async function shard(configs) {
230219
// created above.
231220
const sharded = [];
232221
for (const config of configs) {
233-
// Special case 32-bit configs. Only some crates, according to
234-
// `supports32Bit`, run on this target. At this time the set of supported
235-
// crates is small enough that they're not sharded. A second shard, however,
236-
// is included which runs `--test wast` to run the full `*.wast` test suite
237-
// in CI on 32-bit platforms, at this time effectively testing Pulley.
238-
if (config["32-bit"] === true) {
239-
sharded.push(Object.assign(
240-
{},
241-
config,
242-
{
243-
bucket: members
244-
.map(c => supports32Bit(c) ? `--package ${c}` : `--exclude ${c}`)
245-
.join(" "),
246-
}
247-
));
248-
sharded.push(Object.assign(
249-
{},
250-
config,
251-
{ bucket: '--test wast' },
252-
));
253-
continue;
254-
}
255-
256222
for (const bucket of buckets) {
257223
sharded.push(Object.assign(
258224
{},
@@ -311,16 +277,6 @@ async function main() {
311277
return true;
312278
}
313279

314-
// For matrix entries that represent 32-bit only some crates support that,
315-
// so whenever the crates are changed be sure to run 32-bit tests on PRs
316-
// too.
317-
if (config["32-bit"] === true) {
318-
if (names.includes("pulley"))
319-
return true;
320-
if (names.includes("fiber"))
321-
return true;
322-
}
323-
324280
// If the commit explicitly asks for this test config, then include it.
325281
if (config.filter && commits.includes(`prtest:${config.filter}`)) {
326282
return true;

cranelift/codegen/build.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ fn main() {
5353
if isas.is_empty() || host_isa {
5454
// Try to match native target.
5555
let target_name = target_triple.split('-').next().unwrap();
56-
let isa = meta::isa_from_arch(&target_name).expect("error when identifying target");
57-
println!("cargo:rustc-cfg=feature=\"{isa}\"");
58-
isas.push(isa);
56+
if let Ok(isa) = meta::isa_from_arch(&target_name) {
57+
println!("cargo:rustc-cfg=feature=\"{isa}\"");
58+
isas.push(isa);
59+
}
5960
}
6061

6162
let cur_dir = env::current_dir().expect("Can't access current working directory");

cranelift/codegen/src/isa/aarch64/inst/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3051,6 +3051,11 @@ mod tests {
30513051
fn inst_size_test() {
30523052
// This test will help with unintentionally growing the size
30533053
// of the Inst enum.
3054-
assert_eq!(32, std::mem::size_of::<Inst>());
3054+
let expected = if cfg!(target_pointer_width = "32") && !cfg!(target_arch = "arm") {
3055+
28
3056+
} else {
3057+
32
3058+
};
3059+
assert_eq!(expected, std::mem::size_of::<Inst>());
30553060
}
30563061
}

cranelift/codegen/src/isa/pulley_shared/abi.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -481,15 +481,19 @@ where
481481
}
482482
// "far" calls are pulley->host calls so they use a different opcode
483483
// which is lowered with a special relocation in the backend.
484-
CallDest::ExtName(name, RelocDistance::Far) => smallvec![Inst::IndirectCallHost {
485-
info: Box::new(info.map(|()| name.clone()))
484+
CallDest::ExtName(name, RelocDistance::Far) => {
485+
smallvec![Inst::IndirectCallHost {
486+
info: Box::new(info.map(|()| name.clone()))
487+
}
488+
.into()]
486489
}
487-
.into()],
488490
// Indirect calls are all assumed to be pulley->pulley calls
489-
CallDest::Reg(reg) => smallvec![Inst::IndirectCall {
490-
info: Box::new(info.map(|()| XReg::new(*reg).unwrap()))
491+
CallDest::Reg(reg) => {
492+
smallvec![Inst::IndirectCall {
493+
info: Box::new(info.map(|()| XReg::new(*reg).unwrap()))
494+
}
495+
.into()]
491496
}
492-
.into()],
493497
}
494498
}
495499

cranelift/codegen/src/machinst/vcode.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,11 +1749,11 @@ mod test {
17491749
fn size_of_constant_structs() {
17501750
assert_eq!(size_of::<Constant>(), 4);
17511751
assert_eq!(size_of::<VCodeConstant>(), 4);
1752-
assert_eq!(size_of::<ConstantData>(), 24);
1753-
assert_eq!(size_of::<VCodeConstantData>(), 32);
1752+
assert_eq!(size_of::<ConstantData>(), 3 * size_of::<usize>());
1753+
assert_eq!(size_of::<VCodeConstantData>(), 4 * size_of::<usize>());
17541754
assert_eq!(
17551755
size_of::<PrimaryMap<VCodeConstant, VCodeConstantData>>(),
1756-
24
1756+
3 * size_of::<usize>()
17571757
);
17581758
// TODO The VCodeConstants structure's memory size could be further optimized.
17591759
// With certain versions of Rust, each `HashMap` in `VCodeConstants` occupied at

cranelift/filetests/src/function_runner.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,10 @@ mod test {
621621

622622
#[test]
623623
fn nop() {
624+
// Skip this test when cranelift doesn't support the native platform.
625+
if cranelift_native::builder().is_err() {
626+
return;
627+
}
624628
let code = String::from(
625629
"
626630
test run
@@ -655,6 +659,10 @@ mod test {
655659

656660
#[test]
657661
fn trampolines() {
662+
// Skip this test when cranelift doesn't support the native platform.
663+
if cranelift_native::builder().is_err() {
664+
return;
665+
}
658666
let function = parse(
659667
"
660668
function %test(f32, i8, i64x2, i8) -> f32x4, i64 {

cranelift/filetests/src/test_run.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,33 @@ fn build_host_isa(
3434
infer_native_flags: bool,
3535
flags: settings::Flags,
3636
isa_flags: Vec<settings::Value>,
37-
) -> OwnedTargetIsa {
37+
) -> anyhow::Result<OwnedTargetIsa> {
3838
let mut builder = cranelift_native::builder_with_options(infer_native_flags)
39-
.expect("Unable to build a TargetIsa for the current host");
39+
.map_err(|e| anyhow::Error::msg(e))?;
4040

4141
// Copy ISA Flags
4242
for value in isa_flags {
43-
builder.set(value.name, &value.value_string()).unwrap();
43+
builder.set(value.name, &value.value_string())?;
4444
}
4545

46-
builder.finish(flags).unwrap()
46+
let isa = builder.finish(flags)?;
47+
Ok(isa)
4748
}
4849

4950
/// Checks if the host's ISA is compatible with the one requested by the test.
5051
fn is_isa_compatible(
5152
file_path: &str,
52-
host: &dyn TargetIsa,
53+
host: Option<&dyn TargetIsa>,
5354
requested: &dyn TargetIsa,
5455
) -> Result<(), String> {
56+
let host_triple = match host {
57+
Some(host) => host.triple().clone(),
58+
None => target_lexicon::Triple::host(),
59+
};
5560
// If this test requests to run on a completely different
5661
// architecture than the host platform then we skip it entirely,
5762
// since we won't be able to natively execute machine code.
58-
let host_arch = host.triple().architecture;
63+
let host_arch = host_triple.architecture;
5964
let requested_arch = requested.triple().architecture;
6065

6166
match (host_arch, requested_arch) {
@@ -73,8 +78,8 @@ fn is_isa_compatible(
7378
| Architecture::Pulley64
7479
| Architecture::Pulley32be
7580
| Architecture::Pulley64be,
76-
) if host.triple().pointer_width() == requested.triple().pointer_width()
77-
&& host.triple().endianness() == requested.triple().endianness() => {}
81+
) if host_triple.pointer_width() == requested.triple().pointer_width()
82+
&& host_triple.endianness() == requested.triple().endianness() => {}
7883

7984
_ => {
8085
return Err(format!(
@@ -95,8 +100,15 @@ fn is_isa_compatible(
95100
Some(requested) => requested,
96101
None => unimplemented!("ISA flag {} of kind {:?}", req_value.name, req_value.kind()),
97102
};
98-
let available_in_host = host
99-
.isa_flags()
103+
let host_isa_flags = match host {
104+
Some(host) => host.isa_flags(),
105+
None => {
106+
return Err(format!(
107+
"host not available on this platform for isa-specific flag"
108+
))
109+
}
110+
};
111+
let available_in_host = host_isa_flags
100112
.iter()
101113
.find(|val| val.name == req_value.name)
102114
.and_then(|val| val.as_bool())
@@ -153,7 +165,7 @@ fn compile_testfile(
153165
// about the operating system / calling convention / etc..
154166
//
155167
// Copy the requested ISA flags into the host ISA and use that.
156-
_ => build_host_isa(false, flags.clone(), isa.isa_flags()),
168+
_ => build_host_isa(false, flags.clone(), isa.isa_flags()).unwrap(),
157169
};
158170

159171
let mut tfc = TestFileCompiler::new(isa);
@@ -221,8 +233,8 @@ impl SubTest for TestRun {
221233
}
222234

223235
// Check that the host machine can run this test case (i.e. has all extensions)
224-
let host_isa = build_host_isa(true, flags.clone(), vec![]);
225-
if let Err(e) = is_isa_compatible(file_path, host_isa.as_ref(), isa.unwrap()) {
236+
let host_isa = build_host_isa(true, flags.clone(), vec![]).ok();
237+
if let Err(e) = is_isa_compatible(file_path, host_isa.as_deref(), isa.unwrap()) {
226238
log::info!("{}", e);
227239
return Ok(());
228240
}

0 commit comments

Comments
 (0)