diff options
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()) |