Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix remaining failures and re-enable x64 new backend CI #2219

Merged
merged 4 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,32 @@ jobs:
env:
RUST_BACKTRACE: 1

# Perform all tests (debug mode) for `wasmtime` with the experimental x64
# backend. This runs on the nightly channel of Rust (because of issues with
# unifying Cargo features on stable) on Ubuntu.
test_x64:
name: Test x64 new backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: ./.github/actions/install-rust
with:
toolchain: nightly-2020-08-25
- uses: ./.github/actions/define-llvm-env

# Install wasm32 targets in order to build various tests throughout the
# repo.
- run: rustup target add wasm32-wasi
- run: rustup target add wasm32-unknown-unknown

# Run the x64 CI script.
- run: ./ci/run-experimental-x64-ci.sh
env:
CARGO_VERSION: "+nightly-2020-08-25"
RUST_BACKTRACE: 1

# Verify that cranelift's code generation is deterministic
meta_determinist_check:
name: Meta deterministic check
Expand Down
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ fn experimental_x64_should_panic(testsuite: &str, testname: &str, strategy: &str
match (testsuite, testname) {
("simd", "simd_address") => return false,
("simd", "simd_const") => return false,
("simd", "simd_i8x16_arith") => return false,
("simd", "simd_i16x8_arith") => return false,
("simd", "simd_i32x4_arith") => return false,
("simd", "simd_i64x2_arith") => return false,
("simd", "simd_f32x4_arith") => return false,
("simd", "simd_f32x4_cmp") => return false,
("simd", "simd_f64x2_arith") => return false,
Expand Down
10 changes: 8 additions & 2 deletions ci/run-experimental-x64-ci.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#!/bin/bash

cargo +nightly \
# Use the Nightly variant of the compiler to properly unify the
# experimental_x64 feature across all crates. Once the feature has stabilized
# and become the default, we can remove this.
CARGO_VERSION=${CARGO_VERSION:-"+nightly"}

cargo $CARGO_VERSION \
-Zfeatures=all -Zpackage-features \
test \
--features test-programs/test_programs \
Expand All @@ -14,4 +19,5 @@ cargo +nightly \
--exclude peepmatic-runtime \
--exclude peepmatic-test \
--exclude peepmatic-souper \
--exclude lightbeam
--exclude lightbeam \
$@
66 changes: 12 additions & 54 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,65 +195,23 @@ impl ABIMachineSpec for X64ABIMachineSpec {
}

fn gen_load_stack(mem: StackAMode, into_reg: Writable<Reg>, ty: Type) -> Self::I {
let (is_int, ext_mode) = match ty {
types::B1 | types::B8 | types::I8 => (true, Some(ExtMode::BQ)),
types::B16 | types::I16 => (true, Some(ExtMode::WQ)),
types::B32 | types::I32 => (true, Some(ExtMode::LQ)),
types::B64 | types::I64 | types::R64 => (true, None),
types::F32 | types::F64 => (false, None),
let ext_kind = match ty {
types::B1
| types::B8
| types::I8
| types::B16
| types::I16
| types::B32
| types::I32 => ExtKind::SignExtend,
types::B64 | types::I64 | types::R64 | types::F32 | types::F64 => ExtKind::None,
_ if ty.bytes() == 16 => ExtKind::None,
_ => panic!("load_stack({})", ty),
};

let mem = SyntheticAmode::from(mem);

if is_int {
match ext_mode {
Some(ext_mode) => Inst::movsx_rm_r(
ext_mode,
RegMem::mem(mem),
into_reg,
/* infallible load */ None,
),
None => Inst::mov64_m_r(mem, into_reg, None /* infallible */),
}
} else {
let sse_op = match ty {
types::F32 => SseOpcode::Movss,
types::F64 => SseOpcode::Movsd,
_ => unreachable!(),
};
Inst::xmm_mov(
sse_op,
RegMem::mem(mem),
into_reg,
None, /* infallible */
)
}
Inst::load(ty, mem, into_reg, ext_kind, /* infallible */ None)
}

fn gen_store_stack(mem: StackAMode, from_reg: Reg, ty: Type) -> Self::I {
let (is_int, size) = match ty {
types::B1 | types::B8 | types::I8 => (true, 1),
types::B16 | types::I16 => (true, 2),
types::B32 | types::I32 => (true, 4),
types::B64 | types::I64 | types::R64 => (true, 8),
types::F32 => (false, 4),
types::F64 => (false, 8),
_ => unimplemented!("store_stack({})", ty),
};

let mem = SyntheticAmode::from(mem);

if is_int {
Inst::mov_r_m(size, from_reg, mem, /* infallible store */ None)
} else {
let sse_op = match size {
4 => SseOpcode::Movss,
8 => SseOpcode::Movsd,
_ => unreachable!(),
};
Inst::xmm_mov_r_m(sse_op, from_reg, mem, /* infallible store */ None)
}
Inst::store(ty, from_reg, mem, /* infallible */ None)
}

fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self::I {
Expand Down
24 changes: 22 additions & 2 deletions crates/runtime/src/libcalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,22 @@ pub extern "C" fn wasmtime_f32_trunc(x: f32) -> f32 {
/// Implementation of f32.nearest
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
pub extern "C" fn wasmtime_f32_nearest(x: f32) -> f32 {
// Rust doesn't have a nearest function, so do it manually.
// Rust doesn't have a nearest function; there's nearbyint, but it's not
// stabilized, so do it manually.
// Nearest is either ceil or floor depending on which is nearest or even.
// This approach exploited round half to even default mode.
let i = x.to_bits();
let e = i >> 23 & 0xff;
if e >= 0x7f_u32 + 23 {
// Check for NaNs.
if e == 0xff {
// Read the 23-bits significand.
if i & 0x7fffff != 0 {
// Ensure it's arithmetic by setting the significand's most
// significant bit to 1; it also works for canonical NaNs.
return f32::from_bits(i | (1 << 22));
}
}
x
} else {
(x.abs() + TOINT_32 - TOINT_32).copysign(x)
Expand Down Expand Up @@ -153,12 +163,22 @@ pub extern "C" fn wasmtime_f64_trunc(x: f64) -> f64 {
/// Implementation of f64.nearest
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 {
// Rust doesn't have a nearest function, so do it manually.
// Rust doesn't have a nearest function; there's nearbyint, but it's not
// stabilized, so do it manually.
// Nearest is either ceil or floor depending on which is nearest or even.
// This approach exploited round half to even default mode.
let i = x.to_bits();
let e = i >> 52 & 0x7ff;
if e >= 0x3ff_u64 + 52 {
// Check for NaNs.
if e == 0x7ff {
// Read the 52-bits significand.
if i & 0xfffffffffffff != 0 {
// Ensure it's arithmetic by setting the significand's most
// significant bit to 1; it also works for canonical NaNs.
return f64::from_bits(i | (1 << 51));
}
}
x
} else {
(x.abs() + TOINT_64 - TOINT_64).copysign(x)
Expand Down