summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-02-14 16:36:36 -0600
committerGitHub <noreply@github.com>2023-02-14 14:36:36 -0800
commit8f98375c051f2b8e1be87e7eb97e88d73cfb2c26 (patch)
tree171ab05759465e63ebe7ce898585813801820cbd
parent3a315fb8248be7a2a7b7e27ebfde634d05668bf3 (diff)
downloadbinaryen-8f98375c051f2b8e1be87e7eb97e88d73cfb2c26.tar.gz
binaryen-8f98375c051f2b8e1be87e7eb97e88d73cfb2c26.tar.bz2
binaryen-8f98375c051f2b8e1be87e7eb97e88d73cfb2c26.zip
[wasm2js] Support nonzero offsets in memory.atomic.wait32 (#5489)
The assertion that the offset is zero does not necessarily hold for code that uses this instruction via the clang builtin. Add support so that Emscripten wasm2js tests pass in the presence of such code.
-rw-r--r--src/abi/js.h5
-rw-r--r--src/passes/I64ToI32Lowering.cpp4
-rw-r--r--src/wasm2js.h5
-rw-r--r--test/passes/remove-non-js-ops.txt4
-rw-r--r--test/wasm2js/atomics_32.2asm.js7
-rw-r--r--test/wasm2js/atomics_32.2asm.js.opt7
-rw-r--r--test/wasm2js/atomics_32.wast2
7 files changed, 19 insertions, 15 deletions
diff --git a/src/abi/js.h b/src/abi/js.h
index 735f71af7..d22376c13 100644
--- a/src/abi/js.h
+++ b/src/abi/js.h
@@ -82,8 +82,9 @@ inline void ensureHelpers(Module* wasm, IString specific = IString()) {
ensureImport(MEMORY_FILL, {Type::i32, Type::i32, Type::i32}, Type::none);
ensureImport(MEMORY_COPY, {Type::i32, Type::i32, Type::i32}, Type::none);
ensureImport(DATA_DROP, {Type::i32}, Type::none);
- ensureImport(
- ATOMIC_WAIT_I32, {Type::i32, Type::i32, Type::i32, Type::i32}, Type::i32);
+ ensureImport(ATOMIC_WAIT_I32,
+ {Type::i32, Type::i32, Type::i32, Type::i32, Type::i32},
+ Type::i32);
ensureImport(
ATOMIC_RMW_I64,
{Type::i32, Type::i32, Type::i32, Type::i32, Type::i32, Type::i32},
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index aee65c22a..dfcc65a51 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -478,10 +478,10 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
void visitAtomicWait(AtomicWait* curr) {
// The last parameter is an i64, so we cannot leave it as it is
- assert(curr->offset == 0);
replaceCurrent(builder->makeCall(
ABI::wasm2js::ATOMIC_WAIT_I32,
- {curr->ptr,
+ {builder->makeConst(int32_t(curr->offset)),
+ curr->ptr,
curr->expected,
curr->timeout,
builder->makeLocalGet(fetchOutParam(curr->timeout), Type::i32)},
diff --git a/src/wasm2js.h b/src/wasm2js.h
index eddb26866..08969b8ba 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -2989,7 +2989,8 @@ void Wasm2JSGlue::emitSpecialSupport() {
)";
} else if (import->base == ABI::wasm2js::ATOMIC_WAIT_I32) {
out << R"(
- function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) {
+ function wasm2js_atomic_wait_i32(offset, ptr, expected, timeoutLow, timeoutHigh) {
+ ptr = (ptr + offset) >> 2;
var timeout = Infinity;
if (timeoutHigh >= 0) {
// Convert from nanoseconds to milliseconds
@@ -2997,7 +2998,7 @@ void Wasm2JSGlue::emitSpecialSupport() {
timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6);
}
var view = new Int32Array(bufferView.buffer); // TODO cache
- var result = Atomics.wait(view, ptr >> 2, expected, timeout);
+ var result = Atomics.wait(view, ptr, expected, timeout);
if (result == 'ok') return 0;
if (result == 'not-equal') return 1;
if (result == 'timed-out') return 2;
diff --git a/test/passes/remove-non-js-ops.txt b/test/passes/remove-non-js-ops.txt
index d3fa090a5..ec42a28e1 100644
--- a/test/passes/remove-non-js-ops.txt
+++ b/test/passes/remove-non-js-ops.txt
@@ -14,7 +14,7 @@
(type $f64_=>_none (func (param f64)))
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
(type $i32_=>_none (func (param i32)))
- (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32)))
+ (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32)))
(type $i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32) (result i32)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_none (func))
@@ -28,7 +28,7 @@
(import "env" "wasm2js_memory_fill" (func $wasm2js_memory_fill (param i32 i32 i32)))
(import "env" "wasm2js_memory_copy" (func $wasm2js_memory_copy (param i32 i32 i32)))
(import "env" "wasm2js_data_drop" (func $wasm2js_data_drop (param i32)))
- (import "env" "wasm2js_atomic_wait_i32" (func $wasm2js_atomic_wait_i32 (param i32 i32 i32 i32) (result i32)))
+ (import "env" "wasm2js_atomic_wait_i32" (func $wasm2js_atomic_wait_i32 (param i32 i32 i32 i32 i32) (result i32)))
(import "env" "wasm2js_atomic_rmw_i64" (func $wasm2js_atomic_rmw_i64 (param i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "wasm2js_get_stashed_bits" (func $wasm2js_get_stashed_bits (result i32)))
(import "env" "wasm2js_trap" (func $wasm2js_trap))
diff --git a/test/wasm2js/atomics_32.2asm.js b/test/wasm2js/atomics_32.2asm.js
index 66a9c1769..98c5677e6 100644
--- a/test/wasm2js/atomics_32.2asm.js
+++ b/test/wasm2js/atomics_32.2asm.js
@@ -24,7 +24,8 @@
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
- function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) {
+ function wasm2js_atomic_wait_i32(offset, ptr, expected, timeoutLow, timeoutHigh) {
+ ptr = (ptr + offset) >> 2;
var timeout = Infinity;
if (timeoutHigh >= 0) {
// Convert from nanoseconds to milliseconds
@@ -32,7 +33,7 @@ memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29y
timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6);
}
var view = new Int32Array(bufferView.buffer); // TODO cache
- var result = Atomics.wait(view, ptr >> 2, expected, timeout);
+ var result = Atomics.wait(view, ptr, expected, timeout);
if (result == 'ok') return 0;
if (result == 'not-equal') return 1;
if (result == 'timed-out') return 2;
@@ -119,7 +120,7 @@ function asmFunc(imports) {
Atomics.load(HEAP32, 1028 >> 2) | 0;
Atomics.store(HEAP32, 100 >> 2, 200);
i64toi32_i32$0 = -1;
- wasm2js_atomic_wait_i32(4 | 0, 8 | 0, -1 | 0, i64toi32_i32$0 | 0) | 0;
+ wasm2js_atomic_wait_i32(4 | 0, 8 | 0, 16 | 0, -1 | 0, i64toi32_i32$0 | 0) | 0;
wasm2js_memory_init(0, 512, 0, 4);
wasm2js_memory_init(1, 1024, 4, 2);
Atomics.notify(HEAP32, 4 >> 2, 2);
diff --git a/test/wasm2js/atomics_32.2asm.js.opt b/test/wasm2js/atomics_32.2asm.js.opt
index 6f42d5df5..5cb990b7d 100644
--- a/test/wasm2js/atomics_32.2asm.js.opt
+++ b/test/wasm2js/atomics_32.2asm.js.opt
@@ -24,7 +24,8 @@
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
- function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) {
+ function wasm2js_atomic_wait_i32(offset, ptr, expected, timeoutLow, timeoutHigh) {
+ ptr = (ptr + offset) >> 2;
var timeout = Infinity;
if (timeoutHigh >= 0) {
// Convert from nanoseconds to milliseconds
@@ -32,7 +33,7 @@ memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29y
timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6);
}
var view = new Int32Array(bufferView.buffer); // TODO cache
- var result = Atomics.wait(view, ptr >> 2, expected, timeout);
+ var result = Atomics.wait(view, ptr, expected, timeout);
if (result == 'ok') return 0;
if (result == 'not-equal') return 1;
if (result == 'timed-out') return 2;
@@ -117,7 +118,7 @@ function asmFunc(imports) {
Atomics.load(HEAPU16, 514);
Atomics.load(HEAP32, 257);
Atomics.store(HEAP32, 25, 200);
- wasm2js_atomic_wait_i32(4, 8, -1, -1) | 0;
+ wasm2js_atomic_wait_i32(4, 8, 16, -1, -1) | 0;
wasm2js_memory_init(0, 512, 0, 4);
wasm2js_memory_init(1, 1024, 4, 2);
Atomics.notify(HEAP32, 1, 2);
diff --git a/test/wasm2js/atomics_32.wast b/test/wasm2js/atomics_32.wast
index c6408f162..73ec8f152 100644
--- a/test/wasm2js/atomics_32.wast
+++ b/test/wasm2js/atomics_32.wast
@@ -12,7 +12,7 @@
(local.set $x (i32.atomic.load16_u (i32.const 1028)))
(local.set $x (i32.atomic.load (i32.const 1028)))
(i32.atomic.store (i32.const 100) (i32.const 200))
- (local.set $x (memory.atomic.wait32 (i32.const 4) (i32.const 8) (i64.const -1)))
+ (local.set $x (memory.atomic.wait32 offset=4 (i32.const 8) (i32.const 16) (i64.const -1)))
(memory.init 0 (i32.const 512) (i32.const 0) (i32.const 4))
(memory.init 1 (i32.const 1024) (i32.const 4) (i32.const 2))
(local.set $x (memory.atomic.notify (i32.const 4) (i32.const 2)))