Skip to content

Commit 74d026b

Browse files
authored
Atomics support in interpreter + optimizer + fuzz fixes for that (#1227)
1 parent 939706d commit 74d026b

18 files changed

Lines changed: 1152 additions & 939 deletions

src/asm2wasm.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "pass.h"
3333
#include "parsing.h"
3434
#include "ast_utils.h"
35+
#include "ast/bits.h"
3536
#include "ast/branch-utils.h"
3637
#include "ast/literal-utils.h"
3738
#include "ast/trapping.h"
@@ -1884,7 +1885,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
18841885
View& view = views[heap];
18851886
wasm.memory.shared = true;
18861887
if (name == Atomics_load) {
1887-
return builder.makeAtomicLoad(view.bytes, view.signed_, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type));
1888+
Expression* ret = builder.makeAtomicLoad(view.bytes, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type));
1889+
if (view.signed_) {
1890+
// atomic loads are unsigned; add a signing
1891+
ret = Bits::makeSignExt(ret, view.bytes, wasm);
1892+
}
1893+
return ret;
18881894
} else if (name == Atomics_store) {
18891895
// asm.js stores return the value, wasm does not
18901896
auto type = asmToWasmType(view.type);

src/ast/ExpressionManipulator.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,28 +97,28 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom
9797
}
9898
Expression* visitLoad(Load *curr) {
9999
if (curr->isAtomic) {
100-
return builder.makeAtomicLoad(curr->bytes, curr->signed_, curr->offset,
101-
copy(curr->ptr), curr->type);
100+
return builder.makeAtomicLoad(curr->bytes, curr->offset,
101+
copy(curr->ptr), curr->type);
102102
}
103103
return builder.makeLoad(curr->bytes, curr->signed_, curr->offset, curr->align, copy(curr->ptr), curr->type);
104104
}
105105
Expression* visitStore(Store *curr) {
106106
if (curr->isAtomic) {
107-
return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType);
107+
return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType);
108108
}
109109
return builder.makeStore(curr->bytes, curr->offset, curr->align, copy(curr->ptr), copy(curr->value), curr->valueType);
110110
}
111111
Expression* visitAtomicRMW(AtomicRMW* curr) {
112112
return builder.makeAtomicRMW(curr->op, curr->bytes, curr->offset,
113-
copy(curr->ptr), copy(curr->value), curr->type);
113+
copy(curr->ptr), copy(curr->value), curr->type);
114114
}
115115
Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
116116
return builder.makeAtomicCmpxchg(curr->bytes, curr->offset,
117-
copy(curr->ptr), copy(curr->expected), copy(curr->replacement),
118-
curr->type);
117+
copy(curr->ptr), copy(curr->expected), copy(curr->replacement),
118+
curr->type);
119119
}
120120
Expression* visitAtomicWait(AtomicWait* curr) {
121-
return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->type);
121+
return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType);
122122
}
123123
Expression* visitAtomicWake(AtomicWake* curr) {
124124
return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount));

src/ast/bits.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define wasm_ast_bits_h
1919

2020
#include "support/bits.h"
21+
#include "wasm-builder.h"
22+
#include "ast/literal-utils.h"
2123

2224
namespace wasm {
2325

@@ -60,6 +62,43 @@ struct Bits {
6062
}
6163
WASM_UNREACHABLE();
6264
}
65+
66+
static Expression* makeSignExt(Expression* value, Index bytes, Module& wasm) {
67+
if (value->type == i32) {
68+
if (bytes == 1 || bytes == 2) {
69+
auto shifts = bytes == 1 ? 24 : 16;
70+
Builder builder(wasm);
71+
return builder.makeBinary(
72+
ShrSInt32,
73+
builder.makeBinary(
74+
ShlInt32,
75+
value,
76+
LiteralUtils::makeFromInt32(shifts, i32, wasm)
77+
),
78+
LiteralUtils::makeFromInt32(shifts, i32, wasm)
79+
);
80+
}
81+
assert(bytes == 4);
82+
return value; // nothing to do
83+
} else {
84+
assert(value->type == i64);
85+
if (bytes == 1 || bytes == 2 || bytes == 4) {
86+
auto shifts = bytes == 1 ? 56 : (bytes == 2 ? 48 : 32);
87+
Builder builder(wasm);
88+
return builder.makeBinary(
89+
ShrSInt64,
90+
builder.makeBinary(
91+
ShlInt64,
92+
value,
93+
LiteralUtils::makeFromInt32(shifts, i64, wasm)
94+
),
95+
LiteralUtils::makeFromInt32(shifts, i64, wasm)
96+
);
97+
}
98+
assert(bytes == 8);
99+
return value; // nothing to do
100+
}
101+
}
63102
};
64103

65104
} // namespace wasm

src/ast/global-utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace wasm {
2727

2828
namespace GlobalUtils {
2929
// find a global initialized to the value of an import, or null if no such global
30-
inline Global* getGlobalInitializedToImport(Module&wasm, Name module, Name base) {
30+
inline Global* getGlobalInitializedToImport(Module& wasm, Name module, Name base) {
3131
// find the import
3232
Name imported;
3333
for (auto& import : wasm.imports) {

src/passes/DeadCodeElimination.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
254254
case Expression::Id::HostId: DELEGATE(Host);
255255
case Expression::Id::NopId: DELEGATE(Nop);
256256
case Expression::Id::UnreachableId: break;
257+
case Expression::Id::AtomicCmpxchgId: DELEGATE(AtomicCmpxchg);
258+
case Expression::Id::AtomicRMWId: DELEGATE(AtomicRMW);
259+
case Expression::Id::AtomicWaitId: DELEGATE(AtomicWait);
260+
case Expression::Id::AtomicWakeId: DELEGATE(AtomicWake);
257261
case Expression::Id::InvalidId:
258262
default: WASM_UNREACHABLE();
259263
}

src/passes/Precompute.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR
8989
Flow visitAtomicCmpxchg(AtomicCmpxchg *curr) {
9090
return Flow(NONSTANDALONE_FLOW);
9191
}
92+
Flow visitAtomicWait(AtomicWait *curr) {
93+
return Flow(NONSTANDALONE_FLOW);
94+
}
95+
Flow visitAtomicWake(AtomicWake *curr) {
96+
return Flow(NONSTANDALONE_FLOW);
97+
}
9298
Flow visitHost(Host *curr) {
9399
return Flow(NONSTANDALONE_FLOW);
94100
}

src/passes/Print.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
352352
}
353353
static void printRMWSize(std::ostream& o, WasmType type, uint8_t bytes) {
354354
prepareColor(o) << printWasmType(type) << ".atomic.rmw";
355-
if (bytes != getWasmTypeSize(type)) {
355+
if (type == unreachable) {
356+
o << '?';
357+
} else if (bytes != getWasmTypeSize(type)) {
356358
if (bytes == 1) {
357359
o << '8';
358360
} else if (bytes == 2) {

src/passes/SafeHeap.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "asm_v_wasm.h"
2626
#include "asmjs/shared-constants.h"
2727
#include "wasm-builder.h"
28+
#include "ast/bits.h"
2829
#include "ast/import-utils.h"
2930

3031
namespace wasm {
@@ -229,7 +230,13 @@ struct SafeHeap : public Pass {
229230
auto* load = module->allocator.alloc<Load>();
230231
*load = style; // basically the same as the template we are given!
231232
load->ptr = builder.makeGetLocal(2, i32);
232-
block->list.push_back(load);
233+
Expression* last = load;
234+
if (load->isAtomic && load->signed_) {
235+
// atomic loads cannot be signed, manually sign it
236+
last = Bits::makeSignExt(load, load->bytes, *module);
237+
load->signed_ = false;
238+
}
239+
block->list.push_back(last);
233240
block->finalize(style.type);
234241
func->body = block;
235242
module->addFunction(func);

0 commit comments

Comments
 (0)