Skip to content

Commit d1aa86f

Browse files
authored
Add AArch64 tests to CI (#1526)
* Add AArch64 tests to CI This commit enhances our CI with an AArch64 builder. Currently we have no physical hardware to run on so for now we run all tests in an emulator. The AArch64 build is cross-compiled from x86_64 from Linux. Tests all happen in release mode with a recent version of QEMU (recent version because it's so much faster, and in release mode because debug mode tests take quite a long time in an emulator). The goal here was not to get all tests passing on CI, but rather to get AArch64 running on CI and get it green at the same time. To achieve that goal many tests are now ignored on aarch64 platforms. Many tests fail due to unimplemented functionality in the aarch64 backend (#1521), and all wasmtime tests involving compilation are also disabled due to panicking attempting to generate generate instruction offset information for trap symbolication (#1523). Despite this, though, all Cranelift tests and other wasmtime tests should be runnin on AArch64 through QEMU with this PR. Additionally we'll have an AArch64 binary release of Wasmtime for Linux, although it won't be too useful just yet since it will panic on almost all wasm modules. * Review comments
1 parent 25cbd8b commit d1aa86f

File tree

24 files changed

+207
-25
lines changed

24 files changed

+207
-25
lines changed

.github/workflows/main.yml

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,52 @@ jobs:
266266
runs-on: ${{ matrix.os }}
267267
strategy:
268268
matrix:
269-
os: [ubuntu-latest, macos-latest, windows-latest]
269+
include:
270+
- build: x86_64-linux
271+
os: ubuntu-latest
272+
- build: x86_64-macos
273+
os: macos-latest
274+
- build: x86_64-windows
275+
os: windows-latest
276+
- build: aarch64-linux
277+
os: ubuntu-latest
278+
rust: stable
279+
target: aarch64-unknown-linux-gnu
280+
gcc_package: gcc-aarch64-linux-gnu
281+
gcc: aarch64-linux-gnu-gcc
282+
qemu: qemu-aarch64 -L /usr/aarch64-linux-gnu
283+
qemu_target: aarch64-linux-user
270284
steps:
271285
- uses: actions/checkout@v1
272286
with:
273287
submodules: true
274288
- uses: ./.github/actions/install-rust
275289
- uses: ./.github/actions/binary-compatible-builds
290+
if: matrix.target == ''
291+
292+
- name: Install cross-compilation tools
293+
run: |
294+
set -ex
295+
sudo apt-get update
296+
sudo apt-get install -y ${{ matrix.gcc_package }}
297+
298+
# Download and build qemu from source since the most recent release is
299+
# way faster at arm emulation than the current version github actions'
300+
# ubuntu image uses. Disable as much as we can to get it to build
301+
# quickly.
302+
curl https://download.qemu.org/qemu-4.2.0.tar.xz | tar xJf -
303+
cd qemu-4.2.0
304+
./configure --target-list=${{ matrix.qemu_target }} --prefix=$HOME/qemu --disable-tools --disable-slirp --disable-fdt --disable-capstone --disable-docs
305+
make -j$(nproc) install
306+
307+
# Configure Cargo for cross compilation and tell it how it can run
308+
# cross executables
309+
upcase=$(echo ${{ matrix.target }} | awk '{ print toupper($0) }' | sed 's/-/_/g')
310+
echo ::set-env name=CARGO_TARGET_${upcase}_RUNNER::$HOME/qemu/bin/${{ matrix.qemu }}
311+
echo ::set-env name=CARGO_TARGET_${upcase}_LINKER::${{ matrix.gcc }}
312+
echo ::set-env name=CARGO_BUILD_TARGET::${{ matrix.target }}
313+
rustup target add ${{ matrix.target }}
314+
if: matrix.target != ''
276315

277316
# Install wasm32-wasi target in order to build wasi-common's integration
278317
# tests
@@ -285,7 +324,7 @@ jobs:
285324
- run: $CENTOS cargo build --release --manifest-path crates/c-api/Cargo.toml
286325
shell: bash
287326
# Test what we just built
288-
- run: $CENTOS cargo test --features test-programs/test_programs --release --all --exclude lightbeam --exclude wasmtime --exclude wasmtime-c-api --exclude wasmtime-fuzzing
327+
- run: $CENTOS cargo test --features test-programs/test_programs --release --all --exclude lightbeam
289328
shell: bash
290329
env:
291330
RUST_BACKTRACE: 1
@@ -304,14 +343,18 @@ jobs:
304343

305344
# Move binaries to dist folder
306345
- run: cp target/release/wasmtime dist
307-
if: matrix.os != 'windows-latest'
346+
if: matrix.os != 'windows-latest' && matrix.target == ''
347+
- run: cp target/${{ matrix.target }}/release/wasmtime dist
348+
if: matrix.os != 'windows-latest' && matrix.target != ''
308349
- run: cp target/release/wasmtime.exe dist
309350
shell: bash
310351
if: matrix.os == 'windows-latest'
311352

312353
# Move libwasmtime dylib to dist folder
313354
- run: cp target/release/libwasmtime.{so,a} dist
314-
if: matrix.os == 'ubuntu-latest'
355+
if: matrix.os == 'ubuntu-latest' && matrix.target == ''
356+
- run: cp target/${{ matrix.target }}/release/libwasmtime.{so,a} dist
357+
if: matrix.os == 'ubuntu-latest' && matrix.target != ''
315358
- run: cp target/release/libwasmtime.{dylib,a} dist
316359
if: matrix.os == 'macos-latest'
317360
- run: cp target/release/wasmtime.{dll,lib,dll.lib} dist
@@ -329,7 +372,7 @@ jobs:
329372
330373
- uses: actions/upload-artifact@v1
331374
with:
332-
name: bins-${{ matrix.os }}
375+
name: bins-${{ matrix.build }}
333376
path: dist
334377

335378
# Consumes all published artifacts from all the previous build steps, creates
@@ -357,18 +400,22 @@ jobs:
357400
uses: actions/download-artifact@v1
358401
with:
359402
name: doc-api
360-
- name: Download macOS binaries
403+
- name: Download x86_64 macOS binaries
404+
uses: actions/download-artifact@v1
405+
with:
406+
name: bins-x86_64-macos
407+
- name: Download x86_64 Linux binaries
361408
uses: actions/download-artifact@v1
362409
with:
363-
name: bins-macos-latest
364-
- name: Download Linux binaries
410+
name: bins-x86_64-linux
411+
- name: Download AArch64 Linux binaries
365412
uses: actions/download-artifact@v1
366413
with:
367-
name: bins-ubuntu-latest
368-
- name: Download Windows binaries
414+
name: bins-aarch64-linux
415+
- name: Download x86_64 Windows binaries
369416
uses: actions/download-artifact@v1
370417
with:
371-
name: bins-windows-latest
418+
name: bins-x86_64-windows
372419

373420
- name: Assemble gh-pages
374421
run: |
@@ -400,9 +447,10 @@ jobs:
400447
# Assemble all the build artifacts into tarballs and zip archives.
401448
- name: Assemble tarballs
402449
run: |
403-
./ci/build-tarballs.sh x86_64-linux ubuntu-latest
404-
./ci/build-tarballs.sh x86_64-windows windows-latest .exe
405-
./ci/build-tarballs.sh x86_64-macos macos-latest
450+
./ci/build-tarballs.sh x86_64-linux
451+
./ci/build-tarballs.sh x86_64-windows .exe
452+
./ci/build-tarballs.sh x86_64-macos
453+
./ci/build-tarballs.sh aarch64-linux
406454
407455
# Upload all assembled tarballs as an artifact of the github action run, so
408456
# that way even PRs can inspect the output.

build.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,13 @@ fn write_testsuite_tests(
154154
if ignore(testsuite, &testname, strategy) {
155155
writeln!(out, "#[ignore]")?;
156156
}
157-
writeln!(out, "fn r#{}() -> anyhow::Result<()> {{", &testname)?;
157+
if should_panic(testsuite, &testname) {
158+
writeln!(out, "#[should_panic]")?;
159+
}
160+
writeln!(out, "fn r#{}() {{", &testname)?;
158161
writeln!(
159162
out,
160-
"crate::wast::run_wast(r#\"{}\"#, crate::wast::Strategy::{})",
163+
"crate::wast::run_wast(r#\"{}\"#, crate::wast::Strategy::{}).unwrap();",
161164
path.display(),
162165
strategy
163166
)?;
@@ -168,6 +171,7 @@ fn write_testsuite_tests(
168171

169172
/// Ignore tests that aren't supported yet.
170173
fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
174+
let target = env::var("TARGET").unwrap();
171175
match strategy {
172176
#[cfg(feature = "lightbeam")]
173177
"Lightbeam" => match (testsuite, testname) {
@@ -205,10 +209,53 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
205209
return true;
206210
}
207211

212+
// FIXME(#1569) stack protection isn't implemented yet and these
213+
// tests segfault.
214+
("spec_testsuite", "skip_stack_guard_page")
215+
| ("spec_testsuite", "stack")
216+
| ("misc_testsuite", "stack_overflow")
217+
if target.contains("aarch64") =>
218+
{
219+
return true
220+
}
221+
208222
_ => {}
209223
},
210224
_ => panic!("unrecognized strategy"),
211225
}
212226

213227
false
214228
}
229+
230+
/// Determine whether to add a should_panic attribute. These tests currently
231+
/// panic because of unfinished backend implementation work; we will remove them
232+
/// from this list as we finish the implementation
233+
fn should_panic(testsuite: &str, testname: &str) -> bool {
234+
let target = env::var("TARGET").unwrap();
235+
if !target.contains("aarch64") {
236+
return false;
237+
}
238+
match (testsuite, testname) {
239+
// FIXME(#1521)
240+
("bulk_memory_operations", "imports")
241+
| ("misc_testsuite", "func_400_params")
242+
| ("misc_testsuite", "misc_traps")
243+
| ("simd", _)
244+
| ("multi_value", "call")
245+
| ("spec_testsuite", "address")
246+
| ("spec_testsuite", "align")
247+
| ("spec_testsuite", "call")
248+
| ("spec_testsuite", "conversions")
249+
| ("spec_testsuite", "f32_bitwise")
250+
| ("spec_testsuite", "float_misc")
251+
| ("spec_testsuite", "i32")
252+
| ("spec_testsuite", "i64")
253+
| ("spec_testsuite", "imports")
254+
| ("spec_testsuite", "int_exprs")
255+
| ("spec_testsuite", "memory_grow")
256+
| ("spec_testsuite", "memory_trap")
257+
| ("spec_testsuite", "traps") => true,
258+
259+
_ => false,
260+
}
261+
}

ci/build-tarballs.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
# the second argument is the name of the github actions platform which is where
1010
# we source binaries from. The final third argument is ".exe" on Windows to
1111
# handle executable extensions right.
12+
#
13+
# Usage: build-tarballs.sh PLATFORM [.exe]
14+
15+
# where PLATFORM is e.g. x86_64-linux, aarch64-linux, ...
1216

1317
set -ex
1418

1519
platform=$1
16-
src=$2
17-
exe=$3
20+
exe=$2
1821

1922
rm -rf tmp
2023
mkdir tmp
@@ -33,12 +36,12 @@ mktarball() {
3336
bin_pkgname=wasmtime-$TAG-$platform
3437
mkdir tmp/$bin_pkgname
3538
cp LICENSE README.md tmp/$bin_pkgname
36-
mv bins-$src/wasmtime$exe tmp/$bin_pkgname
39+
mv bins-$platform/wasmtime$exe tmp/$bin_pkgname
3740
chmod +x tmp/$bin_pkgname/wasmtime$exe
3841
mktarball $bin_pkgname
3942

4043
if [ "$exe" = ".exe" ]; then
41-
mv bins-$src/installer.msi dist/$bin_pkgname.msi
44+
mv bins-$platform/installer.msi dist/$bin_pkgname.msi
4245
fi
4346

4447
# Create tarball of API libraries
@@ -47,7 +50,7 @@ mkdir tmp/$api_pkgname
4750
mkdir tmp/$api_pkgname/lib
4851
mkdir tmp/$api_pkgname/include
4952
cp LICENSE README.md tmp/$api_pkgname
50-
mv bins-$src/* tmp/$api_pkgname/lib
53+
mv bins-$platform/* tmp/$api_pkgname/lib
5154
cp crates/c-api/wasm-c-api/include/wasm.h tmp/$api_pkgname/include
5255
cp crates/c-api/include/{wasmtime,wasi}.h tmp/$api_pkgname/include
5356
mktarball $api_pkgname

cranelift/docs/testing.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,15 @@ functions must have the signature `() -> bNN` where `bNN` is some sort of
316316
boolean, e.g. `b1` or `b32`. A `true` value is interpreted as a successful
317317
test execution, whereas a `false` value is interpreted as a failed test.
318318

319+
Currently a `target` is required but is only used to indicate whether the host
320+
platform can run the test, and currently only the architecture is filtered. The
321+
host platform's native target will be used to actually compile the test.
322+
319323
Example:
320324

321325
```
322326
test run
327+
target x86_64
323328
324329
function %trivial_test() -> b1 {
325330
ebb0:

cranelift/filetests/filetests/isa/x86/run-const.clif

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
test run
2+
target x86_64
23

34
function %test_compare_i32() -> b1 {
45
block0:

cranelift/filetests/filetests/isa/x86/simd-comparison-run.clif

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
test run
22
set enable_simd
3+
target x86_64
34

45
function %icmp_eq_i8x16() -> b8 {
56
block0:

cranelift/filetests/filetests/isa/x86/simd-conversion-run.clif

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
test run
22
set enable_simd
3+
target x86_64
34

45
function %fcvt_from_sint() -> b1 {
56
block0:

cranelift/filetests/filetests/isa/x86/simd-lane-access-run.clif

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
test run
22
set enable_simd
3+
target x86_64
34

45
function %shuffle_different_ssa_values() -> b1 {
56
block0:

cranelift/filetests/filetests/isa/x86/simd-vconst-run.clif

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
test run
22
set enable_simd
3+
target x86_64
34

45
function %vconst_syntax() -> b1 {
56
block0:

cranelift/filetests/src/test_run.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
55
use crate::function_runner::FunctionRunner;
66
use crate::subtest::{Context, SubTest, SubtestResult};
7-
use cranelift_codegen;
87
use cranelift_codegen::ir;
98
use cranelift_reader::parse_run_command;
109
use cranelift_reader::TestCommand;
1110
use log::trace;
1211
use std::borrow::Cow;
12+
use target_lexicon::Architecture;
1313

1414
struct TestRun;
1515

@@ -32,7 +32,7 @@ impl SubTest for TestRun {
3232
}
3333

3434
fn needs_isa(&self) -> bool {
35-
false
35+
true
3636
}
3737

3838
fn run(&self, func: Cow<ir::Function>, context: &Context) -> SubtestResult<()> {
@@ -42,8 +42,22 @@ impl SubTest for TestRun {
4242
let command = parse_run_command(trimmed_comment, &func.signature)
4343
.map_err(|e| format!("{}", e))?;
4444
trace!("Parsed run command: {}", command);
45-
// TODO in following changes we will use the parsed command to alter FunctionRunner's behavior.
4645

46+
// If this test requests to run on a completely different
47+
// architecture than the host platform then we skip it entirely,
48+
// since we won't be able to natively execute machine code.
49+
let requested_arch = context.isa.unwrap().triple().architecture;
50+
if requested_arch != Architecture::host() {
51+
return Ok(());
52+
}
53+
54+
// TODO in following changes we will use the parsed command to alter FunctionRunner's behavior.
55+
//
56+
// Note that here we're also explicitly ignoring `context.isa`,
57+
// regardless of what's requested. We want to use the native
58+
// host ISA no matter what here, so the ISA listed in the file
59+
// is only used as a filter to not run into situations like
60+
// running x86_64 code on aarch64 platforms.
4761
let runner =
4862
FunctionRunner::with_host_isa(func.clone().into_owned(), context.flags.clone());
4963
runner.run()?

0 commit comments

Comments
 (0)