summaryrefslogtreecommitdiff
path: root/src/passes/I64ToI32Lowering.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-06-23 18:43:08 -0700
committerGitHub <noreply@github.com>2020-06-23 18:43:08 -0700
commitdf660c241dcde92d634bb0704a449c8e1b4dd5a4 (patch)
treec12a1b4633dbd5194d11d4fda77e22b92655a431 /src/passes/I64ToI32Lowering.cpp
parent8540db83abf2044bbabb85e293e5b98a4bb4b9a8 (diff)
downloadbinaryen-df660c241dcde92d634bb0704a449c8e1b4dd5a4.tar.gz
binaryen-df660c241dcde92d634bb0704a449c8e1b4dd5a4.tar.bz2
binaryen-df660c241dcde92d634bb0704a449c8e1b4dd5a4.zip
Wasm2js Atomics support (#2924)
Atomic loads, stores, RMW, cmpXchg, wait, and notify. This is enough to get the asm.js atomics tests in the emscripten test suite to pass, at least (but they are a subset of the entire pthreads suite).
Diffstat (limited to 'src/passes/I64ToI32Lowering.cpp')
-rw-r--r--src/passes/I64ToI32Lowering.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index 711900e1d..912d6336c 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -367,7 +367,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (curr->type != Type::i64) {
return;
}
- assert(!curr->isAtomic && "atomic load not implemented");
+ assert(!curr->isAtomic && "64-bit atomic load not implemented");
TempVar lowBits = getTemp();
TempVar highBits = getTemp();
TempVar ptrTemp = getTemp();
@@ -433,11 +433,49 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitAtomicRMW(AtomicRMW* curr) {
- assert(false && "AtomicRMW not implemented");
+ if (handleUnreachable(curr)) {
+ return;
+ }
+ if (curr->type != Type::i64) {
+ return;
+ }
+ // We cannot break this up into smaller operations as it must be atomic.
+ // Lower to an instrinsic function that wasm2js will implement.
+ TempVar lowBits = getTemp();
+ TempVar highBits = getTemp();
+ auto* getLow = builder->makeCall(
+ ABI::wasm2js::ATOMIC_RMW_I64,
+ {builder->makeConst(Literal(int32_t(curr->op))),
+ builder->makeConst(Literal(int32_t(curr->bytes))),
+ builder->makeConst(Literal(int32_t(curr->offset))),
+ curr->ptr,
+ curr->value,
+ builder->makeLocalGet(fetchOutParam(curr->value), Type::i32)},
+ Type::i32);
+ auto* getHigh =
+ builder->makeCall(ABI::wasm2js::GET_STASHED_BITS, {}, Type::i32);
+ auto* setLow = builder->makeLocalSet(lowBits, getLow);
+ auto* setHigh = builder->makeLocalSet(highBits, getHigh);
+ auto* finalGet = builder->makeLocalGet(lowBits, Type::i32);
+ auto* result = builder->makeBlock({setLow, setHigh, finalGet});
+ setOutParam(result, std::move(highBits));
+ replaceCurrent(result);
}
void visitAtomicCmpxchg(AtomicCmpxchg* curr) {
- assert(false && "AtomicCmpxchg not implemented");
+ assert(curr->type != Type::i64 && "64-bit AtomicCmpxchg not implemented");
+ }
+
+ 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,
+ curr->expected,
+ curr->timeout,
+ builder->makeLocalGet(fetchOutParam(curr->timeout), Type::i32)},
+ Type::i32));
}
void visitConst(Const* curr) {