diff --git a/.github/workflows/cargo-audit.yml b/.github/workflows/cargo-audit.yml index d17cc3674230..0f4b3bcb80ac 100644 --- a/.github/workflows/cargo-audit.yml +++ b/.github/workflows/cargo-audit.yml @@ -7,7 +7,7 @@ jobs: if: github.repository == 'bytecodealliance/wasmtime' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: actions-rs/audit-check@v1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 63fd4685c573..2db5779b2806 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -60,7 +60,7 @@ jobs: name: Clang format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - run: git ls-files '*.h' '*.c' '*.cpp' | xargs clang-format-15 --dry-run --Werror --verbose @@ -79,7 +79,7 @@ jobs: if: needs.determine.outputs.audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -103,7 +103,7 @@ jobs: if: needs.determine.outputs.audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -138,7 +138,7 @@ jobs: audit: ${{ steps.calculate.outputs.audit }} preview1-adapter: ${{ steps.calculate.outputs.preview1-adapter }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: calculate env: GH_TOKEN: ${{ github.token }} @@ -202,7 +202,7 @@ jobs: RUSTDOCFLAGS: -Dbroken_intra_doc_links --cfg nightlydoc OPENVINO_SKIP_LINKING: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -269,7 +269,7 @@ jobs: env: CARGO_NDK_VERSION: 2.12.2 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -351,7 +351,7 @@ jobs: name: Check Windows ARM64 runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -371,7 +371,7 @@ jobs: name: Fuzz Targets runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true # Note that building with fuzzers requires nightly since it uses unstable @@ -410,7 +410,7 @@ jobs: fail-fast: ${{ github.event_name != 'pull_request' }} matrix: ${{ fromJson(needs.determine.outputs.test-matrix) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -529,7 +529,7 @@ jobs: name: Test wasi-nn module runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -557,7 +557,7 @@ jobs: deployments: write contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - run: rustup update stable && rustup default stable @@ -591,7 +591,7 @@ jobs: name: Run benchmarks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -611,7 +611,7 @@ jobs: name: Meta deterministic check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -629,7 +629,7 @@ jobs: if: github.repository == 'bytecodealliance/wasmtime' && needs.determine.outputs.run-full runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - run: rustup update stable && rustup default stable @@ -667,7 +667,7 @@ jobs: env: CARGO_NEXTEST_VERSION: 0.9.51 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -709,7 +709,7 @@ jobs: fail-fast: ${{ github.event_name != 'pull_request' }} matrix: ${{ fromJson(needs.determine.outputs.build-matrix) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true @@ -824,7 +824,7 @@ jobs: && startsWith(github.ref, 'refs/heads/release-') && github.repository == 'bytecodealliance/wasmtime' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 0b39524a70f6..f3544251cbfd 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -74,7 +74,7 @@ jobs: cargo build --release - name: Checkout patch from bytecodealliance/wasmtime (pushed and triggering on this perf repo) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true path: wasmtime_commit @@ -89,7 +89,7 @@ jobs: cp target/release/libwasmtime_bench_api.so /tmp/wasmtime_commit.so - name: Checkout main from bytecodealliance/wasmtime - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: 'main' repository: 'bytecodealliance/wasmtime' diff --git a/.github/workflows/publish-artifacts.yml b/.github/workflows/publish-artifacts.yml index 8c149003dc91..191d0cc4fd21 100644 --- a/.github/workflows/publish-artifacts.yml +++ b/.github/workflows/publish-artifacts.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'bytecodealliance/wasmtime' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | sha=${{ github.sha }} run_id=$( diff --git a/.github/workflows/publish-to-cratesio.yml b/.github/workflows/publish-to-cratesio.yml index 6d05b66778a4..23af15a85785 100644 --- a/.github/workflows/publish-to-cratesio.yml +++ b/.github/workflows/publish-to-cratesio.yml @@ -14,7 +14,7 @@ jobs: if: github.repository == 'bytecodealliance/wasmtime' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - run: rustup update stable && rustup default stable diff --git a/.github/workflows/release-process.yml b/.github/workflows/release-process.yml index e2003a456d92..004c00f85ce3 100644 --- a/.github/workflows/release-process.yml +++ b/.github/workflows/release-process.yml @@ -38,7 +38,7 @@ jobs: name: Run the release process runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Setup diff --git a/RELEASES.md b/RELEASES.md index 8c60992f147a..03f2b857f015 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -16,8 +16,69 @@ Unreleased. ### Added +* Add yielding support in `wasmtime_store_epoch_deadline_callback` in the C API. + [#7476](https://github.com/bytecodealliance/wasmtime/pull/7476) + +* Support for the `wasi_unstable` module ("wasi preview0" canonically) has been + added to the `-Spreview2` support in the CLI. + [#7548](https://github.com/bytecodealliance/wasmtime/pull/7548) + +* The original module can now be obtained from an "instance pre" in the C API. + [#7572](https://github.com/bytecodealliance/wasmtime/pull/7572) + +* Usage of Mach ports on macOS can now be disabled in the C API. + [#7595](https://github.com/bytecodealliance/wasmtime/pull/7595) + ### Changed +* The preview1-to-preview2 component adapters now import a smaller number of + interfaces by default. + [#7543](https://github.com/bytecodealliance/wasmtime/pull/7543) + [#7544](https://github.com/bytecodealliance/wasmtime/pull/7544) + +* Wasmtime and Cranelift now require Rust 1.72.0 to build. + [#7554](https://github.com/bytecodealliance/wasmtime/pull/7554) + +* The default `world` supported by `wasmtime serve` has been slimmed down to + exactly what `wasi:http/proxy` specifies by default. Support for other WASI + APIs can be included with the `-S common` command-line flag. + [#7597](https://github.com/bytecodealliance/wasmtime/pull/7597) + +* The `wasmtime --version` CLI output will now include date/commit information + when Wasmtime is built from a git checkout. + [#7610](https://github.com/bytecodealliance/wasmtime/pull/7610) + +### Fixed + +* MPK support is now explicitly disabled on AMD-based CPUs since the + implementation does not currently support it. + [#7513](https://github.com/bytecodealliance/wasmtime/pull/7513) + +* Initialization of a WebAssembly data segment with a negative offset is fixed + to zero-extend the offset instead of sign-extend. + [#7559](https://github.com/bytecodealliance/wasmtime/pull/7559) + +* The reported offset of `O_APPEND` files in preview1 has been fixed. + [#7586](https://github.com/bytecodealliance/wasmtime/pull/7586) + +* MPK support does a better job of compacting memories to minimize virtual + memory used. + [#7622](https://github.com/bytecodealliance/wasmtime/pull/7622) + +### Cranelift + +* Union node bitpacking has been fixed with egraph optimizations to ensure the + minimal cost node is selected. + [#7465](https://github.com/bytecodealliance/wasmtime/pull/7465) + +* Equivalent-cost expressions now have ties broken with expression depth in + egraphs to prefer "shallow" expression trees. + [#7456](https://github.com/bytecodealliance/wasmtime/pull/7456) + +* Long-and-narrow chains of expressions are now optimized into shallow-and-wide + trees. + [#7466](https://github.com/bytecodealliance/wasmtime/pull/7466) + -------------------------------------------------------------------------------- ## 15.0.1 diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index 2d9309dd5734..15112a585763 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -1709,6 +1709,9 @@ (decl pure partial imm_logic_from_u64 (Type u64) ImmLogic) (extern constructor imm_logic_from_u64 imm_logic_from_u64) +(decl pure partial imm_size_from_type (Type) u16) +(extern constructor imm_size_from_type imm_size_from_type) + (decl pure partial imm_logic_from_imm64 (Type Imm64) ImmLogic) (extern constructor imm_logic_from_imm64 imm_logic_from_imm64) @@ -2938,9 +2941,10 @@ ;; we only match when we are zero-extending the value. (rule 1 (imm (integral_ty ty) (ImmExtend.Zero) k) (if-let n (imm_logic_from_u64 ty k)) + (if-let m (imm_size_from_type ty)) (add_range_fact (orr_imm ty (zero_reg) n) - 64 k k)) + m k k)) (decl load_constant64_full (Type ImmExtend u64) Reg) (extern constructor load_constant64_full load_constant64_full) diff --git a/cranelift/codegen/src/isa/aarch64/lower/isle.rs b/cranelift/codegen/src/isa/aarch64/lower/isle.rs index a70e895fbd28..91ea3a73594b 100644 --- a/cranelift/codegen/src/isa/aarch64/lower/isle.rs +++ b/cranelift/codegen/src/isa/aarch64/lower/isle.rs @@ -174,6 +174,14 @@ impl Context for IsleContext<'_, '_, MInst, AArch64Backend> { ImmLogic::maybe_from_u64(n, ty) } + fn imm_size_from_type(&mut self, ty: Type) -> Option { + match ty { + I32 => Some(32), + I64 => Some(64), + _ => None, + } + } + fn imm_logic_from_imm64(&mut self, ty: Type, n: Imm64) -> Option { let ty = if ty.bits() < 32 { I32 } else { ty }; self.imm_logic_from_u64(ty, n.bits() as u64) @@ -395,7 +403,7 @@ impl Context for IsleContext<'_, '_, MInst, AArch64Backend> { size, }); if pcc { - running_value = !(imm16 << shift); + running_value = !(u64::from(imm.bits) << shift); self.lower_ctx.add_range_fact( rd.to_reg(), 64, diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs index a2ee1563f7a4..0ad5bfa824d3 100644 --- a/cranelift/codegen/src/isle_prelude.rs +++ b/cranelift/codegen/src/isle_prelude.rs @@ -734,18 +734,6 @@ macro_rules! isle_common_prelude_methods { Imm64::new((x & self.ty_mask(ty)) as i64) } - #[inline] - fn simm32(&mut self, x: Imm64) -> Option { - i64::from(x).try_into().ok() - } - - #[inline] - fn uimm8(&mut self, x: Imm64) -> Option { - let x64: i64 = x.into(); - let x8: u8 = x64.try_into().ok()?; - Some(x8) - } - #[inline] fn offset32(&mut self, x: Offset32) -> i32 { x.into() diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs index 7add8208eff1..6967aa9bce82 100644 --- a/cranelift/codegen/src/machinst/isle.rs +++ b/cranelift/codegen/src/machinst/isle.rs @@ -562,6 +562,18 @@ macro_rules! isle_lower_prelude_methods { Some(value) } + #[inline] + fn simm32(&mut self, x: Imm64) -> Option { + i64::from(x).try_into().ok() + } + + #[inline] + fn uimm8(&mut self, x: Imm64) -> Option { + let x64: i64 = x.into(); + let x8: u8 = x64.try_into().ok()?; + Some(x8) + } + #[inline] fn preg_to_reg(&mut self, preg: PReg) -> Reg { preg.into() diff --git a/cranelift/codegen/src/machinst/pcc.rs b/cranelift/codegen/src/machinst/pcc.rs index db1bf3256533..d737d83dacc3 100644 --- a/cranelift/codegen/src/machinst/pcc.rs +++ b/cranelift/codegen/src/machinst/pcc.rs @@ -6,8 +6,7 @@ use crate::trace; pub(crate) fn get_fact_or_default(vcode: &VCode, reg: Reg, width: u16) -> Fact { trace!( - "get_fact_or_default: reg v{} -> {:?}", - reg.to_virtual_reg().unwrap().index(), + "get_fact_or_default: reg {reg:?} -> {:?}", vcode.vreg_fact(reg.into()) ); vcode diff --git a/cranelift/codegen/src/opts.rs b/cranelift/codegen/src/opts.rs index 3ec3e116593c..8796b62e1094 100644 --- a/cranelift/codegen/src/opts.rs +++ b/cranelift/codegen/src/opts.rs @@ -27,6 +27,8 @@ const MAX_ISLE_RETURNS: usize = 8; pub type ConstructorVec = SmallVec<[T; MAX_ISLE_RETURNS]>; +type TypeAndInstructionData = (Type, InstructionData); + impl generated_code::Length for SmallVec { #[inline] fn len(&self) -> usize { @@ -128,6 +130,13 @@ impl<'a, 'b, 'c> generated_code::Context for IsleContext<'a, 'b, 'c> { *returns = InstDataEtorIter::new(eclass); } + type inst_data_tupled_etor_returns = InstDataEtorIter<'a, 'b, 'c>; + + fn inst_data_tupled_etor(&mut self, eclass: Value, returns: &mut InstDataEtorIter<'a, 'b, 'c>) { + // Literally identical to `inst_data_etor`, just a different nominal type in ISLE + self.inst_data_etor(eclass, returns); + } + fn make_inst_ctor(&mut self, ty: Type, op: &InstructionData) -> Value { let value = self .ctx @@ -149,6 +158,21 @@ impl<'a, 'b, 'c> generated_code::Context for IsleContext<'a, 'b, 'c> { self.ctx.func.dfg.value_type(val) } + fn iconst_sextend_etor( + &mut self, + (ty, inst_data): (Type, InstructionData), + ) -> Option<(Type, i64)> { + if let InstructionData::UnaryImm { + opcode: Opcode::Iconst, + imm, + } = inst_data + { + Some((ty, self.i64_sextend_imm64(ty, imm))) + } else { + None + } + } + fn remat(&mut self, value: Value) -> Value { trace!("remat: {}", value); self.ctx.remat_values.insert(value); diff --git a/cranelift/codegen/src/opts/arithmetic.isle b/cranelift/codegen/src/opts/arithmetic.isle index 3ac4381a92fd..5ed3669e7745 100644 --- a/cranelift/codegen/src/opts/arithmetic.isle +++ b/cranelift/codegen/src/opts/arithmetic.isle @@ -7,16 +7,16 @@ ;; x+0 == x. (rule (simplify (iadd ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) ;; x-0 == x. (rule (simplify (isub ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) ;; 0-x == (ineg x). (rule (simplify (isub ty - (iconst ty (u64_from_imm64 0)) + (iconst_u ty 0) x)) (ineg ty x)) @@ -47,51 +47,49 @@ (subsume inner)) ;; x-x == 0. -(rule (simplify (isub (fits_in_64 (ty_int ty)) x x)) (subsume (iconst ty (imm64 0)))) +(rule (simplify (isub (fits_in_64 (ty_int ty)) x x)) (subsume (iconst_u ty 0))) ;; x*1 == x. (rule (simplify (imul ty x - (iconst ty (u64_from_imm64 1)))) + (iconst_u ty 1))) (subsume x)) ;; x*0 == 0. (rule (simplify (imul ty _ - zero @ (iconst ty (u64_from_imm64 0)))) + zero @ (iconst_u ty 0))) (subsume zero)) ;; x*-1 == ineg(x). -(rule (simplify (imul ty x (iconst ty c))) - (if-let -1 (i64_sextend_imm64 ty c)) +(rule (simplify (imul ty x (iconst_s ty -1))) (ineg ty x)) ;; (!x) + 1 == ineg(x) -(rule (simplify (iadd ty (bnot ty x) (iconst ty (u64_from_imm64 1)))) +(rule (simplify (iadd ty (bnot ty x) (iconst_u ty 1))) (ineg ty x)) ;; !(x - 1) == !(x + (-1)) == ineg(x) -(rule (simplify (bnot ty (isub ty x (iconst ty (u64_from_imm64 1))))) +(rule (simplify (bnot ty (isub ty x (iconst_s ty 1)))) (ineg ty x)) -(rule (simplify (bnot ty (iadd ty x (iconst ty c)))) - (if-let -1 (i64_sextend_imm64 ty c)) +(rule (simplify (bnot ty (iadd ty x (iconst_s ty -1)))) (ineg ty x)) ;; x/1 == x. (rule (simplify (sdiv ty x - (iconst ty (u64_from_imm64 1)))) + (iconst_u ty 1))) (subsume x)) (rule (simplify (udiv ty x - (iconst ty (u64_from_imm64 1)))) + (iconst_u ty 1))) (subsume x)) ;; TODO: strength reduction: div to shifts ;; TODO: div/rem by constants -> magic multiplications ;; x*2 == x+x. -(rule (simplify (imul ty x (iconst _ (simm32 2)))) +(rule (simplify (imul ty x (iconst_u _ 2))) (iadd ty x x)) ;; x*c == x< uextend(icmp(x, y)) (rule (simplify (select ty cmp@(icmp _ cc x y) - (iconst _ (u64_from_imm64 1)) - (iconst _ (u64_from_imm64 0)))) + (iconst_u _ 1) + (iconst_u _ 0))) (uextend_from_i8 ty cmp)) ;; if icmp(x, y) { 0 } else { 1 } => uextend(!icmp(x, y)) (rule (simplify (select sty (icmp cty cc x y) - (iconst _ (u64_from_imm64 0)) - (iconst _ (u64_from_imm64 1)))) + (iconst_u _ 0) + (iconst_u _ 1))) (uextend_from_i8 sty (icmp cty (intcc_complement cc) x y))) ;; Transform select-of-icmp into {u,s}{min,max} instructions where possible. diff --git a/cranelift/codegen/src/opts/shifts.isle b/cranelift/codegen/src/opts/shifts.isle index 272c5c90bf65..0849d541ecb4 100644 --- a/cranelift/codegen/src/opts/shifts.isle +++ b/cranelift/codegen/src/opts/shifts.isle @@ -3,23 +3,23 @@ ;; x>>0 == x<<0 == x rotr 0 == x rotl 0 == x. (rule (simplify (ishl ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) (rule (simplify (ushr ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) (rule (simplify (sshr ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) (rule (simplify (rotr ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) (rule (simplify (rotl ty x - (iconst ty (u64_from_imm64 0)))) + (iconst_u ty 0))) (subsume x)) ;; `(x >> k) << k` is the same as masking off the bottom `k` bits (regardless if @@ -159,7 +159,7 @@ (u64_and k1 (ty_shift_mask ty)) (u64_and k2 (ty_shift_mask ty)))) (if-let $true (u64_lt shift_amt (ty_bits_u64 (lane_type ty)))) - (ishl ty x (iconst_u64 kty shift_amt))) + (ishl ty x (iconst_u kty shift_amt))) (rule (simplify (ushr ty (ushr ty x (iconst kty (u64_from_imm64 k1))) @@ -168,7 +168,7 @@ (u64_and k1 (ty_shift_mask ty)) (u64_and k2 (ty_shift_mask ty)))) (if-let $true (u64_lt shift_amt (ty_bits_u64 (lane_type ty)))) - (ushr ty x (iconst_u64 kty shift_amt))) + (ushr ty x (iconst_u kty shift_amt))) (rule (simplify (sshr ty (sshr ty x (iconst kty (u64_from_imm64 k1))) @@ -177,7 +177,7 @@ (u64_and k1 (ty_shift_mask ty)) (u64_and k2 (ty_shift_mask ty)))) (if-let $true (u64_lt shift_amt (ty_bits_u64 (lane_type ty)))) - (sshr ty x (iconst_u64 kty shift_amt))) + (sshr ty x (iconst_u kty shift_amt))) ;; Simliarly, if the shift amount overflows the type, then we can turn ;; it into a 0 @@ -191,7 +191,7 @@ (u64_and k1 (ty_shift_mask ty)) (u64_and k2 (ty_shift_mask ty)))) (if-let $true (u64_le (ty_bits_u64 ty) shift_amt)) - (subsume (iconst_u64 ty 0))) + (subsume (iconst_u ty 0))) (rule (simplify (ushr ty (ushr ty x (iconst _ (u64_from_imm64 k1))) @@ -200,7 +200,7 @@ (u64_and k1 (ty_shift_mask ty)) (u64_and k2 (ty_shift_mask ty)))) (if-let $true (u64_le (ty_bits_u64 ty) shift_amt)) - (subsume (iconst_u64 ty 0))) + (subsume (iconst_u ty 0))) ;; (rotl (rotr x y) y) == x ;; (rotr (rotl x y) y) == x diff --git a/cranelift/codegen/src/opts/spaceship.isle b/cranelift/codegen/src/opts/spaceship.isle index 809274317332..d7d2071528d6 100644 --- a/cranelift/codegen/src/opts/spaceship.isle +++ b/cranelift/codegen/src/opts/spaceship.isle @@ -11,92 +11,80 @@ ;; x < y ? -1 : x == y ? 0 : +1 ;; x < y ? -1 : x != y ? +1 : 0 (rule (simplify (select ty (ult rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (ne rty x y))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_u rty x y))) (rule (simplify (select ty (ult rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (uextend ty (ne rty x y)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x < y ? -1 : x <= y ? 0 : +1 ;; x < y ? -1 : x > y ? +1 : 0 (rule (simplify (select ty (ult rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (ugt rty x y))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_u rty x y))) (rule (simplify (select ty (ult rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (uextend ty (ugt rty x y)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x == y ? 0 : x < y ? -1 : +1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (ult rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 1))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x == y ? 0 : x <= y ? -1 : +1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (ule rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 1))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x == y ? 0 : x > y ? +1 : -1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (ugt rty x y) - (iconst ty (u64_from_imm64 1)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 1) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x == y ? 0 : x >= y ? +1 : -1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (uge rty x y) - (iconst ty (u64_from_imm64 1)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 1) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x > y ? 1 : x < y ? -1 : 0 (rule (simplify (select ty (ugt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (ult rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 0))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 0)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x > y ? 1 : x != y ? -1 : 0 (rule (simplify (select ty (ugt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (ne rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 0))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 0)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x > y ? 1 : x == y ? 0 : -1 (rule (simplify (select ty (ugt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 0) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; x > y ? 1 : x >= y ? 0 : -1 (rule (simplify (select ty (ugt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (uge rty x y) - (iconst ty (u64_from_imm64 0)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 0) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_u rty x y))) ;; Same, but for signed comparisons this time @@ -104,92 +92,80 @@ ;; x < y ? -1 : x == y ? 0 : +1 ;; x < y ? -1 : x != y ? +1 : 0 (rule (simplify (select ty (slt rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (ne rty x y))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (spaceship_s rty x y)) (rule (simplify (select ty (slt rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (uextend ty (ne rty x y)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x < y ? -1 : x <= y ? 0 : +1 ;; x < y ? -1 : x > y ? +1 : 0 (rule (simplify (select ty (slt rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (sgt rty x y))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (spaceship_s rty x y)) (rule (simplify (select ty (slt rty x y) - (iconst ty neg_1) + (iconst_s ty -1) (uextend ty (sgt rty x y)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x == y ? 0 : x < y ? -1 : +1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (slt rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 1))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x == y ? 0 : x <= y ? -1 : +1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (sle rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 1))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x == y ? 0 : x > y ? +1 : -1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (sgt rty x y) - (iconst ty (u64_from_imm64 1)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 1) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x == y ? 0 : x >= y ? +1 : -1 (rule (simplify (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) + (iconst_s ty 0) (select ty (sge rty x y) - (iconst ty (u64_from_imm64 1)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 1) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x > y ? 1 : x < y ? -1 : 0 (rule (simplify (select ty (sgt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (slt rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 0))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 0)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x > y ? 1 : x != y ? -1 : 0 (rule (simplify (select ty (sgt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (ne rty x y) - (iconst ty neg_1) - (iconst ty (u64_from_imm64 0))))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty -1) + (iconst_s ty 0)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x > y ? 1 : x == y ? 0 : -1 (rule (simplify (select ty (sgt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (eq rty x y) - (iconst ty (u64_from_imm64 0)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 0) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; x > y ? 1 : x >= y ? 0 : -1 (rule (simplify (select ty (sgt rty x y) - (iconst ty (u64_from_imm64 1)) + (iconst_s ty 1) (select ty (sge rty x y) - (iconst ty (u64_from_imm64 0)) - (iconst ty neg_1)))) - (if-let -1 (i64_sextend_imm64 ty neg_1)) + (iconst_s ty 0) + (iconst_s ty -1)))) (sextend_from_i8 ty (spaceship_s rty x y))) ;; Then once we have it normalized, we can apply some basic simplifications. @@ -199,35 +175,35 @@ ;; also matching things like `(a <=> b) < 1` or `(a <=> b) <= -1`. ;; (a <=> b) == 0 --> a == b -(rule (simplify (eq _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (eq _ (spaceship_s ty x y) (iconst_s _ 0))) (eq ty x y)) -(rule (simplify (eq _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (eq _ (spaceship_u ty x y) (iconst_s _ 0))) (eq ty x y)) ;; (a <=> b) != 0 --> a != b -(rule (simplify (ne _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (ne _ (spaceship_s ty x y) (iconst_s _ 0))) (ne ty x y)) -(rule (simplify (ne _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (ne _ (spaceship_u ty x y) (iconst_s _ 0))) (ne ty x y)) ;; (a <=> b) < 0 --> a < b -(rule (simplify (slt _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (slt _ (spaceship_s ty x y) (iconst_s _ 0))) (slt ty x y)) -(rule (simplify (slt _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (slt _ (spaceship_u ty x y) (iconst_s _ 0))) (ult ty x y)) ;; (a <=> b) <= 0 --> a <= b -(rule (simplify (sle _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sle _ (spaceship_s ty x y) (iconst_s _ 0))) (sle ty x y)) -(rule (simplify (sle _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sle _ (spaceship_u ty x y) (iconst_s _ 0))) (ule ty x y)) ;; (a <=> b) > 0 --> a > b -(rule (simplify (sgt _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sgt _ (spaceship_s ty x y) (iconst_s _ 0))) (sgt ty x y)) -(rule (simplify (sgt _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sgt _ (spaceship_u ty x y) (iconst_s _ 0))) (ugt ty x y)) ;; (a <=> b) >= 0 --> a >= b -(rule (simplify (sge _ (spaceship_s ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sge _ (spaceship_s ty x y) (iconst_s _ 0))) (sge ty x y)) -(rule (simplify (sge _ (spaceship_u ty x y) (iconst _ (u64_from_imm64 0)))) +(rule (simplify (sge _ (spaceship_u ty x y) (iconst_s _ 0))) (uge ty x y)) ;; extend from i8 to i8 is invalid CLIF, so this allows fixing that in the output diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index c4416a4f9bca..ed625559fe63 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -67,14 +67,6 @@ (decl pure partial u8_lt (u8 u8) Unit) (extern constructor u8_lt u8_lt) -;; Get a signed 32-bit immediate in an u32 from an Imm64, if possible. -(decl simm32 (i32) Imm64) -(extern extractor simm32 simm32) - -;; Get an unsigned 8-bit immediate in a u8 from an Imm64, if possible. -(decl uimm8 (u8) Imm64) -(extern extractor uimm8 uimm8) - ;;;; Primitive Type Conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (decl pure u8_as_i8 (u8) i8) diff --git a/cranelift/codegen/src/prelude_lower.isle b/cranelift/codegen/src/prelude_lower.isle index d90286e88a6f..54851de654ad 100644 --- a/cranelift/codegen/src/prelude_lower.isle +++ b/cranelift/codegen/src/prelude_lower.isle @@ -302,6 +302,18 @@ (decl maybe_uextend (Value) Value) (extern extractor maybe_uextend maybe_uextend) +;; Get a signed 32-bit immediate in an u32 from an Imm64, if possible. +;; Note that this checks that the raw i64 value from the Imm64 fits in i32, +;; so `-1_u32` will not actually match -- it's treated as `0xFFFF_FFFF_i64`, +;; which doesn't fit in an i32 and thus doesn't match the extractor. +;; An Imm64 of `-1_i64` *will* match, however. +(decl simm32 (i32) Imm64) +(extern extractor simm32 simm32) + +;; Get an unsigned 8-bit immediate in a u8 from an Imm64, if possible. +(decl uimm8 (u8) Imm64) +(extern extractor uimm8 uimm8) + ;; Instruction creation helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Emit an instruction. diff --git a/cranelift/codegen/src/prelude_opt.isle b/cranelift/codegen/src/prelude_opt.isle index 55dc75f0b41a..5011481afddf 100644 --- a/cranelift/codegen/src/prelude_opt.isle +++ b/cranelift/codegen/src/prelude_opt.isle @@ -6,6 +6,14 @@ (decl multi inst_data (Type InstructionData) Value) (extern extractor inst_data inst_data_etor) +;; Identical to `inst_data`, just with a different ISLE type. +;; This is basically a manual version of `curry`/`uncurry` in Haskell: +;; to compose extractors the outer one needs to be single-parameter, +;; so this combines the two parameters of `inst_data` into one. +(type TypeAndInstructionData (primitive TypeAndInstructionData)) +(decl multi inst_data_tupled (TypeAndInstructionData) Value) +(extern extractor inst_data_tupled inst_data_tupled_etor) + ;; Construct a pure node, returning a new (or deduplicated ;; already-existing) eclass ID. (decl make_inst (Type InstructionData) Value) @@ -54,13 +62,33 @@ ;;;;; constructors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(decl iconst_u64 (Type u64) Value) +(decl iconst_sextend_etor (Type i64) TypeAndInstructionData) +(extern extractor iconst_sextend_etor iconst_sextend_etor) -;; Use a single iconst for types that fit in 64 bits. -(rule 0 (iconst_u64 (ty_int_ref_scalar_64 ty) val) - (if-let $true (u64_le val (ty_umax ty))) - (iconst ty (imm64_masked ty val))) +;; Construct an `iconst` from an `i64` or Extract an `i64` from an `iconst` +;; by treating the constant as signed. +;; When extracting, smaller types get their value sign-extended to 64-bits, +;; so that `iconst.i8 255` will give you a `-1_i64`. +;; When constructing, the rule will fail if the value cannot be represented in +;; the target type. If it fits, it'll be masked accordingly in the constant. +(decl iconst_s (Type i64) Value) +(extractor (iconst_s ty c) (inst_data_tupled (iconst_sextend_etor ty c))) +(rule 0 (iconst_s ty c) + (if-let c_masked (u64_and (i64_as_u64 c) (ty_umax ty))) + (if-let c_reextended (i64_sextend_u64 ty c_masked)) + (if-let $true (u64_eq (i64_as_u64 c) (i64_as_u64 c_reextended))) + (iconst ty (imm64 c_masked))) +(rule 1 (iconst_s $I128 c) (sextend $I128 (iconst_s $I64 c))) -;; For i128 types use a iconst, but zero extend it to i128. -(rule 1 (iconst_u64 $I128 val) - (uextend $I128 (iconst $I64 (imm64_masked $I64 val)))) +;; Construct an `iconst` from a `u64` or Extract a `u64` from an `iconst` +;; by treating the constant as unsigned. +;; When extracting, smaller types get their value zero-extended to 64-bits, +;; so that `iconst.i8 255` will give you a `255_u64`. +;; When constructing, the rule will fail if the value cannot be represented in +;; the target type. +(decl iconst_u (Type u64) Value) +(extractor (iconst_u ty c) (iconst ty (u64_from_imm64 c))) +(rule 0 (iconst_u ty c) + (if-let $true (u64_le c (ty_umax ty))) + (iconst ty (imm64 c))) +(rule 1 (iconst_u $I128 c) (uextend $I128 (iconst_u $I64 c))) diff --git a/cranelift/filetests/filetests/pcc/succeed/const.clif b/cranelift/filetests/filetests/pcc/succeed/const.clif index da0c8a08655c..d0c381c5c0ac 100644 --- a/cranelift/filetests/filetests/pcc/succeed/const.clif +++ b/cranelift/filetests/filetests/pcc/succeed/const.clif @@ -16,3 +16,15 @@ block0: v8 ! range(64, 0xffff_0000_0000_ffff, 0xffff_0000_0000_ffff) = iconst.i64 0xffff_0000_0000_ffff return } + +function %f1() -> i32 { +block0: + v0 = iconst.i32 0x10_0010 + return v0 +} + +function %f2() -> i64 { +block0: + v0 = iconst.i64 0x9_ffff_ffff + return v0 +} diff --git a/crates/component-macro/tests/codegen/multiversion/root.wit b/crates/component-macro/tests/codegen/multiversion/root.wit index 52225f02beb3..b3bb3c80d3da 100644 --- a/crates/component-macro/tests/codegen/multiversion/root.wit +++ b/crates/component-macro/tests/codegen/multiversion/root.wit @@ -3,5 +3,6 @@ package foo:bar; world foo { import my:dep/a@0.1.0; import my:dep/a@0.2.0; + export my:dep/a@0.1.0; export my:dep/a@0.2.0; } diff --git a/crates/test-programs/src/bin/preview2_adapter_badfd.rs b/crates/test-programs/src/bin/preview2_adapter_badfd.rs index 7baa33717225..e437dd668dcc 100644 --- a/crates/test-programs/src/bin/preview2_adapter_badfd.rs +++ b/crates/test-programs/src/bin/preview2_adapter_badfd.rs @@ -2,15 +2,15 @@ fn main() { #[link(wasm_import_module = "wasi_snapshot_preview1")] extern "C" { #[cfg_attr(target_arch = "wasm32", link_name = "adapter_open_badfd")] - fn adapter_open_badfd(fd: *mut u32) -> bool; + fn adapter_open_badfd(fd: *mut u32) -> wasi::Errno; #[cfg_attr(target_arch = "wasm32", link_name = "adapter_close_badfd")] - fn adapter_close_badfd(fd: u32) -> bool; + fn adapter_close_badfd(fd: u32) -> wasi::Errno; } unsafe { let mut fd = 0; - assert!(adapter_open_badfd(&mut fd)); + assert_eq!(adapter_open_badfd(&mut fd), wasi::ERRNO_SUCCESS); assert_eq!(wasi::fd_close(fd), Err(wasi::ERRNO_BADF)); @@ -41,6 +41,6 @@ fn main() { Err(wasi::ERRNO_BADF) ); - assert!(adapter_close_badfd(fd)); + assert_eq!(adapter_close_badfd(fd), wasi::ERRNO_SUCCESS); } } diff --git a/crates/wasi-common/src/snapshots/preview_1/error.rs b/crates/wasi-common/src/snapshots/preview_1/error.rs index f0b7cdf4ad94..f5b8afcfcce0 100644 --- a/crates/wasi-common/src/snapshots/preview_1/error.rs +++ b/crates/wasi-common/src/snapshots/preview_1/error.rs @@ -216,6 +216,7 @@ impl From for Error { std::io::ErrorKind::PermissionDenied => Errno::Perm.into(), std::io::ErrorKind::AlreadyExists => Errno::Exist.into(), std::io::ErrorKind::InvalidInput => Errno::Inval.into(), + std::io::ErrorKind::WouldBlock => Errno::Again.into(), _ => Error::trap(anyhow::anyhow!(err).context("Unknown OS error")), }, } diff --git a/crates/wasi-preview1-component-adapter/src/lib.rs b/crates/wasi-preview1-component-adapter/src/lib.rs index 59561f3ef150..8ef496d56441 100644 --- a/crates/wasi-preview1-component-adapter/src/lib.rs +++ b/crates/wasi-preview1-component-adapter/src/lib.rs @@ -152,17 +152,17 @@ impl TrappingUnwrap for Result { /// from WASI Preview 1 to Preview 2. It will use this function to reserve /// descriptors for its own use, valid only for use with libc functions. #[no_mangle] -pub unsafe extern "C" fn adapter_open_badfd(fd: *mut u32) -> bool { +pub unsafe extern "C" fn adapter_open_badfd(fd: *mut u32) -> Errno { State::with(|state| { *fd = state.descriptors_mut().open(Descriptor::Bad)?; Ok(()) - }) == wasi::ERRNO_SUCCESS + }) } /// Close a descriptor previously opened using `adapter_open_badfd`. #[no_mangle] -pub unsafe extern "C" fn adapter_close_badfd(fd: u32) -> bool { - State::with(|state| state.descriptors_mut().close(fd)) == wasi::ERRNO_SUCCESS +pub unsafe extern "C" fn adapter_close_badfd(fd: u32) -> Errno { + State::with(|state| state.descriptors_mut().close(fd)) } #[no_mangle] diff --git a/crates/wasi/src/preview2/ctx.rs b/crates/wasi/src/preview2/ctx.rs index d3d52408dc96..a0447711adf4 100644 --- a/crates/wasi/src/preview2/ctx.rs +++ b/crates/wasi/src/preview2/ctx.rs @@ -1,18 +1,17 @@ -use super::clocks::host::{monotonic_clock, wall_clock}; use crate::preview2::{ - clocks::{self, HostMonotonicClock, HostWallClock}, + clocks::{ + host::{monotonic_clock, wall_clock}, + HostMonotonicClock, HostWallClock, + }, filesystem::Dir, + network::{SocketAddrCheck, SocketAddrUse}, pipe, random, stdio, stdio::{StdinStream, StdoutStream}, DirPerms, FilePerms, }; use cap_rand::{Rng, RngCore, SeedableRng}; -use cap_std::ipnet::{self, IpNet}; -use cap_std::net::Pool; -use cap_std::{ambient_authority, AmbientAuthority}; -use std::mem; -use std::net::{Ipv4Addr, Ipv6Addr}; use std::sync::Arc; +use std::{mem, net::SocketAddr}; use wasmtime::component::ResourceTable; pub struct WasiCtxBuilder { @@ -22,8 +21,7 @@ pub struct WasiCtxBuilder { env: Vec<(String, String)>, args: Vec, preopens: Vec<(Dir, String)>, - - pool: Pool, + socket_addr_check: SocketAddrCheck, random: Box, insecure_random: Box, insecure_random_seed: u128, @@ -73,7 +71,7 @@ impl WasiCtxBuilder { env: Vec::new(), args: Vec::new(), preopens: Vec::new(), - pool: Pool::new(), + socket_addr_check: SocketAddrCheck::default(), random: random::thread_rng(), insecure_random, insecure_random_seed, @@ -173,80 +171,36 @@ impl WasiCtxBuilder { self.insecure_random = Box::new(insecure_random); self } + pub fn insecure_random_seed(&mut self, insecure_random_seed: u128) -> &mut Self { self.insecure_random_seed = insecure_random_seed; self } - pub fn wall_clock(&mut self, clock: impl clocks::HostWallClock + 'static) -> &mut Self { + pub fn wall_clock(&mut self, clock: impl HostWallClock + 'static) -> &mut Self { self.wall_clock = Box::new(clock); self } - pub fn monotonic_clock( - &mut self, - clock: impl clocks::HostMonotonicClock + 'static, - ) -> &mut Self { + pub fn monotonic_clock(&mut self, clock: impl HostMonotonicClock + 'static) -> &mut Self { self.monotonic_clock = Box::new(clock); self } - /// Add all network addresses accessable to the host to the pool. - pub fn inherit_network(&mut self, ambient_authority: AmbientAuthority) -> &mut Self { - self.pool.insert_ip_net_port_any( - IpNet::new(Ipv4Addr::UNSPECIFIED.into(), 0).unwrap(), - ambient_authority, - ); - self.pool.insert_ip_net_port_any( - IpNet::new(Ipv6Addr::UNSPECIFIED.into(), 0).unwrap(), - ambient_authority, - ); - self - } - - /// Add network addresses to the pool. - pub fn insert_addr( - &mut self, - addrs: A, - ) -> std::io::Result<&mut Self> { - self.pool.insert(addrs, ambient_authority())?; - Ok(self) - } - - /// Add a specific [`cap_std::net::SocketAddr`] to the pool. - pub fn insert_socket_addr(&mut self, addr: cap_std::net::SocketAddr) -> &mut Self { - self.pool.insert_socket_addr(addr, ambient_authority()); - self - } - - /// Add a range of network addresses, accepting any port, to the pool. - /// - /// Unlike `insert_ip_net`, this function grants access to any requested port. - pub fn insert_ip_net_port_any(&mut self, ip_net: ipnet::IpNet) -> &mut Self { - self.pool - .insert_ip_net_port_any(ip_net, ambient_authority()); - self + /// Allow all network addresses accessible to the host + pub fn inherit_network(&mut self) -> &mut Self { + self.socket_addr_check(|_, _| true) } - /// Add a range of network addresses, accepting a range of ports, to - /// per-instance networks. + /// A check that will be called for each socket address that is used. /// - /// This grants access to the port range starting at `ports_start` and, if - /// `ports_end` is provided, ending before `ports_end`. - pub fn insert_ip_net_port_range( - &mut self, - ip_net: ipnet::IpNet, - ports_start: u16, - ports_end: Option, - ) -> &mut Self { - self.pool - .insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority()); - self - } - - /// Add a range of network addresses with a specific port to the pool. - pub fn insert_ip_net(&mut self, ip_net: ipnet::IpNet, port: u16) -> &mut Self { - self.pool.insert_ip_net(ip_net, port, ambient_authority()); + /// Returning `true` will permit socket connections to the `SocketAddr`, + /// while returning `false` will reject the connection. + pub fn socket_addr_check(&mut self, check: F) -> &mut Self + where + F: Fn(&SocketAddr, SocketAddrUse) -> bool + Send + Sync + 'static, + { + self.socket_addr_check = SocketAddrCheck(Arc::new(check)); self } @@ -286,7 +240,7 @@ impl WasiCtxBuilder { env, args, preopens, - pool, + socket_addr_check, random, insecure_random, insecure_random_seed, @@ -304,7 +258,7 @@ impl WasiCtxBuilder { env, args, preopens, - pool: Arc::new(pool), + socket_addr_check, random, insecure_random, insecure_random_seed, @@ -334,7 +288,7 @@ pub struct WasiCtx { pub(crate) stdin: Box, pub(crate) stdout: Box, pub(crate) stderr: Box, - pub(crate) pool: Arc, + pub(crate) socket_addr_check: SocketAddrCheck, pub(crate) allowed_network_uses: AllowedNetworkUses, } @@ -360,8 +314,7 @@ impl AllowedNetworkUses { return Err(std::io::Error::new( std::io::ErrorKind::PermissionDenied, "UDP is not allowed", - ) - .into()); + )); } Ok(()) @@ -372,8 +325,7 @@ impl AllowedNetworkUses { return Err(std::io::Error::new( std::io::ErrorKind::PermissionDenied, "TCP is not allowed", - ) - .into()); + )); } Ok(()) diff --git a/crates/wasi/src/preview2/host/instance_network.rs b/crates/wasi/src/preview2/host/instance_network.rs index 428151dcc7c4..382bae913c0e 100644 --- a/crates/wasi/src/preview2/host/instance_network.rs +++ b/crates/wasi/src/preview2/host/instance_network.rs @@ -6,7 +6,7 @@ use wasmtime::component::Resource; impl instance_network::Host for T { fn instance_network(&mut self) -> Result, anyhow::Error> { let network = Network { - pool: self.ctx().pool.clone(), + socket_addr_check: self.ctx().socket_addr_check.clone(), allow_ip_name_lookup: self.ctx().allowed_network_uses.ip_name_lookup, }; let network = self.table_mut().push(network)?; diff --git a/crates/wasi/src/preview2/host/network.rs b/crates/wasi/src/preview2/host/network.rs index ddb4b7d63b2c..e7e025e8eb90 100644 --- a/crates/wasi/src/preview2/host/network.rs +++ b/crates/wasi/src/preview2/host/network.rs @@ -218,9 +218,9 @@ pub(crate) mod util { use crate::preview2::bindings::sockets::network::ErrorCode; use crate::preview2::network::SocketAddressFamily; use crate::preview2::SocketResult; - use cap_net_ext::{Blocking, TcpBinder, TcpConnecter, TcpListenerExt, UdpBinder}; - use cap_std::net::{TcpListener, TcpStream, UdpSocket}; - use rustix::fd::AsFd; + use cap_net_ext::{AddressFamily, Blocking, TcpListenerExt, UdpSocketExt}; + use io_lifetimes::AsSocketlike; + use rustix::fd::{AsFd, OwnedFd}; use rustix::io::Errno; use rustix::net::sockopt; @@ -302,46 +302,64 @@ pub(crate) mod util { * Syscalls wrappers with (opinionated) portability fixes. */ - pub fn tcp_bind(listener: &TcpListener, binder: &TcpBinder) -> std::io::Result<()> { - binder - .bind_existing_tcp_listener(listener) - .map_err(|error| match Errno::from_io_error(&error) { - // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS - // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted. - #[cfg(windows)] - Some(Errno::NOBUFS) => Errno::ADDRINUSE.into(), - _ => error, - }) + pub fn tcp_socket(family: AddressFamily, blocking: Blocking) -> std::io::Result { + // Delegate socket creation to cap_net_ext. They handle a couple of things for us: + // - On Windows: call WSAStartup if not done before. + // - Set the NONBLOCK and CLOEXEC flags. Either immediately during socket creation, + // or afterwards using ioctl or fcntl. Exact method depends on the platform. + + let listener = cap_std::net::TcpListener::new(family, blocking)?; + Ok(OwnedFd::from(listener)) } - pub fn udp_bind(socket: &UdpSocket, binder: &UdpBinder) -> std::io::Result<()> { - binder.bind_existing_udp_socket(socket).map_err(|error| { - match Errno::from_io_error(&error) { - // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS - // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted. - #[cfg(windows)] - Some(Errno::NOBUFS) => Errno::ADDRINUSE.into(), - _ => error, - } + pub fn udp_socket(family: AddressFamily, blocking: Blocking) -> std::io::Result { + // Delegate socket creation to cap_net_ext. They handle a couple of things for us: + // - On Windows: call WSAStartup if not done before. + // - Set the NONBLOCK and CLOEXEC flags. Either immediately during socket creation, + // or afterwards using ioctl or fcntl. Exact method depends on the platform. + + let socket = cap_std::net::UdpSocket::new(family, blocking)?; + Ok(OwnedFd::from(socket)) + } + + pub fn tcp_bind(sockfd: Fd, addr: &SocketAddr) -> rustix::io::Result<()> { + rustix::net::bind(sockfd, addr).map_err(|error| match error { + // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS + // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted. + #[cfg(windows)] + Errno::NOBUFS => Errno::ADDRINUSE, + _ => error, }) } - pub fn tcp_connect(listener: &TcpListener, connecter: &TcpConnecter) -> std::io::Result<()> { - connecter.connect_existing_tcp_listener(listener).map_err( - |error| match Errno::from_io_error(&error) { - // On POSIX, non-blocking `connect` returns `EINPROGRESS`. - // Windows returns `WSAEWOULDBLOCK`. - // - // This normalized error code is depended upon by: tcp.rs - #[cfg(windows)] - Some(Errno::WOULDBLOCK) => Errno::INPROGRESS.into(), - _ => error, - }, - ) + pub fn udp_bind(sockfd: Fd, addr: &SocketAddr) -> rustix::io::Result<()> { + rustix::net::bind(sockfd, addr).map_err(|error| match error { + // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS + // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted. + #[cfg(windows)] + Errno::NOBUFS => Errno::ADDRINUSE, + _ => error, + }) + } + + pub fn tcp_connect(sockfd: Fd, addr: &SocketAddr) -> rustix::io::Result<()> { + rustix::net::connect(sockfd, addr).map_err(|error| match error { + // On POSIX, non-blocking `connect` returns `EINPROGRESS`. + // Windows returns `WSAEWOULDBLOCK`. + // + // This normalized error code is depended upon by: tcp.rs + #[cfg(windows)] + Errno::WOULDBLOCK => Errno::INPROGRESS, + _ => error, + }) } - pub fn tcp_listen(listener: &TcpListener, backlog: Option) -> std::io::Result<()> { - listener + pub fn tcp_listen(sockfd: Fd, backlog: Option) -> std::io::Result<()> { + // Delegate `listen` to cap_net_ext. That is a thin wrapper around rustix::net::listen, + // with a platform-dependent default value for the backlog size. + sockfd + .as_fd() + .as_socketlike_view::() .listen(backlog) .map_err(|error| match Errno::from_io_error(&error) { // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen#:~:text=WSAEMFILE @@ -355,15 +373,22 @@ pub(crate) mod util { // on Microsoft's documentation here. #[cfg(windows)] Some(Errno::MFILE) => Errno::NOBUFS.into(), + _ => error, }) } - pub fn tcp_accept( - listener: &TcpListener, + pub fn tcp_accept( + sockfd: Fd, blocking: Blocking, - ) -> std::io::Result<(TcpStream, SocketAddr)> { - listener + ) -> std::io::Result<(OwnedFd, SocketAddr)> { + // Delegate `accept` to cap_net_ext. They set the NONBLOCK and CLOEXEC flags + // for us. Either immediately as a flag to `accept`, or afterwards using + // ioctl or fcntl. Exact method depends on the platform. + + let (client, addr) = sockfd + .as_fd() + .as_socketlike_view::() .accept_with(blocking) .map_err(|error| match Errno::from_io_error(&error) { // From: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept#:~:text=WSAEINPROGRESS @@ -397,7 +422,9 @@ pub(crate) mod util { ) => Errno::CONNABORTED.into(), _ => error, - }) + })?; + + Ok((client.into(), addr)) } pub fn udp_disconnect(sockfd: Fd) -> rustix::io::Result<()> { diff --git a/crates/wasi/src/preview2/host/tcp.rs b/crates/wasi/src/preview2/host/tcp.rs index 436a92367010..1fe8bc5a6771 100644 --- a/crates/wasi/src/preview2/host/tcp.rs +++ b/crates/wasi/src/preview2/host/tcp.rs @@ -1,4 +1,5 @@ use crate::preview2::host::network::util; +use crate::preview2::network::SocketAddrUse; use crate::preview2::tcp::{TcpSocket, TcpState}; use crate::preview2::{ bindings::{ @@ -9,8 +10,7 @@ use crate::preview2::{ network::SocketAddressFamily, }; use crate::preview2::{Pollable, SocketResult, WasiView}; -use cap_net_ext::{Blocking, PoolExt}; -use cap_std::net::TcpListener; +use cap_net_ext::Blocking; use io_lifetimes::AsSocketlike; use rustix::io::Errno; use rustix::net::sockopt; @@ -44,22 +44,20 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { util::validate_address_family(&local_address, &socket.family)?; { - let binder = network.pool.tcp_binder(local_address)?; - let listener = &*socket.tcp_socket().as_socketlike_view::(); + // Ensure that we're allowed to connect to this address. + network.check_socket_addr(&local_address, SocketAddrUse::TcpBind)?; // Perform the OS bind call. - util::tcp_bind(listener, &binder).map_err(|error| { - match Errno::from_io_error(&error) { - // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html: - // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket - // - // The most common reasons for this error should have already - // been handled by our own validation slightly higher up in this - // function. This error mapping is here just in case there is - // an edge case we didn't catch. - Some(Errno::AFNOSUPPORT) => ErrorCode::InvalidArgument, - _ => ErrorCode::from(error), - } + util::tcp_bind(socket.tcp_socket(), &local_address).map_err(|error| match error { + // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html: + // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket + // + // The most common reasons for this error should have already + // been handled by our own validation slightly higher up in this + // function. This error mapping is here just in case there is + // an edge case we didn't catch. + Errno::AFNOSUPPORT => ErrorCode::InvalidArgument, + _ => ErrorCode::from(error), })?; } @@ -112,11 +110,11 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { util::validate_remote_address(&remote_address)?; util::validate_address_family(&remote_address, &socket.family)?; - let connecter = network.pool.tcp_connecter(remote_address)?; - let listener = &*socket.tcp_socket().as_socketlike_view::(); + // Ensure that we're allowed to connect to this address. + network.check_socket_addr(&remote_address, SocketAddrUse::TcpConnect)?; // Do an OS `connect`. Our socket is non-blocking, so it'll either... - util::tcp_connect(listener, &connecter) + util::tcp_connect(socket.tcp_socket(), &remote_address) }; match r { @@ -127,11 +125,11 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { return Ok(()); } // continue in progress, - Err(err) if Errno::from_io_error(&err) == Some(Errno::INPROGRESS) => {} + Err(err) if err == Errno::INPROGRESS => {} // or fail immediately. Err(err) => { - return Err(match Errno::from_io_error(&err) { - Some(Errno::AFNOSUPPORT) => ErrorCode::InvalidArgument.into(), // See `bind` implementation. + return Err(match err { + Errno::AFNOSUPPORT => ErrorCode::InvalidArgument.into(), // See `bind` implementation. _ => err.into(), }); } @@ -204,10 +202,7 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { | TcpState::BindStarted => return Err(ErrorCode::ConcurrencyConflict.into()), } - { - let listener = &*socket.tcp_socket().as_socketlike_view::(); - util::tcp_listen(listener, socket.listen_backlog_size)?; - } + util::tcp_listen(socket.tcp_socket(), socket.listen_backlog_size)?; socket.tcp_state = TcpState::ListenStarted; @@ -247,9 +242,8 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { // Do the OS accept call. let tcp_socket = socket.tcp_socket(); - let (connection, _addr) = tcp_socket.try_io(Interest::READABLE, || { - let listener = &*tcp_socket.as_socketlike_view::(); - util::tcp_accept(listener, Blocking::No) + let (client_fd, _addr) = tcp_socket.try_io(Interest::READABLE, || { + util::tcp_accept(tcp_socket, Blocking::No) })?; #[cfg(target_os = "macos")] @@ -259,25 +253,25 @@ impl crate::preview2::host::tcp::tcp::HostTcpSocket for T { // and only if a specific value was explicitly set on the listener. if let Some(size) = socket.receive_buffer_size { - _ = util::set_socket_recv_buffer_size(&connection, size); // Ignore potential error. + _ = util::set_socket_recv_buffer_size(&client_fd, size); // Ignore potential error. } if let Some(size) = socket.send_buffer_size { - _ = util::set_socket_send_buffer_size(&connection, size); // Ignore potential error. + _ = util::set_socket_send_buffer_size(&client_fd, size); // Ignore potential error. } // For some reason, IP_TTL is inherited, but IPV6_UNICAST_HOPS isn't. if let (SocketAddressFamily::Ipv6 { .. }, Some(ttl)) = (socket.family, socket.hop_limit) { - _ = util::set_ipv6_unicast_hops(&connection, ttl); // Ignore potential error. + _ = util::set_ipv6_unicast_hops(&client_fd, ttl); // Ignore potential error. } if let Some(value) = socket.keep_alive_idle_time { - _ = util::set_tcp_keepidle(&connection, value); // Ignore potential error. + _ = util::set_tcp_keepidle(&client_fd, value); // Ignore potential error. } } - let mut tcp_socket = TcpSocket::from_tcp_stream(connection, socket.family)?; + let mut tcp_socket = TcpSocket::from_fd(client_fd, socket.family)?; // Mark the socket as connected so that we can exit early from methods like `start-bind`. tcp_socket.tcp_state = TcpState::Connected; diff --git a/crates/wasi/src/preview2/host/udp.rs b/crates/wasi/src/preview2/host/udp.rs index cd6dd62c3b93..b256fd861760 100644 --- a/crates/wasi/src/preview2/host/udp.rs +++ b/crates/wasi/src/preview2/host/udp.rs @@ -1,5 +1,5 @@ use crate::preview2::host::network::util; -use crate::preview2::network::SocketAddressFamily; +use crate::preview2::network::{SocketAddrUse, SocketAddressFamily}; use crate::preview2::{ bindings::{ sockets::network::{ErrorCode, IpAddressFamily, IpSocketAddress, Network}, @@ -11,7 +11,6 @@ use crate::preview2::{ use crate::preview2::{Pollable, SocketError, SocketResult, WasiView}; use anyhow::anyhow; use async_trait::async_trait; -use cap_net_ext::PoolExt; use io_lifetimes::AsSocketlike; use rustix::io::Errno; use rustix::net::sockopt; @@ -42,9 +41,12 @@ impl udp::HostUdpSocket for T { UdpState::Bound | UdpState::Connected => return Err(ErrorCode::InvalidState.into()), } - // Set the pool on the socket so later functions have access to it through the socket handle - let pool = table.get(&network)?.pool.clone(); - table.get_mut(&this)?.pool.replace(pool.clone()); + // Set the socket addr check on the socket so later functions have access to it through the socket handle + let check = table.get(&network)?.socket_addr_check.clone(); + table + .get_mut(&this)? + .socket_addr_check + .replace(check.clone()); let socket = table.get(&this)?; let local_address: SocketAddr = local_address.into(); @@ -52,24 +54,19 @@ impl udp::HostUdpSocket for T { util::validate_address_family(&local_address, &socket.family)?; { - let binder = pool.udp_binder(local_address)?; - let udp_socket = &*socket - .udp_socket() - .as_socketlike_view::(); + check.check(&local_address, SocketAddrUse::UdpBind)?; // Perform the OS bind call. - util::udp_bind(udp_socket, &binder).map_err(|error| { - match Errno::from_io_error(&error) { - // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html: - // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket - // - // The most common reasons for this error should have already - // been handled by our own validation slightly higher up in this - // function. This error mapping is here just in case there is - // an edge case we didn't catch. - Some(Errno::AFNOSUPPORT) => ErrorCode::InvalidArgument, - _ => ErrorCode::from(error), - } + util::udp_bind(socket.udp_socket(), &local_address).map_err(|error| match error { + // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html: + // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket + // + // The most common reasons for this error should have already + // been handled by our own validation slightly higher up in this + // function. This error mapping is here just in case there is + // an edge case we didn't catch. + Errno::AFNOSUPPORT => ErrorCode::InvalidArgument, + _ => ErrorCode::from(error), })?; } @@ -132,13 +129,12 @@ impl udp::HostUdpSocket for T { // Step #2: (Re)connect if let Some(connect_addr) = remote_address { - let Some(pool) = socket.pool.as_ref() else { + let Some(check) = socket.socket_addr_check.as_ref() else { return Err(ErrorCode::InvalidState.into()); }; util::validate_remote_address(&connect_addr)?; util::validate_address_family(&connect_addr, &socket.family)?; - // We don't actually use the connecter, we just use it to verify that `connect_addr` is allowed - let _ = pool.udp_connecter(connect_addr)?; + check.check(&connect_addr, SocketAddrUse::UdpConnect)?; rustix::net::connect(socket.udp_socket(), &connect_addr).map_err( |error| match error { @@ -162,7 +158,7 @@ impl udp::HostUdpSocket for T { remote_address, family: socket.family, send_state: SendState::Idle, - pool: socket.pool.clone(), + socket_addr_check: socket.socket_addr_check.clone(), }; Ok(( @@ -458,13 +454,10 @@ impl udp::HostOutgoingDatagramStream for T { let provided_addr = datagram.remote_address.map(SocketAddr::from); let addr = match (stream.remote_address, provided_addr) { (None, Some(addr)) => { - let Some(pool) = stream.pool.as_ref() else { + let Some(check) = stream.socket_addr_check.as_ref() else { return Err(ErrorCode::InvalidState.into()); }; - // We don't actually use the connecter, we just use it to verify that `addr` - // is allowed. We only need to check the provided addr as the stream's remote - // address was checked when the stream was created. - let _ = pool.udp_connecter(addr)?; + check.check(&addr, SocketAddrUse::UdpOutgoingDatagram)?; addr } (Some(addr), None) => addr, diff --git a/crates/wasi/src/preview2/network.rs b/crates/wasi/src/preview2/network.rs index 6384b1803981..0cd86cba8fe2 100644 --- a/crates/wasi/src/preview2/network.rs +++ b/crates/wasi/src/preview2/network.rs @@ -1,14 +1,64 @@ use crate::preview2::bindings::sockets::network::{Ipv4Address, Ipv6Address}; use crate::preview2::bindings::wasi::sockets::network::ErrorCode; use crate::preview2::TrappableError; -use cap_std::net::Pool; +use std::net::SocketAddr; use std::sync::Arc; pub struct Network { - pub pool: Arc, + pub socket_addr_check: SocketAddrCheck, pub allow_ip_name_lookup: bool, } +impl Network { + pub fn check_socket_addr( + &self, + addr: &SocketAddr, + reason: SocketAddrUse, + ) -> std::io::Result<()> { + self.socket_addr_check.check(addr, reason) + } +} + +/// A check that will be called for each socket address that is used of whether the address is permitted. +#[derive(Clone)] +pub struct SocketAddrCheck( + pub(crate) Arc bool + Send + Sync>, +); + +impl SocketAddrCheck { + pub fn check(&self, addr: &SocketAddr, reason: SocketAddrUse) -> std::io::Result<()> { + if (self.0)(addr, reason) { + Ok(()) + } else { + Err(std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "An address was not permitted by the socket address check.", + )) + } + } +} + +impl Default for SocketAddrCheck { + fn default() -> Self { + Self(Arc::new(|_, _| false)) + } +} + +/// The reason what a socket address is being used for. +#[derive(Clone, Copy, Debug)] +pub enum SocketAddrUse { + /// Binding TCP socket + TcpBind, + /// Connecting TCP socket + TcpConnect, + /// Binding UDP socket + UdpBind, + /// Connecting UDP socket + UdpConnect, + /// Sending datagram on non-connected UDP socket + UdpOutgoingDatagram, +} + pub type SocketResult = Result; pub type SocketError = TrappableError; diff --git a/crates/wasi/src/preview2/tcp.rs b/crates/wasi/src/preview2/tcp.rs index 23061760c27b..fe803306fc3a 100644 --- a/crates/wasi/src/preview2/tcp.rs +++ b/crates/wasi/src/preview2/tcp.rs @@ -1,11 +1,11 @@ use super::network::SocketAddressFamily; use super::{HostInputStream, HostOutputStream, StreamError}; +use crate::preview2::host::network::util; use crate::preview2::{ with_ambient_tokio_runtime, AbortOnDropJoinHandle, InputStream, OutputStream, Subscribe, }; use anyhow::{Error, Result}; -use cap_net_ext::{AddressFamily, Blocking, TcpListenerExt}; -use cap_std::net::TcpListener; +use cap_net_ext::{AddressFamily, Blocking}; use io_lifetimes::raw::{FromRawSocketlike, IntoRawSocketlike}; use rustix::net::sockopt; use std::io; @@ -261,36 +261,26 @@ impl TcpSocket { pub fn new(family: AddressFamily) -> io::Result { // Create a new host socket and set it to non-blocking, which is needed // by our async implementation. - let tcp_listener = TcpListener::new(family, Blocking::No)?; + let fd = util::tcp_socket(family, Blocking::No)?; let socket_address_family = match family { AddressFamily::Ipv4 => SocketAddressFamily::Ipv4, AddressFamily::Ipv6 => SocketAddressFamily::Ipv6 { - v6only: sockopt::get_ipv6_v6only(&tcp_listener)?, + v6only: sockopt::get_ipv6_v6only(&fd)?, }, }; - Self::from_tcp_listener(tcp_listener, socket_address_family) + Self::from_fd(fd, socket_address_family) } /// Create a `TcpSocket` from an existing socket. /// /// The socket must be in non-blocking mode. - pub(crate) fn from_tcp_stream( - tcp_socket: cap_std::net::TcpStream, + pub(crate) fn from_fd( + fd: rustix::fd::OwnedFd, family: SocketAddressFamily, ) -> io::Result { - let tcp_listener = TcpListener::from(rustix::fd::OwnedFd::from(tcp_socket)); - Self::from_tcp_listener(tcp_listener, family) - } - - pub(crate) fn from_tcp_listener( - tcp_listener: cap_std::net::TcpListener, - family: SocketAddressFamily, - ) -> io::Result { - let fd = tcp_listener.into_raw_socketlike(); - let std_stream = unsafe { std::net::TcpStream::from_raw_socketlike(fd) }; - let stream = with_ambient_tokio_runtime(|| tokio::net::TcpStream::try_from(std_stream))?; + let stream = Self::setup_tokio_tcp_stream(fd)?; Ok(Self { inner: Arc::new(stream), @@ -308,6 +298,12 @@ impl TcpSocket { }) } + fn setup_tokio_tcp_stream(fd: rustix::fd::OwnedFd) -> io::Result { + let std_stream = + unsafe { std::net::TcpStream::from_raw_socketlike(fd.into_raw_socketlike()) }; + with_ambient_tokio_runtime(|| tokio::net::TcpStream::try_from(std_stream)) + } + pub fn tcp_socket(&self) -> &tokio::net::TcpStream { &self.inner } diff --git a/crates/wasi/src/preview2/udp.rs b/crates/wasi/src/preview2/udp.rs index 13194c1f512e..34d46402475b 100644 --- a/crates/wasi/src/preview2/udp.rs +++ b/crates/wasi/src/preview2/udp.rs @@ -1,14 +1,14 @@ +use crate::preview2::host::network::util; use crate::preview2::poll::Subscribe; use crate::preview2::with_ambient_tokio_runtime; use async_trait::async_trait; -use cap_net_ext::{AddressFamily, Blocking, UdpSocketExt}; -use cap_std::net::Pool; +use cap_net_ext::{AddressFamily, Blocking}; use io_lifetimes::raw::{FromRawSocketlike, IntoRawSocketlike}; use std::io; use std::net::SocketAddr; use std::sync::Arc; -use super::network::SocketAddressFamily; +use super::network::{SocketAddrCheck, SocketAddressFamily}; /// The state of a UDP socket. /// @@ -44,8 +44,8 @@ pub struct UdpSocket { /// Socket address family. pub(crate) family: SocketAddressFamily, - /// The pool of allowed addresses - pub(crate) pool: Option>, + /// The check of allowed addresses + pub(crate) socket_addr_check: Option, } #[async_trait] @@ -58,33 +58,31 @@ impl Subscribe for UdpSocket { impl UdpSocket { /// Create a new socket in the given family. pub fn new(family: AddressFamily) -> io::Result { - let socket = Self::new_tokio_socket(family)?; + // Create a new host socket and set it to non-blocking, which is needed + // by our async implementation. + let fd = util::udp_socket(family, Blocking::No)?; let socket_address_family = match family { AddressFamily::Ipv4 => SocketAddressFamily::Ipv4, AddressFamily::Ipv6 => SocketAddressFamily::Ipv6 { - v6only: rustix::net::sockopt::get_ipv6_v6only(&socket)?, + v6only: rustix::net::sockopt::get_ipv6_v6only(&fd)?, }, }; + let socket = Self::setup_tokio_udp_socket(fd)?; + Ok(UdpSocket { inner: Arc::new(socket), udp_state: UdpState::Default, family: socket_address_family, - pool: None, + socket_addr_check: None, }) } - fn new_tokio_socket(family: AddressFamily) -> io::Result { - // Create a new host socket and set it to non-blocking, which is needed - // by our async implementation. - let cap_std_socket = cap_std::net::UdpSocket::new(family, Blocking::No)?; - let fd = cap_std_socket.into_raw_socketlike(); - let std_socket = unsafe { std::net::UdpSocket::from_raw_socketlike(fd) }; - let tokio_socket = - with_ambient_tokio_runtime(|| tokio::net::UdpSocket::try_from(std_socket))?; - - Ok(tokio_socket) + fn setup_tokio_udp_socket(fd: rustix::fd::OwnedFd) -> io::Result { + let std_socket = + unsafe { std::net::UdpSocket::from_raw_socketlike(fd.into_raw_socketlike()) }; + with_ambient_tokio_runtime(|| tokio::net::UdpSocket::try_from(std_socket)) } pub fn udp_socket(&self) -> &tokio::net::UdpSocket { @@ -110,8 +108,8 @@ pub struct OutgoingDatagramStream { pub(crate) send_state: SendState, - /// The pool of allowed addresses - pub(crate) pool: Option>, + /// The check of allowed addresses + pub(crate) socket_addr_check: Option, } pub(crate) enum SendState { diff --git a/crates/wasi/tests/all/main.rs b/crates/wasi/tests/all/main.rs index 03cf8031b157..eaf9a766edd1 100644 --- a/crates/wasi/tests/all/main.rs +++ b/crates/wasi/tests/all/main.rs @@ -1,5 +1,4 @@ use anyhow::Result; -use cap_std::ambient_authority; use tempfile::TempDir; use wasmtime::{ component::{Component, Linker, ResourceTable}, @@ -64,7 +63,7 @@ fn store(engine: &Engine, name: &str, inherit_stdio: bool) -> Result<(Store builder .args(&[name, "."]) - .inherit_network(ambient_authority()) + .inherit_network() .allow_ip_name_lookup(true); println!("preopen: {:?}", workspace); let preopen_dir = diff --git a/crates/wasmtime/src/component/component.rs b/crates/wasmtime/src/component/component.rs index 280b3fdef60e..6b6a90c42ea9 100644 --- a/crates/wasmtime/src/component/component.rs +++ b/crates/wasmtime/src/component/component.rs @@ -127,14 +127,54 @@ impl Component { #[cfg(any(feature = "cranelift", feature = "winch"))] #[cfg_attr(nightlydoc, doc(cfg(any(feature = "cranelift", feature = "winch"))))] pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result { + use crate::module::HashedEngineCompileEnv; + engine .check_compatible_with_native_host() .context("compilation settings are not compatible with the native host")?; - let (mmap, artifacts) = Component::build_artifacts(engine, binary)?; - let mut code_memory = CodeMemory::new(mmap)?; - code_memory.publish()?; - Component::from_parts(engine, Arc::new(code_memory), Some(artifacts)) + cfg_if::cfg_if! { + if #[cfg(feature = "cache")] { + let state = (HashedEngineCompileEnv(engine), binary); + let (code, artifacts) = wasmtime_cache::ModuleCacheEntry::new( + "wasmtime", + engine.cache_config(), + ) + .get_data_raw( + &state, + + // Cache miss, compute the actual artifacts + |(engine, wasm)| -> Result<_> { + let (mmap, artifacts) = Component::build_artifacts(engine.0, wasm)?; + let code = publish_mmap(mmap)?; + Ok((code, Some(artifacts))) + }, + + // Implementation of how to serialize artifacts + |(_engine, _wasm), (code, _info_and_types)| { + Some(code.mmap().to_vec()) + }, + + // Cache hit, deserialize the provided artifacts + |(engine, _wasm), serialized_bytes| { + let code = engine.0.load_code_bytes(&serialized_bytes, ObjectKind::Component).ok()?; + Some((code, None)) + }, + )?; + } else { + let (mmap, artifacts) = Component::build_artifacts(engine, binary)?; + let artifacts = Some(artifacts); + let code = publish_mmap(mmap)?; + } + }; + + return Component::from_parts(engine, code, artifacts); + + fn publish_mmap(mmap: MmapVec) -> Result> { + let mut code = CodeMemory::new(mmap)?; + code.publish()?; + Ok(Arc::new(code)) + } } /// Same as [`Module::deserialize`], but for components. diff --git a/crates/wasmtime/src/component/linker.rs b/crates/wasmtime/src/component/linker.rs index 5e490fa9ae99..58e6600449f9 100644 --- a/crates/wasmtime/src/component/linker.rs +++ b/crates/wasmtime/src/component/linker.rs @@ -417,12 +417,9 @@ impl LinkerInstance<'_, T> { self.insert(name, Definition::Module(module.clone())) } - /// Defines a new host [`ResourceType`] in this linker. + /// Defines a new resource of a given [`ResourceType`] in this linker. /// - /// This function is used to specify resources defined in the host. The `U` - /// type parameter here is the type parameter to [`Resource`]. This means - /// that component types using this resource type will be visible in - /// Wasmtime as [`Resource`]. + /// This function is used to specify resources defined in the host. /// /// The `name` argument is the name to define the resource within this /// linker. @@ -442,9 +439,10 @@ impl LinkerInstance<'_, T> { /// The provided `dtor` closure returns an error if something goes wrong /// when a guest calls the `dtor` to drop a `Resource` such as /// a runtime trap or a runtime limit being exceeded. - pub fn resource( + pub fn resource( &mut self, name: &str, + ty: ResourceType, dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static, ) -> Result<()> { let name = self.strings.intern(name); @@ -452,7 +450,7 @@ impl LinkerInstance<'_, T> { &self.engine, move |mut cx: crate::Caller<'_, T>, param: u32| dtor(cx.as_context_mut(), param), )); - self.insert(name, Definition::Resource(ResourceType::host::(), dtor)) + self.insert(name, Definition::Resource(ty, dtor)) } /// Defines a nested instance within this instance. diff --git a/crates/wasmtime/src/func/typed.rs b/crates/wasmtime/src/func/typed.rs index f1188faad4aa..e88eb23e769e 100644 --- a/crates/wasmtime/src/func/typed.rs +++ b/crates/wasmtime/src/func/typed.rs @@ -239,7 +239,7 @@ pub unsafe trait WasmTy: Send { } macro_rules! integers { - ($($primitive:ident/$get_primitive:ident => $ty:ident in $raw:ident)*) => ($( + ($($primitive:ident/$get_primitive:ident => $ty:ident)*) => ($( unsafe impl WasmTy for $primitive { type Abi = $primitive; #[inline] @@ -275,10 +275,10 @@ macro_rules! integers { } integers! { - i32/get_i32 => I32 in i32 - i64/get_i64 => I64 in i64 - u32/get_u32 => I32 in i32 - u64/get_u64 => I64 in i64 + i32/get_i32 => I32 + i64/get_i64 => I64 + u32/get_u32 => I32 + u64/get_u64 => I64 } macro_rules! floats { diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs index 17d49b7c294d..5f00ba73ac87 100644 --- a/crates/wast/src/spectest.rs +++ b/crates/wast/src/spectest.rs @@ -59,7 +59,7 @@ pub fn link_spectest( pub fn link_component_spectest(linker: &mut component::Linker) -> Result<()> { use std::sync::atomic::{AtomicU32, Ordering::SeqCst}; use std::sync::Arc; - use wasmtime::component::Resource; + use wasmtime::component::{Resource, ResourceType}; let engine = linker.engine().clone(); linker @@ -92,7 +92,7 @@ pub fn link_component_spectest(linker: &mut component::Linker) -> Result<( let state = Arc::new(ResourceState::default()); - i.resource::("resource1", { + i.resource("resource1", ResourceType::host::(), { let state = state.clone(); move |_, rep| { state.drops.fetch_add(1, SeqCst); @@ -101,13 +101,21 @@ pub fn link_component_spectest(linker: &mut component::Linker) -> Result<( Ok(()) } })?; - i.resource::("resource2", |_, _| Ok(()))?; + i.resource( + "resource2", + ResourceType::host::(), + |_, _| Ok(()), + )?; // Currently the embedder API requires redefining the resource destructor // here despite this being the same type as before, and fixing that is left // for a future refactoring. - i.resource::("resource1-again", |_, _| { - panic!("shouldn't be destroyed"); - })?; + i.resource( + "resource1-again", + ResourceType::host::(), + |_, _| { + panic!("shouldn't be destroyed"); + }, + )?; i.func_wrap("[constructor]resource1", |_cx, (rep,): (u32,)| { Ok((Resource::::new_own(rep),)) diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index eca7fd3916cd..a73f6bcca4e5 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -474,7 +474,7 @@ impl Wasmtime { format!( "{}_{}_{snake}", pkgname.namespace.to_snake_case(), - pkgname.name.to_snake_case() + self.name_package_module(resolve, iface.package.unwrap()) ), ), None => (format!("exports::{snake}::{camel}"), snake.clone()), @@ -807,8 +807,9 @@ impl Wasmtime { let camel = name.to_upper_camel_case(); uwriteln!( self.src, - "linker.resource::<{camel}>( + "linker.resource( \"{name}\", + wasmtime::component::ResourceType::host::<{camel}>(), move |mut store, rep| -> wasmtime::Result<()> {{ Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep)) }}, @@ -1604,8 +1605,9 @@ impl<'a> InterfaceGenerator<'a> { let camel = name.to_upper_camel_case(); uwriteln!( self.src, - "inst.resource::<{camel}>( + "inst.resource( \"{name}\", + wasmtime::component::ResourceType::host::<{camel}>(), move |mut store, rep| -> wasmtime::Result<()> {{ Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep)) }}, diff --git a/fuzz/fuzz_targets/differential.rs b/fuzz/fuzz_targets/differential.rs index 648923768915..e166fa069d03 100644 --- a/fuzz/fuzz_targets/differential.rs +++ b/fuzz/fuzz_targets/differential.rs @@ -369,6 +369,14 @@ fn winch_supports_module(module: &[u8]) -> bool { | I64Ctz { .. } | I32Popcnt { .. } | I64Popcnt { .. } + | I32WrapI64 { .. } + | I64ExtendI32S { .. } + | I64ExtendI32U { .. } + | I32Extend8S { .. } + | I32Extend16S { .. } + | I64Extend8S { .. } + | I64Extend16S { .. } + | I64Extend32S { .. } | LocalGet { .. } | LocalSet { .. } | LocalTee { .. } diff --git a/src/commands/run.rs b/src/commands/run.rs index 964a50bdeb9c..81c724bd7c48 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -772,7 +772,7 @@ impl RunCommand { } if self.run.common.wasi.inherit_network == Some(true) { - builder.inherit_network(ambient_authority()); + builder.inherit_network(); } if let Some(enable) = self.run.common.wasi.allow_ip_name_lookup { builder.allow_ip_name_lookup(enable); diff --git a/tests/all/component_model/resources.rs b/tests/all/component_model/resources.rs index ba821251f79c..ae3893b12d19 100644 --- a/tests/all/component_model/resources.rs +++ b/tests/all/component_model/resources.rs @@ -37,8 +37,12 @@ fn host_resource_types() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; - linker.root().resource::("u", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; + linker + .root() + .resource("u", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let t1 = i.get_resource(&mut store, "t1").unwrap(); let t2 = i.get_resource(&mut store, "t2").unwrap(); @@ -367,7 +371,9 @@ fn drop_host_twice() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let dtor = i.get_typed_func::<(&Resource,), ()>(&mut store, "dtor")?; @@ -431,12 +437,14 @@ fn manually_destroy() -> Result<()> { let mut store = Store::new(&engine, Data::default()); let mut linker = Linker::new(&engine); - linker.root().resource::("t1", |mut cx, rep| { - let data: &mut Data = cx.data_mut(); - data.drops += 1; - data.last_drop = Some(rep); - Ok(()) - })?; + linker + .root() + .resource("t1", ResourceType::host::(), |mut cx, rep| { + let data: &mut Data = cx.data_mut(); + data.drops += 1; + data.last_drop = Some(rep); + Ok(()) + })?; let i = linker.instantiate(&mut store, &c)?; let t2_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]t2")?; let t2_drops = i.get_typed_func::<(), (u32,)>(&mut store, "[static]t2.drops")?; @@ -497,7 +505,9 @@ fn dynamic_type() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t1", |_, _| Ok(()))?; + linker + .root() + .resource("t1", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let a = i.get_func(&mut store, "a").unwrap(); @@ -548,7 +558,9 @@ fn dynamic_val() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t1", |_, _| Ok(()))?; + linker + .root() + .resource("t1", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let a = i.get_func(&mut store, "a").unwrap(); @@ -665,7 +677,9 @@ fn active_borrows_at_end_of_call() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let f = i.get_typed_func::<(&Resource,), ()>(&mut store, "f")?; @@ -720,7 +734,9 @@ fn thread_through_borrow() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; linker .root() .func_wrap("f", |_cx, (r,): (Resource,)| { @@ -764,7 +780,9 @@ fn cannot_use_borrow_for_own() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let f = i.get_typed_func::<(&Resource,), (Resource,)>(&mut store, "f")?; @@ -809,7 +827,9 @@ fn passthrough_wrong_type() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; linker .root() .func_wrap("f", |_cx, (r,): (Resource,)| Ok((r,)))?; @@ -849,7 +869,9 @@ fn pass_moved_resource() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let f = i.get_typed_func::<(&Resource, &Resource), ()>(&mut store, "f")?; @@ -980,7 +1002,9 @@ fn host_borrow_as_resource_any() -> Result<()> { // First test the above component where the host properly drops the argument { let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; linker .root() .func_wrap("f", |mut cx, (r,): (ResourceAny,)| { @@ -998,7 +1022,9 @@ fn host_borrow_as_resource_any() -> Result<()> { // Then also test the case where the host forgets a drop { let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; linker.root().func_wrap("f", |_cx, (_r,): (ResourceAny,)| { // ... no drop here Ok(()) @@ -1107,7 +1133,9 @@ fn pass_host_borrow_to_guest() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; let i = linker.instantiate(&mut store, &c)?; let take = i.get_typed_func::<(&Resource,), ()>(&mut store, "take")?; @@ -1180,7 +1208,9 @@ fn drop_on_owned_resource() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t", |_, _| Ok(()))?; + linker + .root() + .resource("t", ResourceType::host::(), |_, _| Ok(()))?; linker.root().func_wrap("[constructor]t", |_cx, ()| { Ok((Resource::::new_own(300),)) })?; @@ -1257,8 +1287,12 @@ fn guest_different_host_same() -> Result<()> { let mut store = Store::new(&engine, ()); let mut linker = Linker::new(&engine); - linker.root().resource::("t1", |_, _| Ok(()))?; - linker.root().resource::("t2", |_, _| Ok(()))?; + linker + .root() + .resource("t1", ResourceType::host::(), |_, _| Ok(()))?; + linker + .root() + .resource("t2", ResourceType::host::(), |_, _| Ok(()))?; linker.root().func_wrap( "f", |_cx, (r1, r2): (Resource, Resource)| { diff --git a/tests/misc_testsuite/winch/conversions.wast b/tests/misc_testsuite/winch/conversions.wast new file mode 100644 index 000000000000..6f84e57d2421 --- /dev/null +++ b/tests/misc_testsuite/winch/conversions.wast @@ -0,0 +1,38 @@ +(module + (func (export "i64.extend_i32_s") (param $x i32) (result i64) (i64.extend_i32_s (local.get $x))) + (func (export "i64.extend_i32_u") (param $x i32) (result i64) (i64.extend_i32_u (local.get $x))) + (func (export "i32.wrap_i64") (param $x i64) (result i32) (i32.wrap_i64 (local.get $x))) +) + +(assert_return (invoke "i64.extend_i32_s" (i32.const 0)) (i64.const 0)) +(assert_return (invoke "i64.extend_i32_s" (i32.const 10000)) (i64.const 10000)) +(assert_return (invoke "i64.extend_i32_s" (i32.const -10000)) (i64.const -10000)) +(assert_return (invoke "i64.extend_i32_s" (i32.const -1)) (i64.const -1)) +(assert_return (invoke "i64.extend_i32_s" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff)) +(assert_return (invoke "i64.extend_i32_s" (i32.const 0x80000000)) (i64.const 0xffffffff80000000)) + +(assert_return (invoke "i64.extend_i32_u" (i32.const 0)) (i64.const 0)) +(assert_return (invoke "i64.extend_i32_u" (i32.const 10000)) (i64.const 10000)) +(assert_return (invoke "i64.extend_i32_u" (i32.const -10000)) (i64.const 0x00000000ffffd8f0)) +(assert_return (invoke "i64.extend_i32_u" (i32.const -1)) (i64.const 0xffffffff)) +(assert_return (invoke "i64.extend_i32_u" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff)) +(assert_return (invoke "i64.extend_i32_u" (i32.const 0x80000000)) (i64.const 0x0000000080000000)) + +(assert_return (invoke "i32.wrap_i64" (i64.const -1)) (i32.const -1)) +(assert_return (invoke "i32.wrap_i64" (i64.const -100000)) (i32.const -100000)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0x80000000)) (i32.const 0x80000000)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0xffffffff7fffffff)) (i32.const 0x7fffffff)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0xffffffff00000000)) (i32.const 0x00000000)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0xfffffffeffffffff)) (i32.const 0xffffffff)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0xffffffff00000001)) (i32.const 0x00000001)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0)) (i32.const 0)) +(assert_return (invoke "i32.wrap_i64" (i64.const 1311768467463790320)) (i32.const 0x9abcdef0)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0x00000000ffffffff)) (i32.const 0xffffffff)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0x0000000100000000)) (i32.const 0x00000000)) +(assert_return (invoke "i32.wrap_i64" (i64.const 0x0000000100000001)) (i32.const 0x00000001)) + +;; Type check + +(assert_invalid (module (func (result i32) (i32.wrap_i64 (f32.const 0)))) "type mismatch") +(assert_invalid (module (func (result i64) (i64.extend_i32_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (func (result i64) (i64.extend_i32_u (f32.const 0)))) "type mismatch") diff --git a/tests/misc_testsuite/winch/i32.wast b/tests/misc_testsuite/winch/i32.wast index 8a06d0914500..e4084be3fa8d 100644 --- a/tests/misc_testsuite/winch/i32.wast +++ b/tests/misc_testsuite/winch/i32.wast @@ -19,6 +19,8 @@ (func (export "clz") (param $x i32) (result i32) (i32.clz (local.get $x))) (func (export "ctz") (param $x i32) (result i32) (i32.ctz (local.get $x))) (func (export "popcnt") (param $x i32) (result i32) (i32.popcnt (local.get $x))) + (func (export "extend8_s") (param $x i32) (result i32) (i32.extend8_s (local.get $x))) + (func (export "extend16_s") (param $x i32) (result i32) (i32.extend16_s (local.get $x))) (func (export "eqz") (param $x i32) (result i32) (i32.eqz (local.get $x))) (func (export "eq") (param $x i32) (param $y i32) (result i32) (i32.eq (local.get $x) (local.get $y))) (func (export "ne") (param $x i32) (param $y i32) (result i32) (i32.ne (local.get $x) (local.get $y))) @@ -265,6 +267,22 @@ (assert_return (invoke "popcnt" (i32.const 0x55555555)) (i32.const 16)) (assert_return (invoke "popcnt" (i32.const 0xDEADBEEF)) (i32.const 24)) +(assert_return (invoke "extend8_s" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "extend8_s" (i32.const 0x7f)) (i32.const 127)) +(assert_return (invoke "extend8_s" (i32.const 0x80)) (i32.const -128)) +(assert_return (invoke "extend8_s" (i32.const 0xff)) (i32.const -1)) +(assert_return (invoke "extend8_s" (i32.const 0x012345_00)) (i32.const 0)) +(assert_return (invoke "extend8_s" (i32.const 0xfedcba_80)) (i32.const -0x80)) +(assert_return (invoke "extend8_s" (i32.const -1)) (i32.const -1)) + +(assert_return (invoke "extend16_s" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "extend16_s" (i32.const 0x7fff)) (i32.const 32767)) +(assert_return (invoke "extend16_s" (i32.const 0x8000)) (i32.const -32768)) +(assert_return (invoke "extend16_s" (i32.const 0xffff)) (i32.const -1)) +(assert_return (invoke "extend16_s" (i32.const 0x0123_0000)) (i32.const 0)) +(assert_return (invoke "extend16_s" (i32.const 0xfedc_8000)) (i32.const -0x8000)) +(assert_return (invoke "extend16_s" (i32.const -1)) (i32.const -1)) + (assert_return (invoke "eqz" (i32.const 0)) (i32.const 1)) (assert_return (invoke "eqz" (i32.const 1)) (i32.const 0)) (assert_return (invoke "eqz" (i32.const 0x80000000)) (i32.const 0)) diff --git a/tests/misc_testsuite/winch/i64.wast b/tests/misc_testsuite/winch/i64.wast index 1783c61782d1..73aa4c19cd27 100644 --- a/tests/misc_testsuite/winch/i64.wast +++ b/tests/misc_testsuite/winch/i64.wast @@ -19,6 +19,9 @@ (func (export "clz") (param $x i64) (result i64) (i64.clz (local.get $x))) (func (export "ctz") (param $x i64) (result i64) (i64.ctz (local.get $x))) (func (export "popcnt") (param $x i64) (result i64) (i64.popcnt (local.get $x))) + (func (export "extend8_s") (param $x i64) (result i64) (i64.extend8_s (local.get $x))) + (func (export "extend16_s") (param $x i64) (result i64) (i64.extend16_s (local.get $x))) + (func (export "extend32_s") (param $x i64) (result i64) (i64.extend32_s (local.get $x))) (func (export "eqz") (param $x i64) (result i32) (i64.eqz (local.get $x))) (func (export "eq") (param $x i64) (param $y i64) (result i32) (i64.eq (local.get $x) (local.get $y))) (func (export "ne") (param $x i64) (param $y i64) (result i32) (i64.ne (local.get $x) (local.get $y))) @@ -265,6 +268,33 @@ (assert_return (invoke "popcnt" (i64.const 0x99999999AAAAAAAA)) (i64.const 32)) (assert_return (invoke "popcnt" (i64.const 0xDEADBEEFDEADBEEF)) (i64.const 48)) +(assert_return (invoke "extend8_s" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "extend8_s" (i64.const 0x7f)) (i64.const 127)) +(assert_return (invoke "extend8_s" (i64.const 0x80)) (i64.const -128)) +(assert_return (invoke "extend8_s" (i64.const 0xff)) (i64.const -1)) +(assert_return (invoke "extend8_s" (i64.const 0x01234567_89abcd_00)) (i64.const 0)) +(assert_return (invoke "extend8_s" (i64.const 0xfedcba98_765432_80)) (i64.const -0x80)) +(assert_return (invoke "extend8_s" (i64.const -1)) (i64.const -1)) + +(assert_return (invoke "extend16_s" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "extend16_s" (i64.const 0x7fff)) (i64.const 32767)) +(assert_return (invoke "extend16_s" (i64.const 0x8000)) (i64.const -32768)) +(assert_return (invoke "extend16_s" (i64.const 0xffff)) (i64.const -1)) +(assert_return (invoke "extend16_s" (i64.const 0x12345678_9abc_0000)) (i64.const 0)) +(assert_return (invoke "extend16_s" (i64.const 0xfedcba98_7654_8000)) (i64.const -0x8000)) +(assert_return (invoke "extend16_s" (i64.const -1)) (i64.const -1)) + +(assert_return (invoke "extend32_s" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "extend32_s" (i64.const 0x7fff)) (i64.const 32767)) +(assert_return (invoke "extend32_s" (i64.const 0x8000)) (i64.const 32768)) +(assert_return (invoke "extend32_s" (i64.const 0xffff)) (i64.const 65535)) +(assert_return (invoke "extend32_s" (i64.const 0x7fffffff)) (i64.const 0x7fffffff)) +(assert_return (invoke "extend32_s" (i64.const 0x80000000)) (i64.const -0x80000000)) +(assert_return (invoke "extend32_s" (i64.const 0xffffffff)) (i64.const -1)) +(assert_return (invoke "extend32_s" (i64.const 0x01234567_00000000)) (i64.const 0)) +(assert_return (invoke "extend32_s" (i64.const 0xfedcba98_80000000)) (i64.const -0x80000000)) +(assert_return (invoke "extend32_s" (i64.const -1)) (i64.const -1)) + (assert_return (invoke "eqz" (i64.const 0)) (i32.const 1)) (assert_return (invoke "eqz" (i64.const 1)) (i32.const 0)) (assert_return (invoke "eqz" (i64.const 0x8000000000000000)) (i32.const 0)) diff --git a/winch/codegen/src/codegen/context.rs b/winch/codegen/src/codegen/context.rs index 28b4a25daa27..7bcedf0891c4 100644 --- a/winch/codegen/src/codegen/context.rs +++ b/winch/codegen/src/codegen/context.rs @@ -225,25 +225,29 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> { } /// Prepares arguments for emitting a unary operation. + /// + /// The `emit` function returns the `TypedReg` to put on the value stack. pub fn unop(&mut self, masm: &mut M, size: OperandSize, emit: &mut F) where - F: FnMut(&mut M, Reg, OperandSize), + F: FnMut(&mut M, Reg, OperandSize) -> TypedReg, M: MacroAssembler, { let typed_reg = self.pop_to_reg(masm, None); - emit(masm, typed_reg.reg, size); - self.stack.push(typed_reg.into()); + let dst = emit(masm, typed_reg.reg, size); + self.stack.push(dst.into()); } /// Prepares arguments for emitting a binary operation. + /// + /// The `emit` function returns the `TypedReg` to put on the value stack. pub fn binop(&mut self, masm: &mut M, size: OperandSize, mut emit: F) where - F: FnMut(&mut M, Reg, Reg, OperandSize), + F: FnMut(&mut M, Reg, Reg, OperandSize) -> TypedReg, M: MacroAssembler, { let src = self.pop_to_reg(masm, None); let dst = self.pop_to_reg(masm, None); - emit(masm, dst.reg, src.reg.into(), size); + let dst = emit(masm, dst.reg, src.reg.into(), size); self.free_reg(src); self.stack.push(dst.into()); } @@ -270,9 +274,11 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> { } /// Prepares arguments for emitting an i32 binary operation. + /// + /// The `emit` function returns the `TypedReg` to put on the value stack. pub fn i32_binop(&mut self, masm: &mut M, mut emit: F) where - F: FnMut(&mut M, Reg, RegImm, OperandSize), + F: FnMut(&mut M, Reg, RegImm, OperandSize) -> TypedReg, M: MacroAssembler, { let top = self.stack.peek().expect("value at stack top"); @@ -283,8 +289,8 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> { .pop_i32_const() .expect("i32 const value at stack top"); let typed_reg = self.pop_to_reg(masm, None); - emit(masm, typed_reg.reg, RegImm::i32(val), OperandSize::S32); - self.stack.push(typed_reg.into()); + let dst = emit(masm, typed_reg.reg, RegImm::i32(val), OperandSize::S32); + self.stack.push(dst.into()); } else { self.binop(masm, OperandSize::S32, |masm, dst, src, size| { emit(masm, dst, src.into(), size) @@ -293,9 +299,11 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> { } /// Prepares arguments for emitting an i64 binary operation. + /// + /// The `emit` function returns the `TypedReg` to put on the value stack. pub fn i64_binop(&mut self, masm: &mut M, mut emit: F) where - F: FnMut(&mut M, Reg, RegImm, OperandSize), + F: FnMut(&mut M, Reg, RegImm, OperandSize) -> TypedReg, M: MacroAssembler, { let top = self.stack.peek().expect("value at stack top"); @@ -305,13 +313,13 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> { .pop_i64_const() .expect("i64 const value at stack top"); let typed_reg = self.pop_to_reg(masm, None); - emit(masm, typed_reg.reg, RegImm::i64(val), OperandSize::S64); - self.stack.push(typed_reg.into()); + let dst = emit(masm, typed_reg.reg, RegImm::i64(val), OperandSize::S64); + self.stack.push(dst.into()); } else { self.binop(masm, OperandSize::S64, |masm, dst, src, size| { emit(masm, dst, src.into(), size) }); - } + }; } /// Drops the last `n` elements of the stack, calling the provided diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index 06dfef32601b..74ce2d96e093 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -4,8 +4,9 @@ use crate::{ codegen::{ptr_type_from_ptr_size, CodeGenContext, TableData}, isa::reg::Reg, masm::{ - CalleeKind, DivKind, FloatCmpKind, Imm as I, IntCmpKind, MacroAssembler as Masm, - OperandSize, RegImm, RemKind, RoundingMode, SPOffset, ShiftKind, StackSlot, TrapCode, + CalleeKind, DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind, + MacroAssembler as Masm, OperandSize, RegImm, RemKind, RoundingMode, SPOffset, ShiftKind, + StackSlot, TrapCode, }, }; use cranelift_codegen::{settings, Final, MachBufferFinalized, MachLabel}; @@ -382,6 +383,14 @@ impl Masm for MacroAssembler { todo!() } + fn wrap(&mut self, _src: Reg, _dst: Reg) { + todo!() + } + + fn extend(&mut self, _src: Reg, _dst: Reg, _kind: ExtendKind) { + todo!() + } + fn get_label(&mut self) -> MachLabel { self.asm.get_label() } diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs index f4ce1be6d40e..9fa1d1cb51dd 100644 --- a/winch/codegen/src/isa/x64/asm.rs +++ b/winch/codegen/src/isa/x64/asm.rs @@ -2,7 +2,7 @@ use crate::{ isa::reg::Reg, - masm::{DivKind, IntCmpKind, OperandSize, RemKind, RoundingMode, ShiftKind}, + masm::{DivKind, ExtendKind, IntCmpKind, OperandSize, RemKind, RoundingMode, ShiftKind}, }; use cranelift_codegen::{ entity::EntityRef, @@ -132,6 +132,20 @@ impl From for CraneliftShiftKind { } } +impl From for ExtMode { + fn from(value: ExtendKind) -> Self { + match value { + ExtendKind::I64ExtendI32S | ExtendKind::I64ExtendI32U | ExtendKind::I64Extend32S => { + ExtMode::LQ + } + ExtendKind::I32Extend8S => ExtMode::BL, + ExtendKind::I32Extend16S => ExtMode::WL, + ExtendKind::I64Extend8S => ExtMode::BQ, + ExtendKind::I64Extend16S => ExtMode::WQ, + } + } +} + /// Low level assembler implementation for x64. pub(crate) struct Assembler { /// The machine instruction buffer. @@ -301,6 +315,24 @@ impl Assembler { } } + /// Register-to-register move with zero extension. + pub fn movzx_rr(&mut self, src: Reg, dst: Reg, kind: ExtendKind) { + self.emit(Inst::MovzxRmR { + ext_mode: kind.into(), + src: src.into(), + dst: dst.into(), + }) + } + + /// Register-to-register move with sign extension. + pub fn movsx_rr(&mut self, src: Reg, dst: Reg, kind: ExtendKind) { + self.emit(Inst::MovsxRmR { + ext_mode: kind.into(), + src: src.into(), + dst: dst.into(), + }); + } + /// Integer register conditional move. pub fn cmov(&mut self, src: Reg, dst: Reg, cc: IntCmpKind, size: OperandSize) { self.emit(Inst::Cmove { diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs index 15c108aaeb09..c5ea1ac886e2 100644 --- a/winch/codegen/src/isa/x64/masm.rs +++ b/winch/codegen/src/isa/x64/masm.rs @@ -6,8 +6,8 @@ use super::{ }; use crate::masm::{ - DivKind, FloatCmpKind, Imm as I, IntCmpKind, MacroAssembler as Masm, OperandSize, RegImm, - RemKind, RoundingMode, ShiftKind, TrapCode, + DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind, MacroAssembler as Masm, OperandSize, + RegImm, RemKind, RoundingMode, ShiftKind, TrapCode, }; use crate::{ abi::ABI, @@ -904,6 +904,18 @@ impl Masm for MacroAssembler { } } + fn wrap(&mut self, src: Reg, dst: Reg) { + self.asm.mov_rr(src.into(), dst.into(), OperandSize::S32); + } + + fn extend(&mut self, src: Reg, dst: Reg, kind: ExtendKind) { + if let ExtendKind::I64ExtendI32U = kind { + self.asm.movzx_rr(src, dst, kind); + } else { + self.asm.movsx_rr(src, dst, kind); + } + } + fn unreachable(&mut self) { self.asm.trap(TrapCode::UnreachableCodeReached) } diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index b4613635ad4e..42ea92f97420 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -114,6 +114,26 @@ pub(crate) enum ShiftKind { Rotr, } +/// Kinds of extends in WebAssembly. The [`masm`] implementation for each ISA +/// is responsible for emitting the correct sequence of instructions when +/// lowering to machine code. +pub(crate) enum ExtendKind { + /// Sign extends i32 to i64. + I64ExtendI32S, + /// Zero extends i32 to i64. + I64ExtendI32U, + // Sign extends the 8 least significant bits to 32 bits. + I32Extend8S, + // Sign extends the 16 least significant bits to 32 bits. + I32Extend16S, + /// Sign extends the 8 least significant bits to 64 bits. + I64Extend8S, + /// Sign extends the 16 least significant bits to 64 bits. + I64Extend16S, + /// Sign extends the 32 least significant bits to 64 bits. + I64Extend32S, +} + /// Operand size, in bits. #[derive(Copy, Debug, Clone, Eq, PartialEq)] pub(crate) enum OperandSize { @@ -580,6 +600,12 @@ pub(crate) trait MacroAssembler { /// this will emit multiple instructions if the `has_popcnt` flag is false. fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize); + /// Converts an i64 to an i32 by discarding the high 32 bits. + fn wrap(&mut self, src: Reg, dst: Reg); + + /// Extends an integer of a given size to a larger size. + fn extend(&mut self, src: Reg, dst: Reg, kind: ExtendKind); + /// Zero a given memory range. /// /// The default implementation divides the given memory range diff --git a/winch/codegen/src/stack.rs b/winch/codegen/src/stack.rs index ffdfac397c24..a8491882bedd 100644 --- a/winch/codegen/src/stack.rs +++ b/winch/codegen/src/stack.rs @@ -34,6 +34,22 @@ impl TypedReg { reg, } } + + /// Create an f64 [`TypedReg`]. + pub fn f64(reg: Reg) -> Self { + Self { + ty: WasmType::F64, + reg, + } + } + + /// Create an f32 [`TypedReg`]. + pub fn f32(reg: Reg) -> Self { + Self { + ty: WasmType::F32, + reg, + } + } } impl From for Reg { diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index 4db1150e2ca8..a82ecce9a39a 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -7,8 +7,8 @@ use crate::abi::ABI; use crate::codegen::{control_index, Callee, CodeGen, ControlStackFrame, FnCall}; use crate::masm::{ - DivKind, FloatCmpKind, IntCmpKind, MacroAssembler, OperandSize, RegImm, RemKind, RoundingMode, - ShiftKind, + DivKind, ExtendKind, FloatCmpKind, IntCmpKind, MacroAssembler, OperandSize, RegImm, RemKind, + RoundingMode, ShiftKind, }; use crate::stack::{TypedReg, Val}; use cranelift_codegen::ir::TrapCode; @@ -143,6 +143,14 @@ macro_rules! def_unsupported { (emit I64Ctz $($rest:tt)*) => {}; (emit I32Popcnt $($rest:tt)*) => {}; (emit I64Popcnt $($rest:tt)*) => {}; + (emit I32WrapI64 $($rest:tt)*) => {}; + (emit I64ExtendI32S $($rest:tt)*) => {}; + (emit I64ExtendI32U $($rest:tt)*) => {}; + (emit I32Extend8S $($rest:tt)*) => {}; + (emit I32Extend16S $($rest:tt)*) => {}; + (emit I64Extend8S $($rest:tt)*) => {}; + (emit I64Extend16S $($rest:tt)*) => {}; + (emit I64Extend32S $($rest:tt)*) => {}; (emit LocalGet $($rest:tt)*) => {}; (emit LocalSet $($rest:tt)*) => {}; (emit Call $($rest:tt)*) => {}; @@ -203,6 +211,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_add(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -213,6 +222,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_add(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -223,6 +233,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_sub(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -233,6 +244,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_sub(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -243,6 +255,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_mul(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -253,6 +266,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_mul(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -263,6 +277,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_div(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -273,6 +288,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_div(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -283,6 +299,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_min(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -293,6 +310,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_min(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -303,6 +321,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_max(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -313,6 +332,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_max(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -323,6 +343,7 @@ where OperandSize::S32, &mut |masm: &mut M, dst, src, size| { masm.float_copysign(dst, dst, src, size); + TypedReg::f32(dst) }, ); } @@ -333,6 +354,7 @@ where OperandSize::S64, &mut |masm: &mut M, dst, src, size| { masm.float_copysign(dst, dst, src, size); + TypedReg::f64(dst) }, ); } @@ -341,6 +363,7 @@ where self.context .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| { masm.float_abs(reg, size); + TypedReg::f32(reg) }); } @@ -348,6 +371,7 @@ where self.context .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| { masm.float_abs(reg, size); + TypedReg::f64(reg) }); } @@ -355,6 +379,7 @@ where self.context .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| { masm.float_neg(reg, size); + TypedReg::f32(reg) }); } @@ -362,6 +387,7 @@ where self.context .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| { masm.float_neg(reg, size); + TypedReg::f64(reg) }); } @@ -409,6 +435,7 @@ where self.context .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| { masm.float_sqrt(reg, reg, size); + TypedReg::f32(reg) }); } @@ -416,6 +443,7 @@ where self.context .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| { masm.float_sqrt(reg, reg, size); + TypedReg::f64(reg) }); } @@ -542,36 +570,42 @@ where fn visit_i32_add(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.add(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_add(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.add(dst, dst, src, size); + TypedReg::i64(dst) }); } fn visit_i32_sub(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.sub(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_sub(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.sub(dst, dst, src, size); + TypedReg::i64(dst) }); } fn visit_i32_mul(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.mul(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_mul(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.mul(dst, dst, src, size); + TypedReg::i64(dst) }); } @@ -716,6 +750,7 @@ where self.context.unop(self.masm, S32, &mut |masm, reg, size| { masm.cmp_with_set(RegImm::i32(0), reg.into(), IntCmpKind::Eq, size); + TypedReg::i32(reg) }); } @@ -724,6 +759,7 @@ where self.context.unop(self.masm, S64, &mut |masm, reg, size| { masm.cmp_with_set(RegImm::i64(0), reg.into(), IntCmpKind::Eq, size); + TypedReg::i32(reg) // Return value for `i64.eqz` is an `i32`. }); } @@ -732,6 +768,7 @@ where self.context.unop(self.masm, S32, &mut |masm, reg, size| { masm.clz(reg, reg, size); + TypedReg::i32(reg) }); } @@ -740,6 +777,7 @@ where self.context.unop(self.masm, S64, &mut |masm, reg, size| { masm.clz(reg, reg, size); + TypedReg::i64(reg) }); } @@ -748,6 +786,7 @@ where self.context.unop(self.masm, S32, &mut |masm, reg, size| { masm.ctz(reg, reg, size); + TypedReg::i32(reg) }); } @@ -756,42 +795,49 @@ where self.context.unop(self.masm, S64, &mut |masm, reg, size| { masm.ctz(reg, reg, size); + TypedReg::i64(reg) }); } fn visit_i32_and(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.and(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_and(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.and(dst, dst, src, size); + TypedReg::i64(dst) }); } fn visit_i32_or(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.or(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_or(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.or(dst, dst, src, size); + TypedReg::i64(dst) }); } fn visit_i32_xor(&mut self) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.xor(dst, dst, src, size); + TypedReg::i32(dst) }); } fn visit_i64_xor(&mut self) { self.context.i64_binop(self.masm, |masm, dst, src, size| { masm.xor(dst, dst, src, size); + TypedReg::i64(dst) }); } @@ -897,6 +943,78 @@ where self.masm.popcnt(&mut self.context, S64); } + fn visit_i32_wrap_i64(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S64, &mut |masm, reg, _size| { + masm.wrap(reg, reg); + TypedReg::i32(reg) + }); + } + + fn visit_i64_extend_i32_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S32, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I64ExtendI32S); + TypedReg::i64(reg) + }); + } + + fn visit_i64_extend_i32_u(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S32, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I64ExtendI32U); + TypedReg::i64(reg) + }); + } + + fn visit_i32_extend8_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S32, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I32Extend8S); + TypedReg::i32(reg) + }); + } + + fn visit_i32_extend16_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S32, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I32Extend16S); + TypedReg::i32(reg) + }); + } + + fn visit_i64_extend8_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S64, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I64Extend8S); + TypedReg::i64(reg) + }); + } + + fn visit_i64_extend16_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S64, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I64Extend16S); + TypedReg::i64(reg) + }); + } + + fn visit_i64_extend32_s(&mut self) { + use OperandSize::*; + + self.context.unop(self.masm, S64, &mut |masm, reg, _size| { + masm.extend(reg, reg, ExtendKind::I64Extend32S); + TypedReg::i64(reg) + }); + } + fn visit_local_get(&mut self, index: u32) { use WasmType::*; let context = &mut self.context; @@ -1368,6 +1486,7 @@ where fn cmp_i32s(&mut self, kind: IntCmpKind) { self.context.i32_binop(self.masm, |masm, dst, src, size| { masm.cmp_with_set(src, dst, kind, size); + TypedReg::i32(dst) }); } @@ -1375,6 +1494,7 @@ where self.context .i64_binop(self.masm, move |masm, dst, src, size| { masm.cmp_with_set(src, dst, kind, size); + TypedReg::i32(dst) // Return value for comparisons is an `i32`. }); } } diff --git a/winch/filetests/filetests/x64/i32_extend_16_s/const.wat b/winch/filetests/filetests/x64/i32_extend_16_s/const.wat new file mode 100644 index 000000000000..fa454fd9348a --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_16_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 1) + (i32.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 0fbfc0 movsx eax, ax +;; 14: 4883c408 add rsp, 8 +;; 18: 5d pop rbp +;; 19: c3 ret diff --git a/winch/filetests/filetests/x64/i32_extend_16_s/locals.wat b/winch/filetests/filetests/x64/i32_extend_16_s/locals.wat new file mode 100644 index 000000000000..d68af51408ce --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_16_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (local i32) + + (local.get 0) + (i32.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 19: 0fbfc0 movsx eax, ax +;; 1c: 4883c410 add rsp, 0x10 +;; 20: 5d pop rbp +;; 21: c3 ret diff --git a/winch/filetests/filetests/x64/i32_extend_16_s/params.wat b/winch/filetests/filetests/x64/i32_extend_16_s/params.wat new file mode 100644 index 000000000000..e38a190fb825 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_16_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i32) (result i32) + (local.get 0) + (i32.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c893424 mov qword ptr [rsp], r14 +;; 10: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 14: 0fbfc0 movsx eax, ax +;; 17: 4883c410 add rsp, 0x10 +;; 1b: 5d pop rbp +;; 1c: c3 ret diff --git a/winch/filetests/filetests/x64/i32_extend_8_s/const.wat b/winch/filetests/filetests/x64/i32_extend_8_s/const.wat new file mode 100644 index 000000000000..e4de257fa8ef --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_8_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 1) + (i32.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 0fbec0 movsx eax, al +;; 14: 4883c408 add rsp, 8 +;; 18: 5d pop rbp +;; 19: c3 ret diff --git a/winch/filetests/filetests/x64/i32_extend_8_s/locals.wat b/winch/filetests/filetests/x64/i32_extend_8_s/locals.wat new file mode 100644 index 000000000000..d6149375d2f0 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_8_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (local i32) + + (local.get 0) + (i32.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 19: 0fbec0 movsx eax, al +;; 1c: 4883c410 add rsp, 0x10 +;; 20: 5d pop rbp +;; 21: c3 ret diff --git a/winch/filetests/filetests/x64/i32_extend_8_s/params.wat b/winch/filetests/filetests/x64/i32_extend_8_s/params.wat new file mode 100644 index 000000000000..33ffb463f3e5 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_extend_8_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i32) (result i32) + (local.get 0) + (i32.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c893424 mov qword ptr [rsp], r14 +;; 10: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 14: 0fbec0 movsx eax, al +;; 17: 4883c410 add rsp, 0x10 +;; 1b: 5d pop rbp +;; 1c: c3 ret diff --git a/winch/filetests/filetests/x64/i32_wrap_i64/const.wat b/winch/filetests/filetests/x64/i32_wrap_i64/const.wat new file mode 100644 index 000000000000..70e76e0411c4 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_wrap_i64/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i64.const 1) + (i32.wrap_i64) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 89c0 mov eax, eax +;; 15: 4883c408 add rsp, 8 +;; 19: 5d pop rbp +;; 1a: c3 ret diff --git a/winch/filetests/filetests/x64/i32_wrap_i64/locals.wat b/winch/filetests/filetests/x64/i32_wrap_i64/locals.wat new file mode 100644 index 000000000000..264365c166ce --- /dev/null +++ b/winch/filetests/filetests/x64/i32_wrap_i64/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (local i64) + + (local.get 0) + (i32.wrap_i64) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 89c0 mov eax, eax +;; 1c: 4883c410 add rsp, 0x10 +;; 20: 5d pop rbp +;; 21: c3 ret diff --git a/winch/filetests/filetests/x64/i32_wrap_i64/params.wat b/winch/filetests/filetests/x64/i32_wrap_i64/params.wat new file mode 100644 index 000000000000..5707ffb24aa9 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_wrap_i64/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i64) (result i32) + (local.get 0) + (i32.wrap_i64) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 4c893424 mov qword ptr [rsp], r14 +;; 11: 488b442408 mov rax, qword ptr [rsp + 8] +;; 16: 89c0 mov eax, eax +;; 18: 4883c410 add rsp, 0x10 +;; 1c: 5d pop rbp +;; 1d: c3 ret diff --git a/winch/filetests/filetests/x64/i32_wrap_i64/spilled.wat b/winch/filetests/filetests/x64/i32_wrap_i64/spilled.wat new file mode 100644 index 000000000000..bf3bc1004af1 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_wrap_i64/spilled.wat @@ -0,0 +1,23 @@ +;;! target = "x86_64" + +(module + (func (result i32) + i64.const 1 + i32.wrap_i64 + block + end + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 89c0 mov eax, eax +;; 15: 4883ec04 sub rsp, 4 +;; 19: 890424 mov dword ptr [rsp], eax +;; 1c: 8b0424 mov eax, dword ptr [rsp] +;; 1f: 4883c404 add rsp, 4 +;; 23: 4883c408 add rsp, 8 +;; 27: 5d pop rbp +;; 28: c3 ret diff --git a/winch/filetests/filetests/x64/i64_eq/locals.wat b/winch/filetests/filetests/x64/i64_eq/locals.wat index 8884b9d68459..6761c2e7fec8 100644 --- a/winch/filetests/filetests/x64/i64_eq/locals.wat +++ b/winch/filetests/filetests/x64/i64_eq/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f94c1 sete cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_eq/params.wat b/winch/filetests/filetests/x64/i64_eq/params.wat index aed5174e312f..27fa74cb6561 100644 --- a/winch/filetests/filetests/x64/i64_eq/params.wat +++ b/winch/filetests/filetests/x64/i64_eq/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f94c1 sete cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_eqz/spilled.wat b/winch/filetests/filetests/x64/i64_eqz/spilled.wat new file mode 100644 index 000000000000..b2e09645c203 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_eqz/spilled.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i32) + i64.const 1 + i64.eqz + block + end + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 4883f800 cmp rax, 0 +;; 17: b800000000 mov eax, 0 +;; 1c: 400f94c0 sete al +;; 20: 4883ec04 sub rsp, 4 +;; 24: 890424 mov dword ptr [rsp], eax +;; 27: 8b0424 mov eax, dword ptr [rsp] +;; 2a: 4883c404 add rsp, 4 +;; 2e: 4883c408 add rsp, 8 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_16_s/const.wat b/winch/filetests/filetests/x64/i64_extend_16_s/const.wat new file mode 100644 index 000000000000..5ab076bd30a2 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_16_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 1) + (i64.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 480fbfc0 movsx rax, ax +;; 17: 4883c408 add rsp, 8 +;; 1b: 5d pop rbp +;; 1c: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_16_s/locals.wat b/winch/filetests/filetests/x64/i64_extend_16_s/locals.wat new file mode 100644 index 000000000000..a39a9990e4aa --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_16_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (local i64) + + (local.get 0) + (i64.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 480fbfc0 movsx rax, ax +;; 1e: 4883c410 add rsp, 0x10 +;; 22: 5d pop rbp +;; 23: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_16_s/params.wat b/winch/filetests/filetests/x64/i64_extend_16_s/params.wat new file mode 100644 index 000000000000..98a61767a66c --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_16_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i64) (result i64) + (local.get 0) + (i64.extend16_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 4c893424 mov qword ptr [rsp], r14 +;; 11: 488b442408 mov rax, qword ptr [rsp + 8] +;; 16: 480fbfc0 movsx rax, ax +;; 1a: 4883c410 add rsp, 0x10 +;; 1e: 5d pop rbp +;; 1f: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_32_s/const.wat b/winch/filetests/filetests/x64/i64_extend_32_s/const.wat new file mode 100644 index 000000000000..666ebd52ca49 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_32_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 1) + (i64.extend32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 4863c0 movsxd rax, eax +;; 16: 4883c408 add rsp, 8 +;; 1a: 5d pop rbp +;; 1b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_32_s/locals.wat b/winch/filetests/filetests/x64/i64_extend_32_s/locals.wat new file mode 100644 index 000000000000..d6cfac6d128d --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_32_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (local i64) + + (local.get 0) + (i64.extend32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 4863c0 movsxd rax, eax +;; 1d: 4883c410 add rsp, 0x10 +;; 21: 5d pop rbp +;; 22: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_32_s/params.wat b/winch/filetests/filetests/x64/i64_extend_32_s/params.wat new file mode 100644 index 000000000000..0cf607420ce8 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_32_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i64) (result i64) + (local.get 0) + (i64.extend32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 4c893424 mov qword ptr [rsp], r14 +;; 11: 488b442408 mov rax, qword ptr [rsp + 8] +;; 16: 4863c0 movsxd rax, eax +;; 19: 4883c410 add rsp, 0x10 +;; 1d: 5d pop rbp +;; 1e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_8_s/const.wat b/winch/filetests/filetests/x64/i64_extend_8_s/const.wat new file mode 100644 index 000000000000..a77763091c36 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_8_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 1) + (i64.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 48c7c001000000 mov rax, 1 +;; 13: 480fbec0 movsx rax, al +;; 17: 4883c408 add rsp, 8 +;; 1b: 5d pop rbp +;; 1c: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_8_s/locals.wat b/winch/filetests/filetests/x64/i64_extend_8_s/locals.wat new file mode 100644 index 000000000000..62b51071b8ed --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_8_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (local i64) + + (local.get 0) + (i64.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 480fbec0 movsx rax, al +;; 1e: 4883c410 add rsp, 0x10 +;; 22: 5d pop rbp +;; 23: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_8_s/params.wat b/winch/filetests/filetests/x64/i64_extend_8_s/params.wat new file mode 100644 index 000000000000..4ad6018bd995 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_8_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i64) (result i64) + (local.get 0) + (i64.extend8_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 4c893424 mov qword ptr [rsp], r14 +;; 11: 488b442408 mov rax, qword ptr [rsp + 8] +;; 16: 480fbec0 movsx rax, al +;; 1a: 4883c410 add rsp, 0x10 +;; 1e: 5d pop rbp +;; 1f: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_s/const.wat b/winch/filetests/filetests/x64/i64_extend_i32_s/const.wat new file mode 100644 index 000000000000..363d69902e72 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_s/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i32.const 1) + (i64.extend_i32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 4863c0 movsxd rax, eax +;; 14: 4883c408 add rsp, 8 +;; 18: 5d pop rbp +;; 19: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_s/locals.wat b/winch/filetests/filetests/x64/i64_extend_i32_s/locals.wat new file mode 100644 index 000000000000..ab2629b14194 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_s/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (local i32) + + (local.get 0) + (i64.extend_i32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 19: 4863c0 movsxd rax, eax +;; 1c: 4883c410 add rsp, 0x10 +;; 20: 5d pop rbp +;; 21: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_s/params.wat b/winch/filetests/filetests/x64/i64_extend_i32_s/params.wat new file mode 100644 index 000000000000..2d4ad7213380 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_s/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i32) (result i64) + (local.get 0) + (i64.extend_i32_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c893424 mov qword ptr [rsp], r14 +;; 10: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 14: 4863c0 movsxd rax, eax +;; 17: 4883c410 add rsp, 0x10 +;; 1b: 5d pop rbp +;; 1c: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_s/spilled.wat b/winch/filetests/filetests/x64/i64_extend_i32_s/spilled.wat new file mode 100644 index 000000000000..20ba1a2c40e2 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_s/spilled.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + i32.const 1 + i64.extend_i32_s + block + end + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 4863c0 movsxd rax, eax +;; 14: 50 push rax +;; 15: 58 pop rax +;; 16: 4883c408 add rsp, 8 +;; 1a: 5d pop rbp +;; 1b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_u/const.wat b/winch/filetests/filetests/x64/i64_extend_i32_u/const.wat new file mode 100644 index 000000000000..6f1c21f93b14 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_u/const.wat @@ -0,0 +1,17 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i32.const 1) + (i64.extend_i32_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 8bc0 mov eax, eax +;; 13: 4883c408 add rsp, 8 +;; 17: 5d pop rbp +;; 18: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_u/locals.wat b/winch/filetests/filetests/x64/i64_extend_i32_u/locals.wat new file mode 100644 index 000000000000..364d40325ee2 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_u/locals.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (local i32) + + (local.get 0) + (i64.extend_i32_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48c744240800000000 +;; mov qword ptr [rsp + 8], 0 +;; 11: 4c893424 mov qword ptr [rsp], r14 +;; 15: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 19: 8bc0 mov eax, eax +;; 1b: 4883c410 add rsp, 0x10 +;; 1f: 5d pop rbp +;; 20: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_u/params.wat b/winch/filetests/filetests/x64/i64_extend_i32_u/params.wat new file mode 100644 index 000000000000..3dbdc85983bd --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_u/params.wat @@ -0,0 +1,18 @@ +;;! target = "x86_64" + +(module + (func (param i32) (result i64) + (local.get 0) + (i64.extend_i32_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c893424 mov qword ptr [rsp], r14 +;; 10: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 14: 8bc0 mov eax, eax +;; 16: 4883c410 add rsp, 0x10 +;; 1a: 5d pop rbp +;; 1b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_extend_i32_u/spilled.wat b/winch/filetests/filetests/x64/i64_extend_i32_u/spilled.wat new file mode 100644 index 000000000000..4722e1b826b6 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_extend_i32_u/spilled.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + i32.const 1 + i64.extend_i32_u + block + end + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: b801000000 mov eax, 1 +;; 11: 8bc0 mov eax, eax +;; 13: 50 push rax +;; 14: 58 pop rax +;; 15: 4883c408 add rsp, 8 +;; 19: 5d pop rbp +;; 1a: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ge_s/locals.wat b/winch/filetests/filetests/x64/i64_ge_s/locals.wat index 6339d2f2312c..6f91547cc333 100644 --- a/winch/filetests/filetests/x64/i64_ge_s/locals.wat +++ b/winch/filetests/filetests/x64/i64_ge_s/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f9dc1 setge cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ge_s/params.wat b/winch/filetests/filetests/x64/i64_ge_s/params.wat index 49a3ab656f81..f8b849b82278 100644 --- a/winch/filetests/filetests/x64/i64_ge_s/params.wat +++ b/winch/filetests/filetests/x64/i64_ge_s/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f9dc1 setge cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ge_u/locals.wat b/winch/filetests/filetests/x64/i64_ge_u/locals.wat index f8b2d35f9134..626a483d27fb 100644 --- a/winch/filetests/filetests/x64/i64_ge_u/locals.wat +++ b/winch/filetests/filetests/x64/i64_ge_u/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f93c1 setae cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ge_u/params.wat b/winch/filetests/filetests/x64/i64_ge_u/params.wat index 2ca43e57eba1..68d707d11b93 100644 --- a/winch/filetests/filetests/x64/i64_ge_u/params.wat +++ b/winch/filetests/filetests/x64/i64_ge_u/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f93c1 setae cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_gt_s/locals.wat b/winch/filetests/filetests/x64/i64_gt_s/locals.wat index 10c5c4ec360a..a8e347eb4732 100644 --- a/winch/filetests/filetests/x64/i64_gt_s/locals.wat +++ b/winch/filetests/filetests/x64/i64_gt_s/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f9fc1 setg cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_gt_s/params.wat b/winch/filetests/filetests/x64/i64_gt_s/params.wat index 5e30853e0a9a..ee6fc2953601 100644 --- a/winch/filetests/filetests/x64/i64_gt_s/params.wat +++ b/winch/filetests/filetests/x64/i64_gt_s/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f9fc1 setg cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_gt_u/locals.wat b/winch/filetests/filetests/x64/i64_gt_u/locals.wat index 9890d2ca6bb1..203adfe7a5e6 100644 --- a/winch/filetests/filetests/x64/i64_gt_u/locals.wat +++ b/winch/filetests/filetests/x64/i64_gt_u/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f97c1 seta cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_gt_u/params.wat b/winch/filetests/filetests/x64/i64_gt_u/params.wat index e2e9d8654c3f..d2d5e91715c3 100644 --- a/winch/filetests/filetests/x64/i64_gt_u/params.wat +++ b/winch/filetests/filetests/x64/i64_gt_u/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f97c1 seta cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_le_s/locals.wat b/winch/filetests/filetests/x64/i64_le_s/locals.wat index d363621c3b18..479cab46142b 100644 --- a/winch/filetests/filetests/x64/i64_le_s/locals.wat +++ b/winch/filetests/filetests/x64/i64_le_s/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f9ec1 setle cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_le_s/params.wat b/winch/filetests/filetests/x64/i64_le_s/params.wat index 1df814ef2f03..94ec67536632 100644 --- a/winch/filetests/filetests/x64/i64_le_s/params.wat +++ b/winch/filetests/filetests/x64/i64_le_s/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f9ec1 setle cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_le_u/locals.wat b/winch/filetests/filetests/x64/i64_le_u/locals.wat index 85eddc58343f..fcdcde159977 100644 --- a/winch/filetests/filetests/x64/i64_le_u/locals.wat +++ b/winch/filetests/filetests/x64/i64_le_u/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f96c1 setbe cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_le_u/params.wat b/winch/filetests/filetests/x64/i64_le_u/params.wat index 113b16ffacad..11dd179ef606 100644 --- a/winch/filetests/filetests/x64/i64_le_u/params.wat +++ b/winch/filetests/filetests/x64/i64_le_u/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f96c1 setbe cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_lt_s/locals.wat b/winch/filetests/filetests/x64/i64_lt_s/locals.wat index 0a10518f54c9..a22f1ff7037f 100644 --- a/winch/filetests/filetests/x64/i64_lt_s/locals.wat +++ b/winch/filetests/filetests/x64/i64_lt_s/locals.wat @@ -32,7 +32,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f9cc1 setl cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_lt_s/params.wat b/winch/filetests/filetests/x64/i64_lt_s/params.wat index daafe27aa99d..2de32038d091 100644 --- a/winch/filetests/filetests/x64/i64_lt_s/params.wat +++ b/winch/filetests/filetests/x64/i64_lt_s/params.wat @@ -19,7 +19,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f9cc1 setl cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_lt_u/locals.wat b/winch/filetests/filetests/x64/i64_lt_u/locals.wat index eb5197430270..cd62dc77d1e0 100644 --- a/winch/filetests/filetests/x64/i64_lt_u/locals.wat +++ b/winch/filetests/filetests/x64/i64_lt_u/locals.wat @@ -31,7 +31,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f92c1 setb cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_lt_u/params.wat b/winch/filetests/filetests/x64/i64_lt_u/params.wat index c0697c6614d0..a24abe412ce7 100644 --- a/winch/filetests/filetests/x64/i64_lt_u/params.wat +++ b/winch/filetests/filetests/x64/i64_lt_u/params.wat @@ -18,7 +18,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f92c1 setb cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ne/locals.wat b/winch/filetests/filetests/x64/i64_ne/locals.wat index 49090a56e9e7..23655ea63721 100644 --- a/winch/filetests/filetests/x64/i64_ne/locals.wat +++ b/winch/filetests/filetests/x64/i64_ne/locals.wat @@ -32,7 +32,7 @@ ;; 3b: 4839c1 cmp rcx, rax ;; 3e: b900000000 mov ecx, 0 ;; 43: 400f95c1 setne cl -;; 47: 4889c8 mov rax, rcx -;; 4a: 4883c418 add rsp, 0x18 -;; 4e: 5d pop rbp -;; 4f: c3 ret +;; 47: 89c8 mov eax, ecx +;; 49: 4883c418 add rsp, 0x18 +;; 4d: 5d pop rbp +;; 4e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_ne/params.wat b/winch/filetests/filetests/x64/i64_ne/params.wat index 0d08508c8f57..a77f746376f8 100644 --- a/winch/filetests/filetests/x64/i64_ne/params.wat +++ b/winch/filetests/filetests/x64/i64_ne/params.wat @@ -19,7 +19,7 @@ ;; 20: 4839c1 cmp rcx, rax ;; 23: b900000000 mov ecx, 0 ;; 28: 400f95c1 setne cl -;; 2c: 4889c8 mov rax, rcx -;; 2f: 4883c418 add rsp, 0x18 -;; 33: 5d pop rbp -;; 34: c3 ret +;; 2c: 89c8 mov eax, ecx +;; 2e: 4883c418 add rsp, 0x18 +;; 32: 5d pop rbp +;; 33: c3 ret