summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/test/wasm2js.py3
-rw-r--r--src/binaryen-c.cpp2
-rw-r--r--src/ir/ExpressionAnalyzer.cpp4
-rw-r--r--src/literal.h15
-rw-r--r--src/passes/AlignmentLowering.cpp52
-rw-r--r--src/passes/AvoidReinterprets.cpp9
-rw-r--r--src/passes/InstrumentMemory.cpp17
-rw-r--r--src/passes/MemoryPacking.cpp22
-rw-r--r--src/passes/OptimizeInstructions.cpp18
-rw-r--r--src/passes/Print.cpp5
-rw-r--r--src/passes/SafeHeap.cpp102
-rw-r--r--src/passes/StackIR.cpp2
-rw-r--r--src/tools/tool-options.h1
-rw-r--r--src/tools/wasm2js.cpp2
-rw-r--r--src/wasm-binary.h15
-rw-r--r--src/wasm-builder.h15
-rw-r--r--src/wasm-features.h6
-rw-r--r--src/wasm-interpreter.h60
-rw-r--r--src/wasm-s-parser.h2
-rw-r--r--src/wasm-stack.h8
-rw-r--r--src/wasm.h41
-rw-r--r--src/wasm/wasm-binary.cpp74
-rw-r--r--src/wasm/wasm-s-parser.cpp75
-rw-r--r--src/wasm/wasm-stack.cpp2
-rw-r--r--src/wasm/wasm-validator.cpp128
-rw-r--r--src/wasm/wasm.cpp7
-rw-r--r--src/wasm2js.h4
-rw-r--r--test/atomics64.wast188
-rw-r--r--test/atomics64.wast.from-wast188
-rw-r--r--test/atomics64.wast.fromBinary189
-rw-r--r--test/atomics64.wast.fromBinary.noDebugInfo189
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt2
-rw-r--r--test/example/c-api-kitchen-sink.txt2
-rw-r--r--test/example/stack-utils.cpp4
-rw-r--r--test/memory-import64.wast9
-rw-r--r--test/memory-import64.wast.from-wast9
-rw-r--r--test/memory-import64.wast.fromBinary10
-rw-r--r--test/memory-import64.wast.fromBinary.noDebugInfo10
-rw-r--r--test/memory-import64.wast.wasm.fromBinary10
-rw-r--r--test/passes/alignment-lowering64.passes1
-rw-r--r--test/passes/alignment-lowering64.txt1948
-rw-r--r--test/passes/alignment-lowering64.wast103
-rw-r--r--test/passes/avoid-reinterprets64.passes1
-rw-r--r--test/passes/avoid-reinterprets64.txt182
-rw-r--r--test/passes/avoid-reinterprets64.wast69
-rw-r--r--test/passes/dealign64.passes1
-rw-r--r--test/passes/dealign64.txt33
-rw-r--r--test/passes/dealign64.wast11
-rw-r--r--test/passes/instrument-memory64.passes1
-rw-r--r--test/passes/instrument-memory64.txt603
-rw-r--r--test/passes/instrument-memory64.wast57
-rw-r--r--test/passes/safe-heap_enable-threads_enable-simd64.passes1
-rw-r--r--test/passes/safe-heap_enable-threads_enable-simd64.txt8705
-rw-r--r--test/passes/safe-heap_enable-threads_enable-simd64.wast56
-rw-r--r--test/passes/strip-target-features_roundtrip_print-features_all-features.txt1
-rw-r--r--test/simd64.wast74
-rw-r--r--test/simd64.wast.from-wast76
-rw-r--r--test/simd64.wast.fromBinary77
-rw-r--r--test/simd64.wast.fromBinary.noDebugInfo77
-rw-r--r--test/spec/address64.wast589
-rw-r--r--test/spec/align64.wast866
-rw-r--r--test/spec/bulk-memory64.wast167
-rw-r--r--test/spec/endianness64.wast217
-rw-r--r--test/spec/float_memory64.wast157
-rw-r--r--test/spec/load64.wast567
-rw-r--r--test/spec/memory64.wast188
-rw-r--r--test/spec/memory_grow64.wast95
-rw-r--r--test/spec/memory_redundancy64.wast65
-rw-r--r--test/spec/memory_trap64.wast269
-rw-r--r--test/spec/old_address64.wast34
-rw-r--r--test/spec/resizing64.wast58
-rw-r--r--test/unit/test_features.py3
72 files changed, 16590 insertions, 263 deletions
diff --git a/scripts/test/wasm2js.py b/scripts/test/wasm2js.py
index 5ae146d19..5ddab0b2b 100644
--- a/scripts/test/wasm2js.py
+++ b/scripts/test/wasm2js.py
@@ -18,8 +18,11 @@ from scripts.test import shared
from scripts.test import support
tests = shared.get_tests(shared.options.binaryen_test)
+# memory64 is not supported in wasm2js yet (but may be with BigInt eventually).
+tests = [t for t in tests if '64.wast' not in t]
spec_tests = shared.options.spec_tests
spec_tests = [t for t in spec_tests if '.fail' not in t]
+spec_tests = [t for t in spec_tests if '64.wast' not in t]
wasm2js_tests = shared.get_tests(shared.get_test_dir('wasm2js'), ['.wast'])
assert_tests = ['wasm2js.wast.asserts']
# These tests exercise functionality not supported by wasm2js
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index e833692d5..1c938faab 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -3262,7 +3262,7 @@ void BinaryenSetMemory(BinaryenModuleRef module,
uint8_t shared) {
auto* wasm = (Module*)module;
wasm->memory.initial = initial;
- wasm->memory.max = maximum;
+ wasm->memory.max = int32_t(maximum); // Make sure -1 extends.
wasm->memory.exists = true;
wasm->memory.shared = shared;
if (exportName) {
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index 37ba82e81..a8d9ce44a 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -475,13 +475,11 @@ size_t ExpressionAnalyzer::hash(Expression* curr) {
void visitLiteral(Literal curr) { rehash(digest, curr); }
void visitType(Type curr) { rehash(digest, curr.getID()); }
void visitIndex(Index curr) {
- static_assert(sizeof(Index) == sizeof(int32_t),
+ static_assert(sizeof(Index) == sizeof(uint32_t),
"wasm64 will need changes here");
rehash(digest, curr);
}
void visitAddress(Address curr) {
- static_assert(sizeof(Address) == sizeof(int32_t),
- "wasm64 will need changes here");
rehash(digest, curr.addr);
}
};
diff --git a/src/literal.h b/src/literal.h
index 981f5b6d4..c617f56f0 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -117,6 +117,21 @@ public:
}
}
+ static Literal makeFromUInt64(uint64_t x, Type type) {
+ switch (type.getBasic()) {
+ case Type::i32:
+ return Literal(int32_t(x));
+ case Type::i64:
+ return Literal(int64_t(x));
+ case Type::f32:
+ return Literal(float(x));
+ case Type::f64:
+ return Literal(double(x));
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+ }
+
static Literals makeZero(Type type);
static Literal makeSingleZero(Type type);
diff --git a/src/passes/AlignmentLowering.cpp b/src/passes/AlignmentLowering.cpp
index b12e49c4f..8cab58072 100644
--- a/src/passes/AlignmentLowering.cpp
+++ b/src/passes/AlignmentLowering.cpp
@@ -34,9 +34,10 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
if (curr->align == 0 || curr->align == curr->bytes) {
return curr;
}
+ auto indexType = getModule()->memory.indexType;
Builder builder(*getModule());
assert(curr->type == Type::i32);
- auto temp = builder.addVar(getFunction(), Type::i32);
+ auto temp = builder.addVar(getFunction(), indexType);
Expression* ret;
if (curr->bytes == 2) {
ret = builder.makeBinary(
@@ -45,7 +46,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeBinary(
ShlInt32,
@@ -53,7 +54,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 1,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeConst(int32_t(8))));
if (curr->signed_) {
@@ -69,7 +70,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeBinary(
ShlInt32,
@@ -77,7 +78,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 1,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeConst(int32_t(8)))),
builder.makeBinary(
@@ -88,7 +89,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 2,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeConst(int32_t(16))),
builder.makeBinary(
@@ -97,7 +98,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 3,
1,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeConst(int32_t(24)))));
} else if (curr->align == 2) {
@@ -107,7 +108,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset,
2,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeBinary(
ShlInt32,
@@ -115,7 +116,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 2,
2,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32),
builder.makeConst(int32_t(16))));
} else {
@@ -134,7 +135,8 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
}
Builder builder(*getModule());
assert(curr->value->type == Type::i32);
- auto tempPtr = builder.addVar(getFunction(), Type::i32);
+ auto indexType = getModule()->memory.indexType;
+ auto tempPtr = builder.addVar(getFunction(), indexType);
auto tempValue = builder.addVar(getFunction(), Type::i32);
auto* block =
builder.makeBlock({builder.makeLocalSet(tempPtr, curr->ptr),
@@ -144,14 +146,14 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(1,
curr->offset,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeLocalGet(tempValue, Type::i32),
Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 1,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeBinary(ShrUInt32,
builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(int32_t(8))),
@@ -162,14 +164,14 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(1,
curr->offset,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeLocalGet(tempValue, Type::i32),
Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 1,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeBinary(ShrUInt32,
builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(int32_t(8))),
@@ -178,7 +180,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
1,
curr->offset + 2,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeBinary(ShrUInt32,
builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(int32_t(16))),
@@ -187,7 +189,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
1,
curr->offset + 3,
1,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeBinary(ShrUInt32,
builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(int32_t(24))),
@@ -197,14 +199,14 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(2,
curr->offset,
2,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeLocalGet(tempValue, Type::i32),
Type::i32));
block->list.push_back(builder.makeStore(
2,
curr->offset + 2,
2,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
builder.makeBinary(ShrUInt32,
builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(int32_t(16))),
@@ -254,14 +256,15 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
break;
}
// Load two 32-bit pieces, and combine them.
- auto temp = builder.addVar(getFunction(), Type::i32);
+ auto indexType = getModule()->memory.indexType;
+ auto temp = builder.addVar(getFunction(), indexType);
auto* set = builder.makeLocalSet(temp, curr->ptr);
Expression* low =
lowerLoadI32(builder.makeLoad(4,
false,
curr->offset,
curr->align,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32));
low = builder.makeUnary(ExtendUInt32, low);
// Note that the alignment is assumed to be the same here, even though
@@ -273,7 +276,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
false,
curr->offset + 4,
curr->align,
- builder.makeLocalGet(temp, Type::i32),
+ builder.makeLocalGet(temp, indexType),
Type::i32));
high = builder.makeUnary(ExtendUInt32, high);
high =
@@ -332,7 +335,8 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
value = builder.makeUnary(ReinterpretFloat64, value);
}
// Store as two 32-bit pieces.
- auto tempPtr = builder.addVar(getFunction(), Type::i32);
+ auto indexType = getModule()->memory.indexType;
+ auto tempPtr = builder.addVar(getFunction(), indexType);
auto* setPtr = builder.makeLocalSet(tempPtr, curr->ptr);
auto tempValue = builder.addVar(getFunction(), Type::i64);
auto* setValue = builder.makeLocalSet(tempValue, value);
@@ -342,7 +346,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(4,
curr->offset,
curr->align,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
low,
Type::i32));
Expression* high =
@@ -358,7 +362,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(4,
curr->offset + 4,
curr->align,
- builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempPtr, indexType),
high,
Type::i32));
replacement = builder.makeBlock({setPtr, setValue, low, high});
diff --git a/src/passes/AvoidReinterprets.cpp b/src/passes/AvoidReinterprets.cpp
index 8668b9703..cc5871a2a 100644
--- a/src/passes/AvoidReinterprets.cpp
+++ b/src/passes/AvoidReinterprets.cpp
@@ -117,12 +117,13 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
void optimize(Function* func) {
std::set<Load*> unoptimizables;
+ auto indexType = getModule()->memory.indexType;
for (auto& pair : infos) {
auto* load = pair.first;
auto& info = pair.second;
if (info.reinterpreted && canReplaceWithReinterpret(load)) {
// We should use another load here, to avoid reinterprets.
- info.ptrLocal = Builder::addVar(func, Type::i32);
+ info.ptrLocal = Builder::addVar(func, indexType);
info.reinterpretedLocal =
Builder::addVar(func, load->type.reinterpret());
} else {
@@ -176,7 +177,8 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
auto& info = iter->second;
Builder builder(*module);
auto* ptr = curr->ptr;
- curr->ptr = builder.makeLocalGet(info.ptrLocal, Type::i32);
+ auto indexType = getModule()->memory.indexType;
+ curr->ptr = builder.makeLocalGet(info.ptrLocal, indexType);
// Note that the other load can have its sign set to false - if the
// original were an integer, the other is a float anyhow; and if
// original were a float, we don't know what sign to use.
@@ -185,7 +187,7 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
builder.makeLocalSet(
info.reinterpretedLocal,
makeReinterpretedLoad(
- curr, builder.makeLocalGet(info.ptrLocal, Type::i32))),
+ curr, builder.makeLocalGet(info.ptrLocal, indexType))),
curr}));
}
}
@@ -201,6 +203,7 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
}
} finalOptimizer(infos, localGraph, getModule(), getPassOptions());
+ finalOptimizer.setModule(getModule());
finalOptimizer.walk(func->body);
}
};
diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp
index fca3ff510..9e4788456 100644
--- a/src/passes/InstrumentMemory.cpp
+++ b/src/passes/InstrumentMemory.cpp
@@ -78,12 +78,14 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> {
void visitLoad(Load* curr) {
id++;
Builder builder(*getModule());
+ auto indexType = getModule()->memory.indexType;
+ auto offset = builder.makeConstPtr(curr->offset.addr);
curr->ptr = builder.makeCall(load_ptr,
{builder.makeConst(int32_t(id)),
builder.makeConst(int32_t(curr->bytes)),
- builder.makeConst(int32_t(curr->offset.addr)),
+ offset,
curr->ptr},
- Type::i32);
+ indexType);
Name target;
switch (curr->type.getBasic()) {
case Type::i32:
@@ -108,12 +110,14 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> {
void visitStore(Store* curr) {
id++;
Builder builder(*getModule());
+ auto indexType = getModule()->memory.indexType;
+ auto offset = builder.makeConstPtr(curr->offset.addr);
curr->ptr = builder.makeCall(store_ptr,
{builder.makeConst(int32_t(id)),
builder.makeConst(int32_t(curr->bytes)),
- builder.makeConst(int32_t(curr->offset.addr)),
+ offset,
curr->ptr},
- Type::i32);
+ indexType);
Name target;
switch (curr->value->type.getBasic()) {
case Type::i32:
@@ -136,14 +140,15 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> {
}
void visitModule(Module* curr) {
+ auto indexType = curr->memory.indexType;
addImport(
- curr, load_ptr, {Type::i32, Type::i32, Type::i32, Type::i32}, Type::i32);
+ curr, load_ptr, {Type::i32, Type::i32, indexType, indexType}, indexType);
addImport(curr, load_val_i32, {Type::i32, Type::i32}, Type::i32);
addImport(curr, load_val_i64, {Type::i32, Type::i64}, Type::i64);
addImport(curr, load_val_f32, {Type::i32, Type::f32}, Type::f32);
addImport(curr, load_val_f64, {Type::i32, Type::f64}, Type::f64);
addImport(
- curr, store_ptr, {Type::i32, Type::i32, Type::i32, Type::i32}, Type::i32);
+ curr, store_ptr, {Type::i32, Type::i32, indexType, indexType}, indexType);
addImport(curr, store_val_i32, {Type::i32, Type::i32}, Type::i32);
addImport(curr, store_val_i64, {Type::i32, Type::i64}, Type::i64);
addImport(curr, store_val_f32, {Type::i32, Type::f32}, Type::f32);
diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp
index eac7fb7f0..1018ce1c7 100644
--- a/src/passes/MemoryPacking.cpp
+++ b/src/passes/MemoryPacking.cpp
@@ -76,9 +76,14 @@ const size_t DATA_DROP_SIZE = 3;
namespace {
-Expression* makeShiftedMemorySize(Builder& builder) {
+Expression*
+makeGtShiftedMemorySize(Builder& builder, Module& module, MemoryInit* curr) {
return builder.makeBinary(
- ShlInt32, builder.makeMemorySize(), builder.makeConst(int32_t(16)));
+ module.memory.is64() ? GtUInt64 : GtUInt32,
+ curr->dest,
+ builder.makeBinary(module.memory.is64() ? ShlInt64 : ShlInt32,
+ builder.makeMemorySize(),
+ builder.makeConstPtr(16)));
}
} // anonymous namespace
@@ -317,10 +322,9 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) {
assert(!mustNop || !mustTrap);
if (mustNop) {
// Offset and size are 0, so just trap if dest > memory.size
- replaceCurrent(builder.makeIf(
- builder.makeBinary(
- GtUInt32, curr->dest, makeShiftedMemorySize(builder)),
- builder.makeUnreachable()));
+ replaceCurrent(
+ builder.makeIf(makeGtShiftedMemorySize(builder, *getModule(), curr),
+ builder.makeUnreachable()));
} else if (mustTrap) {
// Drop dest, offset, and size then trap
replaceCurrent(builder.blockify(builder.makeDrop(curr->dest),
@@ -333,8 +337,7 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) {
replaceCurrent(builder.makeIf(
builder.makeBinary(
OrInt32,
- builder.makeBinary(
- GtUInt32, curr->dest, makeShiftedMemorySize(builder)),
+ makeGtShiftedMemorySize(builder, *getModule(), curr),
builder.makeBinary(OrInt32, curr->offset, curr->size)),
builder.makeUnreachable()));
}
@@ -527,8 +530,7 @@ void MemoryPacking::createReplacements(Module* module,
Expression* result = builder.makeIf(
builder.makeBinary(
OrInt32,
- builder.makeBinary(
- GtUInt32, init->dest, makeShiftedMemorySize(builder)),
+ makeGtShiftedMemorySize(builder, *module, init),
builder.makeGlobalGet(getDropStateGlobal(), Type::i32)),
builder.makeUnreachable());
replacements[init] = [result](Function*) { return result; };
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index e3d2b3a57..9cc16004d 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1107,14 +1107,20 @@ private:
// as for readability.
auto* last = ptr->dynCast<Const>();
if (last) {
- // don't do this if it would wrap the pointer
- uint64_t value64 = last->value.geti32();
+ uint64_t value64 = last->value.getInteger();
uint64_t offset64 = offset;
- if (value64 <= uint64_t(std::numeric_limits<int32_t>::max()) &&
- offset64 <= uint64_t(std::numeric_limits<int32_t>::max()) &&
- value64 + offset64 <= uint64_t(std::numeric_limits<int32_t>::max())) {
- last->value = Literal(int32_t(value64 + offset64));
+ if (getModule()->memory.is64()) {
+ last->value = Literal(int64_t(value64 + offset64));
offset = 0;
+ } else {
+ // don't do this if it would wrap the pointer
+ if (value64 <= uint64_t(std::numeric_limits<int32_t>::max()) &&
+ offset64 <= uint64_t(std::numeric_limits<int32_t>::max()) &&
+ value64 + offset64 <=
+ uint64_t(std::numeric_limits<int32_t>::max())) {
+ last->value = Literal(int32_t(value64 + offset64));
+ offset = 0;
+ }
}
}
}
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 916615e07..6955a7a5e 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2298,6 +2298,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
o << '(';
printMedium(o, "shared ");
}
+ if (curr->is64()) {
+ o << "i64 ";
+ }
o << curr->initial;
if (curr->hasMax()) {
o << ' ' << curr->max;
@@ -2446,7 +2449,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
<< section.data.size();
bool isPrintable = true;
for (auto c : section.data) {
- if (!isprint(c)) {
+ if (!isprint(static_cast<unsigned char>(c))) {
isPrintable = false;
break;
}
diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp
index 108739d66..0335c174e 100644
--- a/src/passes/SafeHeap.cpp
+++ b/src/passes/SafeHeap.cpp
@@ -85,10 +85,7 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> {
Builder builder(*getModule());
replaceCurrent(
builder.makeCall(getLoadName(curr),
- {
- curr->ptr,
- builder.makeConst(Literal(int32_t(curr->offset))),
- },
+ {curr->ptr, builder.makeConstPtr(curr->offset.addr)},
curr->type));
}
@@ -97,14 +94,10 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> {
return;
}
Builder builder(*getModule());
- replaceCurrent(
- builder.makeCall(getStoreName(curr),
- {
- curr->ptr,
- builder.makeConst(Literal(int32_t(curr->offset))),
- curr->value,
- },
- Type::none));
+ replaceCurrent(builder.makeCall(
+ getStoreName(curr),
+ {curr->ptr, builder.makeConstPtr(curr->offset.addr), curr->value},
+ Type::none));
}
};
@@ -125,6 +118,7 @@ struct SafeHeap : public Pass {
void addImports(Module* module) {
ImportInfo info(*module);
+ auto indexType = module->memory.indexType;
// Older emscripten imports env.DYNAMICTOP_PTR.
// Newer emscripten imports or exports emscripten_get_sbrk_ptr().
if (auto* existing = info.getImportedGlobal(ENV, DYNAMICTOP_PTR_IMPORT)) {
@@ -140,7 +134,7 @@ struct SafeHeap : public Pass {
import->name = getSbrkPtr = GET_SBRK_PTR;
import->module = ENV;
import->base = GET_SBRK_PTR;
- import->sig = Signature(Type::none, Type::i32);
+ import->sig = Signature(Type::none, indexType);
module->addFunction(import);
}
if (auto* existing = info.getImportedFunction(ENV, SEGFAULT_IMPORT)) {
@@ -251,25 +245,27 @@ struct SafeHeap : public Pass {
auto* func = new Function;
func->name = name;
// pointer, offset
- func->sig = Signature({Type::i32, Type::i32}, style.type);
- func->vars.push_back(Type::i32); // pointer + offset
+ auto indexType = module->memory.indexType;
+ func->sig = Signature({indexType, indexType}, style.type);
+ func->vars.push_back(indexType); // pointer + offset
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
2,
- builder.makeBinary(AddInt32,
- builder.makeLocalGet(0, Type::i32),
- builder.makeLocalGet(1, Type::i32))));
+ builder.makeBinary(module->memory.is64() ? AddInt64 : AddInt32,
+ builder.makeLocalGet(0, indexType),
+ builder.makeLocalGet(1, indexType))));
// check for reading past valid memory: if pointer + offset + bytes
- block->list.push_back(makeBoundsCheck(style.type, builder, 2, style.bytes));
+ block->list.push_back(
+ makeBoundsCheck(style.type, builder, 2, style.bytes, module));
// check proper alignment
if (style.align > 1) {
- block->list.push_back(makeAlignCheck(style.align, builder, 2));
+ block->list.push_back(makeAlignCheck(style.align, builder, 2, module));
}
// do the load
auto* load = module->allocator.alloc<Load>();
*load = style; // basically the same as the template we are given!
- load->ptr = builder.makeLocalGet(2, Type::i32);
+ load->ptr = builder.makeLocalGet(2, indexType);
Expression* last = load;
if (load->isAtomic && load->signed_) {
// atomic loads cannot be signed, manually sign it
@@ -291,26 +287,27 @@ struct SafeHeap : public Pass {
auto* func = new Function;
func->name = name;
// pointer, offset, value
- func->sig = Signature({Type::i32, Type::i32, style.valueType}, Type::none);
- func->vars.push_back(Type::i32); // pointer + offset
+ auto indexType = module->memory.indexType;
+ func->sig = Signature({indexType, indexType, style.valueType}, Type::none);
+ func->vars.push_back(indexType); // pointer + offset
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
3,
- builder.makeBinary(AddInt32,
- builder.makeLocalGet(0, Type::i32),
- builder.makeLocalGet(1, Type::i32))));
+ builder.makeBinary(module->memory.is64() ? AddInt64 : AddInt32,
+ builder.makeLocalGet(0, indexType),
+ builder.makeLocalGet(1, indexType))));
// check for reading past valid memory: if pointer + offset + bytes
block->list.push_back(
- makeBoundsCheck(style.valueType, builder, 3, style.bytes));
+ makeBoundsCheck(style.valueType, builder, 3, style.bytes, module));
// check proper alignment
if (style.align > 1) {
- block->list.push_back(makeAlignCheck(style.align, builder, 3));
+ block->list.push_back(makeAlignCheck(style.align, builder, 3, module));
}
// do the store
auto* store = module->allocator.alloc<Store>();
*store = style; // basically the same as the template we are given!
- store->ptr = builder.makeLocalGet(3, Type::i32);
+ store->ptr = builder.makeLocalGet(3, indexType);
store->value = builder.makeLocalGet(2, style.valueType);
block->list.push_back(store);
block->finalize(Type::none);
@@ -318,42 +315,53 @@ struct SafeHeap : public Pass {
module->addFunction(func);
}
- Expression* makeAlignCheck(Address align, Builder& builder, Index local) {
+ Expression*
+ makeAlignCheck(Address align, Builder& builder, Index local, Module* module) {
+ auto indexType = module->memory.indexType;
+ Expression* ptrBits = builder.makeLocalGet(local, indexType);
+ if (module->memory.is64()) {
+ ptrBits = builder.makeUnary(WrapInt64, ptrBits);
+ }
return builder.makeIf(
- builder.makeBinary(AndInt32,
- builder.makeLocalGet(local, Type::i32),
- builder.makeConst(Literal(int32_t(align - 1)))),
+ builder.makeBinary(
+ AndInt32, ptrBits, builder.makeConst(int32_t(align - 1))),
builder.makeCall(alignfault, {}, Type::none));
}
- Expression*
- makeBoundsCheck(Type type, Builder& builder, Index local, Index bytes) {
- auto upperOp = options.lowMemoryUnused ? LtUInt32 : EqInt32;
+ Expression* makeBoundsCheck(
+ Type type, Builder& builder, Index local, Index bytes, Module* module) {
+ auto indexType = module->memory.indexType;
+ auto upperOp = module->memory.is64()
+ ? options.lowMemoryUnused ? LtUInt64 : EqInt64
+ : options.lowMemoryUnused ? LtUInt32 : EqInt32;
auto upperBound = options.lowMemoryUnused ? PassOptions::LowMemoryBound : 0;
Expression* brkLocation;
if (sbrk.is()) {
- brkLocation = builder.makeCall(
- sbrk, {builder.makeConst(Literal(int32_t(0)))}, Type::i32);
+ brkLocation =
+ builder.makeCall(sbrk, {builder.makeConstPtr(0)}, indexType);
} else {
Expression* sbrkPtr;
if (dynamicTopPtr.is()) {
- sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, Type::i32);
+ sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, indexType);
} else {
- sbrkPtr = builder.makeCall(getSbrkPtr, {}, Type::i32);
+ sbrkPtr = builder.makeCall(getSbrkPtr, {}, indexType);
}
- brkLocation = builder.makeLoad(4, false, 0, 4, sbrkPtr, Type::i32);
+ auto size = module->memory.is64() ? 8 : 4;
+ brkLocation = builder.makeLoad(size, false, 0, size, sbrkPtr, indexType);
}
+ auto gtuOp = module->memory.is64() ? GtUInt64 : GtUInt32;
+ auto addOp = module->memory.is64() ? AddInt64 : AddInt32;
return builder.makeIf(
builder.makeBinary(
OrInt32,
builder.makeBinary(upperOp,
- builder.makeLocalGet(local, Type::i32),
- builder.makeConst(Literal(int32_t(upperBound)))),
+ builder.makeLocalGet(local, indexType),
+ builder.makeConstPtr(upperBound)),
builder.makeBinary(
- GtUInt32,
- builder.makeBinary(AddInt32,
- builder.makeLocalGet(local, Type::i32),
- builder.makeConst(Literal(int32_t(bytes)))),
+ gtuOp,
+ builder.makeBinary(addOp,
+ builder.makeLocalGet(local, indexType),
+ builder.makeConstPtr(bytes)),
brkLocation)),
builder.makeCall(segfault, {}, Type::none));
}
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp
index a628468fb..ee2062b3d 100644
--- a/src/passes/StackIR.cpp
+++ b/src/passes/StackIR.cpp
@@ -36,7 +36,7 @@ struct GenerateStackIR : public WalkerPass<PostWalker<GenerateStackIR>> {
bool modifiesBinaryenIR() override { return false; }
void doWalkFunction(Function* func) {
- StackIRGenerator stackIRGen(getModule()->allocator, func);
+ StackIRGenerator stackIRGen(*getModule(), func);
stackIRGen.write();
func->stackIR = make_unique<StackIR>();
func->stackIR->swap(stackIRGen.getStackIR());
diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h
index 2e7158b34..83d5b38d7 100644
--- a/src/tools/tool-options.h
+++ b/src/tools/tool-options.h
@@ -88,6 +88,7 @@ struct ToolOptions : public Options {
.addFeature(FeatureSet::ReferenceTypes, "reference types")
.addFeature(FeatureSet::Multivalue, "multivalue functions")
.addFeature(FeatureSet::GC, "garbage collection")
+ .addFeature(FeatureSet::Memory64, "memory64")
.add("--no-validation",
"-n",
"Disables validation, assumes inputs are correct",
diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp
index 68334708f..95d93cdbd 100644
--- a/src/tools/wasm2js.cpp
+++ b/src/tools/wasm2js.cpp
@@ -810,7 +810,7 @@ void AssertionEmitter::emit() {
}
)";
- Builder wasmBuilder(sexpBuilder.getAllocator());
+ Builder wasmBuilder(sexpBuilder.getAllocator(), sexpBuilder.getModule());
Name asmModule = std::string("ret") + ASM_FUNC.str;
for (size_t i = 0; i < root.size(); ++i) {
Element& e = *root[i];
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index da2378993..7666fa842 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -331,10 +331,7 @@ enum Section {
Event = 13
};
-enum SegmentFlag {
- IsPassive = 0x01,
- HasMemIndex = 0x02,
-};
+enum SegmentFlag { IsPassive = 0x01, HasMemIndex = 0x02 };
enum EncodedType {
// value_type
@@ -384,6 +381,7 @@ extern const char* TailCallFeature;
extern const char* ReferenceTypesFeature;
extern const char* MultivalueFeature;
extern const char* GCFeature;
+extern const char* Memory64Feature;
enum Subsection {
NameModule = 0,
@@ -938,7 +936,7 @@ enum MemoryAccess {
NaturalAlignment = 0
};
-enum MemoryFlags { HasMaximum = 1 << 0, IsShared = 1 << 1 };
+enum MemoryFlags { HasMaximum = 1 << 0, IsShared = 1 << 1, Is64 = 1 << 2 };
enum FeaturePrefix {
FeatureUsed = '+',
@@ -1097,10 +1095,8 @@ public:
void write();
void writeHeader();
int32_t writeU32LEBPlaceholder();
- void writeResizableLimits(Address initial,
- Address maximum,
- bool hasMaximum,
- bool shared);
+ void writeResizableLimits(
+ Address initial, Address maximum, bool hasMaximum, bool shared, bool is64);
template<typename T> int32_t startSection(T code);
void finishSection(int32_t start);
int32_t startSubsection(BinaryConsts::UserSections::Subsection code);
@@ -1264,6 +1260,7 @@ public:
void getResizableLimits(Address& initial,
Address& max,
bool& shared,
+ Type& indexType,
Address defaultIfNoMax);
void readImports();
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 762d89dbe..b35fde376 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -35,10 +35,12 @@ struct NameType {
class Builder {
MixedArena& allocator;
+ Module& wasm;
public:
- Builder(MixedArena& allocator) : allocator(allocator) {}
- Builder(Module& wasm) : allocator(wasm.allocator) {}
+ Builder(MixedArena& allocator, Module& wasm)
+ : allocator(allocator), wasm(wasm) {}
+ Builder(Module& wasm) : allocator(wasm.allocator), wasm(wasm) {}
// make* functions, other globals
@@ -486,6 +488,9 @@ public:
ret->finalize();
return ret;
}
+ Const* makeConstPtr(uint64_t val) {
+ return makeConst(Literal::makeFromUInt64(val, wasm.memory.indexType));
+ }
Binary* makeBinary(BinaryOp op, Expression* left, Expression* right) {
auto* ret = allocator.alloc<Binary>();
ret->op = op;
@@ -521,11 +526,17 @@ public:
}
MemorySize* makeMemorySize() {
auto* ret = allocator.alloc<MemorySize>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->finalize();
return ret;
}
MemoryGrow* makeMemoryGrow(Expression* delta) {
auto* ret = allocator.alloc<MemoryGrow>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->delta = delta;
ret->finalize();
return ret;
diff --git a/src/wasm-features.h b/src/wasm-features.h
index 56436bd6a..6e74e0b29 100644
--- a/src/wasm-features.h
+++ b/src/wasm-features.h
@@ -37,7 +37,8 @@ struct FeatureSet {
ReferenceTypes = 1 << 8,
Multivalue = 1 << 9,
GC = 1 << 10,
- All = (1 << 11) - 1
+ Memory64 = 1 << 11,
+ All = (1 << 12) - 1
};
static std::string toString(Feature f) {
@@ -64,6 +65,8 @@ struct FeatureSet {
return "multivalue";
case GC:
return "gc";
+ case Memory64:
+ return "memory64";
default:
WASM_UNREACHABLE("unexpected feature");
}
@@ -105,6 +108,7 @@ struct FeatureSet {
void setReferenceTypes(bool v = true) { set(ReferenceTypes, v); }
void setMultivalue(bool v = true) { set(Multivalue, v); }
void setGC(bool v = true) { set(GC, v); }
+ void setMemory64(bool v = true) { set(Memory64, v); }
void setAll(bool v = true) { features = v ? All : MVP; }
void enable(const FeatureSet& other) { features |= other.features; }
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 8fc595034..51cc24d01 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2295,31 +2295,34 @@ private:
}
Flow visitMemorySize(MemorySize* curr) {
NOTE_ENTER("MemorySize");
- return Literal(int32_t(instance.memorySize));
+ return Literal::makeFromUInt64(instance.memorySize,
+ instance.wasm.memory.indexType);
}
Flow visitMemoryGrow(MemoryGrow* curr) {
NOTE_ENTER("MemoryGrow");
- auto fail = Literal(int32_t(-1));
+ auto indexType = instance.wasm.memory.indexType;
+ auto fail = Literal::makeFromUInt64(-1, indexType);
Flow flow = this->visit(curr->delta);
if (flow.breaking()) {
return flow;
}
- int32_t ret = instance.memorySize;
- uint32_t delta = flow.getSingleValue().geti32();
- if (delta > uint32_t(-1) / Memory::kPageSize) {
+ Flow ret = Literal::makeFromUInt64(instance.memorySize, indexType);
+ uint64_t delta = flow.getSingleValue().getInteger();
+ if (delta > uint32_t(-1) / Memory::kPageSize && indexType == Type::i32) {
return fail;
}
- if (instance.memorySize >= uint32_t(-1) - delta) {
+ if (instance.memorySize >= uint32_t(-1) - delta &&
+ indexType == Type::i32) {
return fail;
}
- uint32_t newSize = instance.memorySize + delta;
+ auto newSize = instance.memorySize + delta;
if (newSize > instance.wasm.memory.max) {
return fail;
}
instance.externalInterface->growMemory(
instance.memorySize * Memory::kPageSize, newSize * Memory::kPageSize);
instance.memorySize = newSize;
- return Literal(int32_t(ret));
+ return ret;
}
Flow visitMemoryInit(MemoryInit* curr) {
NOTE_ENTER("MemoryInit");
@@ -2342,7 +2345,7 @@ private:
assert(curr->segment < instance.wasm.memory.segments.size());
Memory::Segment& segment = instance.wasm.memory.segments[curr->segment];
- Address destVal(uint32_t(dest.getSingleValue().geti32()));
+ Address destVal(dest.getSingleValue().getInteger());
Address offsetVal(uint32_t(offset.getSingleValue().geti32()));
Address sizeVal(uint32_t(size.getSingleValue().geti32()));
@@ -2353,12 +2356,11 @@ private:
if ((uint64_t)offsetVal + sizeVal > segment.data.size()) {
trap("out of bounds segment access in memory.init");
}
- if ((uint64_t)destVal + sizeVal >
- (uint64_t)instance.memorySize * Memory::kPageSize) {
+ if (destVal + sizeVal > instance.memorySize * Memory::kPageSize) {
trap("out of bounds memory access in memory.init");
}
for (size_t i = 0; i < sizeVal; ++i) {
- Literal addr(uint32_t(destVal + i));
+ Literal addr(destVal + i);
instance.externalInterface->store8(
instance.getFinalAddressWithoutOffset(addr, 1),
segment.data[offsetVal + i]);
@@ -2387,14 +2389,15 @@ private:
NOTE_EVAL1(dest);
NOTE_EVAL1(source);
NOTE_EVAL1(size);
- Address destVal(uint32_t(dest.getSingleValue().geti32()));
- Address sourceVal(uint32_t(source.getSingleValue().geti32()));
- Address sizeVal(uint32_t(size.getSingleValue().geti32()));
-
- if ((uint64_t)sourceVal + sizeVal >
- (uint64_t)instance.memorySize * Memory::kPageSize ||
- (uint64_t)destVal + sizeVal >
- (uint64_t)instance.memorySize * Memory::kPageSize) {
+ Address destVal(dest.getSingleValue().getInteger());
+ Address sourceVal(source.getSingleValue().getInteger());
+ Address sizeVal(size.getSingleValue().getInteger());
+
+ if (sourceVal + sizeVal > instance.memorySize * Memory::kPageSize ||
+ destVal + sizeVal > instance.memorySize * Memory::kPageSize ||
+ // FIXME: better/cheaper way to detect wrapping?
+ sourceVal + sizeVal < sourceVal || sourceVal + sizeVal < sizeVal ||
+ destVal + sizeVal < destVal || destVal + sizeVal < sizeVal) {
trap("out of bounds segment access in memory.copy");
}
@@ -2409,11 +2412,9 @@ private:
}
for (int64_t i = start; i != end; i += step) {
instance.externalInterface->store8(
- instance.getFinalAddressWithoutOffset(Literal(uint32_t(destVal + i)),
- 1),
+ instance.getFinalAddressWithoutOffset(Literal(destVal + i), 1),
instance.externalInterface->load8s(
- instance.getFinalAddressWithoutOffset(
- Literal(uint32_t(sourceVal + i)), 1)));
+ instance.getFinalAddressWithoutOffset(Literal(sourceVal + i), 1)));
}
return {};
}
@@ -2434,19 +2435,16 @@ private:
NOTE_EVAL1(dest);
NOTE_EVAL1(value);
NOTE_EVAL1(size);
- Address destVal(uint32_t(dest.getSingleValue().geti32()));
- Address sizeVal(uint32_t(size.getSingleValue().geti32()));
+ Address destVal(dest.getSingleValue().getInteger());
+ Address sizeVal(size.getSingleValue().getInteger());
- if ((uint64_t)destVal + sizeVal >
- (uint64_t)instance.memorySize * Memory::kPageSize) {
+ if (destVal + sizeVal > instance.memorySize * Memory::kPageSize) {
trap("out of bounds memory access in memory.fill");
}
uint8_t val(value.getSingleValue().geti32());
for (size_t i = 0; i < sizeVal; ++i) {
instance.externalInterface->store8(
- instance.getFinalAddressWithoutOffset(Literal(uint32_t(destVal + i)),
- 1),
- val);
+ instance.getFinalAddressWithoutOffset(Literal(destVal + i), 1), val);
}
return {};
}
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 68baf7b08..f413ab5d4 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -174,6 +174,7 @@ public:
Expression* parseExpression(Element& s);
MixedArena& getAllocator() { return allocator; }
+ Module& getModule() { return wasm; }
private:
Expression* makeExpression(Element& s);
@@ -246,6 +247,7 @@ private:
// Helper functions
Type parseOptionalResultType(Element& s, Index& i);
Index parseMemoryLimits(Element& s, Index i);
+ Index parseMemoryIndex(Element& s, Index i);
std::vector<Type> parseParamOrLocal(Element& s);
std::vector<NameType> parseParamOrLocal(Element& s, size_t& localIndex);
std::vector<Type> parseResults(Element& s);
diff --git a/src/wasm-stack.h b/src/wasm-stack.h
index 6a926eddf..13cce6d6f 100644
--- a/src/wasm-stack.h
+++ b/src/wasm-stack.h
@@ -429,8 +429,8 @@ private:
// Queues the expressions linearly in Stack IR (SIR)
class StackIRGenerator : public BinaryenIRWriter<StackIRGenerator> {
public:
- StackIRGenerator(MixedArena& allocator, Function* func)
- : BinaryenIRWriter<StackIRGenerator>(func), allocator(allocator) {}
+ StackIRGenerator(Module& module, Function* func)
+ : BinaryenIRWriter<StackIRGenerator>(func), module(module) {}
void emit(Expression* curr);
void emitScopeEnd(Expression* curr);
@@ -443,7 +443,7 @@ public:
}
void emitFunctionEnd() {}
void emitUnreachable() {
- stackIR.push_back(makeStackInst(Builder(allocator).makeUnreachable()));
+ stackIR.push_back(makeStackInst(Builder(module).makeUnreachable()));
}
void emitDebugLocation(Expression* curr) {}
@@ -455,7 +455,7 @@ private:
return makeStackInst(StackInst::Basic, origin);
}
- MixedArena& allocator;
+ Module& module;
StackIR stackIR; // filled in write()
};
diff --git a/src/wasm.h b/src/wasm.h
index 419e02875..9f61fac37 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -42,20 +42,18 @@ namespace wasm {
// An index in a wasm module
typedef uint32_t Index;
-// An address in linear memory. For now only wasm32
+// An address in linear memory.
struct Address {
- typedef uint32_t address_t;
- address_t addr;
+ typedef uint32_t address32_t;
+ typedef uint64_t address64_t;
+ address64_t addr;
Address() : addr(0) {}
- Address(uint64_t a) : addr(static_cast<address_t>(a)) {
- assert(a <= std::numeric_limits<address_t>::max());
- }
+ Address(uint64_t a) : addr(a) {}
Address& operator=(uint64_t a) {
- assert(a <= std::numeric_limits<address_t>::max());
- addr = static_cast<address_t>(a);
+ addr = a;
return *this;
}
- operator address_t() const { return addr; }
+ operator address64_t() const { return addr; }
Address& operator++() {
++addr;
return *this;
@@ -1070,6 +1068,9 @@ public:
MemorySize() { type = Type::i32; }
MemorySize(MixedArena& allocator) : MemorySize() {}
+ Type ptrType = Type::i32;
+
+ void make64();
void finalize();
};
@@ -1079,7 +1080,9 @@ public:
MemoryGrow(MixedArena& allocator) : MemoryGrow() {}
Expression* delta = nullptr;
+ Type ptrType = Type::i32;
+ void make64();
void finalize();
};
@@ -1361,9 +1364,9 @@ public:
class Table : public Importable {
public:
- static const Address::address_t kPageSize = 1;
+ static const Address::address32_t kPageSize = 1;
static const Index kUnlimitedSize = Index(-1);
- // In wasm32, the maximum table size is limited by a 32-bit pointer: 4GB
+ // In wasm32/64, the maximum table size is limited by a 32-bit pointer: 4GB
static const Index kMaxSize = Index(-1);
struct Segment {
@@ -1398,12 +1401,11 @@ public:
class Memory : public Importable {
public:
- static const Address::address_t kPageSize = 64 * 1024;
- static const Address::address_t kUnlimitedSize = Address::address_t(-1);
+ static const Address::address32_t kPageSize = 64 * 1024;
+ static const Address::address64_t kUnlimitedSize = Address::address64_t(-1);
// In wasm32, the maximum memory size is limited by a 32-bit pointer: 4GB
- static const Address::address_t kMaxSize =
+ static const Address::address32_t kMaxSize32 =
(uint64_t(4) * 1024 * 1024 * 1024) / kPageSize;
- static const Address::address_t kPageMask = ~(kPageSize - 1);
struct Segment {
bool isPassive = false;
@@ -1429,21 +1431,24 @@ public:
bool exists = false;
Name name;
Address initial = 0; // sizes are in pages
- Address max = kMaxSize;
+ Address max = kMaxSize32;
std::vector<Segment> segments;
// See comment in Table.
bool shared = false;
+ Type indexType = Type::i32;
Memory() { name = Name::fromInt(0); }
bool hasMax() { return max != kUnlimitedSize; }
+ bool is64() { return indexType == Type::i64; }
void clear() {
exists = false;
name = "";
initial = 0;
- max = kMaxSize;
+ max = kMaxSize32;
segments.clear();
shared = false;
+ indexType = Type::i32;
}
};
@@ -1568,7 +1573,7 @@ public:
namespace std {
template<> struct hash<wasm::Address> {
size_t operator()(const wasm::Address a) const {
- return std::hash<wasm::Address::address_t>()(a.addr);
+ return std::hash<wasm::Address::address64_t>()(a.addr);
}
};
} // namespace std
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index e958dca6e..18a66fb2c 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -99,12 +99,11 @@ int32_t WasmBinaryWriter::writeU32LEBPlaceholder() {
return ret;
}
-void WasmBinaryWriter::writeResizableLimits(Address initial,
- Address maximum,
- bool hasMaximum,
- bool shared) {
+void WasmBinaryWriter::writeResizableLimits(
+ Address initial, Address maximum, bool hasMaximum, bool shared, bool is64) {
uint32_t flags = (hasMaximum ? (uint32_t)BinaryConsts::HasMaximum : 0U) |
- (shared ? (uint32_t)BinaryConsts::IsShared : 0U);
+ (shared ? (uint32_t)BinaryConsts::IsShared : 0U) |
+ (is64 ? (uint32_t)BinaryConsts::Is64 : 0U);
o << U32LEB(flags);
o << U32LEB(initial);
if (hasMaximum) {
@@ -203,7 +202,8 @@ void WasmBinaryWriter::writeMemory() {
writeResizableLimits(wasm->memory.initial,
wasm->memory.max,
wasm->memory.hasMax(),
- wasm->memory.shared);
+ wasm->memory.shared,
+ wasm->memory.is64());
finishSection(start);
}
@@ -267,7 +267,8 @@ void WasmBinaryWriter::writeImports() {
writeResizableLimits(wasm->memory.initial,
wasm->memory.max,
wasm->memory.hasMax(),
- wasm->memory.shared);
+ wasm->memory.shared,
+ wasm->memory.is64());
}
if (wasm->table.imported()) {
BYN_TRACE("write one table\n");
@@ -277,7 +278,8 @@ void WasmBinaryWriter::writeImports() {
writeResizableLimits(wasm->table.initial,
wasm->table.max,
wasm->table.hasMax(),
- /*shared=*/false);
+ /*shared=*/false,
+ /*is64*/ false);
}
finishSection(start);
}
@@ -505,7 +507,8 @@ void WasmBinaryWriter::writeFunctionTableDeclaration() {
writeResizableLimits(wasm->table.initial,
wasm->table.max,
wasm->table.hasMax(),
- /*shared=*/false);
+ /*shared=*/false,
+ /*is64*/ false);
finishSection(start);
}
@@ -752,6 +755,8 @@ void WasmBinaryWriter::writeFeaturesSection() {
return BinaryConsts::UserSections::MultivalueFeature;
case FeatureSet::GC:
return BinaryConsts::UserSections::GCFeature;
+ case FeatureSet::Memory64:
+ return BinaryConsts::UserSections::Memory64Feature;
default:
WASM_UNREACHABLE("unexpected feature flag");
}
@@ -1317,6 +1322,7 @@ void WasmBinaryBuilder::readMemory() {
getResizableLimits(wasm.memory.initial,
wasm.memory.max,
wasm.memory.shared,
+ wasm.memory.indexType,
Memory::kUnlimitedSize);
}
@@ -1370,15 +1376,18 @@ Name WasmBinaryBuilder::getEventName(Index index) {
void WasmBinaryBuilder::getResizableLimits(Address& initial,
Address& max,
bool& shared,
+ Type& indexType,
Address defaultIfNoMax) {
auto flags = getU32LEB();
initial = getU32LEB();
bool hasMax = (flags & BinaryConsts::HasMaximum) != 0;
bool isShared = (flags & BinaryConsts::IsShared) != 0;
+ bool is64 = (flags & BinaryConsts::Is64) != 0;
if (isShared && !hasMax) {
throwError("shared memory must have max size");
}
shared = isShared;
+ indexType = is64 ? Type::i64 : Type::i32;
if (hasMax) {
max = getU32LEB();
} else {
@@ -1425,11 +1434,18 @@ void WasmBinaryBuilder::readImports() {
}
wasm.table.exists = true;
bool is_shared;
- getResizableLimits(
- wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
+ Type indexType;
+ getResizableLimits(wasm.table.initial,
+ wasm.table.max,
+ is_shared,
+ indexType,
+ Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
+ if (indexType == Type::i64) {
+ throwError("Tables may not be 64-bit");
+ }
break;
}
case ExternalKind::Memory: {
@@ -1440,6 +1456,7 @@ void WasmBinaryBuilder::readImports() {
getResizableLimits(wasm.memory.initial,
wasm.memory.max,
wasm.memory.shared,
+ wasm.memory.indexType,
Memory::kUnlimitedSize);
break;
}
@@ -2096,11 +2113,18 @@ void WasmBinaryBuilder::readFunctionTableDeclaration() {
throwError("ElementType must be funcref in MVP");
}
bool is_shared;
- getResizableLimits(
- wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
+ Type indexType;
+ getResizableLimits(wasm.table.initial,
+ wasm.table.max,
+ is_shared,
+ indexType,
+ Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
+ if (indexType == Type::i64) {
+ throwError("Tables may not be 64-bit");
+ }
}
void WasmBinaryBuilder::readTableElements() {
@@ -2309,6 +2333,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) {
wasm.features.setMultivalue();
} else if (name == BinaryConsts::UserSections::GCFeature) {
wasm.features.setGC();
+ } else if (name == BinaryConsts::UserSections::Memory64Feature) {
+ wasm.features.setMemory64();
}
}
}
@@ -2452,14 +2478,24 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::BrOnExn:
visitBrOnExn((curr = allocator.alloc<BrOnExn>())->cast<BrOnExn>());
break;
- case BinaryConsts::MemorySize:
- visitMemorySize(
- (curr = allocator.alloc<MemorySize>())->cast<MemorySize>());
+ case BinaryConsts::MemorySize: {
+ auto size = allocator.alloc<MemorySize>();
+ if (wasm.memory.is64()) {
+ size->make64();
+ }
+ curr = size;
+ visitMemorySize(size);
break;
- case BinaryConsts::MemoryGrow:
- visitMemoryGrow(
- (curr = allocator.alloc<MemoryGrow>())->cast<MemoryGrow>());
+ }
+ case BinaryConsts::MemoryGrow: {
+ auto grow = allocator.alloc<MemoryGrow>();
+ if (wasm.memory.is64()) {
+ grow->make64();
+ }
+ curr = grow;
+ visitMemoryGrow(grow);
break;
+ }
case BinaryConsts::AtomicPrefix: {
code = static_cast<uint8_t>(getU32LEB());
if (maybeVisitLoad(curr, code, /*isAtomic=*/true)) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 2883519f2..8bbcc9ac0 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -50,12 +50,13 @@ int unhex(char c) {
namespace wasm {
-static Address getCheckedAddress(const Element* s, const char* errorText) {
- uint64_t num = atoll(s->c_str());
- if (num > std::numeric_limits<Address::address_t>::max()) {
- throw ParseException(errorText, s->line, s->col);
+static Address getAddress(const Element* s) { return atoll(s->c_str()); }
+
+static void
+checkAddress(Address a, const char* errorText, const Element* errorElem) {
+ if (a > std::numeric_limits<Address::address32_t>::max()) {
+ throw ParseException(errorText, errorElem->line, errorElem->col);
}
- return num;
}
static bool elementStartsWith(Element& s, IString str) {
@@ -1023,12 +1024,18 @@ Expression* SExpressionWasmBuilder::makeDrop(Element& s) {
Expression* SExpressionWasmBuilder::makeMemorySize(Element& s) {
auto ret = allocator.alloc<MemorySize>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->finalize();
return ret;
}
Expression* SExpressionWasmBuilder::makeMemoryGrow(Element& s) {
auto ret = allocator.alloc<MemoryGrow>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->delta = parseExpression(s[1]);
ret->finalize();
return ret;
@@ -2007,18 +2014,40 @@ void SExpressionWasmBuilder::stringToBinary(const char* input,
data.resize(actual);
}
+Index SExpressionWasmBuilder::parseMemoryIndex(Element& s, Index i) {
+ if (i < s.size() && s[i]->isStr()) {
+ if (s[i]->str() == "i64") {
+ i++;
+ wasm.memory.indexType = Type::i64;
+ } else if (s[i]->str() == "i32") {
+ i++;
+ wasm.memory.indexType = Type::i32;
+ }
+ }
+ return i;
+}
+
Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
- wasm.memory.initial = getCheckedAddress(s[i++], "excessive memory init");
+ i = parseMemoryIndex(s, i);
if (i == s.size()) {
- wasm.memory.max = Memory::kUnlimitedSize;
- return i;
+ throw ParseException("missing memory limits", s.line, s.col);
}
- uint64_t max = atoll(s[i]->c_str());
- if (max > Memory::kMaxSize) {
- throw ParseException("total memory must be <= 4GB", s[i]->line, s[i]->col);
+ auto initElem = s[i++];
+ wasm.memory.initial = getAddress(initElem);
+ if (!wasm.memory.is64()) {
+ checkAddress(wasm.memory.initial, "excessive memory init", initElem);
}
- wasm.memory.max = max;
- return ++i;
+ if (i == s.size()) {
+ wasm.memory.max = Memory::kUnlimitedSize;
+ } else {
+ auto maxElem = s[i++];
+ wasm.memory.max = getAddress(maxElem);
+ if (!wasm.memory.is64() && wasm.memory.max > Memory::kMaxSize32) {
+ throw ParseException(
+ "total memory must be <= 4GB", maxElem->line, maxElem->col);
+ }
+ }
+ return i;
}
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
@@ -2031,6 +2060,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (s[i]->dollared()) {
wasm.memory.name = s[i++]->str();
}
+ i = parseMemoryIndex(s, i);
Name importModule, importBase;
if (s[i]->isList()) {
auto& inner = *s[i];
@@ -2057,8 +2087,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
throw ParseException("bad import ending", inner.line, inner.col);
}
// (memory (data ..)) format
+ auto j = parseMemoryIndex(inner, 1);
auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
- parseInnerData(*s[i], 1, offset, false);
+ parseInnerData(inner, j, offset, false);
wasm.memory.initial = wasm.memory.segments[0].data.size();
return;
}
@@ -2075,7 +2106,11 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (elementStartsWith(curr, DATA)) {
offsetValue = 0;
} else {
- offsetValue = getCheckedAddress(curr[j++], "excessive memory offset");
+ auto offsetElem = curr[j++];
+ offsetValue = getAddress(offsetElem);
+ if (!wasm.memory.is64()) {
+ checkAddress(offsetValue, "excessive memory offset", offsetElem);
+ }
}
const char* input = curr[j]->c_str();
auto* offset = allocator.alloc<Const>();
@@ -2263,12 +2298,14 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.table.module = module;
wasm.table.base = base;
if (j < inner.size() - 1) {
- wasm.table.initial =
- getCheckedAddress(inner[j++], "excessive table init size");
+ auto initElem = inner[j++];
+ wasm.table.initial = getAddress(initElem);
+ checkAddress(wasm.table.initial, "excessive table init size", initElem);
}
if (j < inner.size() - 1) {
- wasm.table.max =
- getCheckedAddress(inner[j++], "excessive table max size");
+ auto maxElem = inner[j++];
+ wasm.table.max = getAddress(maxElem);
+ checkAddress(wasm.table.max, "excessive table max size", maxElem);
} else {
wasm.table.max = Table::kUnlimitedSize;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index edfdf31d1..30816546a 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1907,7 +1907,7 @@ void StackIRGenerator::emitScopeEnd(Expression* curr) {
StackInst* StackIRGenerator::makeStackInst(StackInst::Op op,
Expression* origin) {
- auto* ret = allocator.alloc<StackInst>();
+ auto* ret = module.allocator.alloc<StackInst>();
ret->op = op;
ret->origin = origin;
auto stackType = origin->type;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index c141fdd6f..505753c88 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -388,6 +388,8 @@ private:
void validateAlignment(
size_t align, Type type, Index bytes, bool isAtomic, Expression* curr);
void validateMemBytes(uint8_t bytes, Type type, Expression* curr);
+
+ Type indexType() { return getModule()->memory.indexType; }
};
void FunctionValidator::noteLabelName(Name name) {
@@ -931,7 +933,10 @@ 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, Type(Type::i32), curr, "load pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "load pointer type must match memory index type");
if (curr->isAtomic) {
shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned");
shouldBeIntOrUnreachable(
@@ -963,7 +968,10 @@ void FunctionValidator::visitStore(Store* curr) {
validateAlignment(
curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(
- curr->ptr->type, Type(Type::i32), curr, "store pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "store pointer must match memory index type");
shouldBeUnequal(curr->value->type,
Type(Type::none),
curr,
@@ -986,10 +994,11 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
curr,
"Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicRMW pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicRMW pointer type must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->type,
curr->value->type,
curr,
@@ -1009,7 +1018,10 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
"Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
- curr->ptr->type, Type(Type::i32), curr, "cmpxchg pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "cmpxchg pointer must match memory index type");
if (curr->expected->type != Type::unreachable &&
curr->replacement->type != Type::unreachable) {
shouldBeEqual(curr->expected->type,
@@ -1042,10 +1054,11 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
"Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicWait must have type i32");
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicWait pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicWait pointer must match memory index type");
shouldBeIntOrUnreachable(
curr->expected->type, curr, "AtomicWait expected type must be int");
shouldBeEqualOrFirstIsUnreachable(
@@ -1070,10 +1083,11 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
"Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32");
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicNotify pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicNotify pointer must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
curr->notifyCount->type,
Type(Type::i32),
@@ -1230,10 +1244,11 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "load_splat must have type v128");
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "load_splat address must have type i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "load_splat address must match memory index type");
Type memAlignType = Type::none;
switch (curr->op) {
case LoadSplatVec8x16:
@@ -1264,7 +1279,10 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.init must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.init dest must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.init dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->offset->type,
Type(Type::i32),
curr,
@@ -1304,13 +1322,20 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.copy must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.copy dest must be an i32");
- shouldBeEqualOrFirstIsUnreachable(curr->source->type,
- Type(Type::i32),
- curr,
- "memory.copy source must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.copy dest must match memory index type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->source->type,
+ indexType(),
+ curr,
+ "memory.copy source must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "memory.copy size must be an i32");
+ curr->size->type,
+ indexType(),
+ curr,
+ "memory.copy size must match memory index type");
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
}
@@ -1322,13 +1347,19 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.fill must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.fill dest must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.fill dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->value->type,
Type(Type::i32),
curr,
"memory.fill value must be an i32");
shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "memory.fill size must be an i32");
+ curr->size->type,
+ indexType(),
+ curr,
+ "memory.fill size must match memory index type");
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
}
@@ -1907,9 +1938,9 @@ void FunctionValidator::visitMemoryGrow(MemoryGrow* curr) {
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
shouldBeEqualOrFirstIsUnreachable(curr->delta->type,
- Type(Type::i32),
+ indexType(),
curr,
- "memory.grow must have i32 operand");
+ "memory.grow must match memory index type");
}
void FunctionValidator::visitRefIsNull(RefIsNull* curr) {
@@ -2113,7 +2144,7 @@ void FunctionValidator::visitFunction(Function* curr) {
}
}
-static bool checkOffset(Expression* curr, Address add, Address max) {
+static bool checkSegmentOffset(Expression* curr, Address add, Address max) {
if (curr->is<GlobalGet>()) {
return true;
}
@@ -2122,10 +2153,10 @@ static bool checkOffset(Expression* curr, Address add, Address max) {
return false;
}
uint64_t raw = c->value.getInteger();
- if (raw > std::numeric_limits<Address::address_t>::max()) {
+ if (raw > std::numeric_limits<Address::address32_t>::max()) {
return false;
}
- if (raw + uint64_t(add) > std::numeric_limits<Address::address_t>::max()) {
+ if (raw + uint64_t(add) > std::numeric_limits<Address::address32_t>::max()) {
return false;
}
Address offset = raw;
@@ -2354,12 +2385,14 @@ static void validateMemory(Module& module, ValidationInfo& info) {
auto& curr = module.memory;
info.shouldBeFalse(
curr.initial > curr.max, "memory", "memory max >= initial");
- info.shouldBeTrue(curr.initial <= Memory::kMaxSize,
- "memory",
- "initial memory must be <= 4GB");
- info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize,
- "memory",
- "max memory must be <= 4GB, or unlimited");
+ if (!curr.is64()) {
+ info.shouldBeTrue(curr.initial <= Memory::kMaxSize32,
+ "memory",
+ "initial memory must be <= 4GB");
+ info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize32,
+ "memory",
+ "max memory must be <= 4GB, or unlimited");
+ }
info.shouldBeTrue(!curr.shared || curr.hasMax(),
"memory",
"shared memory must have max size");
@@ -2385,9 +2418,9 @@ static void validateMemory(Module& module, ValidationInfo& info) {
"segment offset should be i32")) {
continue;
}
- info.shouldBeTrue(checkOffset(segment.offset,
- segment.data.size(),
- curr.initial * Memory::kPageSize),
+ info.shouldBeTrue(checkSegmentOffset(segment.offset,
+ segment.data.size(),
+ curr.initial * Memory::kPageSize),
segment.offset,
"segment offset should be reasonable");
if (segment.offset->is<Const>()) {
@@ -2416,11 +2449,12 @@ static void validateTable(Module& module, ValidationInfo& info) {
Type(Type::i32),
segment.offset,
"segment offset should be i32");
- info.shouldBeTrue(checkOffset(segment.offset,
- segment.data.size(),
- module.table.initial * Table::kPageSize),
- segment.offset,
- "segment offset should be reasonable");
+ info.shouldBeTrue(
+ checkSegmentOffset(segment.offset,
+ segment.data.size(),
+ module.table.initial * Table::kPageSize),
+ segment.offset,
+ "segment offset should be reasonable");
for (auto name : segment.data) {
info.shouldBeTrue(
module.getFunctionOrNull(name), name, "segment name should be valid");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 87488cfaf..6cc61a8a1 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -46,6 +46,7 @@ const char* TailCallFeature = "tail-call";
const char* ReferenceTypesFeature = "reference-types";
const char* MultivalueFeature = "multivalue";
const char* GCFeature = "gc";
+const char* Memory64Feature = "memory64";
} // namespace UserSections
} // namespace BinaryConsts
@@ -881,13 +882,15 @@ void Drop::finalize() {
}
}
-void MemorySize::finalize() { type = Type::i32; }
+void MemorySize::make64() { type = ptrType = Type::i64; }
+void MemorySize::finalize() { type = ptrType; }
+void MemoryGrow::make64() { type = ptrType = Type::i64; }
void MemoryGrow::finalize() {
if (delta->type == Type::unreachable) {
type = Type::unreachable;
} else {
- type = Type::i32;
+ type = ptrType;
}
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 727e87379..9350b38d6 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -423,7 +423,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
asmFunc[3]->push_back(processFunction(wasm, func));
});
if (generateFetchHighBits) {
- Builder builder(allocator);
+ Builder builder(allocator, *wasm);
asmFunc[3]->push_back(
processFunction(wasm,
wasm->addFunction(builder.makeFunction(
@@ -2122,7 +2122,7 @@ void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {
IString("&&"),
ValueBuilder::makeBinary(ValueBuilder::makeName(IString("newPages")),
LT,
- ValueBuilder::makeInt(Memory::kMaxSize))),
+ ValueBuilder::makeInt(Memory::kMaxSize32))),
block,
NULL));
diff --git a/test/atomics64.wast b/test/atomics64.wast
new file mode 100644
index 000000000..c3855a717
--- /dev/null
+++ b/test/atomics64.wast
@@ -0,0 +1,188 @@
+(module
+ (type $0 (func))
+ (memory $0 (shared i64 23 256))
+ (func $atomic-loadstore (type $0)
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.load8_u offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.load16_u offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.load offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load8_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load16_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load32_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load
+ (local.get $0)
+ )
+ )
+ (i32.atomic.store offset=4 align=4
+ (local.get $0)
+ (local.get $2)
+ )
+ (i32.atomic.store8 offset=4 align=1
+ (local.get $0)
+ (local.get $2)
+ )
+ (i32.atomic.store16 offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ (i64.atomic.store offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store8 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store16 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store32 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $atomic-rmw (type $0)
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.rmw.add offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.add_u offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw16.and_u align=2
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.or_u
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.xchg_u align=1
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ )
+ (func $atomic-cmpxchg (type $0)
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.rmw.cmpxchg offset=4
+ (local.get $0)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.cmpxchg_u
+ (local.get $0)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw.cmpxchg offset=4
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.cmpxchg_u align=4
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ )
+ (func $atomic-wait-notify (type $0)
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.wait
+ (local.get $0)
+ (local.get $2)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.wait offset=4 align=4
+ (local.get $0)
+ (local.get $2)
+ (local.get $1)
+ )
+ )
+ (drop
+ (atomic.notify
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (atomic.notify offset=24 align=4
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.wait
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.wait align=8 offset=16
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ )
+ (func $atomic-fence (type $0)
+ (atomic.fence)
+ )
+)
diff --git a/test/atomics64.wast.from-wast b/test/atomics64.wast.from-wast
new file mode 100644
index 000000000..f9ae56d17
--- /dev/null
+++ b/test/atomics64.wast.from-wast
@@ -0,0 +1,188 @@
+(module
+ (type $none_=>_none (func))
+ (memory $0 (shared i64 23 256))
+ (func $atomic-loadstore
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.load8_u offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.load16_u offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.load offset=4
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load8_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load16_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load32_u
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.load
+ (local.get $0)
+ )
+ )
+ (i32.atomic.store offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ (i32.atomic.store8 offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ (i32.atomic.store16 offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ (i64.atomic.store offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store8 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store16 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ (i64.atomic.store32 offset=4
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $atomic-rmw
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.rmw.add offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.add_u offset=4
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw16.and_u
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.or_u
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.xchg_u
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ )
+ (func $atomic-cmpxchg
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.rmw.cmpxchg offset=4
+ (local.get $0)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.cmpxchg_u
+ (local.get $0)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw.cmpxchg offset=4
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.cmpxchg_u
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ )
+ (func $atomic-wait-notify
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i32)
+ (drop
+ (i32.atomic.wait
+ (local.get $0)
+ (local.get $2)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.wait offset=4
+ (local.get $0)
+ (local.get $2)
+ (local.get $1)
+ )
+ )
+ (drop
+ (atomic.notify
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (atomic.notify offset=24
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.wait
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.wait offset=16
+ (local.get $0)
+ (local.get $1)
+ (local.get $1)
+ )
+ )
+ )
+ (func $atomic-fence
+ (atomic.fence)
+ )
+)
diff --git a/test/atomics64.wast.fromBinary b/test/atomics64.wast.fromBinary
new file mode 100644
index 000000000..1dcf24a1e
--- /dev/null
+++ b/test/atomics64.wast.fromBinary
@@ -0,0 +1,189 @@
+(module
+ (type $none_=>_none (func))
+ (memory $0 (shared i64 23 256))
+ (func $atomic-loadstore
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.load8_u offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.load16_u offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.load offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load8_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load16_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load32_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load
+ (local.get $1)
+ )
+ )
+ (i32.atomic.store offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i32.atomic.store8 offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i32.atomic.store16 offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i64.atomic.store offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store8 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store16 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store32 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ )
+ (func $atomic-rmw
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.rmw.add offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.add_u offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw16.and_u
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.or_u
+ (local.get $1)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.xchg_u
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ )
+ (func $atomic-cmpxchg
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.rmw.cmpxchg offset=4
+ (local.get $1)
+ (local.get $0)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.cmpxchg_u
+ (local.get $1)
+ (local.get $0)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.rmw.cmpxchg offset=4
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.cmpxchg_u
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ )
+ (func $atomic-wait-notify
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.wait
+ (local.get $1)
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.wait offset=4
+ (local.get $1)
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (atomic.notify
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (atomic.notify offset=24
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.wait
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.wait offset=16
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ )
+ (func $atomic-fence
+ (atomic.fence)
+ )
+)
+
diff --git a/test/atomics64.wast.fromBinary.noDebugInfo b/test/atomics64.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..cffb1491e
--- /dev/null
+++ b/test/atomics64.wast.fromBinary.noDebugInfo
@@ -0,0 +1,189 @@
+(module
+ (type $none_=>_none (func))
+ (memory $0 (shared i64 23 256))
+ (func $0
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.load8_u offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.load16_u offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i32.atomic.load offset=4
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load8_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load16_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load32_u
+ (local.get $1)
+ )
+ )
+ (drop
+ (i64.atomic.load
+ (local.get $1)
+ )
+ )
+ (i32.atomic.store offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i32.atomic.store8 offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i32.atomic.store16 offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ (i64.atomic.store offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store8 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store16 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ (i64.atomic.store32 offset=4
+ (local.get $1)
+ (local.get $2)
+ )
+ )
+ (func $1
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.rmw.add offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.add_u offset=4
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw16.and_u
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.or_u
+ (local.get $1)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.xchg_u
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ )
+ (func $2
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.rmw.cmpxchg offset=4
+ (local.get $1)
+ (local.get $0)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i32.atomic.rmw8.cmpxchg_u
+ (local.get $1)
+ (local.get $0)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.rmw.cmpxchg offset=4
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.rmw32.cmpxchg_u
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ )
+ (func $3
+ (local $0 i32)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (i32.atomic.wait
+ (local.get $1)
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i32.atomic.wait offset=4
+ (local.get $1)
+ (local.get $0)
+ (local.get $2)
+ )
+ )
+ (drop
+ (atomic.notify
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (atomic.notify offset=24
+ (local.get $1)
+ (local.get $0)
+ )
+ )
+ (drop
+ (i64.atomic.wait
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (drop
+ (i64.atomic.wait offset=16
+ (local.get $1)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ )
+ (func $4
+ (atomic.fence)
+ )
+)
+
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 54052a597..6bd8329e0 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -36,7 +36,7 @@ Features.TailCall: 128
Features.ReferenceTypes: 256
Features.Multivalue: 512
Features.GC: 1024
-Features.All: 2047
+Features.All: 4095
InvalidId: 0
BlockId: 1
IfId: 2
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index d92009c35..807730e27 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -22,7 +22,7 @@ BinaryenFeatureTailCall: 128
BinaryenFeatureReferenceTypes: 256
BinaryenFeatureMultivalue: 512
BinaryenFeatureGC: 1024
-BinaryenFeatureAll: 2047
+BinaryenFeatureAll: 4095
(f32.neg
(f32.const -33.61199951171875)
)
diff --git a/test/example/stack-utils.cpp b/test/example/stack-utils.cpp
index d35d30120..9f20b8c2a 100644
--- a/test/example/stack-utils.cpp
+++ b/test/example/stack-utils.cpp
@@ -11,8 +11,8 @@
using namespace wasm;
-MixedArena allocator;
-Builder builder(allocator);
+Module module;
+Builder builder(module);
void test_remove_nops() {
std::cout << ";; Test removeNops\n";
diff --git a/test/memory-import64.wast b/test/memory-import64.wast
new file mode 100644
index 000000000..f84f394e7
--- /dev/null
+++ b/test/memory-import64.wast
@@ -0,0 +1,9 @@
+(module
+ (type $0 (func (result i32)))
+ (import "env" "memory" (memory $0 i64 1 1))
+ (func $foo (type $0) (result i32)
+ (i32.load offset=13
+ (i64.const 37)
+ )
+ )
+)
diff --git a/test/memory-import64.wast.from-wast b/test/memory-import64.wast.from-wast
new file mode 100644
index 000000000..60a280c0e
--- /dev/null
+++ b/test/memory-import64.wast.from-wast
@@ -0,0 +1,9 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "memory" (memory $0 i64 1 1))
+ (func $foo (result i32)
+ (i32.load offset=13
+ (i64.const 37)
+ )
+ )
+)
diff --git a/test/memory-import64.wast.fromBinary b/test/memory-import64.wast.fromBinary
new file mode 100644
index 000000000..fc3e57875
--- /dev/null
+++ b/test/memory-import64.wast.fromBinary
@@ -0,0 +1,10 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "memory" (memory $0 i64 1 1))
+ (func $foo (result i32)
+ (i32.load offset=13
+ (i64.const 37)
+ )
+ )
+)
+
diff --git a/test/memory-import64.wast.fromBinary.noDebugInfo b/test/memory-import64.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..cf422a6aa
--- /dev/null
+++ b/test/memory-import64.wast.fromBinary.noDebugInfo
@@ -0,0 +1,10 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "memory" (memory $0 i64 1 1))
+ (func $0 (result i32)
+ (i32.load offset=13
+ (i64.const 37)
+ )
+ )
+)
+
diff --git a/test/memory-import64.wast.wasm.fromBinary b/test/memory-import64.wast.wasm.fromBinary
new file mode 100644
index 000000000..f783ba47e
--- /dev/null
+++ b/test/memory-import64.wast.wasm.fromBinary
@@ -0,0 +1,10 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "memory" (memory $0 1 1 i64))
+ (func $0 (result i32)
+ (i32.load offset=13
+ (i64.const 37)
+ )
+ )
+)
+
diff --git a/test/passes/alignment-lowering64.passes b/test/passes/alignment-lowering64.passes
new file mode 100644
index 000000000..6dfd86e85
--- /dev/null
+++ b/test/passes/alignment-lowering64.passes
@@ -0,0 +1 @@
+alignment-lowering
diff --git a/test/passes/alignment-lowering64.txt b/test/passes/alignment-lowering64.txt
new file mode 100644
index 000000000..31f6fd368
--- /dev/null
+++ b/test/passes/alignment-lowering64.txt
@@ -0,0 +1,1948 @@
+(module
+ (type $none_=>_none (func))
+ (memory $0 i64 1 1)
+ (func $func_4
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i64)
+ (local $4 i64)
+ (local $5 i32)
+ (local $6 i64)
+ (local $7 i32)
+ (local $8 i64)
+ (local $9 i32)
+ (local $10 i64)
+ (local $11 i32)
+ (drop
+ (i32.load
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $0
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $0)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $0)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $0)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $0)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $1
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (drop
+ (i32.load
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $2
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=100
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=101
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=102
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=103
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $3
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.load16_u offset=100
+ (local.get $3)
+ )
+ (i32.shl
+ (i32.load16_u offset=102
+ (local.get $3)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (drop
+ (i32.load offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ (i32.store
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (local.set $4
+ (i64.const 4)
+ )
+ (local.set $5
+ (i32.const 8)
+ )
+ (i32.store8
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=1
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $6
+ (i64.const 4)
+ )
+ (local.set $7
+ (i32.const 8)
+ )
+ (i32.store16
+ (local.get $6)
+ (local.get $7)
+ )
+ (i32.store16 offset=2
+ (local.get $6)
+ (i32.shr_u
+ (local.get $7)
+ (i32.const 16)
+ )
+ )
+ )
+ (i32.store
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (i32.store offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (local.set $8
+ (i64.const 4)
+ )
+ (local.set $9
+ (i32.const 8)
+ )
+ (i32.store8 offset=100
+ (local.get $8)
+ (local.get $9)
+ )
+ (i32.store8 offset=101
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=102
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=103
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $10
+ (i64.const 4)
+ )
+ (local.set $11
+ (i32.const 8)
+ )
+ (i32.store16 offset=100
+ (local.get $10)
+ (local.get $11)
+ )
+ (i32.store16 offset=102
+ (local.get $10)
+ (i32.shr_u
+ (local.get $11)
+ (i32.const 16)
+ )
+ )
+ )
+ (i32.store offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (drop
+ (unreachable)
+ )
+ (drop
+ (i32.const 8)
+ )
+ )
+ (block
+ (drop
+ (i64.const 4)
+ )
+ (drop
+ (unreachable)
+ )
+ )
+ )
+ (func $func_2
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i32)
+ (local $4 i64)
+ (local $5 i32)
+ (drop
+ (i32.load16_u
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $0
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.load8_u
+ (local.get $0)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $0)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (drop
+ (i32.load16_u
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load16_u offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $1
+ (i64.const 4)
+ )
+ (i32.or
+ (i32.load8_u offset=100
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=101
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (drop
+ (i32.load16_u offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ (i32.store16
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (local.set $2
+ (i64.const 4)
+ )
+ (local.set $3
+ (i32.const 8)
+ )
+ (i32.store8
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store8 offset=1
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.store16
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (i32.store16 offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (local.set $4
+ (i64.const 4)
+ )
+ (local.set $5
+ (i32.const 8)
+ )
+ (i32.store8 offset=100
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=101
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.store16 offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (drop
+ (unreachable)
+ )
+ (drop
+ (i32.const 8)
+ )
+ )
+ (block
+ (drop
+ (i64.const 4)
+ )
+ (drop
+ (unreachable)
+ )
+ )
+ )
+ (func $func_1
+ (drop
+ (i32.load8_u
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load8_u
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load8_u offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load8_u offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ (i32.store8
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (i32.store8
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (i32.store8 offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (i32.store8 offset=100
+ (i64.const 4)
+ (i32.const 8)
+ )
+ (block
+ (drop
+ (unreachable)
+ )
+ (drop
+ (i32.const 8)
+ )
+ )
+ (block
+ (drop
+ (i64.const 4)
+ )
+ (drop
+ (unreachable)
+ )
+ )
+ )
+ (func $func_signed
+ (local $0 i64)
+ (local $1 i64)
+ (drop
+ (i32.load16_s
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $0
+ (i64.const 4)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.or
+ (i32.load8_u
+ (local.get $0)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $0)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (drop
+ (i32.load16_s
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load16_s offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $1
+ (i64.const 4)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.or
+ (i32.load8_u offset=100
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=101
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (drop
+ (i32.load16_s offset=100
+ (i64.const 4)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ )
+ (func $i64-load
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i64)
+ (local $4 i64)
+ (local $5 i64)
+ (local $6 i64)
+ (local $7 i64)
+ (local $8 i64)
+ (local $9 i64)
+ (local $10 i64)
+ (local $11 i64)
+ (local $12 i64)
+ (local $13 i64)
+ (drop
+ (block (result i64)
+ (local.set $0
+ (i64.const 12)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $1
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $1)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $2
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=7
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $3
+ (i64.const 16)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $4
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $4)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $4)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $5
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u offset=4
+ (local.get $5)
+ )
+ (i32.shl
+ (i32.load16_u offset=6
+ (local.get $5)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $6
+ (i64.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (block (result i64)
+ (local.set $7
+ (i64.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $8
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $8)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $8)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $8)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $8)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $9
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=7
+ (local.get $9)
+ )
+ (i32.shl
+ (i32.load8_u offset=8
+ (local.get $9)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=9
+ (local.get $9)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=10
+ (local.get $9)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_s
+ (block (result i32)
+ (local.set $10
+ (i64.const 28)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.or
+ (i32.load8_u
+ (local.get $10)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $10)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_s
+ (block (result i32)
+ (local.set $11
+ (i64.const 32)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $11)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $11)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $11)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $11)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $12
+ (i64.const 40)
+ )
+ (i32.or
+ (i32.load8_u
+ (local.get $12)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $12)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $13
+ (i64.const 44)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $13)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $13)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $13)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $13)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $f32-load
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $0
+ (i64.const 12)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $0)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $0)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $0)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $0)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $1
+ (i64.const 16)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (local.set $2
+ (i64.const 20)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $f64-load
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i64)
+ (local $4 i64)
+ (local $5 i64)
+ (local $6 i64)
+ (local $7 i64)
+ (local $8 i64)
+ (local $9 i64)
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $0
+ (i64.const 12)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $1
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u
+ (local.get $1)
+ )
+ (i32.shl
+ (i32.load8_u offset=1
+ (local.get $1)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=2
+ (local.get $1)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=3
+ (local.get $1)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $2
+ (local.get $0)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=4
+ (local.get $2)
+ )
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $2)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=7
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $3
+ (i64.const 16)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $4
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u
+ (local.get $4)
+ )
+ (i32.shl
+ (i32.load16_u offset=2
+ (local.get $4)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $5
+ (local.get $3)
+ )
+ (i32.or
+ (i32.load16_u offset=4
+ (local.get $5)
+ )
+ (i32.shl
+ (i32.load16_u offset=6
+ (local.get $5)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $6
+ (i64.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (f64.reinterpret_i64
+ (block (result i64)
+ (local.set $7
+ (i64.const 20)
+ )
+ (i64.or
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $8
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=3
+ (local.get $8)
+ )
+ (i32.shl
+ (i32.load8_u offset=4
+ (local.get $8)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=5
+ (local.get $8)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=6
+ (local.get $8)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.shl
+ (i64.extend_i32_u
+ (block (result i32)
+ (local.set $9
+ (local.get $7)
+ )
+ (i32.or
+ (i32.or
+ (i32.load8_u offset=7
+ (local.get $9)
+ )
+ (i32.shl
+ (i32.load8_u offset=8
+ (local.get $9)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.or
+ (i32.shl
+ (i32.load8_u offset=9
+ (local.get $9)
+ )
+ (i32.const 16)
+ )
+ (i32.shl
+ (i32.load8_u offset=10
+ (local.get $9)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $i64-store
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i32)
+ (local $4 i64)
+ (local $5 i32)
+ (local $6 i64)
+ (local $7 i64)
+ (local $8 i64)
+ (local $9 i32)
+ (local $10 i64)
+ (local $11 i32)
+ (local $12 i64)
+ (local $13 i64)
+ (local $14 i64)
+ (local $15 i64)
+ (local $16 i64)
+ (local $17 i32)
+ (local $18 i64)
+ (local $19 i32)
+ (local $20 i64)
+ (local $21 i32)
+ (local $22 i64)
+ (local $23 i32)
+ (block
+ (local.set $0
+ (i64.const 12)
+ )
+ (local.set $1
+ (i64.const 100)
+ )
+ (block
+ (local.set $2
+ (local.get $0)
+ )
+ (local.set $3
+ (i32.wrap_i64
+ (local.get $1)
+ )
+ )
+ (i32.store8
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store8 offset=1
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (local.get $0)
+ )
+ (local.set $5
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $1)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $6
+ (i64.const 16)
+ )
+ (local.set $7
+ (i64.const 200)
+ )
+ (block
+ (local.set $8
+ (local.get $6)
+ )
+ (local.set $9
+ (i32.wrap_i64
+ (local.get $7)
+ )
+ )
+ (i32.store16
+ (local.get $8)
+ (local.get $9)
+ )
+ (i32.store16 offset=2
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $10
+ (local.get $6)
+ )
+ (local.set $11
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $7)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store16 offset=4
+ (local.get $10)
+ (local.get $11)
+ )
+ (i32.store16 offset=6
+ (local.get $10)
+ (i32.shr_u
+ (local.get $11)
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $12
+ (i64.const 20)
+ )
+ (local.set $13
+ (i64.const 300)
+ )
+ (i32.store
+ (local.get $12)
+ (i32.wrap_i64
+ (local.get $13)
+ )
+ )
+ (i32.store offset=4
+ (local.get $12)
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $13)
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $14
+ (i64.const 24)
+ )
+ (local.set $15
+ (i64.const 400)
+ )
+ (block
+ (local.set $16
+ (local.get $14)
+ )
+ (local.set $17
+ (i32.wrap_i64
+ (local.get $15)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $16)
+ (local.get $17)
+ )
+ (i32.store8 offset=4
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $18
+ (local.get $14)
+ )
+ (local.set $19
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $15)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $18)
+ (local.get $19)
+ )
+ (i32.store8 offset=8
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=9
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=10
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $20
+ (i64.const 20)
+ )
+ (local.set $21
+ (i32.wrap_i64
+ (i64.const 600)
+ )
+ )
+ (i32.store8
+ (local.get $20)
+ (local.get $21)
+ )
+ (i32.store8 offset=1
+ (local.get $20)
+ (i32.shr_u
+ (local.get $21)
+ (i32.const 8)
+ )
+ )
+ )
+ (block
+ (local.set $22
+ (i64.const 20)
+ )
+ (local.set $23
+ (i32.wrap_i64
+ (i64.const 700)
+ )
+ )
+ (i32.store8
+ (local.get $22)
+ (local.get $23)
+ )
+ (i32.store8 offset=1
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $22)
+ (i32.shr_u
+ (local.get $23)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $f32-store
+ (local $0 i64)
+ (local $1 i32)
+ (local $2 i64)
+ (local $3 i32)
+ (local $4 i64)
+ (local $5 i32)
+ (block
+ (local.set $0
+ (i64.const 12)
+ )
+ (local.set $1
+ (i32.reinterpret_f32
+ (f32.const 100)
+ )
+ )
+ (i32.store8
+ (local.get $0)
+ (local.get $1)
+ )
+ (i32.store8 offset=1
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $0)
+ (i32.shr_u
+ (local.get $1)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $2
+ (i64.const 16)
+ )
+ (local.set $3
+ (i32.reinterpret_f32
+ (f32.const 200)
+ )
+ )
+ (i32.store16
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store16 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i64.const 24)
+ )
+ (local.set $5
+ (i32.reinterpret_f32
+ (f32.const 400)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $f64-store
+ (local $0 i64)
+ (local $1 i64)
+ (local $2 i64)
+ (local $3 i32)
+ (local $4 i64)
+ (local $5 i32)
+ (local $6 i64)
+ (local $7 i64)
+ (local $8 i64)
+ (local $9 i32)
+ (local $10 i64)
+ (local $11 i32)
+ (local $12 i64)
+ (local $13 i64)
+ (local $14 i64)
+ (local $15 i64)
+ (local $16 i64)
+ (local $17 i32)
+ (local $18 i64)
+ (local $19 i32)
+ (block
+ (local.set $0
+ (i64.const 12)
+ )
+ (local.set $1
+ (i64.reinterpret_f64
+ (f64.const 100)
+ )
+ )
+ (block
+ (local.set $2
+ (local.get $0)
+ )
+ (local.set $3
+ (i32.wrap_i64
+ (local.get $1)
+ )
+ )
+ (i32.store8
+ (local.get $2)
+ (local.get $3)
+ )
+ (i32.store8 offset=1
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=2
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $2)
+ (i32.shr_u
+ (local.get $3)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (local.get $0)
+ )
+ (local.set $5
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $1)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=4
+ (local.get $4)
+ (local.get $5)
+ )
+ (i32.store8 offset=5
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $4)
+ (i32.shr_u
+ (local.get $5)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $6
+ (i64.const 16)
+ )
+ (local.set $7
+ (i64.reinterpret_f64
+ (f64.const 200)
+ )
+ )
+ (block
+ (local.set $8
+ (local.get $6)
+ )
+ (local.set $9
+ (i32.wrap_i64
+ (local.get $7)
+ )
+ )
+ (i32.store16
+ (local.get $8)
+ (local.get $9)
+ )
+ (i32.store16 offset=2
+ (local.get $8)
+ (i32.shr_u
+ (local.get $9)
+ (i32.const 16)
+ )
+ )
+ )
+ (block
+ (local.set $10
+ (local.get $6)
+ )
+ (local.set $11
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $7)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store16 offset=4
+ (local.get $10)
+ (local.get $11)
+ )
+ (i32.store16 offset=6
+ (local.get $10)
+ (i32.shr_u
+ (local.get $11)
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $12
+ (i64.const 20)
+ )
+ (local.set $13
+ (i64.reinterpret_f64
+ (f64.const 300)
+ )
+ )
+ (i32.store
+ (local.get $12)
+ (i32.wrap_i64
+ (local.get $13)
+ )
+ )
+ (i32.store offset=4
+ (local.get $12)
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $13)
+ (i64.const 32)
+ )
+ )
+ )
+ )
+ (block
+ (local.set $14
+ (i64.const 24)
+ )
+ (local.set $15
+ (i64.reinterpret_f64
+ (f64.const 400)
+ )
+ )
+ (block
+ (local.set $16
+ (local.get $14)
+ )
+ (local.set $17
+ (i32.wrap_i64
+ (local.get $15)
+ )
+ )
+ (i32.store8 offset=3
+ (local.get $16)
+ (local.get $17)
+ )
+ (i32.store8 offset=4
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=5
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=6
+ (local.get $16)
+ (i32.shr_u
+ (local.get $17)
+ (i32.const 24)
+ )
+ )
+ )
+ (block
+ (local.set $18
+ (local.get $14)
+ )
+ (local.set $19
+ (i32.wrap_i64
+ (i64.shr_u
+ (local.get $15)
+ (i64.const 32)
+ )
+ )
+ )
+ (i32.store8 offset=7
+ (local.get $18)
+ (local.get $19)
+ )
+ (i32.store8 offset=8
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 8)
+ )
+ )
+ (i32.store8 offset=9
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 16)
+ )
+ )
+ (i32.store8 offset=10
+ (local.get $18)
+ (i32.shr_u
+ (local.get $19)
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ )
+)
diff --git a/test/passes/alignment-lowering64.wast b/test/passes/alignment-lowering64.wast
new file mode 100644
index 000000000..c31eb8256
--- /dev/null
+++ b/test/passes/alignment-lowering64.wast
@@ -0,0 +1,103 @@
+(module
+ (memory $0 i64 1 1)
+ (func $func_4
+ (drop (i32.load (i64.const 4)))
+ (drop (i32.load align=1 (i64.const 4)))
+ (drop (i32.load align=2 (i64.const 4)))
+ (drop (i32.load align=4 (i64.const 4)))
+ (drop (i32.load offset=100 (i64.const 4)))
+ (drop (i32.load offset=100 align=1 (i64.const 4)))
+ (drop (i32.load offset=100 align=2 (i64.const 4)))
+ (drop (i32.load offset=100 align=4 (i64.const 4)))
+ (drop (i32.load offset=100 align=1 (unreachable)))
+ (i32.store (i64.const 4) (i32.const 8))
+ (i32.store align=1 (i64.const 4) (i32.const 8))
+ (i32.store align=2 (i64.const 4) (i32.const 8))
+ (i32.store align=4 (i64.const 4) (i32.const 8))
+ (i32.store offset=100 (i64.const 4) (i32.const 8))
+ (i32.store offset=100 align=1 (i64.const 4) (i32.const 8))
+ (i32.store offset=100 align=2 (i64.const 4) (i32.const 8))
+ (i32.store offset=100 align=4 (i64.const 4) (i32.const 8))
+ (i32.store offset=100 align=1 (unreachable) (i32.const 8))
+ (i32.store offset=100 align=1 (i64.const 4) (unreachable))
+ )
+ (func $func_2
+ (drop (i32.load16_u (i64.const 4)))
+ (drop (i32.load16_u align=1 (i64.const 4)))
+ (drop (i32.load16_u align=2 (i64.const 4)))
+ (drop (i32.load16_u offset=100 (i64.const 4)))
+ (drop (i32.load16_u offset=100 align=1 (i64.const 4)))
+ (drop (i32.load16_u offset=100 align=2 (i64.const 4)))
+ (drop (i32.load16_u offset=100 align=1 (unreachable)))
+ (i32.store16 (i64.const 4) (i32.const 8))
+ (i32.store16 align=1 (i64.const 4) (i32.const 8))
+ (i32.store16 align=2 (i64.const 4) (i32.const 8))
+ (i32.store16 offset=100 (i64.const 4) (i32.const 8))
+ (i32.store16 offset=100 align=1 (i64.const 4) (i32.const 8))
+ (i32.store16 offset=100 align=2 (i64.const 4) (i32.const 8))
+ (i32.store16 offset=100 align=1 (unreachable) (i32.const 8))
+ (i32.store16 offset=100 align=1 (i64.const 4) (unreachable))
+ )
+ (func $func_1
+ (drop (i32.load8_u (i64.const 4)))
+ (drop (i32.load8_u align=1 (i64.const 4)))
+ (drop (i32.load8_u offset=100 (i64.const 4)))
+ (drop (i32.load8_u offset=100 align=1 (i64.const 4)))
+ (drop (i32.load8_u offset=100 align=1 (unreachable)))
+ (i32.store8 (i64.const 4) (i32.const 8))
+ (i32.store8 align=1 (i64.const 4) (i32.const 8))
+ (i32.store8 offset=100 (i64.const 4) (i32.const 8))
+ (i32.store8 offset=100 align=1 (i64.const 4) (i32.const 8))
+ (i32.store8 offset=100 align=1 (unreachable) (i32.const 8))
+ (i32.store8 offset=100 align=1 (i64.const 4) (unreachable))
+ )
+ (func $func_signed
+ (drop (i32.load16_s (i64.const 4)))
+ (drop (i32.load16_s align=1 (i64.const 4)))
+ (drop (i32.load16_s align=2 (i64.const 4)))
+ (drop (i32.load16_s offset=100 (i64.const 4)))
+ (drop (i32.load16_s offset=100 align=1 (i64.const 4)))
+ (drop (i32.load16_s offset=100 align=2 (i64.const 4)))
+ (drop (i32.load16_s offset=100 align=1 (unreachable)))
+ )
+ (func $i64-load
+ (drop (i64.load align=1 (i64.const 12)))
+ (drop (i64.load align=2 (i64.const 16)))
+ (drop (i64.load align=4 (i64.const 20)))
+ (drop (i64.load align=1 offset=3 (i64.const 20)))
+ (drop (i64.load16_s align=1 (i64.const 28)))
+ (drop (i64.load32_s align=1 (i64.const 32)))
+ (drop (i64.load16_u align=1 (i64.const 40)))
+ (drop (i64.load32_u align=1 (i64.const 44)))
+ )
+ (func $f32-load
+ (drop (f32.load align=1 (i64.const 12)))
+ (drop (f32.load align=2 (i64.const 16)))
+ (drop (f32.load align=1 offset=3 (i64.const 20)))
+ )
+ (func $f64-load
+ (drop (f64.load align=1 (i64.const 12)))
+ (drop (f64.load align=2 (i64.const 16)))
+ (drop (f64.load align=4 (i64.const 20)))
+ (drop (f64.load align=1 offset=3 (i64.const 20)))
+ )
+ (func $i64-store
+ (i64.store align=1 (i64.const 12) (i64.const 100))
+ (i64.store align=2 (i64.const 16) (i64.const 200))
+ (i64.store align=4 (i64.const 20) (i64.const 300))
+ (i64.store align=1 offset=3 (i64.const 24) (i64.const 400))
+ (i64.store16 align=1 (i64.const 20) (i64.const 600))
+ (i64.store32 align=1 (i64.const 20) (i64.const 700))
+ )
+ (func $f32-store
+ (f32.store align=1 (i64.const 12) (f32.const 100))
+ (f32.store align=2 (i64.const 16) (f32.const 200))
+ (f32.store align=1 offset=3 (i64.const 24) (f32.const 400))
+ )
+ (func $f64-store
+ (f64.store align=1 (i64.const 12) (f64.const 100))
+ (f64.store align=2 (i64.const 16) (f64.const 200))
+ (f64.store align=4 (i64.const 20) (f64.const 300))
+ (f64.store align=1 offset=3 (i64.const 24) (f64.const 400))
+ )
+)
diff --git a/test/passes/avoid-reinterprets64.passes b/test/passes/avoid-reinterprets64.passes
new file mode 100644
index 000000000..4f327b29c
--- /dev/null
+++ b/test/passes/avoid-reinterprets64.passes
@@ -0,0 +1 @@
+avoid-reinterprets
diff --git a/test/passes/avoid-reinterprets64.txt b/test/passes/avoid-reinterprets64.txt
new file mode 100644
index 000000000..1b6f05948
--- /dev/null
+++ b/test/passes/avoid-reinterprets64.txt
@@ -0,0 +1,182 @@
+(module
+ (type $none_=>_none (func))
+ (type $none_=>_f32 (func (result f32)))
+ (memory $0 i64 1)
+ (func $simple
+ (drop
+ (f32.load
+ (i64.const 1024)
+ )
+ )
+ (drop
+ (i32.load
+ (i64.const 1024)
+ )
+ )
+ (drop
+ (f64.load
+ (i64.const 1024)
+ )
+ )
+ (drop
+ (i64.load
+ (i64.const 1024)
+ )
+ )
+ )
+ (func $one
+ (local $x i32)
+ (local $1 i64)
+ (local $2 f32)
+ (local.set $x
+ (block (result i32)
+ (local.set $1
+ (i64.const 1024)
+ )
+ (local.set $2
+ (f32.load
+ (local.get $1)
+ )
+ )
+ (i32.load
+ (local.get $1)
+ )
+ )
+ )
+ (drop
+ (local.get $2)
+ )
+ )
+ (func $one-b
+ (local $x f32)
+ (local $1 i64)
+ (local $2 i32)
+ (local.set $x
+ (block (result f32)
+ (local.set $1
+ (i64.const 1024)
+ )
+ (local.set $2
+ (i32.load
+ (local.get $1)
+ )
+ )
+ (f32.load
+ (local.get $1)
+ )
+ )
+ )
+ (drop
+ (local.get $2)
+ )
+ )
+ (func $both
+ (local $x i32)
+ (local $1 i64)
+ (local $2 f32)
+ (local.set $x
+ (block (result i32)
+ (local.set $1
+ (i64.const 1024)
+ )
+ (local.set $2
+ (f32.load
+ (local.get $1)
+ )
+ )
+ (i32.load
+ (local.get $1)
+ )
+ )
+ )
+ (drop
+ (local.get $2)
+ )
+ (drop
+ (local.get $2)
+ )
+ )
+ (func $half
+ (local $x i32)
+ (local $1 i64)
+ (local $2 f32)
+ (local.set $x
+ (block (result i32)
+ (local.set $1
+ (i64.const 1024)
+ )
+ (local.set $2
+ (f32.load
+ (local.get $1)
+ )
+ )
+ (i32.load
+ (local.get $1)
+ )
+ )
+ )
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $2)
+ )
+ )
+ (func $copy
+ (local $x i32)
+ (local $y i32)
+ (local $2 i64)
+ (local $3 f32)
+ (local.set $x
+ (block (result i32)
+ (local.set $2
+ (i64.const 1024)
+ )
+ (local.set $3
+ (f32.load
+ (local.get $2)
+ )
+ )
+ (i32.load
+ (local.get $2)
+ )
+ )
+ )
+ (local.set $y
+ (local.get $x)
+ )
+ (drop
+ (local.get $3)
+ )
+ )
+ (func $partial1 (result f32)
+ (f32.reinterpret_i32
+ (i32.load16_u
+ (i64.const 3)
+ )
+ )
+ )
+ (func $partial2 (result f32)
+ (f32.reinterpret_i32
+ (i32.load8_u
+ (i64.const 3)
+ )
+ )
+ )
+ (func $nofallthrough
+ (local $x i32)
+ (local.set $x
+ (i32.load
+ (i64.const 1024)
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block $block (result i32)
+ (nop)
+ (local.get $x)
+ )
+ )
+ )
+ )
+)
diff --git a/test/passes/avoid-reinterprets64.wast b/test/passes/avoid-reinterprets64.wast
new file mode 100644
index 000000000..cfc1843de
--- /dev/null
+++ b/test/passes/avoid-reinterprets64.wast
@@ -0,0 +1,69 @@
+(module
+ (memory i64 1)
+ (func $simple
+ (drop (f32.reinterpret_i32 (i32.load (i64.const 1024))))
+ (drop (i32.reinterpret_f32 (f32.load (i64.const 1024))))
+ (drop (f64.reinterpret_i64 (i64.load (i64.const 1024))))
+ (drop (i64.reinterpret_f64 (f64.load (i64.const 1024))))
+ )
+ (func $one
+ (local $x i32)
+ (local.set $x (i32.load (i64.const 1024)))
+ (drop (f32.reinterpret_i32 (local.get $x)))
+ )
+ (func $one-b
+ (local $x f32)
+ (local.set $x (f32.load (i64.const 1024)))
+ (drop (i32.reinterpret_f32 (local.get $x)))
+ )
+ (func $both
+ (local $x i32)
+ (local.set $x (i32.load (i64.const 1024)))
+ (drop (f32.reinterpret_i32 (local.get $x)))
+ (drop (f32.reinterpret_i32 (local.get $x)))
+ )
+ (func $half
+ (local $x i32)
+ (local.set $x (i32.load (i64.const 1024)))
+ (drop (local.get $x))
+ (drop (f32.reinterpret_i32 (local.get $x)))
+ )
+ (func $copy
+ (local $x i32)
+ (local $y i32)
+ (local.set $x (i32.load (i64.const 1024)))
+ (local.set $y (local.get $x))
+ (drop (f32.reinterpret_i32 (local.get $y)))
+ )
+ (func $partial1 (result f32)
+ (f32.reinterpret_i32
+ (i32.load16_u
+ (i64.const 3)
+ )
+ )
+ )
+ (func $partial2 (result f32)
+ (f32.reinterpret_i32
+ (i32.load8_u
+ (i64.const 3)
+ )
+ )
+ )
+ (func $nofallthrough
+ (local $x i32)
+ (local.set $x
+ (i32.load
+ (i64.const 1024)
+ )
+ )
+ (drop
+ (f32.reinterpret_i32
+ (block (result i32)
+ (nop) ;; this would be removed by other opts, but in general, we can't
+ ;; just look at the fallthrough, as we can't just remove code here
+ (local.get $x)
+ )
+ )
+ )
+ )
+)
diff --git a/test/passes/dealign64.passes b/test/passes/dealign64.passes
new file mode 100644
index 000000000..e731892d8
--- /dev/null
+++ b/test/passes/dealign64.passes
@@ -0,0 +1 @@
+dealign
diff --git a/test/passes/dealign64.txt b/test/passes/dealign64.txt
new file mode 100644
index 000000000..cbbe0b375
--- /dev/null
+++ b/test/passes/dealign64.txt
@@ -0,0 +1,33 @@
+(module
+ (type $none_=>_none (func))
+ (memory $0 i64 1 1)
+ (func $test
+ (drop
+ (i32.load align=1
+ (i64.const 4)
+ )
+ )
+ (drop
+ (i32.load align=1
+ (i64.const 8)
+ )
+ )
+ (drop
+ (i32.load align=1
+ (i64.const 12)
+ )
+ )
+ (i32.store align=1
+ (i64.const 16)
+ (i32.const 28)
+ )
+ (i32.store align=1
+ (i64.const 20)
+ (i32.const 32)
+ )
+ (i32.store align=1
+ (i64.const 24)
+ (i32.const 36)
+ )
+ )
+)
diff --git a/test/passes/dealign64.wast b/test/passes/dealign64.wast
new file mode 100644
index 000000000..bce361106
--- /dev/null
+++ b/test/passes/dealign64.wast
@@ -0,0 +1,11 @@
+(module
+ (memory $0 i64 1 1)
+ (func $test
+ (drop (i32.load (i64.const 4)))
+ (drop (i32.load align=1 (i64.const 8)))
+ (drop (i32.load align=2 (i64.const 12)))
+ (i32.store (i64.const 16) (i32.const 28))
+ (i32.store align=1 (i64.const 20) (i32.const 32))
+ (i32.store align=2 (i64.const 24) (i32.const 36))
+ )
+)
diff --git a/test/passes/instrument-memory64.passes b/test/passes/instrument-memory64.passes
new file mode 100644
index 000000000..3b1583bf9
--- /dev/null
+++ b/test/passes/instrument-memory64.passes
@@ -0,0 +1 @@
+instrument-memory
diff --git a/test/passes/instrument-memory64.txt b/test/passes/instrument-memory64.txt
new file mode 100644
index 000000000..0ef357223
--- /dev/null
+++ b/test/passes/instrument-memory64.txt
@@ -0,0 +1,603 @@
+(module
+ (type $none_=>_none (func))
+ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
+ (type $i32_i32_i64_i64_=>_i64 (func (param i32 i32 i64 i64) (result i64)))
+ (type $i32_i64_=>_i64 (func (param i32 i64) (result i64)))
+ (type $i32_f32_=>_f32 (func (param i32 f32) (result f32)))
+ (type $i32_f64_=>_f64 (func (param i32 f64) (result f64)))
+ (import "env" "load_ptr" (func $load_ptr (param i32 i32 i64 i64) (result i64)))
+ (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32)))
+ (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64)))
+ (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32)))
+ (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64)))
+ (import "env" "store_ptr" (func $store_ptr (param i32 i32 i64 i64) (result i64)))
+ (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32)))
+ (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64)))
+ (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32)))
+ (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64)))
+ (memory $0 i64 256 256)
+ (func $A
+ (drop
+ (call $load_val_i32
+ (i32.const 1)
+ (i32.load8_s
+ (call $load_ptr
+ (i32.const 1)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 2)
+ (i32.load8_u
+ (call $load_ptr
+ (i32.const 2)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 3)
+ (i32.load16_s
+ (call $load_ptr
+ (i32.const 3)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 4)
+ (i32.load16_u
+ (call $load_ptr
+ (i32.const 4)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 5)
+ (i32.load
+ (call $load_ptr
+ (i32.const 5)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 6)
+ (i64.load8_s
+ (call $load_ptr
+ (i32.const 6)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 7)
+ (i64.load8_u
+ (call $load_ptr
+ (i32.const 7)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 8)
+ (i64.load16_s
+ (call $load_ptr
+ (i32.const 8)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 9)
+ (i64.load16_u
+ (call $load_ptr
+ (i32.const 9)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 10)
+ (i64.load32_s
+ (call $load_ptr
+ (i32.const 10)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 11)
+ (i64.load32_u
+ (call $load_ptr
+ (i32.const 11)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 12)
+ (i64.load
+ (call $load_ptr
+ (i32.const 12)
+ (i32.const 8)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_f32
+ (i32.const 13)
+ (f32.load
+ (call $load_ptr
+ (i32.const 13)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_f64
+ (i32.const 14)
+ (f64.load
+ (call $load_ptr
+ (i32.const 14)
+ (i32.const 8)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 15)
+ (i32.load8_s offset=1
+ (call $load_ptr
+ (i32.const 15)
+ (i32.const 1)
+ (i64.const 1)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 16)
+ (i32.load8_u offset=2
+ (call $load_ptr
+ (i32.const 16)
+ (i32.const 1)
+ (i64.const 2)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 17)
+ (i32.load16_s offset=3 align=1
+ (call $load_ptr
+ (i32.const 17)
+ (i32.const 2)
+ (i64.const 3)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 18)
+ (i32.load16_u offset=4 align=1
+ (call $load_ptr
+ (i32.const 18)
+ (i32.const 2)
+ (i64.const 4)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i32
+ (i32.const 19)
+ (i32.load offset=5 align=2
+ (call $load_ptr
+ (i32.const 19)
+ (i32.const 4)
+ (i64.const 5)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 20)
+ (i64.load8_s offset=6
+ (call $load_ptr
+ (i32.const 20)
+ (i32.const 1)
+ (i64.const 6)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 21)
+ (i64.load8_u offset=7
+ (call $load_ptr
+ (i32.const 21)
+ (i32.const 1)
+ (i64.const 7)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 22)
+ (i64.load16_s offset=8 align=1
+ (call $load_ptr
+ (i32.const 22)
+ (i32.const 2)
+ (i64.const 8)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 23)
+ (i64.load16_u offset=9 align=1
+ (call $load_ptr
+ (i32.const 23)
+ (i32.const 2)
+ (i64.const 9)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 24)
+ (i64.load32_s offset=10 align=2
+ (call $load_ptr
+ (i32.const 24)
+ (i32.const 4)
+ (i64.const 10)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 25)
+ (i64.load32_u offset=11 align=2
+ (call $load_ptr
+ (i32.const 25)
+ (i32.const 4)
+ (i64.const 11)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_i64
+ (i32.const 26)
+ (i64.load offset=12 align=2
+ (call $load_ptr
+ (i32.const 26)
+ (i32.const 8)
+ (i64.const 12)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_f32
+ (i32.const 27)
+ (f32.load offset=13 align=2
+ (call $load_ptr
+ (i32.const 27)
+ (i32.const 4)
+ (i64.const 13)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ (drop
+ (call $load_val_f64
+ (i32.const 28)
+ (f64.load offset=14 align=2
+ (call $load_ptr
+ (i32.const 28)
+ (i32.const 8)
+ (i64.const 14)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+ )
+ (func $B
+ (i32.store8
+ (call $store_ptr
+ (i32.const 29)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 29)
+ (i32.const 1)
+ )
+ )
+ (i32.store16
+ (call $store_ptr
+ (i32.const 30)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 30)
+ (i32.const 2)
+ )
+ )
+ (i32.store
+ (call $store_ptr
+ (i32.const 31)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 31)
+ (i32.const 3)
+ )
+ )
+ (i64.store8
+ (call $store_ptr
+ (i32.const 32)
+ (i32.const 1)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 32)
+ (i64.const 4)
+ )
+ )
+ (i64.store16
+ (call $store_ptr
+ (i32.const 33)
+ (i32.const 2)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 33)
+ (i64.const 5)
+ )
+ )
+ (i64.store32
+ (call $store_ptr
+ (i32.const 34)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 34)
+ (i64.const 6)
+ )
+ )
+ (i64.store
+ (call $store_ptr
+ (i32.const 35)
+ (i32.const 8)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 35)
+ (i64.const 7)
+ )
+ )
+ (f32.store
+ (call $store_ptr
+ (i32.const 36)
+ (i32.const 4)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_f32
+ (i32.const 36)
+ (f32.const 8)
+ )
+ )
+ (f64.store
+ (call $store_ptr
+ (i32.const 37)
+ (i32.const 8)
+ (i64.const 0)
+ (i64.const 0)
+ )
+ (call $store_val_f64
+ (i32.const 37)
+ (f64.const 9)
+ )
+ )
+ (i32.store8 offset=1
+ (call $store_ptr
+ (i32.const 38)
+ (i32.const 1)
+ (i64.const 1)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 38)
+ (i32.const 1)
+ )
+ )
+ (i32.store16 offset=2 align=1
+ (call $store_ptr
+ (i32.const 39)
+ (i32.const 2)
+ (i64.const 2)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 39)
+ (i32.const 2)
+ )
+ )
+ (i32.store offset=3 align=2
+ (call $store_ptr
+ (i32.const 40)
+ (i32.const 4)
+ (i64.const 3)
+ (i64.const 0)
+ )
+ (call $store_val_i32
+ (i32.const 40)
+ (i32.const 3)
+ )
+ )
+ (i64.store8 offset=4
+ (call $store_ptr
+ (i32.const 41)
+ (i32.const 1)
+ (i64.const 4)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 41)
+ (i64.const 4)
+ )
+ )
+ (i64.store16 offset=5
+ (call $store_ptr
+ (i32.const 42)
+ (i32.const 2)
+ (i64.const 5)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 42)
+ (i64.const 5)
+ )
+ )
+ (i64.store32 offset=6 align=2
+ (call $store_ptr
+ (i32.const 43)
+ (i32.const 4)
+ (i64.const 6)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 43)
+ (i64.const 6)
+ )
+ )
+ (i64.store offset=7 align=2
+ (call $store_ptr
+ (i32.const 44)
+ (i32.const 8)
+ (i64.const 7)
+ (i64.const 0)
+ )
+ (call $store_val_i64
+ (i32.const 44)
+ (i64.const 7)
+ )
+ )
+ (f32.store offset=8 align=2
+ (call $store_ptr
+ (i32.const 45)
+ (i32.const 4)
+ (i64.const 8)
+ (i64.const 0)
+ )
+ (call $store_val_f32
+ (i32.const 45)
+ (f32.const 8)
+ )
+ )
+ (f64.store offset=9 align=2
+ (call $store_ptr
+ (i32.const 46)
+ (i32.const 8)
+ (i64.const 9)
+ (i64.const 0)
+ )
+ (call $store_val_f64
+ (i32.const 46)
+ (f64.const 9)
+ )
+ )
+ )
+)
diff --git a/test/passes/instrument-memory64.wast b/test/passes/instrument-memory64.wast
new file mode 100644
index 000000000..1524b87f3
--- /dev/null
+++ b/test/passes/instrument-memory64.wast
@@ -0,0 +1,57 @@
+(module
+ (memory i64 256 256)
+ (type $1 (func))
+ (func $A (type $1)
+ (drop (i32.load8_s (i64.const 0)))
+ (drop (i32.load8_u (i64.const 0)))
+ (drop (i32.load16_s (i64.const 0)))
+ (drop (i32.load16_u (i64.const 0)))
+ (drop (i32.load (i64.const 0)))
+ (drop (i64.load8_s (i64.const 0)))
+ (drop (i64.load8_u (i64.const 0)))
+ (drop (i64.load16_s (i64.const 0)))
+ (drop (i64.load16_u (i64.const 0)))
+ (drop (i64.load32_s (i64.const 0)))
+ (drop (i64.load32_u (i64.const 0)))
+ (drop (i64.load (i64.const 0)))
+ (drop (f32.load (i64.const 0)))
+ (drop (f64.load (i64.const 0)))
+
+ (drop (i32.load8_s align=1 offset=1 (i64.const 0)))
+ (drop (i32.load8_u align=1 offset=2 (i64.const 0)))
+ (drop (i32.load16_s align=1 offset=3 (i64.const 0)))
+ (drop (i32.load16_u align=1 offset=4 (i64.const 0)))
+ (drop (i32.load align=2 offset=5 (i64.const 0)))
+ (drop (i64.load8_s align=1 offset=6 (i64.const 0)))
+ (drop (i64.load8_u align=1 offset=7 (i64.const 0)))
+ (drop (i64.load16_s align=1 offset=8 (i64.const 0)))
+ (drop (i64.load16_u align=1 offset=9 (i64.const 0)))
+ (drop (i64.load32_s align=2 offset=10 (i64.const 0)))
+ (drop (i64.load32_u align=2 offset=11 (i64.const 0)))
+ (drop (i64.load align=2 offset=12 (i64.const 0)))
+ (drop (f32.load align=2 offset=13 (i64.const 0)))
+ (drop (f64.load align=2 offset=14 (i64.const 0)))
+ )
+
+ (func $B (type $1)
+ (i32.store8 (i64.const 0) (i32.const 1))
+ (i32.store16 (i64.const 0) (i32.const 2))
+ (i32.store (i64.const 0) (i32.const 3))
+ (i64.store8 (i64.const 0) (i64.const 4))
+ (i64.store16 (i64.const 0) (i64.const 5))
+ (i64.store32 (i64.const 0) (i64.const 6))
+ (i64.store (i64.const 0) (i64.const 7))
+ (f32.store (i64.const 0) (f32.const 8))
+ (f64.store (i64.const 0) (f64.const 9))
+
+ (i32.store8 align=1 offset=1 (i64.const 0) (i32.const 1))
+ (i32.store16 align=1 offset=2 (i64.const 0) (i32.const 2))
+ (i32.store align=2 offset=3 (i64.const 0) (i32.const 3))
+ (i64.store8 align=1 offset=4 (i64.const 0) (i64.const 4))
+ (i64.store16 align=2 offset=5 (i64.const 0) (i64.const 5))
+ (i64.store32 align=2 offset=6 (i64.const 0) (i64.const 6))
+ (i64.store align=2 offset=7 (i64.const 0) (i64.const 7))
+ (f32.store align=2 offset=8 (i64.const 0) (f32.const 8))
+ (f64.store align=2 offset=9 (i64.const 0) (f64.const 9))
+ )
+)
diff --git a/test/passes/safe-heap_enable-threads_enable-simd64.passes b/test/passes/safe-heap_enable-threads_enable-simd64.passes
new file mode 100644
index 000000000..f114a557d
--- /dev/null
+++ b/test/passes/safe-heap_enable-threads_enable-simd64.passes
@@ -0,0 +1 @@
+safe-heap_enable-threads_enable-simd
diff --git a/test/passes/safe-heap_enable-threads_enable-simd64.txt b/test/passes/safe-heap_enable-threads_enable-simd64.txt
new file mode 100644
index 000000000..fcfd59694
--- /dev/null
+++ b/test/passes/safe-heap_enable-threads_enable-simd64.txt
@@ -0,0 +1,8705 @@
+(module
+ (type $i64_i64_=>_i64 (func (param i64 i64) (result i64)))
+ (type $i64_i64_i64_=>_none (func (param i64 i64 i64)))
+ (type $i64_i64_=>_i32 (func (param i64 i64) (result i32)))
+ (type $i64_i64_i32_=>_none (func (param i64 i64 i32)))
+ (type $i64_i64_v128_=>_none (func (param i64 i64 v128)))
+ (type $i64_i64_=>_v128 (func (param i64 i64) (result v128)))
+ (type $none_=>_none (func))
+ (type $i64_i64_f64_=>_none (func (param i64 i64 f64)))
+ (type $i64_i64_=>_f64 (func (param i64 i64) (result f64)))
+ (type $i64_i64_f32_=>_none (func (param i64 i64 f32)))
+ (type $i64_i64_=>_f32 (func (param i64 i64) (result f32)))
+ (type $none_=>_i64 (func (result i64)))
+ (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i64)))
+ (import "env" "segfault" (func $segfault))
+ (import "env" "alignfault" (func $alignfault))
+ (memory $0 (shared i64 100 100))
+ (func $loads
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_4
+ (i64.const 1)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_A
+ (i64.const 1)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_4
+ (i64.const 2)
+ (i64.const 31)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_2
+ (i64.const 3)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_1
+ (i64.const 4)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_1_1
+ (i64.const 5)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_2_U_2
+ (i64.const 6)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i64_1_1
+ (i64.const 7)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i64_2_U_2
+ (i64.const 8)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i64_4_4
+ (i64.const 9)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i64_8_4
+ (i64.const 10)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_i64_8_8
+ (i64.const 11)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_f32_4_4
+ (i64.const 12)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_f64_8_8
+ (i64.const 13)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (call $SAFE_HEAP_LOAD_v128_16_16
+ (i64.const 14)
+ (i64.const 0)
+ )
+ )
+ )
+ (func $stores
+ (call $SAFE_HEAP_STORE_i32_4_4
+ (i64.const 1)
+ (i64.const 0)
+ (i32.const 100)
+ )
+ (call $SAFE_HEAP_STORE_i32_4_A
+ (i64.const 1)
+ (i64.const 0)
+ (i32.const 100)
+ )
+ (call $SAFE_HEAP_STORE_i32_4_4
+ (i64.const 2)
+ (i64.const 31)
+ (i32.const 200)
+ )
+ (call $SAFE_HEAP_STORE_i32_4_2
+ (i64.const 3)
+ (i64.const 0)
+ (i32.const 300)
+ )
+ (call $SAFE_HEAP_STORE_i32_4_1
+ (i64.const 4)
+ (i64.const 0)
+ (i32.const 400)
+ )
+ (call $SAFE_HEAP_STORE_i32_1_1
+ (i64.const 5)
+ (i64.const 0)
+ (i32.const 500)
+ )
+ (call $SAFE_HEAP_STORE_i32_2_2
+ (i64.const 6)
+ (i64.const 0)
+ (i32.const 600)
+ )
+ (call $SAFE_HEAP_STORE_i64_1_1
+ (i64.const 7)
+ (i64.const 0)
+ (i64.const 700)
+ )
+ (call $SAFE_HEAP_STORE_i64_2_2
+ (i64.const 8)
+ (i64.const 0)
+ (i64.const 800)
+ )
+ (call $SAFE_HEAP_STORE_i64_4_4
+ (i64.const 9)
+ (i64.const 0)
+ (i64.const 900)
+ )
+ (call $SAFE_HEAP_STORE_i64_8_4
+ (i64.const 10)
+ (i64.const 0)
+ (i64.const 1000)
+ )
+ (call $SAFE_HEAP_STORE_i64_8_8
+ (i64.const 11)
+ (i64.const 0)
+ (i64.const 1100)
+ )
+ (call $SAFE_HEAP_STORE_f32_4_4
+ (i64.const 12)
+ (i64.const 0)
+ (f32.const 1200)
+ )
+ (call $SAFE_HEAP_STORE_f64_8_8
+ (i64.const 13)
+ (i64.const 0)
+ (f64.const 1300)
+ )
+ (call $SAFE_HEAP_STORE_v128_16_16
+ (i64.const 14)
+ (i64.const 0)
+ (v128.const i32x4 0x00000001 0x00000002 0x00000003 0x00000004)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load8_u
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_U_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.atomic.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load16_u
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_4 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load8_u
+ (local.get $2)
+ )
+ (i64.const 56)
+ )
+ (i64.const 56)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.atomic.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load16_u
+ (local.get $2)
+ )
+ (i64.const 48)
+ )
+ (i64.const 48)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load32_u
+ (local.get $2)
+ )
+ (i64.const 32)
+ )
+ (i64.const 32)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load32_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_8 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_1 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_2 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_4 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_1 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_2 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_4 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_8 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_1 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_2 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_4 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_8 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=8
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_16 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_1_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.atomic.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_1_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_4 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_1_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.atomic.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_1_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store32 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store32 align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store32
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store32
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_8 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_1 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_2 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_4 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_1 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_2 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_4 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_8 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_1 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_2 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_4 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_8 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_16 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+)
+(module
+ (type $i64_i64_=>_i64 (func (param i64 i64) (result i64)))
+ (type $i64_i64_i64_=>_none (func (param i64 i64 i64)))
+ (type $i64_i64_=>_i32 (func (param i64 i64) (result i32)))
+ (type $i64_i64_i32_=>_none (func (param i64 i64 i32)))
+ (type $i64_i64_v128_=>_none (func (param i64 i64 v128)))
+ (type $i64_i64_=>_v128 (func (param i64 i64) (result v128)))
+ (type $i64_i64_f64_=>_none (func (param i64 i64 f64)))
+ (type $i64_i64_=>_f64 (func (param i64 i64) (result f64)))
+ (type $none_=>_none (func))
+ (type $i64_i64_f32_=>_none (func (param i64 i64 f32)))
+ (type $i64_i64_=>_f32 (func (param i64 i64) (result f32)))
+ (type $none_=>_i64 (func (result i64)))
+ (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i64)))
+ (import "env" "segfault" (func $segfault))
+ (import "env" "alignfault" (func $alignfault))
+ (memory $0 i64 100 100)
+ (func $loads
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_4
+ (i64.const 1)
+ (i64.const 0)
+ )
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_4 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_8 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_1 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_2 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_4 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_1 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_2 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_4 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_8 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_1 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_2 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_4 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_8 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=8
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_16 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_1_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_4 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_1_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store32 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store32 align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store32
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_8 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_1 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_2 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_4 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_1 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_2 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_4 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_8 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_1 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_2 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_4 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_8 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_16 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (call $emscripten_get_sbrk_ptr)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+)
+(module
+ (type $i64_i64_=>_i64 (func (param i64 i64) (result i64)))
+ (type $i64_i64_i64_=>_none (func (param i64 i64 i64)))
+ (type $i64_i64_=>_i32 (func (param i64 i64) (result i32)))
+ (type $i64_i64_i32_=>_none (func (param i64 i64 i32)))
+ (type $i64_i64_v128_=>_none (func (param i64 i64 v128)))
+ (type $i64_i64_=>_v128 (func (param i64 i64) (result v128)))
+ (type $i64_i64_f64_=>_none (func (param i64 i64 f64)))
+ (type $i64_i64_=>_f64 (func (param i64 i64) (result f64)))
+ (type $none_=>_none (func))
+ (type $i64_i64_f32_=>_none (func (param i64 i64 f32)))
+ (type $i64_i64_=>_f32 (func (param i64 i64) (result f32)))
+ (import "env" "DYNAMICTOP_PTR" (global $DYNAMICTOP_PTR i32))
+ (import "env" "segfault" (func $segfault))
+ (import "env" "alignfault" (func $alignfault))
+ (memory $0 (shared i64 100 100))
+ (func $actions
+ (drop
+ (call $SAFE_HEAP_LOAD_i32_4_4
+ (i64.const 1)
+ (i64.const 0)
+ )
+ )
+ (call $SAFE_HEAP_STORE_i32_4_4
+ (i64.const 1)
+ (i64.const 0)
+ (i32.const 100)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load8_u
+ (local.get $2)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_U_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.atomic.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_1_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.shr_s
+ (i32.shl
+ (i32.atomic.load16_u
+ (local.get $2)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_2_U_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_1 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_2 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_A (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i32_4_4 (param $0 i64) (param $1 i64) (result i32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load8_u
+ (local.get $2)
+ )
+ (i64.const 56)
+ )
+ (i64.const 56)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.atomic.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_1_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load8_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load16_u
+ (local.get $2)
+ )
+ (i64.const 48)
+ )
+ (i64.const 48)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load16_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_2_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load16_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_s align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.shr_s
+ (i64.shl
+ (i64.atomic.load32_u
+ (local.get $2)
+ )
+ (i64.const 32)
+ )
+ (i64.const 32)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_s
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load32_u align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load32_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_4_U_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load32_u
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_1 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_2 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_4 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_A (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_i64_8_8 (param $0 i64) (param $1 i64) (result i64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_1 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_2 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f32_4_4 (param $0 i64) (param $1 i64) (result f32)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_1 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_2 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_4 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_f64_8_8 (param $0 i64) (param $1 i64) (result f64)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_1 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.load align=1
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_2 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=2
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_4 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=4
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_8 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.load align=8
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_LOAD_v128_16_16 (param $0 i64) (param $1 i64) (result v128)
+ (local $2 i64)
+ (local.set $2
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $2)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $2)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $2)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.load
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_1_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.atomic.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_1_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_2_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_1 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_2 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_A (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.atomic.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i32_4_4 (param $0 i64) (param $1 i64) (param $2 i32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_1_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.atomic.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_1_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 1)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store16 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_2_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 2)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store16
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store32 align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store32 align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store32
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_4_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store32
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_1 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (i64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_2 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_4 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (i64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_A (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.atomic.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_i64_8_8 (param $0 i64) (param $1 i64) (param $2 i64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (i64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_1 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f32.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_2 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f32.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f32_4_4 (param $0 i64) (param $1 i64) (param $2 f32)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 4)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f32.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_1 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (f64.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_2 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_4 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (f64.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_f64_8_8 (param $0 i64) (param $1 i64) (param $2 f64)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 8)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (f64.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_1 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (v128.store align=1
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_2 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 1)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=2
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_4 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 3)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=4
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_8 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 7)
+ )
+ (call $alignfault)
+ )
+ (v128.store align=8
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+ (func $SAFE_HEAP_STORE_v128_16_16 (param $0 i64) (param $1 i64) (param $2 v128)
+ (local $3 i64)
+ (local.set $3
+ (i64.add
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (if
+ (i32.or
+ (i64.eq
+ (local.get $3)
+ (i64.const 0)
+ )
+ (i64.gt_u
+ (i64.add
+ (local.get $3)
+ (i64.const 16)
+ )
+ (i64.load
+ (global.get $DYNAMICTOP_PTR)
+ )
+ )
+ )
+ (call $segfault)
+ )
+ (if
+ (i32.and
+ (i32.wrap_i64
+ (local.get $3)
+ )
+ (i32.const 15)
+ )
+ (call $alignfault)
+ )
+ (v128.store
+ (local.get $3)
+ (local.get $2)
+ )
+ )
+)
diff --git a/test/passes/safe-heap_enable-threads_enable-simd64.wast b/test/passes/safe-heap_enable-threads_enable-simd64.wast
new file mode 100644
index 000000000..1907479f4
--- /dev/null
+++ b/test/passes/safe-heap_enable-threads_enable-simd64.wast
@@ -0,0 +1,56 @@
+(module
+ (memory (shared i64 100 100))
+ (func $loads
+ (drop (i32.load (i64.const 1)))
+ (drop (i32.atomic.load (i64.const 1)))
+ (drop (i32.load offset=31 (i64.const 2)))
+ (drop (i32.load align=2 (i64.const 3)))
+ (drop (i32.load align=1 (i64.const 4)))
+ (drop (i32.load8_s (i64.const 5)))
+ (drop (i32.load16_u (i64.const 6)))
+ (drop (i64.load8_s (i64.const 7)))
+ (drop (i64.load16_u (i64.const 8)))
+ (drop (i64.load32_s (i64.const 9)))
+ (drop (i64.load align=4 (i64.const 10)))
+ (drop (i64.load (i64.const 11)))
+ (drop (f32.load (i64.const 12)))
+ (drop (f64.load (i64.const 13)))
+ (drop (v128.load (i64.const 14)))
+ )
+ (func $stores
+ (i32.store (i64.const 1) (i32.const 100))
+ (i32.atomic.store (i64.const 1) (i32.const 100))
+ (i32.store offset=31 (i64.const 2) (i32.const 200))
+ (i32.store align=2 (i64.const 3) (i32.const 300))
+ (i32.store align=1 (i64.const 4) (i32.const 400))
+ (i32.store8 (i64.const 5) (i32.const 500))
+ (i32.store16 (i64.const 6) (i32.const 600))
+ (i64.store8 (i64.const 7) (i64.const 700))
+ (i64.store16 (i64.const 8) (i64.const 800))
+ (i64.store32 (i64.const 9) (i64.const 900))
+ (i64.store align=4 (i64.const 10) (i64.const 1000))
+ (i64.store (i64.const 11) (i64.const 1100))
+ (f32.store (i64.const 12) (f32.const 1200))
+ (f64.store (i64.const 13) (f64.const 1300))
+ (v128.store (i64.const 14) (v128.const i32x4 1 2 3 4))
+ )
+)
+;; not shared
+(module
+ (memory i64 100 100)
+ (func $loads
+ (drop (i32.load (i64.const 1)))
+ )
+)
+;; pre-existing
+(module
+ (type $FUNCSIG$v (func))
+ (import "env" "DYNAMICTOP_PTR" (global $DYNAMICTOP_PTR i32))
+ (import "env" "segfault" (func $segfault))
+ (import "env" "alignfault" (func $alignfault))
+ (memory $0 (shared i64 100 100))
+ (func $actions
+ (drop (i32.load (i64.const 1)))
+ (i32.store (i64.const 1) (i32.const 100))
+ )
+)
diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt
index 33ce4d81a..18cee797f 100644
--- a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt
+++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt
@@ -9,6 +9,7 @@
--enable-reference-types
--enable-multivalue
--enable-gc
+--enable-memory64
(module
(type $none_=>_v128_externref (func (result v128 externref)))
(func $foo (result v128 externref)
diff --git a/test/simd64.wast b/test/simd64.wast
new file mode 100644
index 000000000..65b1ef8b7
--- /dev/null
+++ b/test/simd64.wast
@@ -0,0 +1,74 @@
+(module
+ (memory i64 1 1)
+ (func $v128.load (param $0 i64) (result v128)
+ (v128.load offset=0 align=16
+ (local.get $0)
+ )
+ )
+ (func $v128.store (param $0 i64) (param $1 v128)
+ (v128.store offset=0 align=16
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v8x16.load_splat (param $0 i64) (result v128)
+ (v8x16.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v16x8.load_splat (param $0 i64) (result v128)
+ (v16x8.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v32x4.load_splat (param $0 i64) (result v128)
+ (v32x4.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v64x2.load_splat (param $0 i64) (result v128)
+ (v64x2.load_splat
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_u (param $0 i64) (result v128)
+ (i16x8.load8x8_u
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_s (param $0 i64) (result v128)
+ (i16x8.load8x8_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_s (param $0 i64) (result v128)
+ (i32x4.load16x4_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_u (param $0 i64) (result v128)
+ (i32x4.load16x4_u
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_s (param $0 i64) (result v128)
+ (i64x2.load32x2_s
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_u (param $0 i64) (result v128)
+ (i64x2.load32x2_u
+ (local.get $0)
+ )
+ )
+ (func $v128.load32_zero (param $0 i64) (result v128)
+ (v128.load32_zero
+ (local.get $0)
+ )
+ )
+ (func $v128.load64_zero (param $0 i64) (result v128)
+ (v128.load64_zero
+ (local.get $0)
+ )
+ )
+)
diff --git a/test/simd64.wast.from-wast b/test/simd64.wast.from-wast
new file mode 100644
index 000000000..cd08c79ed
--- /dev/null
+++ b/test/simd64.wast.from-wast
@@ -0,0 +1,76 @@
+(module
+ (type $i64_=>_v128 (func (param i64) (result v128)))
+ (type $i64_v128_=>_none (func (param i64 v128)))
+ (memory $0 i64 1 1)
+ (func $v128.load (param $0 i64) (result v128)
+ (v128.load
+ (local.get $0)
+ )
+ )
+ (func $v128.store (param $0 i64) (param $1 v128)
+ (v128.store
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v8x16.load_splat (param $0 i64) (result v128)
+ (v8x16.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v16x8.load_splat (param $0 i64) (result v128)
+ (v16x8.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v32x4.load_splat (param $0 i64) (result v128)
+ (v32x4.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v64x2.load_splat (param $0 i64) (result v128)
+ (v64x2.load_splat
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_u (param $0 i64) (result v128)
+ (i16x8.load8x8_u
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_s (param $0 i64) (result v128)
+ (i16x8.load8x8_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_s (param $0 i64) (result v128)
+ (i32x4.load16x4_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_u (param $0 i64) (result v128)
+ (i32x4.load16x4_u
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_s (param $0 i64) (result v128)
+ (i64x2.load32x2_s
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_u (param $0 i64) (result v128)
+ (i64x2.load32x2_u
+ (local.get $0)
+ )
+ )
+ (func $v128.load32_zero (param $0 i64) (result v128)
+ (v128.load32_zero
+ (local.get $0)
+ )
+ )
+ (func $v128.load64_zero (param $0 i64) (result v128)
+ (v128.load64_zero
+ (local.get $0)
+ )
+ )
+)
diff --git a/test/simd64.wast.fromBinary b/test/simd64.wast.fromBinary
new file mode 100644
index 000000000..6202b7c06
--- /dev/null
+++ b/test/simd64.wast.fromBinary
@@ -0,0 +1,77 @@
+(module
+ (type $i64_=>_v128 (func (param i64) (result v128)))
+ (type $i64_v128_=>_none (func (param i64 v128)))
+ (memory $0 i64 1 1)
+ (func $v128.load (param $0 i64) (result v128)
+ (v128.load
+ (local.get $0)
+ )
+ )
+ (func $v128.store (param $0 i64) (param $1 v128)
+ (v128.store
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v8x16.load_splat (param $0 i64) (result v128)
+ (v8x16.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v16x8.load_splat (param $0 i64) (result v128)
+ (v16x8.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v32x4.load_splat (param $0 i64) (result v128)
+ (v32x4.load_splat
+ (local.get $0)
+ )
+ )
+ (func $v64x2.load_splat (param $0 i64) (result v128)
+ (v64x2.load_splat
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_u (param $0 i64) (result v128)
+ (i16x8.load8x8_u
+ (local.get $0)
+ )
+ )
+ (func $i16x8.load8x8_s (param $0 i64) (result v128)
+ (i16x8.load8x8_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_s (param $0 i64) (result v128)
+ (i32x4.load16x4_s
+ (local.get $0)
+ )
+ )
+ (func $i32x4.load16x4_u (param $0 i64) (result v128)
+ (i32x4.load16x4_u
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_s (param $0 i64) (result v128)
+ (i64x2.load32x2_s
+ (local.get $0)
+ )
+ )
+ (func $i64x2.load32x2_u (param $0 i64) (result v128)
+ (i64x2.load32x2_u
+ (local.get $0)
+ )
+ )
+ (func $v128.load32_zero (param $0 i64) (result v128)
+ (v128.load32_zero
+ (local.get $0)
+ )
+ )
+ (func $v128.load64_zero (param $0 i64) (result v128)
+ (v128.load64_zero
+ (local.get $0)
+ )
+ )
+)
+
diff --git a/test/simd64.wast.fromBinary.noDebugInfo b/test/simd64.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..67ce14b29
--- /dev/null
+++ b/test/simd64.wast.fromBinary.noDebugInfo
@@ -0,0 +1,77 @@
+(module
+ (type $i64_=>_v128 (func (param i64) (result v128)))
+ (type $i64_v128_=>_none (func (param i64 v128)))
+ (memory $0 i64 1 1)
+ (func $0 (param $0 i64) (result v128)
+ (v128.load
+ (local.get $0)
+ )
+ )
+ (func $1 (param $0 i64) (param $1 v128)
+ (v128.store
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $2 (param $0 i64) (result v128)
+ (v8x16.load_splat
+ (local.get $0)
+ )
+ )
+ (func $3 (param $0 i64) (result v128)
+ (v16x8.load_splat
+ (local.get $0)
+ )
+ )
+ (func $4 (param $0 i64) (result v128)
+ (v32x4.load_splat
+ (local.get $0)
+ )
+ )
+ (func $5 (param $0 i64) (result v128)
+ (v64x2.load_splat
+ (local.get $0)
+ )
+ )
+ (func $6 (param $0 i64) (result v128)
+ (i16x8.load8x8_u
+ (local.get $0)
+ )
+ )
+ (func $7 (param $0 i64) (result v128)
+ (i16x8.load8x8_s
+ (local.get $0)
+ )
+ )
+ (func $8 (param $0 i64) (result v128)
+ (i32x4.load16x4_s
+ (local.get $0)
+ )
+ )
+ (func $9 (param $0 i64) (result v128)
+ (i32x4.load16x4_u
+ (local.get $0)
+ )
+ )
+ (func $10 (param $0 i64) (result v128)
+ (i64x2.load32x2_s
+ (local.get $0)
+ )
+ )
+ (func $11 (param $0 i64) (result v128)
+ (i64x2.load32x2_u
+ (local.get $0)
+ )
+ )
+ (func $12 (param $0 i64) (result v128)
+ (v128.load32_zero
+ (local.get $0)
+ )
+ )
+ (func $13 (param $0 i64) (result v128)
+ (v128.load64_zero
+ (local.get $0)
+ )
+ )
+)
+
diff --git a/test/spec/address64.wast b/test/spec/address64.wast
new file mode 100644
index 000000000..0003e5d00
--- /dev/null
+++ b/test/spec/address64.wast
@@ -0,0 +1,589 @@
+;; Load i32 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i64) (result i32)
+ (i32.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i64) (result i32)
+ (i32.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i64) (result i32)
+ (i32.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i64) (result i32)
+ (i32.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i64) (result i32)
+ (i32.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i64) (result i32)
+ (i32.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i64) (result i32)
+ (i32.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i64) (result i32)
+ (i32.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i64) (result i32)
+ (i32.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i64) (result i32)
+ (i32.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i64) (result i32)
+ (i32.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i64) (result i32)
+ (i32.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i64) (result i32)
+ (i32.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i64) (result i32)
+ (i32.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i64) (result i32)
+ (i32.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i64) (result i32)
+ (i32.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i64) (result i32)
+ (i32.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i64) (result i32)
+ (i32.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i64) (result i32)
+ (i32.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i64) (result i32)
+ (i32.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32_good1") (param $i i64) (result i32)
+ (i32.load offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good2") (param $i i64) (result i32)
+ (i32.load align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good3") (param $i i64) (result i32)
+ (i32.load offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32_good4") (param $i i64) (result i32)
+ (i32.load offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32_good5") (param $i i64) (result i32)
+ (i32.load offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i64)
+ (drop (i32.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i64)
+ (drop (i32.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i64)
+ (drop (i32.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i64)
+ (drop (i32.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32_bad") (param $i i64)
+ (drop (i32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good2" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good3" (i64.const 0)) (i32.const 98))
+(assert_return (invoke "8u_good4" (i64.const 0)) (i32.const 99))
+(assert_return (invoke "8u_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "8s_good1" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good2" (i64.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good3" (i64.const 0)) (i32.const 98))
+(assert_return (invoke "8s_good4" (i64.const 0)) (i32.const 99))
+(assert_return (invoke "8s_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "16u_good1" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good2" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good3" (i64.const 0)) (i32.const 25442))
+(assert_return (invoke "16u_good4" (i64.const 0)) (i32.const 25699))
+(assert_return (invoke "16u_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "16s_good1" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good2" (i64.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good3" (i64.const 0)) (i32.const 25442))
+(assert_return (invoke "16s_good4" (i64.const 0)) (i32.const 25699))
+(assert_return (invoke "16s_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "32_good1" (i64.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good2" (i64.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good3" (i64.const 0)) (i32.const 1701077858))
+(assert_return (invoke "32_good4" (i64.const 0)) (i32.const 1717920867))
+(assert_return (invoke "32_good5" (i64.const 0)) (i32.const 122))
+
+(assert_return (invoke "8u_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good2" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good3" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good4" (i64.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good5" (i64.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8u_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65508)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good2" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good3" (i64.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good4" (i64.const 65508)) (i32.const 0))
+(assert_trap (invoke "32_good5" (i64.const 65508)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 1)) "out of bounds memory access")
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (drop (i32.load offset=4294967296 (i64.const 0))))"
+ )
+ "i32 constant"
+)
+
+;; Load i64 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i64) (result i64)
+ (i64.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i64) (result i64)
+ (i64.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i64) (result i64)
+ (i64.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i64) (result i64)
+ (i64.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i64) (result i64)
+ (i64.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i64) (result i64)
+ (i64.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i64) (result i64)
+ (i64.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i64) (result i64)
+ (i64.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i64) (result i64)
+ (i64.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i64) (result i64)
+ (i64.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i64) (result i64)
+ (i64.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i64) (result i64)
+ (i64.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i64) (result i64)
+ (i64.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i64) (result i64)
+ (i64.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i64) (result i64)
+ (i64.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i64) (result i64)
+ (i64.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i64) (result i64)
+ (i64.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i64) (result i64)
+ (i64.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i64) (result i64)
+ (i64.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i64) (result i64)
+ (i64.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32u_good1") (param $i i64) (result i64)
+ (i64.load32_u offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good2") (param $i i64) (result i64)
+ (i64.load32_u align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good3") (param $i i64) (result i64)
+ (i64.load32_u offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32u_good4") (param $i i64) (result i64)
+ (i64.load32_u offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32u_good5") (param $i i64) (result i64)
+ (i64.load32_u offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "32s_good1") (param $i i64) (result i64)
+ (i64.load32_s offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good2") (param $i i64) (result i64)
+ (i64.load32_s align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good3") (param $i i64) (result i64)
+ (i64.load32_s offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32s_good4") (param $i i64) (result i64)
+ (i64.load32_s offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32s_good5") (param $i i64) (result i64)
+ (i64.load32_s offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "64_good1") (param $i i64) (result i64)
+ (i64.load offset=0 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good2") (param $i i64) (result i64)
+ (i64.load align=1 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good3") (param $i i64) (result i64)
+ (i64.load offset=1 align=1 (local.get $i)) ;; 0x6968676665646362 'bcdefghi'
+ )
+ (func (export "64_good4") (param $i i64) (result i64)
+ (i64.load offset=2 align=2 (local.get $i)) ;; 0x6a69686766656463 'cdefghij'
+ )
+ (func (export "64_good5") (param $i i64) (result i64)
+ (i64.load offset=25 align=8 (local.get $i)) ;; 122 'z\0\0\0\0\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i64)
+ (drop (i64.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i64)
+ (drop (i64.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i64)
+ (drop (i64.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i64)
+ (drop (i64.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32u_bad") (param $i i64)
+ (drop (i64.load32_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "32s_bad") (param $i i64)
+ (drop (i64.load32_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "64_bad") (param $i i64)
+ (drop (i64.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good2" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good3" (i64.const 0)) (i64.const 98))
+(assert_return (invoke "8u_good4" (i64.const 0)) (i64.const 99))
+(assert_return (invoke "8u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "8s_good1" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good2" (i64.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good3" (i64.const 0)) (i64.const 98))
+(assert_return (invoke "8s_good4" (i64.const 0)) (i64.const 99))
+(assert_return (invoke "8s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "16u_good1" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good2" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good3" (i64.const 0)) (i64.const 25442))
+(assert_return (invoke "16u_good4" (i64.const 0)) (i64.const 25699))
+(assert_return (invoke "16u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "16s_good1" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good2" (i64.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good3" (i64.const 0)) (i64.const 25442))
+(assert_return (invoke "16s_good4" (i64.const 0)) (i64.const 25699))
+(assert_return (invoke "16s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "32u_good1" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good2" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good3" (i64.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32u_good4" (i64.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32u_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "32s_good1" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good2" (i64.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good3" (i64.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32s_good4" (i64.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32s_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "64_good1" (i64.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good2" (i64.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good3" (i64.const 0)) (i64.const 0x6968676665646362))
+(assert_return (invoke "64_good4" (i64.const 0)) (i64.const 0x6a69686766656463))
+(assert_return (invoke "64_good5" (i64.const 0)) (i64.const 122))
+
+(assert_return (invoke "8u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good2" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good3" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good4" (i64.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good5" (i64.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i64.const 65504)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good2" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good3" (i64.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good4" (i64.const 65504)) (i64.const 0))
+(assert_trap (invoke "64_good5" (i64.const 65504)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i64.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 1)) "out of bounds memory access")
+
+;; Load f32 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\a0\7f\01\00\d0\7f")
+
+ (func (export "32_good1") (param $i i64) (result f32)
+ (f32.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good2") (param $i i64) (result f32)
+ (f32.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good3") (param $i i64) (result f32)
+ (f32.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good4") (param $i i64) (result f32)
+ (f32.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00'
+ )
+ (func (export "32_good5") (param $i i64) (result f32)
+ (f32.load offset=8 align=4 (local.get $i)) ;; nan:0x500001 '\01\00\d0\7f'
+ )
+ (func (export "32_bad") (param $i i64)
+ (drop (f32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "32_good1" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "32_good5" (i64.const 0)) (f32.const nan:0x500001))
+
+(assert_return (invoke "32_good1" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 65524)) (f32.const 0.0))
+(assert_return (invoke "32_good5" (i64.const 65524)) (f32.const 0.0))
+
+(assert_return (invoke "32_good1" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good2" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good3" (i64.const 65525)) (f32.const 0.0))
+(assert_return (invoke "32_good4" (i64.const 65525)) (f32.const 0.0))
+(assert_trap (invoke "32_good5" (i64.const 65525)) "out of bounds memory access")
+
+(assert_trap (invoke "32_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i64.const 1)) "out of bounds memory access")
+
+;; Load f64 data with different offset/align arguments
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f\01\00\00\00\00\00\fc\7f")
+
+ (func (export "64_good1") (param $i i64) (result f64)
+ (f64.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good2") (param $i i64) (result f64)
+ (f64.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good3") (param $i i64) (result f64)
+ (f64.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good4") (param $i i64) (result f64)
+ (f64.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+ )
+ (func (export "64_good5") (param $i i64) (result f64)
+ (f64.load offset=18 align=8 (local.get $i)) ;; nan:0xc000000000001 '\01\00\00\00\00\00\fc\7f'
+ )
+ (func (export "64_bad") (param $i i64)
+ (drop (f64.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "64_good1" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "64_good5" (i64.const 0)) (f64.const nan:0xc000000000001))
+
+(assert_return (invoke "64_good1" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 65510)) (f64.const 0.0))
+(assert_return (invoke "64_good5" (i64.const 65510)) (f64.const 0.0))
+
+(assert_return (invoke "64_good1" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good2" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good3" (i64.const 65511)) (f64.const 0.0))
+(assert_return (invoke "64_good4" (i64.const 65511)) (f64.const 0.0))
+(assert_trap (invoke "64_good5" (i64.const 65511)) "out of bounds memory access")
+
+(assert_trap (invoke "64_bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i64.const 1)) "out of bounds memory access")
diff --git a/test/spec/align64.wast b/test/spec/align64.wast
new file mode 100644
index 000000000..da34947f6
--- /dev/null
+++ b/test/spec/align64.wast
@@ -0,0 +1,866 @@
+;; Test alignment annotation rules
+
+(module (memory i64 0) (func (drop (i32.load8_s align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load8_u align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load16_s align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load16_u align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i32.load align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load8_s align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load8_u align=1 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load16_s align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load16_u align=2 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load32_s align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load32_u align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (i64.load align=8 (i64.const 0)))))
+(module (memory i64 0) (func (drop (f32.load align=4 (i64.const 0)))))
+(module (memory i64 0) (func (drop (f64.load align=8 (i64.const 0)))))
+(module (memory i64 0) (func (i32.store8 align=1 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i32.store16 align=2 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i32.store align=4 (i64.const 0) (i32.const 1))))
+(module (memory i64 0) (func (i64.store8 align=1 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store16 align=2 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store32 align=4 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (i64.store align=8 (i64.const 0) (i64.const 1))))
+(module (memory i64 0) (func (f32.store align=4 (i64.const 0) (f32.const 1.0))))
+(module (memory i64 0) (func (f64.store align=8 (i64.const 0) (f64.const 1.0))))
+
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load8_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load16_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i32.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load8_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load16_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_s align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_s align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_u align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load32_u align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (i64.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f32.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f32.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f64.load align=0 (i64.const 0)))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (drop (f64.load align=7 (i64.const 0)))))"
+ )
+ "alignment"
+)
+
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store8 align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store8 align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store16 align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store16 align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store align=0 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i32.store align=7 (i64.const 0) (i32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store8 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store8 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store16 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store16 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store32 align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store32 align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store align=0 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (i64.store align=7 (i64.const 0) (i64.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f32.store align=0 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f32.store align=7 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f64.store align=0 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+(assert_malformed
+ (module quote
+ "(module (memory i64 0) (func (f64.store align=7 (i64.const 0) (f32.const 0))))"
+ )
+ "alignment"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_s align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_u align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_s align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load8_u align=2 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_s align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load16_u align=4 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_s align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load32_u align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (i64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f32.load align=8 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (drop (f64.load align=16 (i64.const 0)))))
+ "alignment must not be larger than natural"
+)
+
+(assert_invalid
+ (module (memory i64 0) (func (i32.store8 align=2 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i32.store16 align=4 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i32.store align=8 (i64.const 0) (i32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store8 align=2 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store16 align=4 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store32 align=8 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (i64.store align=16 (i64.const 0) (i64.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (f32.store align=8 (i64.const 0) (f32.const 0))))
+ "alignment must not be larger than natural"
+)
+(assert_invalid
+ (module (memory i64 0) (func (f64.store align=16 (i64.const 0) (f64.const 0))))
+ "alignment must not be larger than natural"
+)
+
+;; Test aligned and unaligned read/write
+
+(module
+ (memory i64 1)
+
+ ;; $default: natural alignment, $1: align=1, $2: align=2, $4: align=4, $8: align=8
+
+ (func (export "f32_align_switch") (param i32) (result f32)
+ (local f32 f32)
+ (local.set 1 (f32.const 10.0))
+ (block $4
+ (block $2
+ (block $1
+ (block $default
+ (block $0
+ (br_table $0 $default $1 $2 $4 (local.get 0))
+ ) ;; 0
+ (f32.store (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load (i64.const 0)))
+ (br $4)
+ ) ;; default
+ (f32.store align=1 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=1 (i64.const 0)))
+ (br $4)
+ ) ;; 1
+ (f32.store align=2 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=2 (i64.const 0)))
+ (br $4)
+ ) ;; 2
+ (f32.store align=4 (i64.const 0) (local.get 1))
+ (local.set 2 (f32.load align=4 (i64.const 0)))
+ ) ;; 4
+ (local.get 2)
+ )
+
+ (func (export "f64_align_switch") (param i32) (result f64)
+ (local f64 f64)
+ (local.set 1 (f64.const 10.0))
+ (block $8
+ (block $4
+ (block $2
+ (block $1
+ (block $default
+ (block $0
+ (br_table $0 $default $1 $2 $4 $8 (local.get 0))
+ ) ;; 0
+ (f64.store (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load (i64.const 0)))
+ (br $8)
+ ) ;; default
+ (f64.store align=1 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=1 (i64.const 0)))
+ (br $8)
+ ) ;; 1
+ (f64.store align=2 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=2 (i64.const 0)))
+ (br $8)
+ ) ;; 2
+ (f64.store align=4 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=4 (i64.const 0)))
+ (br $8)
+ ) ;; 4
+ (f64.store align=8 (i64.const 0) (local.get 1))
+ (local.set 2 (f64.load align=8 (i64.const 0)))
+ ) ;; 8
+ (local.get 2)
+ )
+
+ ;; $8s: i32/i64.load8_s, $8u: i32/i64.load8_u, $16s: i32/i64.load16_s, $16u: i32/i64.load16_u, $32: i32.load
+ ;; $32s: i64.load32_s, $32u: i64.load32_u, $64: i64.load
+
+ (func (export "i32_align_switch") (param i32 i32) (result i32)
+ (local i32 i32)
+ (local.set 2 (i32.const 10))
+ (block $32
+ (block $16u
+ (block $16s
+ (block $8u
+ (block $8s
+ (block $0
+ (br_table $0 $8s $8u $16s $16u $32 (local.get 0))
+ ) ;; 0
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_s align=1 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 8s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load8_u align=1 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 8u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_s align=2 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 16s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load16_u align=2 (i64.const 0)))
+ )
+ )
+ (br $32)
+ ) ;; 16u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i32.store (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i32.store align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i32.store align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i32.store align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i32.load align=4 (i64.const 0)))
+ )
+ )
+ ) ;; 32
+ (local.get 3)
+ )
+
+ (func (export "i64_align_switch") (param i32 i32) (result i64)
+ (local i64 i64)
+ (local.set 2 (i64.const 10))
+ (block $64
+ (block $32u
+ (block $32s
+ (block $16u
+ (block $16s
+ (block $8u
+ (block $8s
+ (block $0
+ (br_table $0 $8s $8u $16s $16u $32s $32u $64 (local.get 0))
+ ) ;; 0
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_s align=1 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 8s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store8 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load8_u align=1 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 8u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_s align=2 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 16s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store16 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store16 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store16 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load16_u align=2 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 16u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store32 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store32 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store32 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store32 align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_s align=4 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 32s
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store32 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store32 align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store32 align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store32 align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load32_u align=4 (i64.const 0)))
+ )
+ )
+ (br $64)
+ ) ;; 32u
+ (if (i32.eq (local.get 1) (i32.const 0))
+ (then
+ (i64.store (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 1))
+ (then
+ (i64.store align=1 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=1 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 2))
+ (then
+ (i64.store align=2 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=2 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 4))
+ (then
+ (i64.store align=4 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=4 (i64.const 0)))
+ )
+ )
+ (if (i32.eq (local.get 1) (i32.const 8))
+ (then
+ (i64.store align=8 (i64.const 0) (local.get 2))
+ (local.set 3 (i64.load align=8 (i64.const 0)))
+ )
+ )
+ ) ;; 64
+ (local.get 3)
+ )
+)
+
+(assert_return (invoke "f32_align_switch" (i32.const 0)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 1)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 2)) (f32.const 10.0))
+(assert_return (invoke "f32_align_switch" (i32.const 3)) (f32.const 10.0))
+
+(assert_return (invoke "f64_align_switch" (i32.const 0)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 1)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 2)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 3)) (f64.const 10.0))
+(assert_return (invoke "f64_align_switch" (i32.const 4)) (f64.const 10.0))
+
+(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 0)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 1)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 2)) (i32.const 10))
+(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 4)) (i32.const 10))
+
+(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 0)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 1)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 2)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 4)) (i64.const 10))
+(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 8)) (i64.const 10))
+
+;; Test that an i64 store with 4-byte alignment that's 4 bytes out of bounds traps without storing anything
+
+(module
+ (memory i64 1)
+ (func (export "store") (param i64 i64)
+ (i64.store align=4 (local.get 0) (local.get 1))
+ )
+ (func (export "load") (param i64) (result i32)
+ (i32.load (local.get 0))
+ )
+)
+
+(assert_trap (invoke "store" (i64.const 65532) (i64.const -1)) "out of bounds memory access")
+;; No memory was changed
+(assert_return (invoke "load" (i64.const 65532)) (i32.const 0))
diff --git a/test/spec/bulk-memory64.wast b/test/spec/bulk-memory64.wast
new file mode 100644
index 000000000..060191216
--- /dev/null
+++ b/test/spec/bulk-memory64.wast
@@ -0,0 +1,167 @@
+;; Passive segment syntax
+(module
+ (memory i64 1)
+ (data passive "foo"))
+
+;; memory.fill
+(module
+ (memory i64 1)
+
+ (func (export "fill") (param i64 i32 i64)
+ (memory.fill
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+;; Basic fill test.
+(invoke "fill" (i64.const 1) (i32.const 0xff) (i64.const 3))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 3)) (i32.const 0xff))
+(assert_return (invoke "load8_u" (i64.const 4)) (i32.const 0))
+
+;; Fill value is stored as a byte.
+(invoke "fill" (i64.const 0) (i32.const 0xbbaa) (i64.const 2))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xaa))
+
+;; Fill all of memory
+(invoke "fill" (i64.const 0) (i32.const 0) (i64.const 0x10000))
+
+;; Succeed when writing 0 bytes at the end of the region.
+(invoke "fill" (i64.const 0x10000) (i32.const 0) (i64.const 0))
+
+;; Writing 0 bytes outside of memory limit is NOT allowed.
+(assert_trap (invoke "fill" (i64.const 0x10001) (i32.const 0) (i64.const 0)))
+
+;; memory.copy
+(module
+ (memory i64 1 1)
+ (data (i32.const 0) "\aa\bb\cc\dd")
+
+ (func (export "copy") (param i64 i64 i64)
+ (memory.copy
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+;; Non-overlapping copy.
+(invoke "copy" (i64.const 10) (i64.const 0) (i64.const 4))
+
+(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0))
+
+;; Overlap, source > dest
+(invoke "copy" (i64.const 8) (i64.const 10) (i64.const 4))
+(assert_return (invoke "load8_u" (i64.const 8)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
+
+;; Overlap, source < dest
+(invoke "copy" (i64.const 10) (i64.const 7) (i64.const 6))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
+
+;; Overlap, source < dest but size is out of bounds
+(assert_trap (invoke "copy" (i64.const 13) (i64.const 11) (i64.const -1)))
+(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
+(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
+(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
+(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
+
+;; Copy ending at memory limit is ok.
+(invoke "copy" (i64.const 0xff00) (i64.const 0) (i64.const 0x100))
+(invoke "copy" (i64.const 0xfe00) (i64.const 0xff00) (i64.const 0x100))
+
+;; Succeed when copying 0 bytes at the end of the region.
+(invoke "copy" (i64.const 0x10000) (i64.const 0) (i64.const 0))
+(invoke "copy" (i64.const 0) (i64.const 0x10000) (i64.const 0))
+
+;; Copying 0 bytes outside of memory limit is NOT allowed.
+(assert_trap (invoke "copy" (i64.const 0x10001) (i64.const 0) (i64.const 0)))
+(assert_trap (invoke "copy" (i64.const 0) (i64.const 0x10001) (i64.const 0)))
+
+;; memory.init
+(module
+ (memory i64 1)
+ (data passive "\aa\bb\cc\dd")
+
+ (func (export "init") (param i64 i32 i32)
+ (memory.init 0
+ (local.get 0)
+ (local.get 1)
+ (local.get 2)))
+
+ (func (export "load8_u") (param i64) (result i32)
+ (i32.load8_u (local.get 0)))
+)
+
+(invoke "init" (i64.const 0) (i32.const 1) (i32.const 2))
+(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xbb))
+(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0))
+
+;; Init ending at memory limit and segment limit is ok.
+(invoke "init" (i64.const 0xfffc) (i32.const 0) (i32.const 4))
+
+;; Out-of-bounds writes trap, and no partial writes has been made.
+(assert_trap (invoke "init" (i64.const 0xfffe) (i32.const 0) (i32.const 3))
+ "out of bounds memory access")
+(assert_return (invoke "load8_u" (i64.const 0xfffe)) (i32.const 0xcc))
+(assert_return (invoke "load8_u" (i64.const 0xffff)) (i32.const 0xdd))
+
+;; Succeed when writing 0 bytes at the end of either region.
+(invoke "init" (i64.const 0x10000) (i32.const 0) (i32.const 0))
+(invoke "init" (i64.const 0) (i32.const 4) (i32.const 0))
+
+;; Writing 0 bytes outside of memory / segment limit is NOT allowed.
+(assert_trap (invoke "init" (i64.const 0x10001) (i32.const 0) (i32.const 0)))
+(assert_trap (invoke "init" (i64.const 0) (i32.const 5) (i32.const 0)))
+
+;; OK to access 0 bytes at offset 0 in a dropped segment.
+(invoke "init" (i64.const 0) (i32.const 0) (i32.const 0))
+
+;; data.drop
+(module
+ (memory i64 1)
+ (data passive "")
+ (data (i32.const 0) "")
+
+ (func (export "drop_passive") (data.drop 0))
+ (func (export "init_passive")
+ (memory.init 0 (i64.const 0) (i32.const 0) (i32.const 0)))
+
+ (func (export "drop_active") (data.drop 1))
+ (func (export "init_active")
+ (memory.init 1 (i64.const 0) (i32.const 0) (i32.const 0)))
+)
+
+;; OK to drop the same segment multiple times or drop an active segment.
+(invoke "init_passive")
+(invoke "drop_passive")
+(invoke "drop_passive")
+(invoke "drop_active")
diff --git a/test/spec/endianness64.wast b/test/spec/endianness64.wast
new file mode 100644
index 000000000..e583ea9b4
--- /dev/null
+++ b/test/spec/endianness64.wast
@@ -0,0 +1,217 @@
+(module
+ (memory i64 1)
+
+ ;; Stores an i16 value in little-endian-format
+ (func $i16_store_little (param $address i64) (param $value i32)
+ (i32.store8 (local.get $address) (local.get $value))
+ (i32.store8 (i64.add (local.get $address) (i64.const 1)) (i32.shr_u (local.get $value) (i32.const 8)))
+ )
+
+ ;; Stores an i32 value in little-endian format
+ (func $i32_store_little (param $address i64) (param $value i32)
+ (call $i16_store_little (local.get $address) (local.get $value))
+ (call $i16_store_little (i64.add (local.get $address) (i64.const 2)) (i32.shr_u (local.get $value) (i32.const 16)))
+ )
+
+ ;; Stores an i64 value in little-endian format
+ (func $i64_store_little (param $address i64) (param $value i64)
+ (call $i32_store_little (local.get $address) (i32.wrap_i64 (local.get $value)))
+ (call $i32_store_little (i64.add (local.get $address) (i64.const 4)) (i32.wrap_i64 (i64.shr_u (local.get $value) (i64.const 32))))
+ )
+
+ ;; Loads an i16 value in little-endian format
+ (func $i16_load_little (param $address i64) (result i32)
+ (i32.or
+ (i32.load8_u (local.get $address))
+ (i32.shl (i32.load8_u (i64.add (local.get $address) (i64.const 1))) (i32.const 8))
+ )
+ )
+
+ ;; Loads an i32 value in little-endian format
+ (func $i32_load_little (param $address i64) (result i32)
+ (i32.or
+ (call $i16_load_little (local.get $address))
+ (i32.shl (call $i16_load_little (i64.add (local.get $address) (i64.const 2))) (i32.const 16))
+ )
+ )
+
+ ;; Loads an i64 value in little-endian format
+ (func $i64_load_little (param $address i64) (result i64)
+ (i64.or
+ (i64.extend_i32_u (call $i32_load_little (local.get $address)))
+ (i64.shl (i64.extend_i32_u (call $i32_load_little (i64.add (local.get $address) (i64.const 4)))) (i64.const 32))
+ )
+ )
+
+ (func (export "i32_load16_s") (param $value i32) (result i32)
+ (call $i16_store_little (i64.const 0) (local.get $value))
+ (i32.load16_s (i64.const 0))
+ )
+
+ (func (export "i32_load16_u") (param $value i32) (result i32)
+ (call $i16_store_little (i64.const 0) (local.get $value))
+ (i32.load16_u (i64.const 0))
+ )
+
+ (func (export "i32_load") (param $value i32) (result i32)
+ (call $i32_store_little (i64.const 0) (local.get $value))
+ (i32.load (i64.const 0))
+ )
+
+ (func (export "i64_load16_s") (param $value i64) (result i64)
+ (call $i16_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load16_s (i64.const 0))
+ )
+
+ (func (export "i64_load16_u") (param $value i64) (result i64)
+ (call $i16_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load16_u (i64.const 0))
+ )
+
+ (func (export "i64_load32_s") (param $value i64) (result i64)
+ (call $i32_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load32_s (i64.const 0))
+ )
+
+ (func (export "i64_load32_u") (param $value i64) (result i64)
+ (call $i32_store_little (i64.const 0) (i32.wrap_i64 (local.get $value)))
+ (i64.load32_u (i64.const 0))
+ )
+
+ (func (export "i64_load") (param $value i64) (result i64)
+ (call $i64_store_little (i64.const 0) (local.get $value))
+ (i64.load (i64.const 0))
+ )
+
+ (func (export "f32_load") (param $value f32) (result f32)
+ (call $i32_store_little (i64.const 0) (i32.reinterpret_f32 (local.get $value)))
+ (f32.load (i64.const 0))
+ )
+
+ (func (export "f64_load") (param $value f64) (result f64)
+ (call $i64_store_little (i64.const 0) (i64.reinterpret_f64 (local.get $value)))
+ (f64.load (i64.const 0))
+ )
+
+
+ (func (export "i32_store16") (param $value i32) (result i32)
+ (i32.store16 (i64.const 0) (local.get $value))
+ (call $i16_load_little (i64.const 0))
+ )
+
+ (func (export "i32_store") (param $value i32) (result i32)
+ (i32.store (i64.const 0) (local.get $value))
+ (call $i32_load_little (i64.const 0))
+ )
+
+ (func (export "i64_store16") (param $value i64) (result i64)
+ (i64.store16 (i64.const 0) (local.get $value))
+ (i64.extend_i32_u (call $i16_load_little (i64.const 0)))
+ )
+
+ (func (export "i64_store32") (param $value i64) (result i64)
+ (i64.store32 (i64.const 0) (local.get $value))
+ (i64.extend_i32_u (call $i32_load_little (i64.const 0)))
+ )
+
+ (func (export "i64_store") (param $value i64) (result i64)
+ (i64.store (i64.const 0) (local.get $value))
+ (call $i64_load_little (i64.const 0))
+ )
+
+ (func (export "f32_store") (param $value f32) (result f32)
+ (f32.store (i64.const 0) (local.get $value))
+ (f32.reinterpret_i32 (call $i32_load_little (i64.const 0)))
+ )
+
+ (func (export "f64_store") (param $value f64) (result f64)
+ (f64.store (i64.const 0) (local.get $value))
+ (f64.reinterpret_i64 (call $i64_load_little (i64.const 0)))
+ )
+)
+
+(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load16_s" (i32.const -4242)) (i32.const -4242))
+(assert_return (invoke "i32_load16_s" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_load16_s" (i32.const 0x3210)) (i32.const 0x3210))
+
+(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 0xFFFF))
+(assert_return (invoke "i32_load16_u" (i32.const -4242)) (i32.const 61294))
+(assert_return (invoke "i32_load16_u" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_load16_u" (i32.const 0xCAFE)) (i32.const 0xCAFE))
+
+(assert_return (invoke "i32_load" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load" (i32.const -42424242)) (i32.const -42424242))
+(assert_return (invoke "i32_load" (i32.const 42424242)) (i32.const 42424242))
+(assert_return (invoke "i32_load" (i32.const 0xABAD1DEA)) (i32.const 0xABAD1DEA))
+
+(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load16_s" (i64.const -4242)) (i64.const -4242))
+(assert_return (invoke "i64_load16_s" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_load16_s" (i64.const 0x3210)) (i64.const 0x3210))
+
+(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 0xFFFF))
+(assert_return (invoke "i64_load16_u" (i64.const -4242)) (i64.const 61294))
+(assert_return (invoke "i64_load16_u" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_load16_u" (i64.const 0xCAFE)) (i64.const 0xCAFE))
+
+(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load32_s" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_load32_s" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_load32_s" (i64.const 0x12345678)) (i64.const 0x12345678))
+
+(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 0xFFFFFFFF))
+(assert_return (invoke "i64_load32_u" (i64.const -42424242)) (i64.const 4252543054))
+(assert_return (invoke "i64_load32_u" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_load32_u" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+
+(assert_return (invoke "i64_load" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_load" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+(assert_return (invoke "i64_load" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA))
+
+(assert_return (invoke "f32_load" (f32.const -1)) (f32.const -1))
+(assert_return (invoke "f32_load" (f32.const 1234e-5)) (f32.const 1234e-5))
+(assert_return (invoke "f32_load" (f32.const 4242.4242)) (f32.const 4242.4242))
+(assert_return (invoke "f32_load" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127))
+
+(assert_return (invoke "f64_load" (f64.const -1)) (f64.const -1))
+(assert_return (invoke "f64_load" (f64.const 123456789e-5)) (f64.const 123456789e-5))
+(assert_return (invoke "f64_load" (f64.const 424242.424242)) (f64.const 424242.424242))
+(assert_return (invoke "f64_load" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023))
+
+
+(assert_return (invoke "i32_store16" (i32.const -1)) (i32.const 0xFFFF))
+(assert_return (invoke "i32_store16" (i32.const -4242)) (i32.const 61294))
+(assert_return (invoke "i32_store16" (i32.const 42)) (i32.const 42))
+(assert_return (invoke "i32_store16" (i32.const 0xCAFE)) (i32.const 0xCAFE))
+
+(assert_return (invoke "i32_store" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_store" (i32.const -4242)) (i32.const -4242))
+(assert_return (invoke "i32_store" (i32.const 42424242)) (i32.const 42424242))
+(assert_return (invoke "i32_store" (i32.const 0xDEADCAFE)) (i32.const 0xDEADCAFE))
+
+(assert_return (invoke "i64_store16" (i64.const -1)) (i64.const 0xFFFF))
+(assert_return (invoke "i64_store16" (i64.const -4242)) (i64.const 61294))
+(assert_return (invoke "i64_store16" (i64.const 42)) (i64.const 42))
+(assert_return (invoke "i64_store16" (i64.const 0xCAFE)) (i64.const 0xCAFE))
+
+(assert_return (invoke "i64_store32" (i64.const -1)) (i64.const 0xFFFFFFFF))
+(assert_return (invoke "i64_store32" (i64.const -4242)) (i64.const 4294963054))
+(assert_return (invoke "i64_store32" (i64.const 42424242)) (i64.const 42424242))
+(assert_return (invoke "i64_store32" (i64.const 0xDEADCAFE)) (i64.const 0xDEADCAFE))
+
+(assert_return (invoke "i64_store" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_store" (i64.const -42424242)) (i64.const -42424242))
+(assert_return (invoke "i64_store" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA))
+(assert_return (invoke "i64_store" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA))
+
+(assert_return (invoke "f32_store" (f32.const -1)) (f32.const -1))
+(assert_return (invoke "f32_store" (f32.const 1234e-5)) (f32.const 1234e-5))
+(assert_return (invoke "f32_store" (f32.const 4242.4242)) (f32.const 4242.4242))
+(assert_return (invoke "f32_store" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127))
+
+(assert_return (invoke "f64_store" (f64.const -1)) (f64.const -1))
+(assert_return (invoke "f64_store" (f64.const 123456789e-5)) (f64.const 123456789e-5))
+(assert_return (invoke "f64_store" (f64.const 424242.424242)) (f64.const 424242.424242))
+(assert_return (invoke "f64_store" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023))
diff --git a/test/spec/float_memory64.wast b/test/spec/float_memory64.wast
new file mode 100644
index 000000000..6834fdf60
--- /dev/null
+++ b/test/spec/float_memory64.wast
@@ -0,0 +1,157 @@
+;; Test that floating-point load and store are bit-preserving.
+
+;; Test that load and store do not canonicalize NaNs as x87 does.
+
+(module
+ (memory (data i64 "\00\00\a0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 0)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 0)))
+ (func (export "f32.store") (f32.store (i64.const 0) (f32.const nan:0x200000)))
+ (func (export "i32.store") (i32.store (i64.const 0) (i32.const 0x7fa00000)))
+ (func (export "reset") (i32.store (i64.const 0) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+
+(module
+ (memory (data i64 "\00\00\00\00\00\00\f4\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 0)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 0)))
+ (func (export "f64.store") (f64.store (i64.const 0) (f64.const nan:0x4000000000000)))
+ (func (export "i64.store") (i64.store (i64.const 0) (i64.const 0x7ff4000000000000)))
+ (func (export "reset") (i64.store (i64.const 0) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+
+;; Test that unaligned load and store do not canonicalize NaNs.
+
+(module
+ (memory (data i64 "\00\00\00\a0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 1)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 1)))
+ (func (export "f32.store") (f32.store (i64.const 1) (f32.const nan:0x200000)))
+ (func (export "i32.store") (i32.store (i64.const 1) (i32.const 0x7fa00000)))
+ (func (export "reset") (i32.store (i64.const 1) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fa00000))
+(assert_return (invoke "f32.load") (f32.const nan:0x200000))
+
+(module
+ (memory (data i64 "\00\00\00\00\00\00\00\f4\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 1)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 1)))
+ (func (export "f64.store") (f64.store (i64.const 1) (f64.const nan:0x4000000000000)))
+ (func (export "i64.store") (i64.store (i64.const 1) (i64.const 0x7ff4000000000000)))
+ (func (export "reset") (i64.store (i64.const 1) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000))
+(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000))
+
+;; Test that load and store do not canonicalize NaNs as some JS engines do.
+
+(module
+ (memory (data i64 "\01\00\d0\7f"))
+
+ (func (export "f32.load") (result f32) (f32.load (i64.const 0)))
+ (func (export "i32.load") (result i32) (i32.load (i64.const 0)))
+ (func (export "f32.store") (f32.store (i64.const 0) (f32.const nan:0x500001)))
+ (func (export "i32.store") (i32.store (i64.const 0) (i32.const 0x7fd00001)))
+ (func (export "reset") (i32.store (i64.const 0) (i32.const 0)))
+)
+
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "f32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+(invoke "reset")
+(assert_return (invoke "i32.load") (i32.const 0x0))
+(assert_return (invoke "f32.load") (f32.const 0.0))
+(invoke "i32.store")
+(assert_return (invoke "i32.load") (i32.const 0x7fd00001))
+(assert_return (invoke "f32.load") (f32.const nan:0x500001))
+
+(module
+ (memory (data i64 "\01\00\00\00\00\00\fc\7f"))
+
+ (func (export "f64.load") (result f64) (f64.load (i64.const 0)))
+ (func (export "i64.load") (result i64) (i64.load (i64.const 0)))
+ (func (export "f64.store") (f64.store (i64.const 0) (f64.const nan:0xc000000000001)))
+ (func (export "i64.store") (i64.store (i64.const 0) (i64.const 0x7ffc000000000001)))
+ (func (export "reset") (i64.store (i64.const 0) (i64.const 0)))
+)
+
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "f64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
+(invoke "reset")
+(assert_return (invoke "i64.load") (i64.const 0x0))
+(assert_return (invoke "f64.load") (f64.const 0.0))
+(invoke "i64.store")
+(assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001))
+(assert_return (invoke "f64.load") (f64.const nan:0xc000000000001))
diff --git a/test/spec/load64.wast b/test/spec/load64.wast
new file mode 100644
index 000000000..e4a6a9833
--- /dev/null
+++ b/test/spec/load64.wast
@@ -0,0 +1,567 @@
+;; Load operator as the argument of control constructs and instructions
+
+(module
+ (memory i64 1)
+
+ (func (export "as-br-value") (result i32)
+ (block (result i32) (br 0 (i32.load (i64.const 0))))
+ )
+
+ (func (export "as-br_if-cond")
+ (block (br_if 0 (i32.load (i64.const 0))))
+ )
+ (func (export "as-br_if-value") (result i32)
+ (block (result i32)
+ (drop (br_if 0 (i32.load (i64.const 0)) (i32.const 1))) (i32.const 7)
+ )
+ )
+ (func (export "as-br_if-value-cond") (result i32)
+ (block (result i32)
+ (drop (br_if 0 (i32.const 6) (i32.load (i64.const 0)))) (i32.const 7)
+ )
+ )
+
+ (func (export "as-br_table-index")
+ (block (br_table 0 0 0 (i32.load (i64.const 0))))
+ )
+ (func (export "as-br_table-value") (result i32)
+ (block (result i32)
+ (br_table 0 0 0 (i32.load (i64.const 0)) (i32.const 1)) (i32.const 7)
+ )
+ )
+ (func (export "as-br_table-value-index") (result i32)
+ (block (result i32)
+ (br_table 0 0 (i32.const 6) (i32.load (i64.const 0))) (i32.const 7)
+ )
+ )
+
+ (func (export "as-return-value") (result i32)
+ (return (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-if-cond") (result i32)
+ (if (result i32) (i32.load (i64.const 0))
+ (then (i32.const 0)) (else (i32.const 1))
+ )
+ )
+ (func (export "as-if-then") (result i32)
+ (if (result i32) (i32.const 1)
+ (then (i32.load (i64.const 0))) (else (i32.const 0))
+ )
+ )
+ (func (export "as-if-else") (result i32)
+ (if (result i32) (i32.const 0)
+ (then (i32.const 0)) (else (i32.load (i64.const 0)))
+ )
+ )
+
+ (func (export "as-select-first") (param i32 i32) (result i32)
+ (select (i32.load (i64.const 0)) (local.get 0) (local.get 1))
+ )
+ (func (export "as-select-second") (param i32 i32) (result i32)
+ (select (local.get 0) (i32.load (i64.const 0)) (local.get 1))
+ )
+ (func (export "as-select-cond") (result i32)
+ (select (i32.const 0) (i32.const 1) (i32.load (i64.const 0)))
+ )
+
+ (func $f (param i32 i32 i32) (result i32) (i32.const -1))
+ (func (export "as-call-first") (result i32)
+ (call $f (i32.load (i64.const 0)) (i32.const 2) (i32.const 3))
+ )
+ (func (export "as-call-mid") (result i32)
+ (call $f (i32.const 1) (i32.load (i64.const 0)) (i32.const 3))
+ )
+ (func (export "as-call-last") (result i32)
+ (call $f (i32.const 1) (i32.const 2) (i32.load (i64.const 0)))
+ )
+
+ (type $sig (func (param i32 i32 i32) (result i32)))
+ (table funcref (elem $f))
+ (func (export "as-call_indirect-first") (result i32)
+ (call_indirect (type $sig)
+ (i32.load (i64.const 0)) (i32.const 2) (i32.const 3) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-mid") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.load (i64.const 0)) (i32.const 3) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-last") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.const 2) (i32.load (i64.const 0)) (i32.const 0)
+ )
+ )
+ (func (export "as-call_indirect-index") (result i32)
+ (call_indirect (type $sig)
+ (i32.const 1) (i32.const 2) (i32.const 3) (i32.load (i64.const 0))
+ )
+ )
+
+ (func (export "as-local.set-value") (local i32)
+ (local.set 0 (i32.load (i64.const 0)))
+ )
+ (func (export "as-local.tee-value") (result i32) (local i32)
+ (local.tee 0 (i32.load (i64.const 0)))
+ )
+ (global $g (mut i32) (i32.const 0))
+ (func (export "as-global.set-value") (local i32)
+ (global.set $g (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-load-address") (result i32)
+ (i32.load (i64.load (i64.const 0)))
+ )
+ (func (export "as-loadN-address") (result i32)
+ (i32.load8_s (i64.load (i64.const 0)))
+ )
+
+ (func (export "as-store-address")
+ (i32.store (i64.load (i64.const 0)) (i32.const 7))
+ )
+ (func (export "as-store-value")
+ (i32.store (i64.const 2) (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-storeN-address")
+ (i32.store8 (i64.load8_s (i64.const 0)) (i32.const 7))
+ )
+ (func (export "as-storeN-value")
+ (i32.store16 (i64.const 2) (i32.load (i64.const 0)))
+ )
+
+ (func (export "as-unary-operand") (result i32)
+ (i32.clz (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-binary-left") (result i32)
+ (i32.add (i32.load (i64.const 100)) (i32.const 10))
+ )
+ (func (export "as-binary-right") (result i32)
+ (i32.sub (i32.const 10) (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-test-operand") (result i32)
+ (i32.eqz (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-compare-left") (result i32)
+ (i32.le_s (i32.load (i64.const 100)) (i32.const 10))
+ )
+ (func (export "as-compare-right") (result i32)
+ (i32.ne (i32.const 10) (i32.load (i64.const 100)))
+ )
+
+ (func (export "as-memory.grow-size") (result i64)
+ (memory.grow (i64.load (i64.const 100)))
+ )
+)
+
+(assert_return (invoke "as-br-value") (i32.const 0))
+
+(assert_return (invoke "as-br_if-cond"))
+(assert_return (invoke "as-br_if-value") (i32.const 0))
+(assert_return (invoke "as-br_if-value-cond") (i32.const 7))
+
+(assert_return (invoke "as-br_table-index"))
+(assert_return (invoke "as-br_table-value") (i32.const 0))
+(assert_return (invoke "as-br_table-value-index") (i32.const 6))
+
+(assert_return (invoke "as-return-value") (i32.const 0))
+
+(assert_return (invoke "as-if-cond") (i32.const 1))
+(assert_return (invoke "as-if-then") (i32.const 0))
+(assert_return (invoke "as-if-else") (i32.const 0))
+
+(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "as-select-cond") (i32.const 1))
+
+(assert_return (invoke "as-call-first") (i32.const -1))
+(assert_return (invoke "as-call-mid") (i32.const -1))
+(assert_return (invoke "as-call-last") (i32.const -1))
+
+(assert_return (invoke "as-call_indirect-first") (i32.const -1))
+(assert_return (invoke "as-call_indirect-mid") (i32.const -1))
+(assert_return (invoke "as-call_indirect-last") (i32.const -1))
+(assert_return (invoke "as-call_indirect-index") (i32.const -1))
+
+(assert_return (invoke "as-local.set-value"))
+(assert_return (invoke "as-local.tee-value") (i32.const 0))
+(assert_return (invoke "as-global.set-value"))
+
+(assert_return (invoke "as-load-address") (i32.const 0))
+(assert_return (invoke "as-loadN-address") (i32.const 0))
+(assert_return (invoke "as-store-address"))
+(assert_return (invoke "as-store-value"))
+(assert_return (invoke "as-storeN-address"))
+(assert_return (invoke "as-storeN-value"))
+
+(assert_return (invoke "as-unary-operand") (i32.const 32))
+
+(assert_return (invoke "as-binary-left") (i32.const 10))
+(assert_return (invoke "as-binary-right") (i32.const 10))
+
+(assert_return (invoke "as-test-operand") (i32.const 1))
+
+(assert_return (invoke "as-compare-left") (i32.const 1))
+(assert_return (invoke "as-compare-right") (i32.const 1))
+
+(assert_return (invoke "as-memory.grow-size") (i64.const 1))
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load32_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i32) (i32.load64_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64_u (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result i64) (i64.load64_s (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f32) (f32.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f32) (f32.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f64) (f64.load32 (local.get 0)))"
+ )
+ "unknown operator"
+)
+(assert_malformed
+ (module quote
+ "(memory i64 1)"
+ "(func (param i64) (result f64) (f64.load64 (local.get 0)))"
+ )
+ "unknown operator"
+)
+
+
+;; load should have retval
+
+(assert_invalid
+ (module (memory i64 1) (func $load_i32 (i32.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_s_i32 (i32.load8_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_u_i32 (i32.load8_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_s_i32 (i32.load16_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_u_i32 (i32.load16_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_i64 (i64.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_s_i64 (i64.load8_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load8_u_i64 (i64.load8_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_s_i64 (i64.load16_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load16_u_i64 (i64.load16_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load32_s_i64 (i64.load32_s (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load32_u_i64 (i64.load32_u (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_f32 (f32.load (i64.const 0))))
+ "type mismatch"
+)
+(assert_invalid
+ (module (memory i64 1) (func $load_f64 (f64.load (i64.const 0))))
+ "type mismatch"
+)
+
+
+;; Type check
+
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load8_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load8_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load16_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i32) (i32.load16_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load8_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load8_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load16_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load16_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load32_s (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result i64) (i64.load32_u (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result f32) (f32.load (f32.const 0)))) "type mismatch")
+(assert_invalid (module (memory i64 1) (func (result f64) (f64.load (f32.const 0)))) "type mismatch")
+
+
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty
+ (i32.load) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-block
+ (i32.const 0)
+ (block (i32.load) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-loop
+ (i32.const 0)
+ (loop (i32.load) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-then
+ (i32.const 0) (i32.const 0)
+ (if (then (i32.load) (drop)))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-else
+ (i32.const 0) (i32.const 0)
+ (if (result i32) (then (i32.const 0)) (else (i32.load))) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br
+ (i32.const 0)
+ (block (br 0 (i32.load)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br_if
+ (i32.const 0)
+ (block (br_if 0 (i32.load) (i32.const 1)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-br_table
+ (i32.const 0)
+ (block (br_table 0 (i32.load)) (drop))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-return
+ (return (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-select
+ (select (i32.load) (i32.const 1) (i32.const 2)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-call
+ (call 1 (i32.load)) (drop)
+ )
+ (func (param i32) (result i32) (local.get 0))
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $f (param i32) (result i32) (local.get 0))
+ (type $sig (func (param i32) (result i32)))
+ (table funcref (elem $f))
+ (func $type-address-empty-in-call_indirect
+ (block (result i32)
+ (call_indirect (type $sig)
+ (i32.load) (i32.const 0)
+ )
+ (drop)
+ )
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-local.set
+ (local i32)
+ (local.set 0 (i32.load)) (local.get 0) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-local.tee
+ (local i32)
+ (local.tee 0 (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (global $x (mut i32) (i32.const 0))
+ (func $type-address-empty-in-global.set
+ (global.set $x (i32.load)) (global.get $x) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-memory.grow
+ (memory.grow (i64.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 0)
+ (func $type-address-empty-in-load
+ (i32.load (i32.load)) (drop)
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (memory i64 1)
+ (func $type-address-empty-in-store
+ (i32.store (i32.load) (i32.const 1))
+ )
+ )
+ "type mismatch"
+)
diff --git a/test/spec/memory64.wast b/test/spec/memory64.wast
new file mode 100644
index 000000000..8424e0c0e
--- /dev/null
+++ b/test/spec/memory64.wast
@@ -0,0 +1,188 @@
+;; Test memory section structure
+
+(module (memory i64 0 0))
+(module (memory i64 0 1))
+(module (memory i64 1 256))
+(module (memory i64 0 65536))
+
+(assert_invalid (module (memory i64 0) (memory i64 0)) "multiple memories")
+(assert_invalid (module (memory (import "spectest" "memory") i64 0) (memory i64 0)) "multiple memories")
+
+(module (memory i64 (data)) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 0))
+(module (memory i64 (data "")) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 0))
+(module (memory i64 (data "x")) (func (export "memsize") (result i64) (memory.size)))
+(assert_return (invoke "memsize") (i64.const 1))
+
+(assert_invalid (module (data (i32.const 0))) "unknown memory")
+(assert_invalid (module (data (i32.const 0) "")) "unknown memory")
+(assert_invalid (module (data (i32.const 0) "x")) "unknown memory")
+
+(assert_invalid
+ (module (func (drop (f32.load (i64.const 0)))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (f32.store (i64.const 0) (f32.const 0))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (i32.load8_s (i64.const 0)))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (i32.store8 (i64.const 0) (i32.const 0))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (memory.size))))
+ "unknown memory"
+)
+(assert_invalid
+ (module (func (drop (memory.grow (i64.const 0)))))
+ "unknown memory"
+)
+
+
+(assert_invalid
+ (module (memory i64 1 0))
+ "size minimum must not be greater than maximum"
+)
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "ABC\a7D") (data (i32.const 20) "WASM")
+
+ ;; Data section
+ (func (export "data") (result i32)
+ (i32.and
+ (i32.and
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 0)) (i32.const 65))
+ (i32.eq (i32.load8_u (i64.const 3)) (i32.const 167))
+ )
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 6)) (i32.const 0))
+ (i32.eq (i32.load8_u (i64.const 19)) (i32.const 0))
+ )
+ )
+ (i32.and
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 20)) (i32.const 87))
+ (i32.eq (i32.load8_u (i64.const 23)) (i32.const 77))
+ )
+ (i32.and
+ (i32.eq (i32.load8_u (i64.const 24)) (i32.const 0))
+ (i32.eq (i32.load8_u (i64.const 1023)) (i32.const 0))
+ )
+ )
+ )
+ )
+
+ ;; Memory cast
+ (func (export "cast") (result f64)
+ (i64.store (i64.const 8) (i64.const -12345))
+ (if
+ (f64.eq
+ (f64.load (i64.const 8))
+ (f64.reinterpret_i64 (i64.const -12345))
+ )
+ (then (return (f64.const 0)))
+ )
+ (i64.store align=1 (i64.const 9) (i64.const 0))
+ (i32.store16 align=1 (i64.const 15) (i32.const 16453))
+ (f64.load align=1 (i64.const 9))
+ )
+
+ ;; Sign and zero extending memory loads
+ (func (export "i32_load8_s") (param $i i32) (result i32)
+ (i32.store8 (i64.const 8) (local.get $i))
+ (i32.load8_s (i64.const 8))
+ )
+ (func (export "i32_load8_u") (param $i i32) (result i32)
+ (i32.store8 (i64.const 8) (local.get $i))
+ (i32.load8_u (i64.const 8))
+ )
+ (func (export "i32_load16_s") (param $i i32) (result i32)
+ (i32.store16 (i64.const 8) (local.get $i))
+ (i32.load16_s (i64.const 8))
+ )
+ (func (export "i32_load16_u") (param $i i32) (result i32)
+ (i32.store16 (i64.const 8) (local.get $i))
+ (i32.load16_u (i64.const 8))
+ )
+ (func (export "i64_load8_s") (param $i i64) (result i64)
+ (i64.store8 (i64.const 8) (local.get $i))
+ (i64.load8_s (i64.const 8))
+ )
+ (func (export "i64_load8_u") (param $i i64) (result i64)
+ (i64.store8 (i64.const 8) (local.get $i))
+ (i64.load8_u (i64.const 8))
+ )
+ (func (export "i64_load16_s") (param $i i64) (result i64)
+ (i64.store16 (i64.const 8) (local.get $i))
+ (i64.load16_s (i64.const 8))
+ )
+ (func (export "i64_load16_u") (param $i i64) (result i64)
+ (i64.store16 (i64.const 8) (local.get $i))
+ (i64.load16_u (i64.const 8))
+ )
+ (func (export "i64_load32_s") (param $i i64) (result i64)
+ (i64.store32 (i64.const 8) (local.get $i))
+ (i64.load32_s (i64.const 8))
+ )
+ (func (export "i64_load32_u") (param $i i64) (result i64)
+ (i64.store32 (i64.const 8) (local.get $i))
+ (i64.load32_u (i64.const 8))
+ )
+)
+
+(assert_return (invoke "data") (i32.const 1))
+(assert_return (invoke "cast") (f64.const 42.0))
+
+(assert_return (invoke "i32_load8_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load8_u" (i32.const -1)) (i32.const 255))
+(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1))
+(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 65535))
+
+(assert_return (invoke "i32_load8_s" (i32.const 100)) (i32.const 100))
+(assert_return (invoke "i32_load8_u" (i32.const 200)) (i32.const 200))
+(assert_return (invoke "i32_load16_s" (i32.const 20000)) (i32.const 20000))
+(assert_return (invoke "i32_load16_u" (i32.const 40000)) (i32.const 40000))
+
+(assert_return (invoke "i32_load8_s" (i32.const 0xfedc6543)) (i32.const 0x43))
+(assert_return (invoke "i32_load8_s" (i32.const 0x3456cdef)) (i32.const 0xffffffef))
+(assert_return (invoke "i32_load8_u" (i32.const 0xfedc6543)) (i32.const 0x43))
+(assert_return (invoke "i32_load8_u" (i32.const 0x3456cdef)) (i32.const 0xef))
+(assert_return (invoke "i32_load16_s" (i32.const 0xfedc6543)) (i32.const 0x6543))
+(assert_return (invoke "i32_load16_s" (i32.const 0x3456cdef)) (i32.const 0xffffcdef))
+(assert_return (invoke "i32_load16_u" (i32.const 0xfedc6543)) (i32.const 0x6543))
+(assert_return (invoke "i32_load16_u" (i32.const 0x3456cdef)) (i32.const 0xcdef))
+
+(assert_return (invoke "i64_load8_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load8_u" (i64.const -1)) (i64.const 255))
+(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 65535))
+(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1))
+(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 4294967295))
+
+(assert_return (invoke "i64_load8_s" (i64.const 100)) (i64.const 100))
+(assert_return (invoke "i64_load8_u" (i64.const 200)) (i64.const 200))
+(assert_return (invoke "i64_load16_s" (i64.const 20000)) (i64.const 20000))
+(assert_return (invoke "i64_load16_u" (i64.const 40000)) (i64.const 40000))
+(assert_return (invoke "i64_load32_s" (i64.const 20000)) (i64.const 20000))
+(assert_return (invoke "i64_load32_u" (i64.const 40000)) (i64.const 40000))
+
+(assert_return (invoke "i64_load8_s" (i64.const 0xfedcba9856346543)) (i64.const 0x43))
+(assert_return (invoke "i64_load8_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffffef))
+(assert_return (invoke "i64_load8_u" (i64.const 0xfedcba9856346543)) (i64.const 0x43))
+(assert_return (invoke "i64_load8_u" (i64.const 0x3456436598bacdef)) (i64.const 0xef))
+(assert_return (invoke "i64_load16_s" (i64.const 0xfedcba9856346543)) (i64.const 0x6543))
+(assert_return (invoke "i64_load16_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffcdef))
+(assert_return (invoke "i64_load16_u" (i64.const 0xfedcba9856346543)) (i64.const 0x6543))
+(assert_return (invoke "i64_load16_u" (i64.const 0x3456436598bacdef)) (i64.const 0xcdef))
+(assert_return (invoke "i64_load32_s" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543))
+(assert_return (invoke "i64_load32_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffff98bacdef))
+(assert_return (invoke "i64_load32_u" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543))
+(assert_return (invoke "i64_load32_u" (i64.const 0x3456436598bacdef)) (i64.const 0x98bacdef))
diff --git a/test/spec/memory_grow64.wast b/test/spec/memory_grow64.wast
new file mode 100644
index 000000000..90d8de607
--- /dev/null
+++ b/test/spec/memory_grow64.wast
@@ -0,0 +1,95 @@
+(module
+ (memory i64 0)
+
+ (func (export "load_at_zero") (result i32) (i32.load (i64.const 0)))
+ (func (export "store_at_zero") (i32.store (i64.const 0) (i32.const 2)))
+
+ (func (export "load_at_page_size") (result i32) (i32.load (i64.const 0x10000)))
+ (func (export "store_at_page_size") (i32.store (i64.const 0x10000) (i32.const 3)))
+
+ (func (export "grow") (param $sz i64) (result i64) (memory.grow (local.get $sz)))
+ (func (export "size") (result i64) (memory.size))
+)
+
+(assert_return (invoke "size") (i64.const 0))
+(assert_trap (invoke "store_at_zero") "out of bounds memory access")
+(assert_trap (invoke "load_at_zero") "out of bounds memory access")
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "size") (i64.const 1))
+(assert_return (invoke "load_at_zero") (i32.const 0))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 4)) (i64.const 1))
+(assert_return (invoke "size") (i64.const 5))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "load_at_page_size") (i32.const 0))
+(assert_return (invoke "store_at_page_size"))
+(assert_return (invoke "load_at_page_size") (i32.const 3))
+
+
+(module
+ (memory i64 0)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 800)) (i64.const 3))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 803))
+
+(module
+ (memory i64 0 10)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 2))
+(assert_return (invoke "grow" (i64.const 6)) (i64.const 4))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 10))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const -1))
+(assert_return (invoke "grow" (i64.const 0x10000)) (i64.const -1))
+
+;; Test that newly allocated memory (program start and memory.grow) is zeroed
+
+(module
+ (memory i64 1)
+ (func (export "grow") (param i64) (result i64)
+ (memory.grow (local.get 0))
+ )
+ (func (export "check-memory-zero") (param i64 i64) (result i32)
+ (local i32)
+ (local.set 2 (i32.const 1))
+ (block
+ (loop
+ (local.set 2 (i32.load8_u (local.get 0)))
+ (br_if 1 (i32.ne (local.get 2) (i32.const 0)))
+ (br_if 1 (i64.ge_u (local.get 0) (local.get 1)))
+ (local.set 0 (i64.add (local.get 0) (i64.const 1)))
+ (br_if 0 (i64.le_u (local.get 0) (local.get 1)))
+ )
+ )
+ (local.get 2)
+ )
+)
+
+(assert_return (invoke "check-memory-zero" (i64.const 0) (i64.const 0xffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "check-memory-zero" (i64.const 0x10000) (i64.const 0x1_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 2))
+(assert_return (invoke "check-memory-zero" (i64.const 0x20000) (i64.const 0x2_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 3))
+(assert_return (invoke "check-memory-zero" (i64.const 0x30000) (i64.const 0x3_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 4))
+(assert_return (invoke "check-memory-zero" (i64.const 0x40000) (i64.const 0x4_ffff)) (i32.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 5))
+(assert_return (invoke "check-memory-zero" (i64.const 0x50000) (i64.const 0x5_ffff)) (i32.const 0))
diff --git a/test/spec/memory_redundancy64.wast b/test/spec/memory_redundancy64.wast
new file mode 100644
index 000000000..4aa1ebac1
--- /dev/null
+++ b/test/spec/memory_redundancy64.wast
@@ -0,0 +1,65 @@
+;; Test that optimizers don't do redundant-load, store-to-load, or dead-store
+;; optimizations when there are interfering stores, even of different types
+;; and to non-identical addresses.
+
+(module
+ (memory i64 1 1)
+
+ (func (export "zero_everything")
+ (i32.store (i64.const 0) (i32.const 0))
+ (i32.store (i64.const 4) (i32.const 0))
+ (i32.store (i64.const 8) (i32.const 0))
+ (i32.store (i64.const 12) (i32.const 0))
+ )
+
+ (func (export "test_store_to_load") (result i32)
+ (i32.store (i64.const 8) (i32.const 0))
+ (f32.store (i64.const 5) (f32.const -0.0))
+ (i32.load (i64.const 8))
+ )
+
+ (func (export "test_redundant_load") (result i32)
+ (local $t i32)
+ (local $s i32)
+ (local.set $t (i32.load (i64.const 8)))
+ (i32.store (i64.const 5) (i32.const 0x80000000))
+ (local.set $s (i32.load (i64.const 8)))
+ (i32.add (local.get $t) (local.get $s))
+ )
+
+ (func (export "test_dead_store") (result f32)
+ (local $t f32)
+ (i32.store (i64.const 8) (i32.const 0x23232323))
+ (local.set $t (f32.load (i64.const 11)))
+ (i32.store (i64.const 8) (i32.const 0))
+ (local.get $t)
+ )
+
+ ;; A function named "malloc" which implementations nonetheless shouldn't
+ ;; assume behaves like C malloc.
+ (func $malloc (export "malloc")
+ (param $size i64)
+ (result i64)
+ (i64.const 16)
+ )
+
+ ;; Call malloc twice, but unlike C malloc, we don't get non-aliasing pointers.
+ (func (export "malloc_aliasing")
+ (result i32)
+ (local $x i64)
+ (local $y i64)
+ (local.set $x (call $malloc (i64.const 4)))
+ (local.set $y (call $malloc (i64.const 4)))
+ (i32.store (local.get $x) (i32.const 42))
+ (i32.store (local.get $y) (i32.const 43))
+ (i32.load (local.get $x))
+ )
+)
+
+(assert_return (invoke "test_store_to_load") (i32.const 0x00000080))
+(invoke "zero_everything")
+(assert_return (invoke "test_redundant_load") (i32.const 0x00000080))
+(invoke "zero_everything")
+(assert_return (invoke "test_dead_store") (f32.const 0x1.18p-144))
+(invoke "zero_everything")
+(assert_return (invoke "malloc_aliasing") (i32.const 43))
diff --git a/test/spec/memory_trap64.wast b/test/spec/memory_trap64.wast
new file mode 100644
index 000000000..77e802ae3
--- /dev/null
+++ b/test/spec/memory_trap64.wast
@@ -0,0 +1,269 @@
+(module
+ (memory i64 1)
+
+ (func $addr_limit (result i64)
+ (i64.mul (memory.size) (i64.const 0x10000))
+ )
+
+ (func (export "store") (param $i i64) (param $v i32)
+ (i32.store (i64.add (call $addr_limit) (local.get $i)) (local.get $v))
+ )
+
+ (func (export "load") (param $i i64) (result i32)
+ (i32.load (i64.add (call $addr_limit) (local.get $i)))
+ )
+
+ (func (export "memory.grow") (param i64) (result i64)
+ (memory.grow (local.get 0))
+ )
+)
+
+(assert_return (invoke "store" (i64.const -4) (i32.const 42)))
+(assert_return (invoke "load" (i64.const -4)) (i32.const 42))
+(assert_trap (invoke "store" (i64.const -3) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const -2) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const -1) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const 0) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "store" (i64.const 0x80000000) (i32.const 13)) "out of bounds memory access")
+(assert_trap (invoke "load" (i64.const 0x80000000)) "out of bounds memory access")
+
+(module
+ (memory i64 1)
+ (data (i32.const 0) "abcdefgh")
+ (data (i32.const 0xfff8) "abcdefgh")
+
+ (func (export "i32.load") (param $a i64) (result i32)
+ (i32.load (local.get $a))
+ )
+ (func (export "i64.load") (param $a i64) (result i64)
+ (i64.load (local.get $a))
+ )
+ (func (export "f32.load") (param $a i64) (result f32)
+ (f32.load (local.get $a))
+ )
+ (func (export "f64.load") (param $a i64) (result f64)
+ (f64.load (local.get $a))
+ )
+ (func (export "i32.load8_s") (param $a i64) (result i32)
+ (i32.load8_s (local.get $a))
+ )
+ (func (export "i32.load8_u") (param $a i64) (result i32)
+ (i32.load8_u (local.get $a))
+ )
+ (func (export "i32.load16_s") (param $a i64) (result i32)
+ (i32.load16_s (local.get $a))
+ )
+ (func (export "i32.load16_u") (param $a i64) (result i32)
+ (i32.load16_u (local.get $a))
+ )
+ (func (export "i64.load8_s") (param $a i64) (result i64)
+ (i64.load8_s (local.get $a))
+ )
+ (func (export "i64.load8_u") (param $a i64) (result i64)
+ (i64.load8_u (local.get $a))
+ )
+ (func (export "i64.load16_s") (param $a i64) (result i64)
+ (i64.load16_s (local.get $a))
+ )
+ (func (export "i64.load16_u") (param $a i64) (result i64)
+ (i64.load16_u (local.get $a))
+ )
+ (func (export "i64.load32_s") (param $a i64) (result i64)
+ (i64.load32_s (local.get $a))
+ )
+ (func (export "i64.load32_u") (param $a i64) (result i64)
+ (i64.load32_u (local.get $a))
+ )
+ (func (export "i32.store") (param $a i64) (param $v i32)
+ (i32.store (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store") (param $a i64) (param $v i64)
+ (i64.store (local.get $a) (local.get $v))
+ )
+ (func (export "f32.store") (param $a i64) (param $v f32)
+ (f32.store (local.get $a) (local.get $v))
+ )
+ (func (export "f64.store") (param $a i64) (param $v f64)
+ (f64.store (local.get $a) (local.get $v))
+ )
+ (func (export "i32.store8") (param $a i64) (param $v i32)
+ (i32.store8 (local.get $a) (local.get $v))
+ )
+ (func (export "i32.store16") (param $a i64) (param $v i32)
+ (i32.store16 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store8") (param $a i64) (param $v i64)
+ (i64.store8 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store16") (param $a i64) (param $v i64)
+ (i64.store16 (local.get $a) (local.get $v))
+ )
+ (func (export "i64.store32") (param $a i64) (param $v i64)
+ (i64.store32 (local.get $a) (local.get $v))
+ )
+)
+
+(assert_trap (invoke "i32.store" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xffff) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xfffe) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const 0xfffd) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -2) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -3) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store" (i64.const -4) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffe) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffd) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffc) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffb) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfffa) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const 0xfff9) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -3) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -4) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -5) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -6) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -7) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store" (i64.const -8) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0x10000) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xffff) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xfffe) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const 0xfffd) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -1) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -2) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -3) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f32.store" (i64.const -4) (f32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0x10000) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xffff) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffe) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffd) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffc) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffb) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfffa) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const 0xfff9) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -1) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -2) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -3) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -4) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -5) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -6) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -7) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "f64.store" (i64.const -8) (f64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store8" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store8" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const 0x10000) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const 0xffff) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const -1) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.store16" (i64.const -2) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store8" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store8" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store16" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0x10000) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xffff) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xfffe) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const 0xfffd) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -1) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -2) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -3) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i64.store32" (i64.const -4) (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i32.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffc)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffb)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfffa)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const 0xfff9)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -5)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -6)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -7)) "out of bounds memory access")
+(assert_trap (invoke "i64.load" (i64.const -8)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "f32.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffc)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffb)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfffa)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const 0xfff9)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -5)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -6)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -7)) "out of bounds memory access")
+(assert_trap (invoke "f64.load" (i64.const -8)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load8_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i32.load16_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load8_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load16_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_s" (i64.const -4)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0x10000)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xffff)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xfffe)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const 0xfffd)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -1)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -2)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -3)) "out of bounds memory access")
+(assert_trap (invoke "i64.load32_u" (i64.const -4)) "out of bounds memory access")
+
+;; No memory was changed
+(assert_return (invoke "i64.load" (i64.const 0xfff8)) (i64.const 0x6867666564636261))
+(assert_return (invoke "i64.load" (i64.const 0)) (i64.const 0x6867666564636261))
diff --git a/test/spec/old_address64.wast b/test/spec/old_address64.wast
new file mode 100644
index 000000000..5fd193b2a
--- /dev/null
+++ b/test/spec/old_address64.wast
@@ -0,0 +1,34 @@
+(module
+ (import "spectest" "print" (func $print (param i32)))
+
+ (memory i64 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "good") (param $i i64)
+ (call $print (i32.load8_u offset=0 (local.get $i))) ;; 97 'a'
+ (call $print (i32.load8_u offset=1 (local.get $i))) ;; 98 'b'
+ (call $print (i32.load8_u offset=2 (local.get $i))) ;; 99 'c'
+ (call $print (i32.load8_u offset=25 (local.get $i))) ;; 122 'z'
+
+ (call $print (i32.load16_u offset=0 (local.get $i))) ;; 25185 'ab'
+ (call $print (i32.load16_u align=1 (local.get $i))) ;; 25185 'ab'
+ (call $print (i32.load16_u offset=1 align=1 (local.get $i))) ;; 25442 'bc'
+ (call $print (i32.load16_u offset=2 (local.get $i))) ;; 25699 'cd'
+ (call $print (i32.load16_u offset=25 align=1 (local.get $i))) ;; 122 'z\0'
+
+ (call $print (i32.load offset=0 (local.get $i))) ;; 1684234849 'abcd'
+ (call $print (i32.load offset=1 align=1 (local.get $i))) ;; 1701077858 'bcde'
+ (call $print (i32.load offset=2 align=2 (local.get $i))) ;; 1717920867 'cdef'
+ (call $print (i32.load offset=25 align=1 (local.get $i))) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "bad") (param $i i64)
+ (drop (i32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(invoke "good" (i64.const 0))
+(invoke "good" (i64.const 65507))
+(assert_trap (invoke "good" (i64.const 65508)) "out of bounds memory access")
+(assert_trap (invoke "bad" (i64.const 0)) "out of bounds memory access")
+(assert_trap (invoke "bad" (i64.const 1)) "out of bounds memory access")
diff --git a/test/spec/resizing64.wast b/test/spec/resizing64.wast
new file mode 100644
index 000000000..3bd9e288d
--- /dev/null
+++ b/test/spec/resizing64.wast
@@ -0,0 +1,58 @@
+(module
+ (memory i64 0)
+
+ (func (export "load_at_zero") (result i32) (i32.load (i64.const 0)))
+ (func (export "store_at_zero") (i32.store (i64.const 0) (i32.const 2)))
+
+ (func (export "load_at_page_size") (result i32) (i32.load (i64.const 0x10000)))
+ (func (export "store_at_page_size") (i32.store (i64.const 0x10000) (i32.const 3)))
+
+ (func (export "grow") (param $sz i64) (result i64) (memory.grow (local.get $sz)))
+ (func (export "size") (result i64) (memory.size))
+)
+
+(assert_return (invoke "size") (i64.const 0))
+(assert_trap (invoke "store_at_zero") "out of bounds memory access")
+(assert_trap (invoke "load_at_zero") "out of bounds memory access")
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "size") (i64.const 1))
+(assert_return (invoke "load_at_zero") (i32.const 0))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
+(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
+(assert_return (invoke "grow" (i64.const 4)) (i64.const 1))
+(assert_return (invoke "size") (i64.const 5))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "store_at_zero"))
+(assert_return (invoke "load_at_zero") (i32.const 2))
+(assert_return (invoke "load_at_page_size") (i32.const 0))
+(assert_return (invoke "store_at_page_size"))
+(assert_return (invoke "load_at_page_size") (i32.const 3))
+
+
+(module
+ (memory i64 0)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 10000)) (i64.const 3))
+
+(module
+ (memory i64 0 10)
+ (func (export "grow") (param i64) (result i64) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 0))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "grow" (i64.const 2)) (i64.const 2))
+(assert_return (invoke "grow" (i64.const 6)) (i64.const 4))
+(assert_return (invoke "grow" (i64.const 0)) (i64.const 10))
+(assert_return (invoke "grow" (i64.const 1)) (i64.const -1))
diff --git a/test/unit/test_features.py b/test/unit/test_features.py
index dca3d33b9..4a82f8cc2 100644
--- a/test/unit/test_features.py
+++ b/test/unit/test_features.py
@@ -387,5 +387,6 @@ class TargetFeaturesSectionTest(utils.BinaryenTestCase):
'--enable-tail-call',
'--enable-reference-types',
'--enable-multivalue',
- '--enable-gc'
+ '--enable-gc',
+ '--enable-memory64'
], p2.stdout.splitlines())