summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h8
-rw-r--r--src/ast/ExpressionManipulator.cpp14
-rw-r--r--src/ast/bits.h39
-rw-r--r--src/ast/global-utils.h2
-rw-r--r--src/passes/DeadCodeElimination.cpp4
-rw-r--r--src/passes/Precompute.cpp6
-rw-r--r--src/passes/Print.cpp4
-rw-r--r--src/passes/SafeHeap.cpp9
-rw-r--r--src/tools/translate-to-fuzz.h186
-rw-r--r--src/wasm-builder.h12
-rw-r--r--src/wasm-interpreter.h164
-rw-r--r--src/wasm/wasm-binary.cpp22
-rw-r--r--src/wasm/wasm-validator.cpp7
-rw-r--r--src/wasm/wasm.cpp2
-rw-r--r--test/passes/inlining-optimizing.txt12
-rw-r--r--test/passes/inlining-optimizing.wast17
-rw-r--r--test/passes/safe-heap.txt50
-rw-r--r--test/passes/translate-to-fuzz.txt1533
18 files changed, 1152 insertions, 939 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 8f3c771be..9a4305f6a 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -32,6 +32,7 @@
#include "pass.h"
#include "parsing.h"
#include "ast_utils.h"
+#include "ast/bits.h"
#include "ast/branch-utils.h"
#include "ast/literal-utils.h"
#include "ast/trapping.h"
@@ -1884,7 +1885,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
View& view = views[heap];
wasm.memory.shared = true;
if (name == Atomics_load) {
- return builder.makeAtomicLoad(view.bytes, view.signed_, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type));
+ Expression* ret = builder.makeAtomicLoad(view.bytes, 0, processUnshifted(ast[2][1], view.bytes), asmToWasmType(view.type));
+ if (view.signed_) {
+ // atomic loads are unsigned; add a signing
+ ret = Bits::makeSignExt(ret, view.bytes, wasm);
+ }
+ return ret;
} else if (name == Atomics_store) {
// asm.js stores return the value, wasm does not
auto type = asmToWasmType(view.type);
diff --git a/src/ast/ExpressionManipulator.cpp b/src/ast/ExpressionManipulator.cpp
index f5b303488..6cb0219c5 100644
--- a/src/ast/ExpressionManipulator.cpp
+++ b/src/ast/ExpressionManipulator.cpp
@@ -97,28 +97,28 @@ Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom
}
Expression* visitLoad(Load *curr) {
if (curr->isAtomic) {
- return builder.makeAtomicLoad(curr->bytes, curr->signed_, curr->offset,
- copy(curr->ptr), curr->type);
+ return builder.makeAtomicLoad(curr->bytes, curr->offset,
+ copy(curr->ptr), curr->type);
}
return builder.makeLoad(curr->bytes, curr->signed_, curr->offset, curr->align, copy(curr->ptr), curr->type);
}
Expression* visitStore(Store *curr) {
if (curr->isAtomic) {
- return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType);
+ return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType);
}
return builder.makeStore(curr->bytes, curr->offset, curr->align, copy(curr->ptr), copy(curr->value), curr->valueType);
}
Expression* visitAtomicRMW(AtomicRMW* curr) {
return builder.makeAtomicRMW(curr->op, curr->bytes, curr->offset,
- copy(curr->ptr), copy(curr->value), curr->type);
+ copy(curr->ptr), copy(curr->value), curr->type);
}
Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
return builder.makeAtomicCmpxchg(curr->bytes, curr->offset,
- copy(curr->ptr), copy(curr->expected), copy(curr->replacement),
- curr->type);
+ copy(curr->ptr), copy(curr->expected), copy(curr->replacement),
+ curr->type);
}
Expression* visitAtomicWait(AtomicWait* curr) {
- return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->type);
+ return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType);
}
Expression* visitAtomicWake(AtomicWake* curr) {
return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount));
diff --git a/src/ast/bits.h b/src/ast/bits.h
index 0aee50ffe..7a86e70f4 100644
--- a/src/ast/bits.h
+++ b/src/ast/bits.h
@@ -18,6 +18,8 @@
#define wasm_ast_bits_h
#include "support/bits.h"
+#include "wasm-builder.h"
+#include "ast/literal-utils.h"
namespace wasm {
@@ -60,6 +62,43 @@ struct Bits {
}
WASM_UNREACHABLE();
}
+
+ static Expression* makeSignExt(Expression* value, Index bytes, Module& wasm) {
+ if (value->type == i32) {
+ if (bytes == 1 || bytes == 2) {
+ auto shifts = bytes == 1 ? 24 : 16;
+ Builder builder(wasm);
+ return builder.makeBinary(
+ ShrSInt32,
+ builder.makeBinary(
+ ShlInt32,
+ value,
+ LiteralUtils::makeFromInt32(shifts, i32, wasm)
+ ),
+ LiteralUtils::makeFromInt32(shifts, i32, wasm)
+ );
+ }
+ assert(bytes == 4);
+ return value; // nothing to do
+ } else {
+ assert(value->type == i64);
+ if (bytes == 1 || bytes == 2 || bytes == 4) {
+ auto shifts = bytes == 1 ? 56 : (bytes == 2 ? 48 : 32);
+ Builder builder(wasm);
+ return builder.makeBinary(
+ ShrSInt64,
+ builder.makeBinary(
+ ShlInt64,
+ value,
+ LiteralUtils::makeFromInt32(shifts, i64, wasm)
+ ),
+ LiteralUtils::makeFromInt32(shifts, i64, wasm)
+ );
+ }
+ assert(bytes == 8);
+ return value; // nothing to do
+ }
+ }
};
} // namespace wasm
diff --git a/src/ast/global-utils.h b/src/ast/global-utils.h
index f5bebe8aa..96fec282b 100644
--- a/src/ast/global-utils.h
+++ b/src/ast/global-utils.h
@@ -27,7 +27,7 @@ namespace wasm {
namespace GlobalUtils {
// find a global initialized to the value of an import, or null if no such global
- inline Global* getGlobalInitializedToImport(Module&wasm, Name module, Name base) {
+ inline Global* getGlobalInitializedToImport(Module& wasm, Name module, Name base) {
// find the import
Name imported;
for (auto& import : wasm.imports) {
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 48fc4a91c..5c0cfc291 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -254,6 +254,10 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
case Expression::Id::HostId: DELEGATE(Host);
case Expression::Id::NopId: DELEGATE(Nop);
case Expression::Id::UnreachableId: break;
+ case Expression::Id::AtomicCmpxchgId: DELEGATE(AtomicCmpxchg);
+ case Expression::Id::AtomicRMWId: DELEGATE(AtomicRMW);
+ case Expression::Id::AtomicWaitId: DELEGATE(AtomicWait);
+ case Expression::Id::AtomicWakeId: DELEGATE(AtomicWake);
case Expression::Id::InvalidId:
default: WASM_UNREACHABLE();
}
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index ab114fa14..d2a7d0b9a 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -89,6 +89,12 @@ public:
Flow visitAtomicCmpxchg(AtomicCmpxchg *curr) {
return Flow(NONSTANDALONE_FLOW);
}
+ Flow visitAtomicWait(AtomicWait *curr) {
+ return Flow(NONSTANDALONE_FLOW);
+ }
+ Flow visitAtomicWake(AtomicWake *curr) {
+ return Flow(NONSTANDALONE_FLOW);
+ }
Flow visitHost(Host *curr) {
return Flow(NONSTANDALONE_FLOW);
}
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 8bb5175ab..6d40034fc 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -352,7 +352,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
static void printRMWSize(std::ostream& o, WasmType type, uint8_t bytes) {
prepareColor(o) << printWasmType(type) << ".atomic.rmw";
- if (bytes != getWasmTypeSize(type)) {
+ if (type == unreachable) {
+ o << '?';
+ } else if (bytes != getWasmTypeSize(type)) {
if (bytes == 1) {
o << '8';
} else if (bytes == 2) {
diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp
index 784bc761d..9b4779ee0 100644
--- a/src/passes/SafeHeap.cpp
+++ b/src/passes/SafeHeap.cpp
@@ -25,6 +25,7 @@
#include "asm_v_wasm.h"
#include "asmjs/shared-constants.h"
#include "wasm-builder.h"
+#include "ast/bits.h"
#include "ast/import-utils.h"
namespace wasm {
@@ -229,7 +230,13 @@ struct SafeHeap : public Pass {
auto* load = module->allocator.alloc<Load>();
*load = style; // basically the same as the template we are given!
load->ptr = builder.makeGetLocal(2, i32);
- block->list.push_back(load);
+ Expression* last = load;
+ if (load->isAtomic && load->signed_) {
+ // atomic loads cannot be signed, manually sign it
+ last = Bits::makeSignExt(load, load->bytes, *module);
+ load->signed_ = false;
+ }
+ block->list.push_back(last);
block->finalize(style.type);
func->body = block;
module->addFunction(func);
diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h
index a316e6528..39b183d6e 100644
--- a/src/tools/translate-to-fuzz.h
+++ b/src/tools/translate-to-fuzz.h
@@ -101,6 +101,9 @@ private:
// cross-VM comparisons harder)
static const bool DE_NAN = true;
+ // Whether to emit atomics
+ static const bool ATOMICS = true;
+
// after we finish the input, we start going through it again, but xoring
// so it's not identical
int xorFactor = 0;
@@ -377,94 +380,36 @@ private:
nesting++;
Expression* ret;
switch (type) {
- case i32: ret = _makei32(); break;
- case i64: ret = _makei64(); break;
- case f32: ret = _makef32(); break;
- case f64: ret = _makef64(); break;
+ case i32:
+ case i64:
+ case f32:
+ case f64: ret = _makeConcrete(type); break;
case none: ret = _makenone(); break;
case unreachable: ret = _makeunreachable(); break;
default: WASM_UNREACHABLE();
}
+ assert(ret->type == type); // we should create the right type of thing
nesting--;
return ret;
}
- Expression* _makei32() {
- switch (upTo(14)) {
- case 0: return makeBlock(i32);
- case 1: return makeIf(i32);
- case 2: return makeLoop(i32);
- case 3: return makeBreak(i32);
- case 4: return makeCall(i32);
- case 5: return makeCallIndirect(i32);
- case 6: return makeGetLocal(i32);
- case 7: return makeSetLocal(i32);
- case 8: return makeLoad(i32);
- case 9: return makeConst(i32);
- case 10: return makeUnary(i32);
- case 11: return makeBinary(i32);
- case 12: return makeSelect(i32);
- case 13: return makeGetGlobal(i32);
- }
- WASM_UNREACHABLE();
- }
-
- Expression* _makei64() {
- switch (upTo(14)) {
- case 0: return makeBlock(i64);
- case 1: return makeIf(i64);
- case 2: return makeLoop(i64);
- case 3: return makeBreak(i64);
- case 4: return makeCall(i64);
- case 5: return makeCallIndirect(i64);
- case 6: return makeGetLocal(i64);
- case 7: return makeSetLocal(i64);
- case 8: return makeLoad(i64);
- case 9: return makeConst(i64);
- case 10: return makeUnary(i64);
- case 11: return makeBinary(i64);
- case 12: return makeSelect(i64);
- case 13: return makeGetGlobal(i64);
- }
- WASM_UNREACHABLE();
- }
-
- Expression* _makef32() {
- switch (upTo(14)) {
- case 0: return makeBlock(f32);
- case 1: return makeIf(f32);
- case 2: return makeLoop(f32);
- case 3: return makeBreak(f32);
- case 4: return makeCall(f32);
- case 5: return makeCallIndirect(f32);
- case 6: return makeGetLocal(f32);
- case 7: return makeSetLocal(f32);
- case 8: return makeLoad(f32);
- case 9: return makeConst(f32);
- case 10: return makeUnary(f32);
- case 11: return makeBinary(f32);
- case 12: return makeSelect(f32);
- case 13: return makeGetGlobal(f32);
- }
- WASM_UNREACHABLE();
- }
-
- Expression* _makef64() {
- switch (upTo(14)) {
- case 0: return makeBlock(f64);
- case 1: return makeIf(f64);
- case 2: return makeLoop(f64);
- case 3: return makeBreak(f64);
- case 4: return makeCall(f64);
- case 5: return makeCallIndirect(f64);
- case 6: return makeGetLocal(f64);
- case 7: return makeSetLocal(f64);
- case 8: return makeLoad(f64);
- case 9: return makeConst(f64);
- case 10: return makeUnary(f64);
- case 11: return makeBinary(f64);
- case 12: return makeSelect(f64);
- case 13: return makeGetGlobal(f64);
+ Expression* _makeConcrete(WasmType type) {
+ switch (upTo(15)) {
+ case 0: return makeBlock(type);
+ case 1: return makeIf(type);
+ case 2: return makeLoop(type);
+ case 3: return makeBreak(type);
+ case 4: return makeCall(type);
+ case 5: return makeCallIndirect(type);
+ case 6: return makeGetLocal(type);
+ case 7: return makeSetLocal(type);
+ case 8: return makeLoad(type);
+ case 9: return makeConst(type);
+ case 10: return makeUnary(type);
+ case 11: return makeBinary(type);
+ case 12: return makeSelect(type);
+ case 13: return makeGetGlobal(type);
+ case 14: return makeAtomic(type);
}
WASM_UNREACHABLE();
}
@@ -821,7 +766,7 @@ private:
return ret;
}
- Expression* makeLoad(WasmType type) {
+ Load* makeNonAtomicLoad(WasmType type) {
auto offset = logify(get());
auto ptr = makePointer();
switch (type) {
@@ -854,10 +799,22 @@ private:
}
}
- Store* makeStore(WasmType type) {
+ Expression* makeLoad(WasmType type) {
+ auto* ret = makeNonAtomicLoad(type);
+ if (type != i32 && type != i64) return ret;
+ if (!ATOMICS || oneIn(2)) return ret;
+ // make it atomic
+ wasm.memory.shared = true;
+ ret->isAtomic = true;
+ ret->signed_ = false;
+ ret->align = ret->bytes;
+ return ret;
+ }
+
+ Store* makeNonAtomicStore(WasmType type) {
if (type == unreachable) {
// make a normal store, then make it unreachable
- auto* ret = makeStore(getConcreteType());
+ auto* ret = makeNonAtomicStore(getConcreteType());
switch (upTo(3)) {
case 0: ret->ptr = make(unreachable); break;
case 1: ret->value = make(unreachable); break;
@@ -902,6 +859,17 @@ private:
}
}
+ Store* makeStore(WasmType type) {
+ auto* ret = makeNonAtomicStore(type);
+ if (ret->value->type != i32 && ret->value->type != i64) return ret;
+ if (!ATOMICS || oneIn(2)) return ret;
+ // make it atomic
+ wasm.memory.shared = true;
+ ret->isAtomic = true;
+ ret->align = ret->bytes;
+ return ret;
+ }
+
Expression* makeConst(WasmType type) {
Literal value;
switch (upTo(4)) {
@@ -1144,6 +1112,58 @@ private:
return builder.makeUnreachable();
}
+ Expression* makeAtomic(WasmType type) {
+ if (!ATOMICS || (type != i32 && type != i64)) return makeTrivial(type);
+ wasm.memory.shared = true;
+ if (type == i32 && oneIn(2)) {
+ if (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);
+ } else {
+ auto* ptr = makePointer();
+ auto* count = make(i32);
+ return builder.makeAtomicWake(ptr, count);
+ }
+ }
+ Index bytes;
+ switch (type) {
+ case i32: {
+ switch (upTo(3)) {
+ case 0: bytes = 1; break;
+ case 1: bytes = pick(1, 2); break;
+ case 2: bytes = pick(1, 2, 4); break;
+ default: WASM_UNREACHABLE();
+ }
+ break;
+ }
+ case i64: {
+ switch (upTo(4)) {
+ case 0: bytes = 1; break;
+ case 1: bytes = pick(1, 2); break;
+ case 2: bytes = pick(1, 2, 4); break;
+ case 3: bytes = pick(1, 2, 4, 8); break;
+ default: WASM_UNREACHABLE();
+ }
+ break;
+ }
+ default: WASM_UNREACHABLE();
+ }
+ auto offset = logify(get());
+ auto* ptr = makePointer();
+ if (oneIn(2)) {
+ auto* value = make(type);
+ return builder.makeAtomicRMW(pick(AtomicRMWOp::Add, AtomicRMWOp::Sub, AtomicRMWOp::And, AtomicRMWOp::Or, AtomicRMWOp::Xor, AtomicRMWOp::Xchg),
+ bytes, offset, ptr, value, type);
+ } else {
+ auto* expected = make(type);
+ auto* replacement = make(type);
+ return builder.makeAtomicCmpxchg(bytes, offset, ptr, expected, replacement, type);
+ }
+ }
+
// special getters
WasmType getType() {
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index bd756297e..e5ca79845 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -202,18 +202,17 @@ public:
ret->type = type;
return ret;
}
- Load* makeAtomicLoad(unsigned bytes, bool signed_, uint32_t offset, Expression* ptr, WasmType type) {
- Load* load = makeLoad(bytes, signed_, offset, bytes, ptr, type);
+ Load* makeAtomicLoad(unsigned bytes, uint32_t offset, Expression* ptr, WasmType type) {
+ Load* load = makeLoad(bytes, false, offset, bytes, ptr, type);
load->isAtomic = true;
return load;
}
- AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType type) {
+ AtomicWait* makeAtomicWait(Expression* ptr, Expression* expected, Expression* timeout, WasmType expectedType) {
auto* wait = allocator.alloc<AtomicWait>();
wait->ptr = ptr;
wait->expected = expected;
wait->timeout = timeout;
- wait->expectedType = type;
- wait->type = i32;
+ wait->expectedType = expectedType;
wait->finalize();
return wait;
}
@@ -221,7 +220,6 @@ public:
auto* wake = allocator.alloc<AtomicWake>();
wake->ptr = ptr;
wake->wakeCount = wakeCount;
- wake->type = i32;
wake->finalize();
return wake;
}
@@ -234,7 +232,7 @@ public:
return ret;
}
Store* makeAtomicStore(unsigned bytes, uint32_t offset, Expression* ptr, Expression* value, WasmType type) {
- Store* store = makeStore(bytes, offset, getWasmTypeSize(type), ptr, value, type);
+ Store* store = makeStore(bytes, offset, bytes, ptr, value, type);
store->isAtomic = true;
return store;
}
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 0b01fb1d3..b3fa3f265 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -32,6 +32,7 @@
#include "wasm.h"
#include "wasm-traversal.h"
+
#ifdef WASM_INTERPRETER_DEBUG
#include "wasm-printing.h"
#endif
@@ -118,7 +119,16 @@ template<typename SubType>
class ExpressionRunner : public Visitor<SubType, Flow> {
public:
Flow visit(Expression *curr) {
- return Visitor<SubType, Flow>::visit(curr);
+ auto ret = Visitor<SubType, Flow>::visit(curr);
+ if (!ret.breaking() && (isConcreteWasmType(curr->type) || isConcreteWasmType(ret.value.type))) {
+#if 1 // def WASM_INTERPRETER_DEBUG
+ if (ret.value.type != curr->type) {
+ std::cerr << "expected " << printWasmType(curr->type) << ", seeing " << printWasmType(ret.value.type) << " from\n" << curr << '\n';
+ }
+#endif
+ assert(ret.value.type == curr->type);
+ }
+ return ret;
}
Flow visitBlock(Block *curr) {
@@ -461,7 +471,7 @@ public:
Flow visitUnreachable(Unreachable *curr) {
NOTE_ENTER("Unreachable");
trap("unreachable");
- return Flow();
+ WASM_UNREACHABLE();
}
Literal truncSFloat(Unary* curr, Literal value) {
@@ -522,7 +532,9 @@ public:
Flow visitCallIndirect(CallIndirect* curr) { WASM_UNREACHABLE(); }
Flow visitGetLocal(GetLocal *curr) { WASM_UNREACHABLE(); }
Flow visitSetLocal(SetLocal *curr) { WASM_UNREACHABLE(); }
- Flow visitGetGlobal(GetGlobal *curr) { return Flow(globals[curr->name]); }
+ Flow visitGetGlobal(GetGlobal *curr) {
+ return Flow(globals[curr->name]);
+ }
Flow visitSetGlobal(SetGlobal *curr) { WASM_UNREACHABLE(); }
Flow visitLoad(Load *curr) { WASM_UNREACHABLE(); }
Flow visitStore(Store *curr) { WASM_UNREACHABLE(); }
@@ -563,7 +575,7 @@ public:
switch (load->bytes) {
case 1: return load->signed_ ? Literal((int32_t)load8s(addr)) : Literal((int32_t)load8u(addr));
case 2: return load->signed_ ? Literal((int32_t)load16s(addr)) : Literal((int32_t)load16u(addr));
- case 4: return load->signed_ ? Literal((int32_t)load32s(addr)) : Literal((int32_t)load32u(addr));
+ case 4: return Literal((int32_t)load32s(addr));
default: WASM_UNREACHABLE();
}
break;
@@ -573,7 +585,7 @@ public:
case 1: return load->signed_ ? Literal((int64_t)load8s(addr)) : Literal((int64_t)load8u(addr));
case 2: return load->signed_ ? Literal((int64_t)load16s(addr)) : Literal((int64_t)load16u(addr));
case 4: return load->signed_ ? Literal((int64_t)load32s(addr)) : Literal((int64_t)load32u(addr));
- case 8: return load->signed_ ? Literal((int64_t)load64s(addr)) : Literal((int64_t)load64u(addr));
+ case 8: return Literal((int64_t)load64s(addr));
default: WASM_UNREACHABLE();
}
break;
@@ -810,8 +822,8 @@ public:
NOTE_ENTER("GetGlobal");
auto name = curr->name;
NOTE_EVAL1(name);
- NOTE_EVAL1(instance.globals[name]);
assert(instance.globals.find(name) != instance.globals.end());
+ NOTE_EVAL1(instance.globals[name]);
return instance.globals[name];
}
Flow visitSetGlobal(SetGlobal *curr) {
@@ -849,6 +861,85 @@ public:
return Flow();
}
+ Flow visitAtomicRMW(AtomicRMW *curr) {
+ NOTE_ENTER("AtomicRMW");
+ Flow ptr = this->visit(curr->ptr);
+ if (ptr.breaking()) return ptr;
+ auto value = this->visit(curr->value);
+ if (value.breaking()) return value;
+ NOTE_EVAL1(ptr);
+ auto addr = instance.getFinalAddress(curr, ptr.value);
+ NOTE_EVAL1(addr);
+ NOTE_EVAL1(value);
+ auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type);
+ NOTE_EVAL1(loaded);
+ auto computed = value.value;
+ switch (curr->op) {
+ case Add: computed = computed.add(value.value); break;
+ case Sub: computed = computed.sub(value.value); break;
+ case And: computed = computed.and_(value.value); break;
+ case Or: computed = computed.or_(value.value); break;
+ case Xor: computed = computed.xor_(value.value); break;
+ case Xchg: computed = value.value; break;
+ default: WASM_UNREACHABLE();
+ }
+ instance.doAtomicStore(addr, curr->bytes, computed);
+ return loaded;
+ }
+ Flow visitAtomicCmpxchg(AtomicCmpxchg *curr) {
+ NOTE_ENTER("AtomicCmpxchg");
+ Flow ptr = this->visit(curr->ptr);
+ if (ptr.breaking()) return ptr;
+ NOTE_EVAL1(ptr);
+ auto expected = this->visit(curr->expected);
+ if (expected.breaking()) return expected;
+ auto replacement = this->visit(curr->replacement);
+ if (replacement.breaking()) return replacement;
+ auto addr = instance.getFinalAddress(curr, ptr.value);
+ NOTE_EVAL1(addr);
+ NOTE_EVAL1(expected);
+ NOTE_EVAL1(replacement);
+ auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type);
+ NOTE_EVAL1(loaded);
+ if (loaded == expected.value) {
+ instance.doAtomicStore(addr, curr->bytes, replacement.value);
+ }
+ return loaded;
+ }
+ Flow visitAtomicWait(AtomicWait *curr) {
+ NOTE_ENTER("AtomicWait");
+ Flow ptr = this->visit(curr->ptr);
+ if (ptr.breaking()) return ptr;
+ NOTE_EVAL1(ptr);
+ auto expected = this->visit(curr->expected);
+ NOTE_EVAL1(expected);
+ if (expected.breaking()) return expected;
+ auto timeout = this->visit(curr->timeout);
+ NOTE_EVAL1(timeout);
+ if (timeout.breaking()) return timeout;
+ auto bytes = getWasmTypeSize(curr->expectedType);
+ auto addr = instance.getFinalAddress(ptr.value, bytes);
+ auto loaded = instance.doAtomicLoad(addr, bytes, curr->expectedType);
+ NOTE_EVAL1(loaded);
+ if (loaded != expected.value) {
+ return Literal(int32_t(1)); // not equal
+ }
+ // TODO: add threads support!
+ // for now, just assume we are woken up
+ return Literal(int32_t(0)); // woken up
+ }
+ Flow visitAtomicWake(AtomicWake *curr) {
+ NOTE_ENTER("AtomicWake");
+ Flow ptr = this->visit(curr->ptr);
+ if (ptr.breaking()) return ptr;
+ NOTE_EVAL1(ptr);
+ auto count = this->visit(curr->wakeCount);
+ NOTE_EVAL1(count);
+ if (count.breaking()) return count;
+ // TODO: add threads support!
+ return Literal(int32_t(0)); // none woken up
+ }
+
Flow visitHost(Host *curr) {
NOTE_ENTER("Host");
switch (curr->op) {
@@ -922,25 +1013,70 @@ protected:
Address memorySize; // in pages
+ void trapIfGt(uint64_t lhs, uint64_t rhs, const char* msg) {
+ if (lhs > rhs) {
+ std::stringstream ss;
+ ss << msg << ": " << lhs << " > " << rhs;
+ externalInterface->trap(ss.str().c_str());
+ }
+ }
+
template <class LS>
Address getFinalAddress(LS* curr, Literal ptr) {
- auto trapIfGt = [this](uint64_t lhs, uint64_t rhs, const char* msg) {
- if (lhs > rhs) {
- std::stringstream ss;
- ss << msg << ": " << lhs << " > " << rhs;
- externalInterface->trap(ss.str().c_str());
- }
- };
Address memorySizeBytes = memorySize * Memory::kPageSize;
uint64_t addr = ptr.type == i32 ? ptr.geti32() : ptr.geti64();
trapIfGt(curr->offset, memorySizeBytes, "offset > memory");
trapIfGt(addr, memorySizeBytes - curr->offset, "final > memory");
addr += curr->offset;
trapIfGt(curr->bytes, memorySizeBytes, "bytes > memory");
- trapIfGt(addr, memorySizeBytes - curr->bytes, "highest > memory");
+ checkLoadAddress(addr, curr->bytes);
return addr;
}
+ Address getFinalAddress(Literal ptr, Index bytes) {
+ Address memorySizeBytes = memorySize * Memory::kPageSize;
+ uint64_t addr = ptr.type == i32 ? ptr.geti32() : ptr.geti64();
+ trapIfGt(addr, memorySizeBytes - bytes, "highest > memory");
+ return addr;
+ }
+
+ void checkLoadAddress(Address addr, Index bytes) {
+ Address memorySizeBytes = memorySize * Memory::kPageSize;
+ trapIfGt(addr, memorySizeBytes - bytes, "highest > memory");
+ }
+
+ Literal doAtomicLoad(Address addr, Index bytes, WasmType type) {
+ checkLoadAddress(addr, bytes);
+ Const ptr;
+ ptr.value = Literal(int32_t(addr));
+ ptr.type = i32;
+ Load load;
+ load.bytes = bytes;
+ load.signed_ = true;
+ load.align = bytes;
+ load.isAtomic = true; // understatement
+ load.ptr = &ptr;
+ load.type = type;
+ return externalInterface->load(&load, addr);
+ }
+
+ void doAtomicStore(Address addr, Index bytes, Literal toStore) {
+ Const ptr;
+ ptr.value = Literal(int32_t(addr));
+ ptr.type = i32;
+ Const value;
+ value.value = toStore;
+ value.type = toStore.type;
+ Store store;
+ store.bytes = bytes;
+ store.align = bytes;
+ store.isAtomic = true; // understatement
+ store.ptr = &ptr;
+ store.value = &value;
+ store.valueType = value.type;
+ return externalInterface->store(&store, addr, toStore);
+ }
+
ExternalInterface* externalInterface;
};
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index ceb230f73..f98eff670 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -791,6 +791,11 @@ void WasmBinaryWriter::visitLoad(Load *curr) {
default: WASM_UNREACHABLE();
}
} else {
+ if (curr->type == unreachable) {
+ // don't even emit it; we don't know the right type
+ o << int8_t(BinaryConsts::Unreachable);
+ return;
+ }
o << int8_t(BinaryConsts::AtomicPrefix);
switch (curr->type) {
case i32: {
@@ -849,6 +854,11 @@ void WasmBinaryWriter::visitStore(Store *curr) {
default: abort();
}
} else {
+ if (curr->type == unreachable) {
+ // don't even emit it; we don't know the right type
+ o << int8_t(BinaryConsts::Unreachable);
+ return;
+ }
o << int8_t(BinaryConsts::AtomicPrefix);
switch (curr->valueType) {
case i32: {
@@ -881,6 +891,12 @@ void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) {
recurse(curr->ptr);
recurse(curr->value);
+ if (curr->type == unreachable) {
+ // don't even emit it; we don't know the right type
+ o << int8_t(BinaryConsts::Unreachable);
+ return;
+ }
+
o << int8_t(BinaryConsts::AtomicPrefix);
#define CASE_FOR_OP(Op) \
@@ -927,6 +943,12 @@ void WasmBinaryWriter::visitAtomicCmpxchg(AtomicCmpxchg *curr) {
recurse(curr->expected);
recurse(curr->replacement);
+ if (curr->type == unreachable) {
+ // don't even emit it; we don't know the right type
+ o << int8_t(BinaryConsts::Unreachable);
+ return;
+ }
+
o << int8_t(BinaryConsts::AtomicPrefix);
switch (curr->type) {
case i32:
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 6d75296a4..5120eea7a 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -487,6 +487,7 @@ void FunctionValidator::visitLoad(Load *curr) {
validateMemBytes(curr->bytes, curr->type, curr);
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "load pointer type must be i32");
+ if (curr->isAtomic) shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned");
}
void FunctionValidator::visitStore(Store *curr) {
@@ -502,7 +503,7 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32");
- shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->type, curr, "AtomicRMW result type must match operand");
+ shouldBeEqualOrFirstIsUnreachable(curr->type, curr->value->type, curr, "AtomicRMW result type must match operand");
shouldBeIntOrUnreachable(curr->type, curr, "Atomic operations are only valid on int types");
}
@@ -513,8 +514,8 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
if (curr->expected->type != unreachable && curr->replacement->type != unreachable) {
shouldBeEqual(curr->expected->type, curr->replacement->type, curr, "cmpxchg operand types must match");
}
- shouldBeEqualOrFirstIsUnreachable(curr->expected->type, curr->type, curr, "Cmpxchg result type must match expected");
- shouldBeEqualOrFirstIsUnreachable(curr->replacement->type, curr->type, curr, "Cmpxchg result type must match replacement");
+ shouldBeEqualOrFirstIsUnreachable(curr->type, curr->expected->type, curr, "Cmpxchg result type must match expected");
+ shouldBeEqualOrFirstIsUnreachable(curr->type, curr->replacement->type, curr, "Cmpxchg result type must match replacement");
shouldBeIntOrUnreachable(curr->expected->type, curr, "Atomic operations are only valid on int types");
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index f4562fe64..6441991c9 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -390,12 +390,14 @@ void AtomicCmpxchg::finalize() {
}
void AtomicWait::finalize() {
+ type = i32;
if (ptr->type == unreachable || expected->type == unreachable || timeout->type == unreachable) {
type = unreachable;
}
}
void AtomicWake::finalize() {
+ type = i32;
if (ptr->type == unreachable || wakeCount->type == unreachable) {
type = unreachable;
}
diff --git a/test/passes/inlining-optimizing.txt b/test/passes/inlining-optimizing.txt
index 19c580063..8079d818a 100644
--- a/test/passes/inlining-optimizing.txt
+++ b/test/passes/inlining-optimizing.txt
@@ -41,3 +41,15 @@
(unreachable)
)
)
+(module
+ (type $0 (func (result i32)))
+ (type $1 (func (result i64)))
+ (memory $0 (shared 1 1))
+ (func $1 (type $1) (result i64)
+ (i32.atomic.store16
+ (i32.const 0)
+ (i32.const 0)
+ )
+ (i64.const 0)
+ )
+)
diff --git a/test/passes/inlining-optimizing.wast b/test/passes/inlining-optimizing.wast
index 4f4f348a6..aac4706fe 100644
--- a/test/passes/inlining-optimizing.wast
+++ b/test/passes/inlining-optimizing.wast
@@ -85,4 +85,19 @@
(unreachable) ;; void function but having unreachable body, when inlined, type must be fixed
)
)
-
+(module
+ (memory $0 (shared 1 1))
+ (func $0 (result i32)
+ (i32.atomic.store16
+ (i32.const 0)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ )
+ (func $1 (result i64)
+ (drop
+ (call $0)
+ )
+ (i64.const 0)
+ )
+)
diff --git a/test/passes/safe-heap.txt b/test/passes/safe-heap.txt
index f34dd7455..144766f1f 100644
--- a/test/passes/safe-heap.txt
+++ b/test/passes/safe-heap.txt
@@ -189,8 +189,14 @@
)
(call $segfault)
)
- (i32.atomic.load8_s
- (get_local $2)
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load8_u
+ (get_local $2)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
)
)
(func $SAFE_HEAP_LOAD_i32_1_1 (param $0 i32) (param $1 i32) (result i32)
@@ -346,8 +352,14 @@
)
(call $alignfault)
)
- (i32.atomic.load16_s
- (get_local $2)
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load16_u
+ (get_local $2)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
)
)
(func $SAFE_HEAP_LOAD_i32_2_2 (param $0 i32) (param $1 i32) (result i32)
@@ -799,8 +811,14 @@
)
(call $segfault)
)
- (i64.atomic.load8_s
- (get_local $2)
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load8_u
+ (get_local $2)
+ )
+ (i64.const 56)
+ )
+ (i64.const 56)
)
)
(func $SAFE_HEAP_LOAD_i64_1_1 (param $0 i32) (param $1 i32) (result i64)
@@ -956,8 +974,14 @@
)
(call $alignfault)
)
- (i64.atomic.load16_s
- (get_local $2)
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load16_u
+ (get_local $2)
+ )
+ (i64.const 48)
+ )
+ (i64.const 48)
)
)
(func $SAFE_HEAP_LOAD_i64_2_2 (param $0 i32) (param $1 i32) (result i64)
@@ -1201,8 +1225,14 @@
)
(call $alignfault)
)
- (i64.atomic.load32_s
- (get_local $2)
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load32_u
+ (get_local $2)
+ )
+ (i64.const 32)
+ )
+ (i64.const 32)
)
)
(func $SAFE_HEAP_LOAD_i64_4_4 (param $0 i32) (param $1 i32) (result i64)
diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt
index fca9307df..f088010f7 100644
--- a/test/passes/translate-to-fuzz.txt
+++ b/test/passes/translate-to-fuzz.txt
@@ -1,17 +1,17 @@
(module
(type $FUNCSIG$ifi (func (param f32 i32) (result i32)))
- (type $FUNCSIG$i (func (result i32)))
- (type $FUNCSIG$j (func (result i64)))
+ (type $FUNCSIG$dj (func (param i64) (result f64)))
+ (type $FUNCSIG$f (func (result f32)))
(global $global$0 (mut f64) (f64.const 138413376))
(global $global$1 (mut f64) (f64.const 1.1754943508222875e-38))
(global $hangLimit (mut i32) (i32.const 100))
- (table 1 anyfunc)
- (elem (i32.const 0) $func_3)
- (memory $0 1 1)
+ (table 2 anyfunc)
+ (elem (i32.const 0) $func_0 $func_5)
+ (memory $0 (shared 1 1))
(data (i32.const 0) "\00C\00[\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(export "func_0" (func $func_0))
(export "func_3" (func $func_3))
- (export "func_4" (func $func_4))
+ (export "func_5" (func $func_5))
(export "hangLimitInitializer" (func $hangLimitInitializer))
(func $func_0 (type $FUNCSIG$ifi) (param $0 f32) (param $1 i32) (result i32)
(block
@@ -20,7 +20,7 @@
(get_global $hangLimit)
)
(return
- (i32.const -2147483648)
+ (get_local $1)
)
)
(set_global $hangLimit
@@ -30,15 +30,141 @@
)
)
)
- (get_local $1)
+ (tee_local $1
+ (i32.eqz
+ (if (result i32)
+ (i32.eqz
+ (f64.le
+ (f64.const -2147483648)
+ (f64.const 8)
+ )
+ )
+ (i32.or
+ (i32.div_s
+ (if (result i32)
+ (i32.eqz
+ (loop $label$0 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (i32.const 24332)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result i32)
+ (loop $label$1
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (get_local $1)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (nop)
+ )
+ (br_if $label$0
+ (i32.eqz
+ (get_local $1)
+ )
+ )
+ (loop $label$3 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (get_local $1)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (i32.trunc_s/f64
+ (f64.const -9223372036854775808)
+ )
+ )
+ )
+ )
+ )
+ (block $label$4 (result i32)
+ (i32.load8_u offset=3
+ (i32.and
+ (br_if $label$4
+ (i32.const -44)
+ (i32.const 437327895)
+ )
+ (i32.const 31)
+ )
+ )
+ )
+ (block $label$5 (result i32)
+ (nop)
+ (return
+ (i32.const 84)
+ )
+ )
+ )
+ (block $label$6 (result i32)
+ (block $label$7
+ (block $label$8
+ (nop)
+ (nop)
+ )
+ (br_if $label$7
+ (i32.eqz
+ (get_local $1)
+ )
+ )
+ )
+ (get_local $1)
+ )
+ )
+ (i32.const 1048576)
+ )
+ (get_local $1)
+ )
+ )
+ )
)
- (func $func_1
+ (func $func_1 (result f64)
+ (local $0 i64)
+ (local $1 f32)
+ (local $2 i32)
+ (local $3 i64)
+ (local $4 f32)
+ (local $5 i32)
+ (local $6 f32)
(block
(if
(i32.eqz
(get_global $hangLimit)
)
- (return)
+ (return
+ (f64.const 61)
+ )
)
(set_global $hangLimit
(i32.sub
@@ -47,40 +173,15 @@
)
)
)
- (loop $label$0
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return)
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$1
- (nop)
- (nop)
- )
- )
+ (get_global $global$1)
)
- (func $func_2 (param $0 f32) (result f64)
- (local $1 f32)
- (local $2 i32)
- (local $3 i32)
- (local $4 i32)
+ (func $func_2
(block
(if
(i32.eqz
(get_global $hangLimit)
)
- (return
- (f64.const 26471)
- )
+ (return)
)
(set_global $hangLimit
(i32.sub
@@ -89,157 +190,93 @@
)
)
)
- (call $deNan64
- (f64.mul
- (f64.const 1)
- (if (result f64)
- (select
- (block $label$10 (result i32)
- (if
- (i32.eqz
- (tee_local $2
- (i32.const -2147483648)
+ (block $label$0
+ (set_global $global$0
+ (loop $label$1 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return)
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block $label$2 (result f64)
+ (loop $label$3 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
)
+ (return)
)
- (drop
- (i32.const -131072)
- )
- (block $label$11
- (br_if $label$11
- (tee_local $4
- (i32.const -128)
- )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
)
- (call $func_1)
)
)
- (return
- (f64.const 4)
- )
- )
- (tee_local $2
- (tee_local $3
- (get_local $3)
- )
- )
- (i32.load16_u offset=4
- (i32.and
- (i32.load offset=4 align=1
- (i32.and
- (loop $label$0 (result i32)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (f64.const -nan:0xfffffffffffb5)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
+ (block $label$4 (result f64)
+ (loop $label$5
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
)
- (block $label$1 (result i32)
- (block $label$2
- (nop)
- (call $func_1)
- )
- (select
- (if (result i32)
- (get_local $3)
- (block $label$3 (result i32)
- (block $label$4
- (set_local $2
- (get_local $3)
- )
- (set_local $0
- (get_local $1)
- )
+ (return)
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (nop)
+ )
+ (call $deNan64
+ (f64.reinterpret/i64
+ (i64.extend_u/i32
+ (block $label$6 (result i32)
+ (loop $label$7
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
)
- (br $label$0)
+ (return)
)
- (if (result i32)
- (i32.eqz
- (get_local $3)
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
)
- (i32.const -123)
- (get_local $4)
)
)
- (tee_local $2
- (if (result i32)
- (i32.eqz
- (call $func_0
- (get_local $1)
- (i32.const 0)
- )
- )
- (block $label$5 (result i32)
- (loop $label$6
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (f64.const -33554432)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block
- (i64.store offset=4 align=1
- (i32.and
- (get_local $4)
- (i32.const 31)
- )
- (i64.const -1)
- )
- (br_if $label$6
- (get_local $2)
- )
- (f32.store offset=4
- (i32.and
- (i32.const -256)
- (i32.const 31)
- )
- (f32.const 2147483648)
- )
- )
- )
- (i32.load8_s offset=4
- (i32.and
- (i32.load16_u offset=3 align=1
- (i32.and
- (get_local $2)
- (i32.const 31)
- )
- )
- (i32.const 31)
- )
+ (block $label$8
+ (nop)
+ (block $label$9
+ (br_if $label$3
+ (i32.eqz
+ (i32.const 185342814)
)
)
- (block $label$7 (result i32)
- (block $label$8
- (nop)
- (loop $label$9
+ (i32.store offset=3 align=2
+ (i32.and
+ (loop $label$10 (result i32)
(block
(if
(i32.eqz
(get_global $hangLimit)
)
- (return
- (f64.const -8192)
- )
+ (return)
)
(set_global $hangLimit
(i32.sub
@@ -248,66 +285,52 @@
)
)
)
- (set_local $2
- (br_if $label$7
- (tee_local $4
- (if (result i32)
- (i32.eqz
- (get_local $4)
- )
- (get_local $2)
- (i32.const 1514756685)
- )
- )
- (i32.eqz
- (i32.load offset=2
- (i32.and
- (i32.const 514)
- (i32.const 31)
- )
+ (block (result i32)
+ (nop)
+ (br_if $label$10
+ (i32.const 1195902538)
+ )
+ (call $func_0
+ (call $deNan32
+ (f32.convert_u/i64
+ (i64.const 2251799813685248)
)
)
+ (i32.const 336464134)
)
)
)
+ (i32.const 31)
)
- (br $label$0)
+ (i32.const 27)
)
)
)
- (i32.const 2147483647)
+ )
+ (i32.reinterpret/f32
+ (f32.const 19533)
)
)
)
- (i32.const 31)
)
)
- (i32.const 31)
)
)
)
- (get_global $global$1)
- (block $label$12 (result f64)
- (call $func_1)
- (return
- (f64.const -140737488355328)
- )
- )
)
)
+ (nop)
)
)
- (func $func_3 (type $FUNCSIG$i) (result i32)
- (local $0 i32)
+ (func $func_3 (type $FUNCSIG$dj) (param $0 i64) (result f64)
(local $1 i64)
- (local $2 f64)
(block
(if
(i32.eqz
(get_global $hangLimit)
)
(return
- (get_local $0)
+ (f64.const -nan:0xffffffffffff9)
)
)
(set_global $hangLimit
@@ -317,171 +340,186 @@
)
)
)
- (block $label$0 (result i32)
+ (block $label$0 (result f64)
(nop)
- (return
- (i32.const -4194304)
- )
- )
- )
- (func $func_4 (type $FUNCSIG$j) (result i64)
- (local $0 i64)
- (local $1 f32)
- (local $2 i64)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (i64.const 68719476736)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0
- (i64.store32 offset=4 align=2
- (i32.and
- (if (result i32)
- (i32.eqz
- (block $label$1 (result i32)
+ (block $label$1
+ (drop
+ (i64.shr_s
+ (loop $label$2 (result i64)
+ (block
(if
(i32.eqz
- (loop $label$2 (result i32)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (i64.const 512)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
+ (get_global $hangLimit)
+ )
+ (return
+ (f64.const 9150713448007298)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block $label$3 (result i64)
+ (f64.store offset=2 align=4
+ (i32.and
+ (i32.const 127)
+ (i32.const 31)
+ )
+ (f64.load offset=3
+ (i32.and
+ (i32.const -16777216)
+ (i32.const 31)
+ )
+ )
+ )
+ (i64.popcnt
+ (block $label$4 (result i64)
+ (br_if $label$1
+ (i32.load offset=1 align=1
+ (i32.and
+ (f64.gt
+ (br_if $label$0
+ (f64.const 7)
+ (i32.eqz
+ (call_indirect $FUNCSIG$ifi
+ (f32.const 2147483648)
+ (i32.const -28)
+ (i32.const 0)
+ )
+ )
+ )
+ (call $func_1)
)
- )
- )
- (block $label$3 (result i32)
- (return
- (get_local $2)
+ (i32.const 31)
)
)
)
- )
- (block $label$4
- (block $label$5
- (set_local $2
- (loop $label$6 (result i64)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
+ (br_if $label$4
+ (if (result i64)
+ (i32.const 825692018)
+ (block $label$8 (result i64)
+ (loop $label$9
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f64.const -nan:0xffffffffffff9)
+ )
)
- (return
- (get_local $0)
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
)
)
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
+ (block $label$10
+ (nop)
+ (nop)
)
)
- (block (result i64)
- (block $label$7
- (drop
- (get_local $1)
+ (i64.load8_u
+ (block $label$11 (result i32)
+ (nop)
+ (i32.const -2)
+ )
+ )
+ )
+ (i64.shl
+ (if (result i64)
+ (f64.ge
+ (f64.const 4294967200)
+ (loop $label$12 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f64.const 16471262202863238)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (f64.const 1812599913)
)
- (br_if $label$5
- (i32.eqz
- (i32.const 1393493003)
+ )
+ (block $label$13 (result i64)
+ (i32.atomic.store8 offset=3
+ (i32.and
+ (i32.const 1026760786)
+ (i32.const 31)
)
+ (i32.const -32769)
)
+ (br $label$1)
)
- (br_if $label$6
- (i32.eqz
- (br_if $label$1
- (i32.const 32766)
- (i32.eqz
- (i32.const -73)
+ (block $label$14 (result i64)
+ (if
+ (i32.const 185339652)
+ (set_local $0
+ (select
+ (get_local $1)
+ (i64.const 9223372036854775807)
+ (if (result i32)
+ (i32.const 0)
+ (i32.const -21)
+ (i32.const 39)
+ )
)
)
+ (nop)
)
+ (br $label$1)
)
- (get_local $0)
)
- )
- )
- (call $func_1)
- )
- (block $label$8
- (drop
- (loop $label$9 (result f64)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (get_local $2)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
+ (i64.div_u
+ (i64.ctz
+ (select
+ (get_local $0)
+ (i64.const 29041)
+ (select
+ (i32.const 256)
+ (i32.const 65535)
+ (call $func_0
+ (f32.const 1.7485578309992735e-21)
+ (i32.const 134217728)
+ )
+ )
)
)
+ (i64.const -131072)
)
- (f64.const 30079)
)
)
- )
- )
- (nop)
- )
- (call_indirect $FUNCSIG$i
- (i32.const 0)
- )
- )
- )
- (block $label$10 (result i32)
- (i32.store8 offset=22
- (i32.and
- (if (result i32)
- (i32.eqz
- (select
- (i32.const 6)
- (if (result i32)
- (i32.const 4103)
- (block $label$12 (result i32)
- (drop
- (i64.ctz
- (i64.const 17)
- )
+ (i32.atomic.load16_u offset=22
+ (i32.and
+ (if (result i32)
+ (i32.eqz
+ (i32.const 268435456)
)
- (return
- (i64.const 18505)
+ (block $label$5 (result i32)
+ (nop)
+ (br $label$1)
)
- )
- (f32.ne
- (loop $label$13 (result f32)
+ (loop $label$6 (result i32)
(block
(if
(i32.eqz
(get_global $hangLimit)
)
(return
- (i64.const 17728)
+ (f64.const 9030)
)
)
(set_global $hangLimit
@@ -491,110 +529,15 @@
)
)
)
- (block (result f32)
- (block $label$14
- (block $label$15
- (nop)
- (nop)
- )
- (if
- (i32.eqz
- (br_if $label$10
- (if (result i32)
- (if (result i32)
- (i32.const -65536)
- (i32.const -32768)
- (call_indirect $FUNCSIG$i
- (i32.const 0)
- )
- )
- (i32.const 454301983)
- (i32.const 18460)
- )
- (i32.const -64)
- )
- )
- (block $label$16
- (if
- (i32.const 1014178876)
- (if
- (i32.eqz
- (i32.const -116)
- )
- (nop)
- (i32.store16 offset=2 align=1
- (i32.and
- (i32.const -16)
- (i32.const 31)
- )
- (i32.load16_s offset=3
- (i32.and
- (block $label$17 (result i32)
- (nop)
- (i32.const 23528569)
- )
- (i32.const 31)
- )
- )
- )
- )
- (nop)
- )
- (br_if $label$16
- (i32.eqz
- (block $label$18 (result i32)
- (nop)
- (i32.const -93)
- )
- )
- )
- )
- (br_if $label$13
- (i32.eqz
- (i32.const 512)
- )
- )
- )
- )
- (br_if $label$13
- (i32.eqz
- (br_if $label$10
- (call $func_0
- (call $deNan32
- (f32.convert_u/i64
- (if (result i64)
- (i32.eqz
- (i32.const 8388608)
- )
- (get_local $0)
- (get_local $0)
- )
- )
- )
- (if (result i32)
- (i32.const 4)
- (i32.const 1196969301)
- (select
- (i32.const 64)
- (i32.trunc_s/f32
- (get_local $1)
- )
- (i32.const -2)
- )
- )
- )
- (i32.const -1048576)
- )
- )
- )
- (loop $label$19 (result f32)
+ (block (result i32)
+ (loop $label$7
(block
(if
(i32.eqz
(get_global $hangLimit)
)
(return
- (i64.const 357908754)
+ (f64.const 1797693134862315708145274e284)
)
)
(set_global $hangLimit
@@ -604,261 +547,232 @@
)
)
)
- (block $label$20 (result f32)
- (nop)
- (br $label$19)
- )
- )
- )
- )
- (call $deNan32
- (f32.floor
- (loop $label$21 (result f32)
(block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (get_local $0)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
+ (nop)
+ (br_if $label$7
+ (i32.const 0)
)
+ (nop)
)
- (loop $label$22 (result f32)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (get_local $0)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block (result f32)
- (br_if $label$21
- (i32.eqz
- (if (result i32)
- (i32.eqz
- (i32.const -4194304)
- )
- (i32.const 9537)
- (i32.const -262144)
- )
- )
- )
- (br_if $label$22
- (call $func_3)
- )
- (tee_local $1
- (get_local $1)
- )
- )
+ )
+ (br_if $label$6
+ (call $func_0
+ (f32.const 82)
+ (i32.const 770)
)
)
+ (call_indirect $FUNCSIG$ifi
+ (f32.const 1.1754943508222875e-38)
+ (i32.const -1)
+ (i32.const 0)
+ )
)
)
)
+ (i32.const 31)
)
+ )
+ )
+ )
+ )
+ )
+ )
+ (i64.const -1)
+ )
+ )
+ (f32.store offset=22
+ (i32.and
+ (i32.const 2147483647)
+ (i32.const 31)
+ )
+ (f32.const -1)
+ )
+ )
+ (return
+ (f64.const 18446744073709551615)
+ )
+ )
+ )
+ (func $func_4 (result f32)
+ (local $0 f32)
+ (local $1 i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f32.const -9223372036854775808)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block $label$0 (result f32)
+ (return
+ (f32.const -1048576)
+ )
+ )
+ )
+ (func $func_5 (type $FUNCSIG$f) (result f32)
+ (local $0 f32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 f64)
+ (local $4 i64)
+ (local $5 i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (get_local $0)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (call $deNan32
+ (f32.convert_s/i64
+ (if (result i64)
+ (loop $label$0 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f32.const 28726)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (i32.const -76)
+ )
+ (block $label$1 (result i64)
+ (nop)
+ (block $label$2 (result i64)
+ (drop
+ (if (result f32)
+ (i32.const -64)
+ (get_local $0)
+ (block $label$5 (result f32)
+ (drop
+ (get_local $2)
+ )
+ (return
+ (f32.const 1.9604099208437475e-30)
+ )
+ )
+ )
+ )
+ (return
+ (get_local $0)
+ )
+ )
+ )
+ (block $label$6 (result i64)
+ (set_local $3
+ (call $deNan64
+ (f64.copysign
+ (get_global $global$1)
+ (block $label$7 (result f64)
+ (block $label$8
+ (br_if $label$8
(i32.load offset=4 align=2
(i32.and
- (select
- (call $func_3)
- (i32.const 1)
- (call $func_0
- (call $deNan32
+ (i32.load16_u offset=4
+ (i32.and
+ (select
+ (get_local $1)
(select
- (tee_local $1
- (f32.const 9223372036854775808)
- )
- (f32.const -1)
- (if (result i32)
- (i32.eqz
- (i32.const 404363289)
- )
- (i32.const 32767)
- (block $label$11 (result i32)
- (nop)
- (i64.eqz
- (i64.popcnt
- (get_local $0)
- )
- )
+ (call $func_0
+ (get_local $0)
+ (select
+ (i32.const 65535)
+ (get_local $1)
+ (i32.const 1999974947)
)
)
+ (i32.const 64)
+ (get_local $5)
)
+ (get_local $2)
)
- (i32.const 4)
+ (i32.const 31)
)
)
(i32.const 31)
)
)
)
- )
- (if (result i32)
- (call_indirect $FUNCSIG$i
- (i32.const 0)
- )
- (block $label$23 (result i32)
- (return
- (i64.const -2)
- )
- )
- (block $label$24 (result i32)
- (i32.store16 offset=22 align=1
- (i32.and
- (i32.load16_s offset=4 align=1
- (i32.and
- (i32.const 125568104)
- (i32.const 31)
- )
+ (loop $label$9
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (get_local $0)
)
- (i32.const 31)
)
- (call $func_3)
- )
- (i32.load16_s offset=3 align=1
- (i32.and
- (call $func_0
- (f32.const 0)
- (i32.load16_u offset=4
- (i32.and
- (if (result i32)
- (call_indirect $FUNCSIG$i
- (i32.const 0)
- )
- (select
- (select
- (i32.const 1734962792)
- (i32.const -4096)
- (i32.const 218824716)
- )
- (i32.const -1073741824)
- (i32.const 40)
- )
- (block $label$25 (result i32)
- (block $label$26
- (nop)
- (block $label$27
- (nop)
- (f64.store offset=4 align=4
- (call $func_0
- (f32.const 9223372036854775808)
- (f32.eq
- (f32.const 18446744073709551615)
- (f32.load offset=4
- (i32.and
- (i32.const 524288)
- (i32.const 31)
- )
- )
- )
- )
- (f64.const -1099511627776)
- )
- )
- )
- (i32.const 128)
- )
- )
- (i32.const 31)
- )
- )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
)
- (i32.const 31)
)
)
- )
- )
- (i32.const 335937919)
- )
- (i32.const 31)
- )
- (if (result i32)
- (i32.eqz
- (call $func_3)
- )
- (block $label$28 (result i32)
- (block $label$29
- (if
- (i32.eqz
- (block $label$30 (result i32)
- (nop)
- (call_indirect $FUNCSIG$i
+ (block $label$10
+ (drop
+ (call_indirect $FUNCSIG$ifi
+ (f32.const 2097640320)
+ (i32.eqz
+ (select
+ (i32.const -128)
+ (get_local $2)
+ (get_local $2)
+ )
+ )
(i32.const 0)
)
)
- )
- (block $label$31
- (nop)
- (nop)
- )
- (block $label$32
- (nop)
- )
- )
- (drop
- (i64.div_s
- (block $label$33 (result i64)
- (call $func_1)
- (i64.const -94)
- )
- (tee_local $2
- (loop $label$34 (result i64)
- (block
+ (if
+ (tee_local $2
+ (get_local $2)
+ )
+ (block $label$11
+ (nop)
+ (call $func_2)
+ )
+ (block $label$12
+ (block $label$13
+ (nop)
(if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (get_local $2)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block (result i64)
- (block $label$35
+ (i32.const 1936882040)
(nop)
- (f64.store offset=4 align=2
- (i32.and
- (i32.const 127)
- (i32.const 31)
- )
- (f64.const -2251799813685248)
- )
- )
- (br_if $label$34
- (i32.const 471406943)
- )
- (select
- (get_local $0)
- (get_local $0)
- (loop $label$36 (result i32)
+ (loop $label$14
(block
(if
(i32.eqz
(get_global $hangLimit)
)
(return
- (get_local $0)
+ (f32.const 4294967296)
)
)
(set_global $hangLimit
@@ -868,84 +782,53 @@
)
)
)
- (select
- (i32.const 23130)
- (i32.const 1111901516)
- (block $label$37 (result i32)
- (nop)
- (i32.const -2147483648)
+ (block
+ (nop)
+ (br_if $label$14
+ (i32.eqz
+ (i32.const -2147483648)
+ )
)
+ (nop)
)
)
)
)
+ (nop)
)
)
)
)
)
(return
- (get_local $2)
- )
- )
- (block $label$39 (result i32)
- (drop
- (i64.const 255)
+ (get_local $0)
)
- (call $func_3)
- )
- )
- )
- (drop
- (block $label$40 (result f32)
- (return
- (i64.const -562949953421312)
- )
- )
- )
- (f32.ne
- (f32.const 217.36842346191406)
- (f32.load offset=4
- (i32.and
- (i32.const 822703163)
- (i32.const 31)
)
)
)
)
- (select
- (i32.const 1931754023)
- (i32.const -128)
- (block $label$41 (result i32)
- (call $func_1)
- (i32.const 1701396008)
+ (i64.atomic.rmw8_u.xor offset=4
+ (i32.and
+ (i32.const 32767)
+ (i32.const 31)
)
+ (i64.const 9223372036854775807)
)
)
- (i32.const 31)
)
- (get_local $2)
- )
- (return
- (get_local $2)
)
)
)
- (func $func_5 (result i64)
- (local $0 i32)
- (local $1 i32)
- (local $2 f32)
+ (func $func_6 (param $0 f32) (param $1 f32) (result f64)
+ (local $2 i64)
(local $3 f32)
- (local $4 f32)
- (local $5 i64)
- (local $6 i64)
(block
(if
(i32.eqz
(get_global $hangLimit)
)
(return
- (get_local $6)
+ (f64.const -nan:0xffffffffffffa)
)
)
(set_global $hangLimit
@@ -955,145 +838,175 @@
)
)
)
- (drop
+ (block $label$0 (result f64)
(drop
- (block $label$0
- (loop $label$1
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (i64.const 6364521229224202323)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
+ (i32.atomic.load8_u offset=4
+ (i32.atomic.load offset=4
+ (i32.and
+ (loop $label$1 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f64.const 1.4089981056487379e-134)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
)
- )
- )
- (nop)
- )
- (f64.store offset=4 align=1
- (block $label$9
- (if
- (i32.eqz
- (if (result i32)
- (if (result i32)
- (if (result i32)
- (f64.eq
- (f64.const 7196)
- (f64.const -562949953421312)
- )
- (call $func_3)
- (block $label$10 (result i32)
- (set_global $global$0
- (f64.const 1.9804914402226382e-202)
- )
- (return
- (get_local $6)
- )
- )
+ (block (result i32)
+ (block $label$2
+ (if
+ (i32.eqz
+ (i32.const 119342106)
)
- (block $label$11 (result i32)
- (loop $label$12
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (i64.const -281474976710656)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
- )
- )
- )
- (set_global $global$0
- (f64.const 127)
- )
- )
- (i32.load8_u offset=2
+ (block $label$3
+ (i64.atomic.store32 offset=3
(i32.and
- (i32.trunc_u/f32
- (f32.const -33554432)
- )
+ (i32.const 127)
(i32.const 31)
)
+ (i64.const 651625613631293707)
)
)
- (block $label$13 (result i32)
- (call_indirect $FUNCSIG$i
- (i32.const 0)
- )
- )
+ (call $func_2)
)
- (block $label$14 (result i32)
- (nop)
- (loop $label$18 (result i32)
- (block
- (if
- (i32.eqz
- (get_global $hangLimit)
- )
- (return
- (i64.const -4096)
- )
- )
- (set_global $hangLimit
- (i32.sub
- (get_global $hangLimit)
- (i32.const 1)
+ (f64.store offset=22
+ (i32.and
+ (i32.atomic.rmw8_u.xchg offset=22
+ (i32.and
+ (block $label$4 (result i32)
+ (nop)
+ (br $label$1)
)
+ (i32.const 31)
)
- )
- (block (result i32)
- (block $label$19
- (set_local $6
- (i64.const 36028797018963968)
+ (select
+ (i32.atomic.rmw16_u.cmpxchg offset=4
+ (i32.and
+ (i32.const 37)
+ (i32.const 31)
+ )
+ (select
+ (i32.atomic.rmw16_u.cmpxchg offset=22
+ (i32.and
+ (f32.ge
+ (get_local $0)
+ (f32.const -2147483648)
+ )
+ (i32.const 31)
+ )
+ (loop $label$6 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (get_global $hangLimit)
+ )
+ (return
+ (f64.const 1791883197976824701597689e116)
+ )
+ )
+ (set_global $hangLimit
+ (i32.sub
+ (get_global $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result i32)
+ (set_local $2
+ (i64.const -55)
+ )
+ (br_if $label$6
+ (i32.eqz
+ (i32.const 131072)
+ )
+ )
+ (i32.const -134217728)
+ )
+ )
+ (i32.const 924871013)
+ )
+ (call_indirect $FUNCSIG$ifi
+ (call $deNan32
+ (f32.sub
+ (call $deNan32
+ (f32.add
+ (get_local $0)
+ (f32.const 4.581032111437074e-16)
+ )
+ )
+ (tee_local $0
+ (block $label$7 (result f32)
+ (nop)
+ (get_local $0)
+ )
+ )
+ )
+ )
+ (i32.const 65446)
+ (i32.const 0)
+ )
+ (call_indirect $FUNCSIG$ifi
+ (call $deNan32
+ (f32.sub
+ (get_local $3)
+ (f32.const -4096)
+ )
+ )
+ (i32.const -2147483648)
+ (i32.const 0)
+ )
+ )
+ (i32.const -42)
)
- (set_local $6
- (tee_local $6
- (call $func_4)
+ (call_indirect $FUNCSIG$ifi
+ (call_indirect $FUNCSIG$f
+ (i32.const -134217728)
)
+ (i32.const -2147483648)
+ (i32.const 0)
)
- )
- (br_if $label$18
- (tee_local $1
- (i32.const 442457430)
+ (block $label$5 (result i32)
+ (drop
+ (call $func_0
+ (tee_local $1
+ (get_local $3)
+ )
+ (call_indirect $FUNCSIG$ifi
+ (get_local $3)
+ (i32.const 2)
+ (i32.const 0)
+ )
+ )
+ )
+ (br $label$1)
)
)
- (i32.const -262144)
)
+ (i32.const 31)
)
+ (f64.const 1.8443913781292733e-124)
)
- (get_local $1)
)
- )
- (set_local $1
- (i32.const -2147483648)
- )
- (block $label$20
- (nop)
+ (br_if $label$1
+ (i32.const 811742759)
+ )
+ (i32.const 19806)
)
)
- (return
- (get_local $5)
- )
- )
- (return
- (i64.const 819399075040401932)
+ (i32.const 31)
)
)
)
)
+ (f64.const 3495358995652723316329699e63)
)
)
(func $hangLimitInitializer