diff options
-rw-r--r-- | src/binaryen-c.cpp | 4 | ||||
-rw-r--r-- | src/ir/ExpressionAnalyzer.cpp | 2 | ||||
-rw-r--r-- | src/ir/ExpressionManipulator.cpp | 4 | ||||
-rw-r--r-- | src/passes/Print.cpp | 6 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 9 | ||||
-rw-r--r-- | src/wasm-binary.h | 2 | ||||
-rw-r--r-- | src/wasm-builder.h | 6 | ||||
-rw-r--r-- | src/wasm.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 43 |
9 files changed, 61 insertions, 17 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 4242abb61..63ce7ee6c 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -809,7 +809,7 @@ BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenIn return static_cast<Expression*>(ret); } BinaryenExpressionRef BinaryenAtomicWait(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef expected, BinaryenExpressionRef timeout, BinaryenType expectedType) { - auto* ret = Builder(*((Module*)module)).makeAtomicWait((Expression*)ptr, (Expression*)expected, (Expression*)timeout, WasmType(expectedType)); + auto* ret = Builder(*((Module*)module)).makeAtomicWait((Expression*)ptr, (Expression*)expected, (Expression*)timeout, WasmType(expectedType), 0); if (tracing) { auto id = noteExpression(ret); @@ -819,7 +819,7 @@ BinaryenExpressionRef BinaryenAtomicWait(BinaryenModuleRef module, BinaryenExpre return static_cast<Expression*>(ret); } BinaryenExpressionRef BinaryenAtomicWake(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef wakeCount) { - auto* ret = Builder(*((Module*)module)).makeAtomicWake((Expression*)ptr, (Expression*)wakeCount); + auto* ret = Builder(*((Module*)module)).makeAtomicWake((Expression*)ptr, (Expression*)wakeCount, 0); if (tracing) { auto id = noteExpression(ret); diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index 05450d567..748b5a0af 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -492,6 +492,7 @@ uint32_t ExpressionAnalyzer::hash(Expression* curr) { break; } case Expression::Id::AtomicWaitId: { + HASH(AtomicWait, offset); HASH(AtomicWait, expectedType); PUSH(AtomicWait, ptr); PUSH(AtomicWait, expected); @@ -499,6 +500,7 @@ uint32_t ExpressionAnalyzer::hash(Expression* curr) { break; } case Expression::Id::AtomicWakeId: { + HASH(AtomicWake, offset); PUSH(AtomicWake, ptr); PUSH(AtomicWake, wakeCount); break; diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp index 812c4f04b..dcbb4a056 100644 --- a/src/ir/ExpressionManipulator.cpp +++ b/src/ir/ExpressionManipulator.cpp @@ -116,10 +116,10 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom curr->type); } Expression* visitAtomicWait(AtomicWait* curr) { - return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType); + return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType, curr->offset); } Expression* visitAtomicWake(AtomicWake* curr) { - return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount)); + return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount), curr->offset); } Expression* visitConst(Const *curr) { return builder.makeConst(curr->value); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 7651414e0..66b0fa8f5 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -411,6 +411,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << '(' ; prepareColor(o); o << printWasmType(curr->expectedType) << ".wait"; + if (curr->offset) { + o << " offset=" << curr->offset; + } restoreNormalColor(o); incIndent(); printFullLine(curr->ptr); @@ -420,6 +423,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } void visitAtomicWake(AtomicWake* curr) { printOpening(o, "wake"); + if (curr->offset) { + o << " offset=" << curr->offset; + } incIndent(); printFullLine(curr->ptr); printFullLine(curr->wakeCount); diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 0b3dbf78e..19bff428e 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -174,6 +174,9 @@ private: // Whether to emit atomics static const bool ATOMICS = true; + // Whether to emit atomic waits (which in single-threaded mode, may hang...) + static const bool ATOMIC_WAITS = false; + // after we finish the input, we start going through it again, but xoring // so it's not identical int xorFactor = 0; @@ -1242,16 +1245,16 @@ private: if (!ATOMICS || (type != i32 && type != i64)) return makeTrivial(type); wasm.memory.shared = true; if (type == i32 && oneIn(2)) { - if (oneIn(2)) { + if (ATOMIC_WAITS && oneIn(2)) { auto* ptr = makePointer(); auto expectedType = pick(i32, i64); auto* expected = make(expectedType); auto* timeout = make(i64); - return builder.makeAtomicWait(ptr, expected, timeout, expectedType); + return builder.makeAtomicWait(ptr, expected, timeout, expectedType, logify(get())); } else { auto* ptr = makePointer(); auto* count = make(i32); - return builder.makeAtomicWake(ptr, count); + return builder.makeAtomicWake(ptr, count, logify(get())); } } Index bytes; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 7e932c305..2ac0ef2d0 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -959,7 +959,7 @@ public: void visitSetLocal(SetLocal *curr, uint8_t code); void visitGetGlobal(GetGlobal *curr); void visitSetGlobal(SetGlobal *curr); - void readMemoryAccess(Address& alignment, size_t bytes, Address& offset); + void readMemoryAccess(Address& alignment, Address& offset); bool maybeVisitLoad(Expression*& out, uint8_t code, bool isAtomic); bool maybeVisitStore(Expression*& out, uint8_t code, bool isAtomic); bool maybeVisitAtomicRMW(Expression*& out, uint8_t code); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 3c200a431..ca04c08b9 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -240,8 +240,9 @@ public: load->isAtomic = true; return load; } - AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType expectedType) { + AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType expectedType, Address offset) { auto* wait = allocator.alloc<AtomicWait>(); + wait->offset = offset; wait->ptr = ptr; wait->expected = expected; wait->timeout = timeout; @@ -249,8 +250,9 @@ public: wait->finalize(); return wait; } - AtomicWake* makeAtomicWake(Expression* ptr, Expression* wakeCount) { + AtomicWake* makeAtomicWake(Expression* ptr, Expression* wakeCount, Address offset) { auto* wake = allocator.alloc<AtomicWake>(); + wake->offset = offset; wake->ptr = ptr; wake->wakeCount = wakeCount; wake->finalize(); diff --git a/src/wasm.h b/src/wasm.h index 4072533a7..cf783adf2 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -474,6 +474,7 @@ class AtomicWait : public SpecificExpression<Expression::AtomicWaitId> { AtomicWait() = default; AtomicWait(MixedArena& allocator) : AtomicWait() {} + Address offset; Expression* ptr; Expression* expected; Expression* timeout; @@ -487,6 +488,7 @@ class AtomicWake : public SpecificExpression<Expression::AtomicWakeId> { AtomicWake() = default; AtomicWake(MixedArena& allocator) : AtomicWake() {} + Address offset; Expression* ptr; Expression* wakeCount; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 44ce9a2d1..c96157f1a 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -954,7 +954,10 @@ void WasmBinaryWriter::visitStore(Store *curr) { void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) { if (debug) std::cerr << "zz node: AtomicRMW" << std::endl; recurse(curr->ptr); + // stop if the rest isn't reachable anyhow + if (curr->ptr->type == unreachable) return; recurse(curr->value); + if (curr->value->type == unreachable) return; if (curr->type == unreachable) { // don't even emit it; we don't know the right type @@ -1005,8 +1008,12 @@ void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) { void WasmBinaryWriter::visitAtomicCmpxchg(AtomicCmpxchg *curr) { if (debug) std::cerr << "zz node: AtomicCmpxchg" << std::endl; recurse(curr->ptr); + // stop if the rest isn't reachable anyhow + if (curr->ptr->type == unreachable) return; recurse(curr->expected); + if (curr->expected->type == unreachable) return; recurse(curr->replacement); + if (curr->replacement->type == unreachable) return; if (curr->type == unreachable) { // don't even emit it; we don't know the right type @@ -1041,13 +1048,25 @@ void WasmBinaryWriter::visitAtomicCmpxchg(AtomicCmpxchg *curr) { void WasmBinaryWriter::visitAtomicWait(AtomicWait *curr) { if (debug) std::cerr << "zz node: AtomicWait" << std::endl; recurse(curr->ptr); + // stop if the rest isn't reachable anyhow + if (curr->ptr->type == unreachable) return; recurse(curr->expected); + if (curr->expected->type == unreachable) return; recurse(curr->timeout); + if (curr->timeout->type == unreachable) return; o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->expectedType) { - case i32: o << int8_t(BinaryConsts::I32AtomicWait); break; - case i64: o << int8_t(BinaryConsts::I64AtomicWait); break; + case i32: { + o << int8_t(BinaryConsts::I32AtomicWait); + emitMemoryAccess(4, 4, 0); + break; + } + case i64: { + o << int8_t(BinaryConsts::I64AtomicWait); + emitMemoryAccess(8, 8, 0); + break; + } default: WASM_UNREACHABLE(); } } @@ -1055,9 +1074,13 @@ void WasmBinaryWriter::visitAtomicWait(AtomicWait *curr) { void WasmBinaryWriter::visitAtomicWake(AtomicWake *curr) { if (debug) std::cerr << "zz node: AtomicWake" << std::endl; recurse(curr->ptr); + // stop if the rest isn't reachable anyhow + if (curr->ptr->type == unreachable) return; recurse(curr->wakeCount); + if (curr->wakeCount->type == unreachable) return; o << int8_t(BinaryConsts::AtomicPrefix) << int8_t(BinaryConsts::AtomicWake); + emitMemoryAccess(4, 4, 0); } void WasmBinaryWriter::visitConst(Const *curr) { @@ -2555,7 +2578,7 @@ void WasmBinaryBuilder::visitSetGlobal(SetGlobal *curr) { curr->finalize(); } -void WasmBinaryBuilder::readMemoryAccess(Address& alignment, size_t bytes, Address& offset) { +void WasmBinaryBuilder::readMemoryAccess(Address& alignment, Address& offset) { auto rawAlignment = getU32LEB(); if (rawAlignment > 4) throw ParseException("Alignment must be of a reasonable size"); alignment = Pow2(rawAlignment); @@ -2599,7 +2622,7 @@ bool WasmBinaryBuilder::maybeVisitLoad(Expression*& out, uint8_t code, bool isAt } curr->isAtomic = isAtomic; - readMemoryAccess(curr->align, curr->bytes, curr->offset); + readMemoryAccess(curr->align, curr->offset); curr->ptr = popNonVoidExpression(); curr->finalize(); out = curr; @@ -2636,7 +2659,7 @@ bool WasmBinaryBuilder::maybeVisitStore(Expression*& out, uint8_t code, bool isA curr->isAtomic = isAtomic; if (debug) std::cerr << "zz node: Store" << std::endl; - readMemoryAccess(curr->align, curr->bytes, curr->offset); + readMemoryAccess(curr->align, curr->offset); curr->value = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); curr->finalize(); @@ -2679,7 +2702,7 @@ bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) { if (debug) std::cerr << "zz node: AtomicRMW" << std::endl; Address readAlign; - readMemoryAccess(readAlign, curr->bytes, curr->offset); + readMemoryAccess(readAlign, curr->offset); if (readAlign != curr->bytes) throw ParseException("Align of AtomicRMW must match size"); curr->value = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); @@ -2710,7 +2733,7 @@ bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg(Expression*& out, uint8_t code) if (debug) std::cerr << "zz node: AtomicCmpxchg" << std::endl; Address readAlign; - readMemoryAccess(readAlign, curr->bytes, curr->offset); + readMemoryAccess(readAlign, curr->offset); if (readAlign != curr->bytes) throw ParseException("Align of AtomicCpxchg must match size"); curr->replacement = popNonVoidExpression(); curr->expected = popNonVoidExpression(); @@ -2734,6 +2757,9 @@ bool WasmBinaryBuilder::maybeVisitAtomicWait(Expression*& out, uint8_t code) { curr->timeout = popNonVoidExpression(); curr->expected = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); + Address readAlign; + readMemoryAccess(readAlign, curr->offset); + if (readAlign != getWasmTypeSize(curr->expectedType)) throw ParseException("Align of AtomicWait must match size"); curr->finalize(); out = curr; return true; @@ -2747,6 +2773,9 @@ bool WasmBinaryBuilder::maybeVisitAtomicWake(Expression*& out, uint8_t code) { curr->type = i32; curr->wakeCount = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); + Address readAlign; + readMemoryAccess(readAlign, curr->offset); + if (readAlign != getWasmTypeSize(curr->type)) throw ParseException("Align of AtomicWake must match size"); curr->finalize(); out = curr; return true; |