Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Winch atomic loads x64 #9970

Merged
merged 24 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,6 @@ impl Config {
Some(Strategy::Winch) => {
let mut unsupported = WasmFeatures::GC
| WasmFeatures::FUNCTION_REFERENCES
| WasmFeatures::THREADS
| WasmFeatures::RELAXED_SIMD
| WasmFeatures::TAIL_CALL
| WasmFeatures::GC_TYPES;
Expand All @@ -1985,6 +1984,7 @@ impl Config {
// winch on aarch64 but this helps gate most spec tests
// by default which otherwise currently cause panics.
unsupported |= WasmFeatures::REFERENCE_TYPES;
unsupported |= WasmFeatures::THREADS
}

// Winch doesn't support other non-x64 architectures at this
Expand Down
12 changes: 11 additions & 1 deletion crates/wast-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ impl Compiler {
// Cranelift has quite yet.
Compiler::Winch => {
if config.gc()
|| config.threads()
|| config.tail_call()
|| config.function_references()
|| config.gc()
Expand Down Expand Up @@ -511,6 +510,17 @@ impl WastTest {
"spec_testsuite/simd_store32_lane.wast",
"spec_testsuite/simd_store64_lane.wast",
"spec_testsuite/simd_store8_lane.wast",
// thread related failures
"proposals/threads/atomic.wast",
"misc_testsuite/threads/MP_wait.wast",
"misc_testsuite/threads/load-store-alignment.wast",
"misc_testsuite/threads/MP_atomic.wast",
"misc_testsuite/threads/SB_atomic.wast",
"misc_testsuite/threads/wait_notify.wast",
"misc_testsuite/threads/LB_atomic.wast",
"misc_testsuite/threads/atomics_wait_address.wast",
"misc_testsuite/threads/atomics_notify.wast",
"misc_testsuite/threads/load-store-alignment.wast",
];

if unsupported.iter().any(|part| self.path.ends_with(part)) {
Expand Down
30 changes: 30 additions & 0 deletions tests/disas/winch/x64/atomic/load/i32_atomic_load.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(import "env" "memory" (memory 1 1 shared))
(func (param $foo i32) (result i32)
(i32.atomic.load
(local.get $foo))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x20, %r11
;; cmpq %rsp, %r11
;; ja 0x47
;; 1c: movq %rdi, %r14
;; subq $0x20, %rsp
;; movq %rdi, 0x18(%rsp)
;; movq %rsi, 0x10(%rsp)
;; movl %edx, 0xc(%rsp)
;; movl 0xc(%rsp), %eax
;; movq 0x58(%r14), %r11
;; movq (%r11), %rcx
;; addq %rax, %rcx
;; movl (%rcx), %eax
;; addq $0x20, %rsp
;; popq %rbp
;; retq
;; 47: ud2
30 changes: 30 additions & 0 deletions tests/disas/winch/x64/atomic/load/i32_atomic_load16_u.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(import "env" "memory" (memory 1 1 shared))
(func (param $foo i32) (result i32)
(i32.atomic.load16_u
(local.get $foo))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x20, %r11
;; cmpq %rsp, %r11
;; ja 0x49
;; 1c: movq %rdi, %r14
;; subq $0x20, %rsp
;; movq %rdi, 0x18(%rsp)
;; movq %rsi, 0x10(%rsp)
;; movl %edx, 0xc(%rsp)
;; movl 0xc(%rsp), %eax
;; movq 0x58(%r14), %r11
;; movq (%r11), %rcx
;; addq %rax, %rcx
;; movzwq (%rcx), %rax
;; addq $0x20, %rsp
;; popq %rbp
;; retq
;; 49: ud2
28 changes: 28 additions & 0 deletions tests/disas/winch/x64/atomic/load/i32_atomic_load8_u.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory (data "\00\00\00\00\00\00\f4\7f"))

(func (result i32)
(i32.atomic.load8_u (i32.const 0))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x42
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movzbq (%rcx), %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 42: ud2
29 changes: 29 additions & 0 deletions tests/disas/winch/x64/atomic/load/i64_atomic_load.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory (data "\00\00\00\00\00\00\f4\7f"))

(func (result i64)
(i64.atomic.load
(i32.const 0))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x41
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movq (%rcx), %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 41: ud2
29 changes: 29 additions & 0 deletions tests/disas/winch/x64/atomic/load/i64_atomic_load16_u.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory (data "\00\00\00\00\00\00\f4\7f"))

(func (result i64)
(i64.atomic.load16_u
(i32.const 0))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x42
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movzwq (%rcx), %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 42: ud2
29 changes: 29 additions & 0 deletions tests/disas/winch/x64/atomic/load/i64_atomic_load32_u.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory (data "\00\00\00\00\00\00\f4\7f"))

(func (result i64)
(i64.atomic.load32_u
(i32.const 0))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x40
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movl (%rcx), %eax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 40: ud2
29 changes: 29 additions & 0 deletions tests/disas/winch/x64/atomic/load/i64_atomic_load8_u.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory (data "\00\00\00\00\00\00\f4\7f"))

(func (result i64)
(i64.atomic.load8_u
(i32.const 0))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x42
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0, %eax
;; movq 0x60(%r14), %rcx
;; addq %rax, %rcx
;; movzbq (%rcx), %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 42: ud2
31 changes: 21 additions & 10 deletions winch/codegen/src/codegen/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub struct HeapData {
pub offset: u32,
/// The offset to the current length field.
pub current_length_offset: u32,
/// If the WebAssembly memory is imported, this field contains the offset to locate the
/// If the WebAssembly memory is imported or shared, this field contains the offset to locate the
/// base of the heap.
pub import_from: Option<u32>,
/// The memory type this heap is associated with.
Expand Down Expand Up @@ -247,22 +247,33 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> {
}

/// Resolve a `HeapData` from a [MemoryIndex].
// TODO: (@saulecabrera)
// Handle shared memories when implementing support for Wasm Threads.
pub fn resolve_heap(&mut self, index: MemoryIndex) -> HeapData {
let mem = self.translation.module.memories[index];
let is_shared = mem.shared;
match self.resolved_heaps.entry(index) {
Occupied(entry) => *entry.get(),
Vacant(entry) => {
let (import_from, base_offset, current_length_offset) =
match self.translation.module.defined_memory_index(index) {
Some(defined) => {
let owned = self.translation.module.owned_memory_index(defined);
(
None,
self.vmoffsets.vmctx_vmmemory_definition_base(owned),
self.vmoffsets
.vmctx_vmmemory_definition_current_length(owned),
)
if is_shared {
(
Some(self.vmoffsets.vmctx_vmmemory_pointer(defined)),
self.vmoffsets.ptr.vmmemory_definition_base().into(),
self.vmoffsets
.ptr
.vmmemory_definition_current_length()
.into(),
)
} else {
let owned = self.translation.module.owned_memory_index(defined);
(
None,
self.vmoffsets.vmctx_vmmemory_definition_base(owned),
self.vmoffsets
.vmctx_vmmemory_definition_current_length(owned),
)
}
}
None => (
Some(self.vmoffsets.vmctx_vmmemory_import_from(index)),
Expand Down
10 changes: 6 additions & 4 deletions winch/codegen/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::{
codegen::BlockSig,
isa::reg::{writable, Reg},
masm::{
ExtendKind, IntCmpKind, MacroAssembler, OperandSize, RegImm, SPOffset, ShiftKind, TrapCode,
ExtendKind, IntCmpKind, MacroAssembler, MemOpKind, OperandSize, RegImm, SPOffset,
ShiftKind, TrapCode,
},
stack::TypedReg,
};
Expand Down Expand Up @@ -846,9 +847,9 @@ where
ty: WasmValType,
size: OperandSize,
sextend: Option<ExtendKind>,
op_kind: MemOpKind,
) -> Result<()> {
let addr = self.emit_compute_heap_address(&arg, size)?;
if let Some(addr) = addr {
if let Some(addr) = self.emit_compute_heap_address(&arg, size)? {
let dst = match ty {
WasmValType::I32 | WasmValType::I64 => self.context.any_gpr(self.masm)?,
WasmValType::F32 | WasmValType::F64 => self.context.any_fpr(self.masm)?,
Expand All @@ -857,7 +858,8 @@ where
};

let src = self.masm.address_at_reg(addr, 0)?;
self.masm.wasm_load(src, writable!(dst), size, sextend)?;
self.masm
.wasm_load(src, writable!(dst), size, sextend, op_kind)?;
self.context.stack.push(TypedReg::new(ty, dst).into());
self.context.free_reg(addr);
}
Expand Down
26 changes: 17 additions & 9 deletions winch/codegen/src/isa/aarch64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::{
},
masm::{
CalleeKind, DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind,
MacroAssembler as Masm, MulWideKind, OperandSize, RegImm, RemKind, RoundingMode, SPOffset,
ShiftKind, StackSlot, TrapCode, TruncKind,
MacroAssembler as Masm, MemOpKind, MulWideKind, OperandSize, RegImm, RemKind, RoundingMode,
SPOffset, ShiftKind, StackSlot, TrapCode, TruncKind,
},
stack::TypedReg,
};
Expand Down Expand Up @@ -216,15 +216,23 @@ impl Masm for MacroAssembler {
dst: WritableReg,
size: OperandSize,
kind: Option<ExtendKind>,
op_kind: MemOpKind,
) -> Result<()> {
// kind is some if the value is signed
// unlike x64, unused bits are set to zero so we don't need to extend
if kind.is_some() {
self.asm.sload(src, dst, size);
} else {
self.asm.uload(src, dst, size);
match op_kind {
MemOpKind::Normal => {
// kind is some if the value is signed
// unlike x64, unused bits are set to zero so we don't need to extend
if kind.is_some() {
self.asm.sload(src, dst, size);
} else {
self.asm.uload(src, dst, size);
}

Ok(())
}

MemOpKind::Atomic => Err(anyhow!(CodeGenError::unimplemented_masm_instruction())),
}
Ok(())
}

fn load_addr(&mut self, src: Self::Address, dst: WritableReg, size: OperandSize) -> Result<()> {
Expand Down
Loading
Loading