diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2019-04-05 19:48:54 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-05 19:48:54 -0700 |
commit | 37443aef8c22f100dc59e81aff6af5a252f3217d (patch) | |
tree | ae68bcc8b6bbc4f2b7fdd1f50349b9980e59f10f | |
parent | 5b24f039ba1f55520a61f6dd6bb8ca46556c592b (diff) | |
download | binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.tar.gz binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.tar.bz2 binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.zip |
Passive segments (#1976)
Adds support for the bulk memory proposal's passive segments. Uses a
new (data passive ...) s-expression syntax to mark sections as
passive.
43 files changed, 1269 insertions, 958 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 052fe100d..e4b6a725d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ Current Trunk - Add `namedGlobals` to metadata output of wasm-emscripten-finalize - Add support for llvm PIC code. - Add --side-module option to wasm-emscripten-finalize. +- Add `segmentPassive` argument to `BinaryenSetMemory` for marking segments + passive. v73 --- @@ -52,4 +54,3 @@ older - Add `shared` parameters to `BinaryenAddMemoryImport` and `BinaryenSetMemory`, to support a shared memory. #1686 - diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 72544d5d7..927cae574 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -2360,7 +2360,7 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, B // Memory. One per module -void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, uint8_t shared) { +void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, int8_t* segmentPassive, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, uint8_t shared) { if (tracing) { std::cout << " {\n"; for (BinaryenIndex i = 0; i < numSegments; i++) { @@ -2378,6 +2378,13 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen } if (numSegments == 0) std::cout << "0"; // ensure the array is not empty, otherwise a compiler error on VS std::cout << " };\n"; + std::cout << " int8_t segmentPassive[] = { "; + for (BinaryenIndex i = 0; i < numSegments; i++) { + if (i > 0) std::cout << ", "; + std::cout << int(segmentPassive[i]); + } + if (numSegments == 0) std::cout << "0"; // ensure the array is not empty, otherwise a compiler error on VS + std::cout << " };\n"; std::cout << " BinaryenExpressionRef segmentOffsets[] = { "; for (BinaryenIndex i = 0; i < numSegments; i++) { if (i > 0) std::cout << ", "; @@ -2394,7 +2401,7 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen std::cout << " };\n"; std::cout << " BinaryenSetMemory(the_module, " << initial << ", " << maximum << ", "; traceNameOrNULL(exportName); - std::cout << ", segments, segmentOffsets, segmentSizes, " << numSegments << ", " << int(shared) << ");\n"; + std::cout << ", segments, segmentPassive, segmentOffsets, segmentSizes, " << numSegments << ", " << int(shared) << ");\n"; std::cout << " }\n"; } @@ -2411,7 +2418,7 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen wasm->addExport(memoryExport.release()); } for (BinaryenIndex i = 0; i < numSegments; i++) { - wasm->memory.segments.emplace_back((Expression*)segmentOffsets[i], segments[i], segmentSizes[i]); + wasm->memory.segments.emplace_back(segmentPassive[i], (Expression*)segmentOffsets[i], segments[i], segmentSizes[i]); } } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 5bc95e0f8..5c5213383 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -744,7 +744,7 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, B // Each segment has data in segments, a start offset in segmentOffsets, and a size in segmentSizes. // exportName can be NULL -void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, uint8_t shared); +void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, int8_t* segmentPassive, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, uint8_t shared); // Start function. One per module diff --git a/src/ir/memory-utils.h b/src/ir/memory-utils.h index c8f39a2ec..ea19ca799 100644 --- a/src/ir/memory-utils.h +++ b/src/ir/memory-utils.h @@ -31,6 +31,9 @@ namespace MemoryUtils { if (memory.segments.size() == 0) return true; std::vector<char> data; for (auto& segment : memory.segments) { + if (segment.isPassive) { + return false; + } auto* offset = segment.offset->dynCast<Const>(); if (!offset) return false; } @@ -61,4 +64,3 @@ namespace MemoryUtils { } // namespace wasm #endif // wasm_ir_memory_h - diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 1796080fc..b9f6b426c 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -1831,8 +1831,8 @@ function wrapModule(module, self) { ); }); }; - self['setMemory'] = function(initial, maximum, exportName, segments, shared) { - // segments are assumed to be { offset: expression ref, data: array of 8-bit data } + self['setMemory'] = function(initial, maximum, exportName, segments, flags, shared) { + // segments are assumed to be { passive: bool, offset: expression ref, data: array of 8-bit data } if (!segments) segments = []; return preserveStack(function() { return Module['_BinaryenSetMemory']( @@ -1842,6 +1842,11 @@ function wrapModule(module, self) { return allocate(segment.data, 'i8', ALLOC_STACK); }) ), + i8sToStack( + segments.map(function(segment) { + return segment.passive; + }) + ), i32sToStack( segments.map(function(segment) { return segment.offset; diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp index c7b20c582..2c0dac395 100644 --- a/src/passes/MemoryPacking.cpp +++ b/src/passes/MemoryPacking.cpp @@ -35,7 +35,8 @@ struct MemoryPacking : public Pass { segment.data.pop_back(); } // we can only handle a constant offset for splitting - if (auto* offset = segment.offset->dynCast<Const>()) { + Const* offset; + if (!segment.isPassive && (offset = segment.offset->dynCast<Const>())) { // Find runs of zeros, and split auto& data = segment.data; auto base = offset->value.geti32(); @@ -79,4 +80,3 @@ Pass *createMemoryPackingPass() { } } // namespace wasm - diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 6d7d512ff..ebfb6c311 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1289,7 +1289,11 @@ struct PrintSExpression : public Visitor<PrintSExpression> { doIndent(o, indent); o << '('; printMajor(o, "data "); - visit(segment.offset); + if (segment.isPassive) { + printMedium(o, "passive"); + } else { + visit(segment.offset); + } o << " \""; for (size_t i = 0; i < segment.data.size(); i++) { unsigned char c = segment.data[i]; diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index b9c8d5150..777d2dacc 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -51,7 +51,9 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { queue = roots; // Globals used in memory/table init expressions are also roots for (auto& segment : module->memory.segments) { - walk(segment.offset); + if (!segment.isPassive) { + walk(segment.offset); + } } for (auto& segment : module->table.segments) { walk(segment.offset); diff --git a/src/shared-constants.h b/src/shared-constants.h index 52124d891..dbbc25e02 100644 --- a/src/shared-constants.h +++ b/src/shared-constants.h @@ -35,7 +35,7 @@ extern Name GROW_WASM_MEMORY, RESULT, MEMORY, DATA, - SEGMENT, + PASSIVE, EXPORT, IMPORT, TABLE, diff --git a/src/shell-interface.h b/src/shell-interface.h index ad553441f..6c6961541 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -97,6 +97,9 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); // apply memory segments for (auto& segment : wasm.memory.segments) { + if (segment.isPassive) { + continue; + } Address offset = (uint32_t)ConstantExpressionRunner<TrivialGlobalManager>(instance.globals).visit(segment.offset).value.geti32(); if (offset + segment.data.size() > wasm.memory.initial * wasm::Memory::kPageSize) { trap("invalid offset when initializing memory"); diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index b17be8afe..b8434353a 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -256,12 +256,32 @@ private: void setupMemory() { MemoryUtils::ensureExists(wasm.memory); - // init some data - wasm.memory.segments.emplace_back(builder.makeConst(Literal(int32_t(0)))); - auto num = upTo(USABLE_MEMORY * 2); - for (size_t i = 0; i < num; i++) { - auto value = upTo(512); - wasm.memory.segments[0].data.push_back(value >= 256 ? 0 : (value & 0xff)); + if (features.hasBulkMemory()) { + size_t memCovered = 0; + // need at least one segment for memory.inits + size_t numSegments = upTo(8) + 1; + for (size_t i = 0; i < numSegments; i++) { + Memory::Segment segment; + segment.isPassive = bool(upTo(2)); + size_t segSize = upTo(USABLE_MEMORY * 2); + segment.data.resize(segSize); + for (size_t j = 0; j < segSize; j++) { + segment.data[j] = upTo(512); + } + if (!segment.isPassive) { + segment.offset = builder.makeConst(Literal(int32_t(memCovered))); + memCovered += segSize; + } + wasm.memory.segments.push_back(segment); + } + } else { + // init some data + wasm.memory.segments.emplace_back(builder.makeConst(Literal(int32_t(0)))); + auto num = upTo(USABLE_MEMORY * 2); + for (size_t i = 0; i < num; i++) { + auto value = upTo(512); + wasm.memory.segments[0].data.push_back(value >= 256 ? 0 : (value & 0xff)); + } } } @@ -742,9 +762,6 @@ private: &Self::makeSelect, &Self::makeGetGlobal) .add(FeatureSet::SIMD, &Self::makeSIMD); - if (type == none) { - options.add(FeatureSet::BulkMemory, &Self::makeBulkMemory); - } if (type == i32 || type == i64) { options.add(FeatureSet::Atomics, &Self::makeAtomic); } @@ -760,20 +777,22 @@ private: if (choice < 70) return makeIf(none); if (choice < 80) return makeLoop(none); if (choice < 90) return makeBreak(none); - switch (upTo(11)) { - case 0: return makeBlock(none); - case 1: return makeIf(none); - case 2: return makeLoop(none); - case 3: return makeBreak(none); - case 4: return makeCall(none); - case 5: return makeCallIndirect(none); - case 6: return makeSetLocal(none); - case 7: return makeStore(none); - case 8: return makeDrop(none); - case 9: return makeNop(none); - case 10: return makeSetGlobal(none); - } - WASM_UNREACHABLE(); + using Self = TranslateToFuzzReader; + auto options = FeatureOptions<Expression* (Self::*)(Type)>() + .add(FeatureSet::MVP, + &Self::makeBlock, + &Self::makeIf, + &Self::makeLoop, + &Self::makeBreak, + &Self::makeCall, + &Self::makeCallIndirect, + &Self::makeSetLocal, + &Self::makeStore, + &Self::makeDrop, + &Self::makeNop, + &Self::makeSetGlobal) + .add(FeatureSet::BulkMemory, &Self::makeBulkMemory); + return (this->*pick(options))(none); } Expression* _makeunreachable() { @@ -1757,30 +1776,33 @@ private: Expression* makeMemoryInit() { if (!allowMemory) return makeTrivial(none); - auto segment = uint32_t(get32()); - Expression* dest = make(i32); - Expression* offset = make(i32); - Expression* size = make(i32); + uint32_t segment = upTo(wasm.memory.segments.size()); + size_t totalSize = wasm.memory.segments[segment].data.size(); + size_t offsetVal = upTo(totalSize); + size_t sizeVal = upTo(totalSize - offsetVal); + Expression* dest = makePointer(); + Expression* offset = builder.makeConst(Literal(int32_t(offsetVal))); + Expression* size = builder.makeConst(Literal(int32_t(sizeVal))); return builder.makeMemoryInit(segment, dest, offset, size); } Expression* makeDataDrop() { if (!allowMemory) return makeTrivial(none); - return builder.makeDataDrop(get32()); + return builder.makeDataDrop(upTo(wasm.memory.segments.size())); } Expression* makeMemoryCopy() { if (!allowMemory) return makeTrivial(none); - Expression* dest = make(i32); - Expression* source = make(i32); + Expression* dest = makePointer(); + Expression* source = makePointer(); Expression* size = make(i32); return builder.makeMemoryCopy(dest, source, size); } Expression* makeMemoryFill() { if (!allowMemory) return makeTrivial(none); - Expression* dest = make(i32); - Expression* value = make(i32); + Expression* dest = makePointer(); + Expression* value = makePointer(); Expression* size = make(i32); return builder.makeMemoryFill(dest, value, size); } diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index c0730877a..8b8eaa4ad 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -162,9 +162,9 @@ public: memorySize = total / Memory::kPageSize; } - // flatten memory into a single segment - void flattenMemory() { - MemoryUtils::flatten(wasm.memory); + // flatten memory into a single segment, return true if successful + bool flattenMemory() { + return MemoryUtils::flatten(wasm.memory); } }; @@ -321,7 +321,9 @@ void evalCtors(Module& wasm, std::vector<std::string> ctors) { // create an instance for evalling EvallingModuleInstance instance(wasm, &interface); // flatten memory, so we do not depend on the layout of data segments - instance.flattenMemory(); + if (!instance.flattenMemory()) { + Fatal() << " ...stopping since could not flatten memory\n"; + } // set up the stack area and other environment details instance.setupEnvironment(); // we should not add new globals from here on; as a result, using diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index f06c41882..adb623ea0 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -195,7 +195,9 @@ struct MetaDCEGraph { rooter.walk(segment.offset); } for (auto& segment : wasm.memory.segments) { - rooter.walk(segment.offset); + if (!segment.isPassive) { + rooter.walk(segment.offset); + } } // A parallel scanner for function bodies diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 7fe543cf6..f13b79654 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -325,6 +325,11 @@ enum Section { Data = 11 }; +enum SegmentFlag { + IsPassive = 0x01, + HasMemIndex = 0x02, +}; + enum EncodedType { // value_type i32 = -0x1, // 0x7f diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index c80fa8b83..295e6b6c9 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -224,7 +224,7 @@ private: void stringToBinary(const char* input, size_t size, std::vector<char>& data); void parseMemory(Element& s, bool preParseImport = false); void parseData(Element& s); - void parseInnerData(Element& s, Index i = 1, Expression* offset = nullptr); + void parseInnerData(Element& s, Index i, Expression* offset, bool isPassive); void parseExport(Element& s); void parseImport(Element& s); void parseGlobal(Element& s, bool preParseImport = false); diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h index 6259bf271..8aa203fa7 100644 --- a/src/wasm-traversal.h +++ b/src/wasm-traversal.h @@ -373,7 +373,9 @@ struct Walker : public VisitorType { void walkMemory(Memory* memory) { for (auto& segment : memory->segments) { - walk(segment.offset); + if (!segment.isPassive) { + walk(segment.offset); + } } static_cast<SubType*>(this)->visitMemory(memory); } diff --git a/src/wasm.h b/src/wasm.h index 12071fdb4..763a4e764 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -858,7 +858,9 @@ public: static const Address::address_t kPageMask = ~(kPageSize - 1); struct Segment { - Expression* offset; + bool isPassive = false; + Index index = 0; + Expression* offset = nullptr; std::vector<char> data; // TODO: optimize Segment() = default; Segment(Expression* offset) : offset(offset) {} @@ -869,6 +871,11 @@ public: Segment(Expression* offset, std::vector<char>& init) : offset(offset) { data.swap(init); } + Segment(bool isPassive, Expression* offset, const char* init, Address size) + : isPassive(isPassive), offset(offset) { + data.resize(size); + std::copy_n(init, size, data.begin()); + } }; bool exists = false; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 385ee0ccb..63adbb08f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -316,13 +316,30 @@ static bool isEmpty(Memory::Segment& segment) { } static bool isConstantOffset(Memory::Segment& segment) { - return segment.offset->is<Const>(); + return segment.offset && segment.offset->is<Const>(); } void WasmBinaryWriter::writeDataSegments() { if (wasm->memory.segments.size() == 0) return; + + Index emitted = 0; + auto emit = [&](Memory::Segment& segment) { + uint32_t flags = 0; + if (segment.isPassive) { + flags |= BinaryConsts::IsPassive; + } + o << U32LEB(flags); + if (!segment.isPassive) { + writeExpression(segment.offset); + o << int8_t(BinaryConsts::End); + } + writeInlineBuffer(&segment.data[0], segment.data.size()); + emitted++; + }; + Index numConstant = 0, numDynamic = 0; + bool hasPassiveSegments = false; for (auto& segment : wasm->memory.segments) { if (!isEmpty(segment)) { if (isConstantOffset(segment)) { @@ -331,6 +348,21 @@ void WasmBinaryWriter::writeDataSegments() { numDynamic++; } } + hasPassiveSegments |= segment.isPassive; + } + + if (hasPassiveSegments) { + if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) { + std::cerr << "too many data segments, wasm VMs may not accept this binary" << std::endl; + } + // TODO: merge segments in a pass that can fix up memory.init instructions + auto section = startSection(BinaryConsts::Section::Data); + o << U32LEB(wasm->memory.segments.size()); + for (auto& segment : wasm->memory.segments) { + emit(segment); + } + finishSection(section); + return; } // check if we have too many dynamic data segments, which we can do nothing about auto num = numConstant + numDynamic; @@ -347,14 +379,6 @@ void WasmBinaryWriter::writeDataSegments() { o << U32LEB(num); // first, emit all non-constant-offset segments; then emit the constants, // which we may merge if forced to - Index emitted = 0; - auto emit = [&](Memory::Segment& segment) { - o << U32LEB(0); // Linear memory 0 in the MVP - writeExpression(segment.offset); - o << int8_t(BinaryConsts::End); - writeInlineBuffer(&segment.data[0], segment.data.size()); - emitted++; - }; auto& segments = wasm->memory.segments; for (auto& segment : segments) { if (isEmpty(segment)) continue; @@ -1536,20 +1560,25 @@ void WasmBinaryBuilder::readDataSegments() { if (debug) std::cerr << "== readDataSegments" << std::endl; auto num = getU32LEB(); for (size_t i = 0; i < num; i++) { - auto memoryIndex = getU32LEB(); - WASM_UNUSED(memoryIndex); - if (memoryIndex != 0) { - throwError("bad memory index, must be 0"); - } Memory::Segment curr; - auto offset = readExpression(); + uint32_t flags = getU32LEB(); + if (flags > 2) { + throwError("bad segment flags, must be 0, 1, or 2, not " + + std::to_string(flags)); + } + curr.isPassive = flags & BinaryConsts::IsPassive; + if (flags & BinaryConsts::HasMemIndex) { + curr.index = getU32LEB(); + } + if (!curr.isPassive) { + curr.offset = readExpression(); + } auto size = getU32LEB(); - std::vector<char> buffer; - buffer.resize(size); + curr.data.resize(size); for (size_t j = 0; j < size; j++) { - buffer[j] = char(getInt8()); + curr.data[j] = char(getInt8()); } - wasm.memory.segments.emplace_back(offset, (const char*)&buffer[0], size); + wasm.memory.segments.push_back(curr); } } diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 7ac7f4802..875212c44 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -944,6 +944,7 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata( void EmscriptenGlueGenerator::separateDataSegments(Output* outfile, Address base) { size_t lastEnd = 0; for (Memory::Segment& seg : wasm.memory.segments) { + assert(!seg.isPassive && "separating passive segments not implemented"); size_t offset = seg.offset->cast<Const>()->value.geti32(); offset -= base; size_t fill = offset - lastEnd; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index ddda991cd..3ba8e0622 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1454,7 +1454,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { } else { if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true)) throw ParseException("bad import ending"); // (memory (data ..)) format - parseInnerData(*s[i]); + auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0))); + parseInnerData(*s[i], 1, offset, false); wasm.memory.initial = wasm.memory.segments[0].data.size(); return; } @@ -1488,16 +1489,26 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { void SExpressionWasmBuilder::parseData(Element& s) { if (!wasm.memory.exists) throw ParseException("data but no memory"); + bool isPassive = false; + Expression* offset = nullptr; Index i = 1; - if (!s[i]->isList()) { - // the memory is named + if (s[i]->isStr()) { + // data is passive or named + if (s[i]->str() == PASSIVE) { + isPassive = true; + } i++; } - auto* offset = parseExpression(s[i++]); - parseInnerData(s, i, offset); + if (!isPassive) { + offset = parseExpression(s[i]); + } + if (s.size() != 3 && s.size() != 4) { + throw ParseException("Unexpected data items"); + } + parseInnerData(s, s.size() - 1, offset, isPassive); } -void SExpressionWasmBuilder::parseInnerData(Element& s, Index i, Expression* offset) { +void SExpressionWasmBuilder::parseInnerData(Element& s, Index i, Expression* offset, bool isPassive) { std::vector<char> data; while (i < s.size()) { const char *input = s[i++]->c_str(); @@ -1505,10 +1516,7 @@ void SExpressionWasmBuilder::parseInnerData(Element& s, Index i, Expression* off stringToBinary(input, size, data); } } - if (!offset) { - offset = allocator.alloc<Const>()->set(Literal(int32_t(0))); - } - wasm.memory.segments.emplace_back(offset, data.data(), data.size()); + wasm.memory.segments.emplace_back(isPassive, offset, data.data(), data.size()); } void SExpressionWasmBuilder::parseExport(Element& s) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 79c1d4f9b..a32dd5b0c 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1304,20 +1304,25 @@ static void validateMemory(Module& module, ValidationInfo& info) { info.shouldBeTrue(!curr.shared || curr.hasMax(), "memory", "shared memory must have max size"); if (curr.shared) info.shouldBeTrue(info.features.hasAtomics(), "memory", "memory is shared, but atomics are disabled"); for (auto& segment : curr.segments) { - if (!info.shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32")) continue; - info.shouldBeTrue(checkOffset(segment.offset, segment.data.size(), curr.initial * Memory::kPageSize), segment.offset, "segment offset should be reasonable"); Index size = segment.data.size(); + if (segment.isPassive) { + info.shouldBeTrue(info.features.hasBulkMemory(), segment.offset, "nonzero segment flags (bulk memory is disabled)"); + info.shouldBeEqual(segment.offset, (Expression*)nullptr, segment.offset, "passive segment should not have an offset"); + } else { + if (!info.shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32")) continue; + info.shouldBeTrue(checkOffset(segment.offset, segment.data.size(), curr.initial * Memory::kPageSize), segment.offset, "segment offset should be reasonable"); + if (segment.offset->is<Const>()) { + Index start = segment.offset->cast<Const>()->value.geti32(); + Index end = start + size; + info.shouldBeTrue(end <= curr.initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory (end)"); + } + } // If the memory is imported we don't actually know its initial size. // Specifically wasm dll's import a zero sized memory which is perfectly // valid. if (!curr.imported()) { info.shouldBeTrue(size <= curr.initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory (initial)"); } - if (segment.offset->is<Const>()) { - Index start = segment.offset->cast<Const>()->value.geti32(); - Index end = start + size; - info.shouldBeTrue(end <= curr.initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory (end)"); - } } } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index e14f6455f..ea1ff2a7c 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -56,7 +56,7 @@ Name GROW_WASM_MEMORY("__growWasmMemory"), RESULT("result"), MEMORY("memory"), DATA("data"), - SEGMENT("segment"), + PASSIVE("passive"), EXPORT("export"), IMPORT("import"), TABLE("table"), diff --git a/src/wasm2js.h b/src/wasm2js.h index 080315490..518a8037b 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -525,6 +525,7 @@ void Wasm2JSBuilder::addEsmExportsAndInstantiate(Ref ast, Module *wasm, Name fun flattenAppend(ast, ValueBuilder::makeName(name)); } for (auto& seg : wasm->memory.segments) { + assert(!seg.isPassive && "passive segments not implemented yet"); std::ostringstream out; out << "assign" << funcName.str << "(" << constOffset(seg) diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 860fdf37d..1efccfd97 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -421,10 +421,18 @@ function test_core() { // Memory. One per module - module.setMemory(1, 256, "mem", [{ - offset: module.i32.const(10), - data: "hello, world".split('').map(function(x) { return x.charCodeAt(0) }) - }]); + module.setMemory(1, 256, "mem", [ + { + passive: false, + offset: module.i32.const(10), + data: "hello, world".split('').map(function(x) { return x.charCodeAt(0) }) + }, + { + passive: true, + offset: null, + data: "I am passive".split('').map(function(x) { return x.charCodeAt(0) }) + } + ]); // Start function. One per module diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index e5eb3cf65..0955fa515 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -59,6 +59,7 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5} (import "module" "base" (func $an-imported (param i32 f64) (result f32))) (memory $0 1 256) (data (i32.const 10) "hello, world") + (data passive "I am passive") (table $0 1 funcref) (elem (i32.const 0) "$kitchen()sinker") (export "kitchen_sinker" (func "$kitchen()sinker")) @@ -3351,10 +3352,12 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5} expressions[656] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); { const char segment0[] = { 104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100 }; - const char* segments[] = { segment0 }; - BinaryenExpressionRef segmentOffsets[] = { expressions[656] }; - BinaryenIndex segmentSizes[] = { 12 }; - BinaryenSetMemory(the_module, 1, 256, "mem", segments, segmentOffsets, segmentSizes, 1, 0); + const char segment1[] = { 73, 32, 97, 109, 32, 112, 97, 115, 115, 105, 118, 101 }; + const char* segments[] = { segment0, segment1 }; + int8_t segmentPassive[] = { 0, 1 }; + BinaryenExpressionRef segmentOffsets[] = { expressions[656], expressions[0] }; + BinaryenIndex segmentSizes[] = { 12, 12 }; + BinaryenSetMemory(the_module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 0); } { BinaryenType paramTypes[] = { 0 }; @@ -3381,6 +3384,7 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5} (import "module" "base" (func $an-imported (param i32 f64) (result f32))) (memory $0 1 256) (data (i32.const 10) "hello, world") + (data passive "I am passive") (table $0 1 funcref) (elem (i32.const 0) "$kitchen()sinker") (export "kitchen_sinker" (func "$kitchen()sinker")) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 244ecc9b5..66d7bee06 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -491,10 +491,11 @@ void test_core() { // Memory. One per module - const char* segments[] = { "hello, world" }; - BinaryenExpressionRef segmentOffsets[] = { BinaryenConst(module, BinaryenLiteralInt32(10)) }; - BinaryenIndex segmentSizes[] = { 12 }; - BinaryenSetMemory(module, 1, 256, "mem", segments, segmentOffsets, segmentSizes, 1, 0); + const char* segments[] = { "hello, world", "I am passive" }; + int8_t segmentPassive[] = { 0, 1 }; + BinaryenExpressionRef segmentOffsets[] = { BinaryenConst(module, BinaryenLiteralInt32(10)), NULL }; + BinaryenIndex segmentSizes[] = { 12, 12 }; + BinaryenSetMemory(module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 0); // Start function. One per module diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 0f8775092..df193c379 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -17,6 +17,7 @@ BinaryenTypeAuto: -1 (import "module" "base" (func $an-imported (param i32 f64) (result f32))) (memory $0 1 256) (data (i32.const 10) "hello, world") + (data passive "I am passive") (table $0 1 1 funcref) (elem (i32.const 0) "$kitchen()sinker") (global $a-global i32 (i32.const 7)) @@ -3288,10 +3289,12 @@ int main() { expressions[655] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); { const char segment0[] = { 104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100 }; - const char* segments[] = { segment0 }; - BinaryenExpressionRef segmentOffsets[] = { expressions[655] }; - BinaryenIndex segmentSizes[] = { 12 }; - BinaryenSetMemory(the_module, 1, 256, "mem", segments, segmentOffsets, segmentSizes, 1, 0); + const char segment1[] = { 73, 32, 97, 109, 32, 112, 97, 115, 115, 105, 118, 101 }; + const char* segments[] = { segment0, segment1 }; + int8_t segmentPassive[] = { 0, 1 }; + BinaryenExpressionRef segmentOffsets[] = { expressions[655], expressions[0] }; + BinaryenIndex segmentSizes[] = { 12, 12 }; + BinaryenSetMemory(the_module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 0); } { BinaryenType paramTypes[] = { 0 }; @@ -3318,6 +3321,7 @@ int main() { (import "module" "base" (func $an-imported (param i32 f64) (result f32))) (memory $0 1 256) (data (i32.const 10) "hello, world") + (data passive "I am passive") (table $0 1 1 funcref) (elem (i32.const 0) "$kitchen()sinker") (global $a-global i32 (i32.const 7)) diff --git a/test/example/c-api-kitchen-sink.txt.txt b/test/example/c-api-kitchen-sink.txt.txt index b7caa1bad..05edca1a2 100644 --- a/test/example/c-api-kitchen-sink.txt.txt +++ b/test/example/c-api-kitchen-sink.txt.txt @@ -9,6 +9,7 @@ (import "module" "base" (func $an-imported (param i32 f64) (result f32))) (memory $0 1 256) (data (i32.const 10) "hello, world") + (data passive "I am passive") (table $0 1 1 funcref) (elem (i32.const 0) "$kitchen()sinker") (global $a-global i32 (i32.const 7)) diff --git a/test/example/c-api-relooper-unreachable-if.cpp b/test/example/c-api-relooper-unreachable-if.cpp index cfd802b58..3acc65d56 100644 --- a/test/example/c-api-relooper-unreachable-if.cpp +++ b/test/example/c-api-relooper-unreachable-if.cpp @@ -14,9 +14,10 @@ int main() { BinaryenModuleAutoDrop(the_module); { const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; - BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentOffsets, segmentSizes, 0, 0); + BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } the_relooper = RelooperCreate(the_module); expressions[1] = BinaryenGetLocal(the_module, 0, 1); @@ -346,8 +347,9 @@ int main() { { const char* segments[] = { 0 }; BinaryenExpressionRef segmentOffsets[] = { 0 }; + int8_t segmentPassive[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; - BinaryenSetMemory(the_module, 1, 1, NULL, segments, segmentOffsets, segmentSizes, 0, 0); + BinaryenSetMemory(the_module, 1, 1, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } expressions[157] = BinaryenConst(the_module, BinaryenLiteralInt32(65535)); expressions[158] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -554,4 +556,3 @@ int main() { functions.clear(); relooperBlocks.clear(); } - diff --git a/test/example/c-api-unused-mem.cpp b/test/example/c-api-unused-mem.cpp index 1c74b2dfd..49d116fdc 100644 --- a/test/example/c-api-unused-mem.cpp +++ b/test/example/c-api-unused-mem.cpp @@ -15,9 +15,10 @@ int main() { BinaryenModuleAutoDrop(the_module); { const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; - BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentOffsets, segmentSizes, 0, 0); + BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } the_relooper = RelooperCreate(the_module); { @@ -56,9 +57,10 @@ int main() { } { const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; - BinaryenSetMemory(the_module, 1024, 1024, NULL, segments, segmentOffsets, segmentSizes, 0, 0); + BinaryenSetMemory(the_module, 1024, 1024, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } expressions[11] = BinaryenConst(the_module, BinaryenLiteralInt32(65535)); expressions[12] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -91,4 +93,3 @@ int main() { BinaryenModuleDispose(the_module); return 0; } - diff --git a/test/example/relooper-fuzz.c b/test/example/relooper-fuzz.c index 606274683..7d8e5aec0 100644 --- a/test/example/relooper-fuzz.c +++ b/test/example/relooper-fuzz.c @@ -256,7 +256,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); assert(BinaryenModuleValidate(module)); diff --git a/test/example/relooper-fuzz1.c b/test/example/relooper-fuzz1.c index 495f7c610..5b6b7f450 100644 --- a/test/example/relooper-fuzz1.c +++ b/test/example/relooper-fuzz1.c @@ -327,7 +327,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); assert(BinaryenModuleValidate(module)); diff --git a/test/example/relooper-fuzz2.c b/test/example/relooper-fuzz2.c index ad687f918..66ffcef36 100644 --- a/test/example/relooper-fuzz2.c +++ b/test/example/relooper-fuzz2.c @@ -492,7 +492,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge1.c b/test/example/relooper-merge1.c index 9bcc403d5..df08e60b5 100644 --- a/test/example/relooper-merge1.c +++ b/test/example/relooper-merge1.c @@ -194,7 +194,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge2.c b/test/example/relooper-merge2.c index 852e75842..2784b4e71 100644 --- a/test/example/relooper-merge2.c +++ b/test/example/relooper-merge2.c @@ -206,7 +206,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge3.c b/test/example/relooper-merge3.c index 09cb98138..a992c0d47 100644 --- a/test/example/relooper-merge3.c +++ b/test/example/relooper-merge3.c @@ -193,7 +193,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge4.c b/test/example/relooper-merge4.c index 41e094315..d8d78d082 100644 --- a/test/example/relooper-merge4.c +++ b/test/example/relooper-merge4.c @@ -193,7 +193,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge5.c b/test/example/relooper-merge5.c index 153ce963a..8c4c25ad0 100644 --- a/test/example/relooper-merge5.c +++ b/test/example/relooper-merge5.c @@ -193,7 +193,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/example/relooper-merge6.c b/test/example/relooper-merge6.c index 25004c9df..7576a6c1e 100644 --- a/test/example/relooper-merge6.c +++ b/test/example/relooper-merge6.c @@ -184,7 +184,7 @@ int main() { BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize if (0) BinaryenModuleOptimize(module); diff --git a/test/passes/translate-to-fuzz.txt b/test/passes/translate-to-fuzz.txt index fb80f7c0d..82a6c20bb 100644 --- a/test/passes/translate-to-fuzz.txt +++ b/test/passes/translate-to-fuzz.txt @@ -3,42 +3,28 @@ (type $FUNCSIG$vj (func (param i64))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$vjVdddV (func (param i64 v128 f64 f64 f64 v128))) (type $FUNCSIG$v (func)) - (type $FUNCSIG$jddfiV (func (param f64 f64 f32 i32 v128) (result i64))) - (type $FUNCSIG$viViVjV (func (param i32 v128 i32 v128 i64 v128))) - (type $FUNCSIG$VVVVVii (func (param v128 v128 v128 v128 i32 i32) (result v128))) - (type $FUNCSIG$fddffj (func (param f64 f64 f32 f32 i64) (result f32))) - (type $FUNCSIG$j (func (result i64))) - (type $FUNCSIG$i (func (result i32))) + (type $FUNCSIG$VidjVji (func (param i32 f64 i64 v128 i64 i32) (result v128))) (type $FUNCSIG$f (func (result f32))) (import "fuzzing-support" "log-i32" (func $log-i32 (param i32))) (import "fuzzing-support" "log-i64" (func $log-i64 (param i64))) (import "fuzzing-support" "log-f32" (func $log-f32 (param f32))) (import "fuzzing-support" "log-f64" (func $log-f64 (param f64))) - (memory $0 (shared 1 1)) - (data (i32.const 0) "n\00\05E\00\00\00\00") - (table $0 10 10 funcref) - (elem (i32.const 0) $func_6 $func_12 $func_12 $func_12 $func_15 $func_16 $func_17 $func_17 $func_17 $func_17) - (global $global$0 (mut f32) (f32.const 536870912)) - (global $global$1 (mut f32) (f32.const 2147483648)) - (global $global$2 (mut f64) (f64.const -1048576)) - (global $global$3 (mut f64) (f64.const 23643)) + (memory $0 1 1) + (data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3") + (table $0 1 funcref) + (elem (i32.const 0) $func_7) + (global $global$0 (mut i32) (i32.const 975664160)) + (global $global$1 (mut i32) (i32.const -536870912)) + (global $global$2 (mut f32) (f32.const 2147483648)) + (global $global$3 (mut f32) (f32.const 1448959360)) (global $hangLimit (mut i32) (i32.const 10)) (export "func_4" (func $func_4)) - (export "func_5" (func $func_5)) - (export "func_6_invoker" (func $func_6_invoker)) + (export "func_4_invoker" (func $func_4_invoker)) (export "func_8" (func $func_8)) - (export "func_8_invoker" (func $func_8_invoker)) - (export "func_10" (func $func_10)) - (export "func_10_invoker" (func $func_10_invoker)) - (export "func_12" (func $func_12)) - (export "func_13" (func $func_13)) - (export "func_14" (func $func_14)) - (export "func_16" (func $func_16)) - (export "func_17" (func $func_17)) (export "hangLimitInitializer" (func $hangLimitInitializer)) - (func $func_4 (; 4 ;) (type $FUNCSIG$v) - (local $0 f64) + (func $func_4 (; 4 ;) (type $FUNCSIG$vjVdddV) (param $0 i64) (param $1 v128) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 v128) (block (if (i32.eqz @@ -54,49 +40,38 @@ ) ) (block $label$0 - (call $log-i32 - (loop $label$22 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (call $log-i32 - (i32.const -16777216) - ) - (br_if $label$22 - (i32.const 520883468) + (call $log-f64 + (local.tee $3 + (local.tee $2 + (local.tee $4 + (f64.const -256) ) - (i32.const 925912624) ) ) ) - (local.set $0 - (local.tee $0 - (local.get $0) - ) + (call $log-i64 + (i64.const 79) ) ) ) - (func $func_5 (; 5 ;) (type $FUNCSIG$jddfiV) (param $0 f64) (param $1 f64) (param $2 f32) (param $3 i32) (param $4 v128) (result i64) - (local $5 i32) + (func $func_4_invoker (; 5 ;) (type $FUNCSIG$v) + (call $func_4 + (i64.const 73) + (v128.const i32x4 0x4e58f5cd 0x337c2b33 0xff7fffff 0xcf000000) + (f64.const 2598385990079483892015151e117) + (f64.const 1797693134862315708145274e284) + (f64.const -256) + (v128.const i32x4 0xff641a00 0x010008b9 0x80004d00 0x594000b3) + ) + ) + (func $func_6 (; 6 ;) (result i64) (block (if (i32.eqz (global.get $hangLimit) ) (return - (i64.const 1) + (i64.const 2825486730639530279) ) ) (global.set $hangLimit @@ -106,37 +81,20 @@ ) ) ) - (block $label$0 - (nop) - (return - (i64.const -16777216) - ) - ) + (i64.const 32) ) - (func $func_6 (; 6 ;) (param $0 i32) (result i64) - (local $1 v128) - (local $2 f64) - (local $3 i32) - (local $4 v128) - (local $5 f64) - (local $6 f32) - (local $7 i64) - (local $8 i64) - (local $9 f64) - (local $10 i64) - (local $11 i64) - (local $12 v128) - (local $13 f32) - (local $14 i32) - (local $15 f64) - (local $16 f32) + (func $func_7 (; 7 ;) (type $FUNCSIG$VidjVji) (param $0 i32) (param $1 f64) (param $2 i64) (param $3 v128) (param $4 i64) (param $5 i32) (result v128) + (local $6 v128) + (local $7 v128) + (local $8 f32) + (local $9 i64) (block (if (i32.eqz (global.get $hangLimit) ) (return - (local.get $7) + (local.get $3) ) ) (global.set $hangLimit @@ -146,22 +104,35 @@ ) ) ) - (i64.const 18014398509481984) - ) - (func $func_6_invoker (; 7 ;) (type $FUNCSIG$v) - (drop - (call $func_6 - (i32.const 225118223) + (local.tee $6 + (block $label$0 + (call $log-i64 + (local.tee $9 + (local.get $9) + ) + ) + (return + (local.get $3) + ) ) ) ) - (func $func_8 (; 8 ;) (type $FUNCSIG$viViVjV) (param $0 i32) (param $1 v128) (param $2 i32) (param $3 v128) (param $4 i64) (param $5 v128) + (func $func_8 (; 8 ;) (type $FUNCSIG$f) (result f32) + (local $0 f32) + (local $1 i64) + (local $2 v128) + (local $3 i32) + (local $4 f32) + (local $5 f64) + (local $6 i32) (block (if (i32.eqz (global.get $hangLimit) ) - (return) + (return + (local.get $0) + ) ) (global.set $hangLimit (i32.sub @@ -170,92 +141,547 @@ ) ) ) - (block $label$0 + (block $label$0 (result f32) (local.set $5 - (local.tee $5 - (loop $label$1 (result v128) - (block - (if - (i32.eqz - (global.get $hangLimit) + (block $label$1 (result f64) + (local.set $4 + (loop $label$2 (result f32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 256) + ) ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) - ) - (block (result v128) - (drop - (if (result i32) - (i32.eqz - (loop $label$25 - (block - (if - (i32.eqz - (global.get $hangLimit) + (block (result f32) + (block $label$3 + (nop) + (local.set $5 + (br_if $label$1 + (local.get $5) + (i32.eqz + (i32.eqz + (if (result i32) + (i32.eqz + (local.get $6) + ) + (block $label$44 (result i32) + (block $label$45 + (local.set $2 + (call_indirect (type $FUNCSIG$VidjVji) + (loop $label$46 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const -nan:0x7fffe6) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$47 (result i32) + (if + (i32.eqz + (local.tee $3 + (local.tee $3 + (if + (local.tee $3 + (i32.const 0) + ) + (block $label$48 + (local.set $2 + (i64x2.shr_u + (local.get $2) + (i32.const 1309412122) + ) + ) + (br $label$46) + ) + (block $label$49 + (local.set $0 + (local.tee $4 + (f32.const -4294967296) + ) + ) + (br $label$45) + ) + ) + ) + ) + ) + (block $label$50 + (if + (block $label$51 + (global.set $global$0 + (local.get $6) + ) + (br $label$46) + ) + (block $label$52 + (call $log-f32 + (local.get $4) + ) + ) + (local.tee $1 + (block $label$53 + (call $log-i64 + (local.tee $1 + (local.tee $1 + (i64.const 2147483647) + ) + ) + ) + (br $label$45) + ) + ) + ) + (local.set $4 + (local.get $0) + ) + ) + (block $label$54 + (loop $label$55 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$56 + (call $log-f64 + (f64.const 15) + ) + (local.set $2 + (v128.const i32x4 0x616a6b2b 0x2c343b35 0xfffff800 0x494b1217) + ) + ) + (br_if $label$55 + (br_if $label$44 + (local.tee $6 + (i32.const 4) + ) + (loop $label$57 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 72) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$58 + (call $log-i64 + (local.tee $1 + (local.tee $1 + (i64.const -134217728) + ) + ) + ) + (local.set $0 + (f32.const -2147483648) + ) + ) + (br_if $label$57 + (loop $label$59 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $0) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$60 + (br_if $label$45 + (local.get $3) + ) + (local.set $2 + (local.get $2) + ) + ) + (br_if $label$59 + (local.get $6) + ) + (local.get $3) + ) + ) + ) + (loop $label$61 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const -9223372036854775808) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$62 + (loop $label$63 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (local.set $2 + (v128.const i32x4 0x07070707 0x1e070707 0xfff80000 0xffffffff) + ) + (br_if $label$63 + (i32.eqz + (i32.const 1094730305) + ) + ) + (local.set $1 + (local.get $1) + ) + ) + ) + ) + (br_if $label$61 + (i32.eqz + (if (result i32) + (i32.eqz + (local.get $3) + ) + (i32.const 512) + (i32.const 128) + ) + ) + ) + (br_if $label$44 + (i32.const 26) + (i32.eqz + (i32.const 24857) + ) + ) + ) + ) + ) + ) + ) + ) + (call $log-i32 + (i32.const 1937132399) + ) + ) + ) + (local.set $2 + (local.tee $2 + (local.tee $2 + (local.tee $2 + (local.tee $2 + (local.tee $2 + (v128.const i32x4 0x0000020b 0xfff4ff01 0xffc00000 0xff02fffe) + ) + ) + ) + ) + ) + ) + ) + ) + (local.tee $3 + (local.tee $3 + (local.tee $3 + (i8x16.extract_lane_s 8 + (local.get $2) + ) + ) + ) + ) + ) + ) + (f64.const -0) + (local.get $1) + (local.tee $2 + (local.tee $2 + (local.get $2) + ) + ) + (if (result i64) + (local.get $6) + (block $label$65 (result i64) + (local.set $0 + (local.tee $0 + (f32.convert_i64_s + (local.tee $1 + (local.get $1) + ) + ) + ) + ) + (local.tee $1 + (if (result i64) + (i32.eqz + (loop $label$66 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 4.714809874508602e-28) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$67 + (local.tee $3 + (loop $label$68 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 549755813888) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$69 + (if + (i32.eqz + (i32.const -96) + ) + (local.set $2 + (v128.const i32x4 0xcf400000 0x41d655d6 0x00000000 0x38100000) + ) + (local.set $5 + (f64.const 6767264718455265491139985e262) + ) + ) + (br $label$45) + ) + ) + ) + (local.set $2 + (v128.const i32x4 0x2235ce00 0x1d01000b 0x39290018 0x352b0000) + ) + ) + (br_if $label$66 + (i32.eqz + (local.get $3) + ) + ) + (i32.const 128) + ) + ) + ) + (i64.const 255) + (i64.const -46) + ) + ) + ) + (block $label$70 (result i64) + (local.get $1) + ) + ) + (local.get $3) + (i32.const 0) + ) + ) + (nop) + ) + (local.get $6) + ) + (i32.const 255) ) - (return) ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) + ) + ) + ) + ) + (br_if $label$2 + (loop $label$4 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) ) ) - (block - (block $label$26 - (if - (local.get $0) - (nop) - (block $label$27 - (nop) - (nop) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$5 + (memory.fill + (i32.and + (local.tee $6 + (local.get $6) ) + (local.get $6) ) - (block $label$28 - (nop) + (i32.and + (local.get $6) + (i32.const 15) ) - (local.set $4 - (block $label$29 (result i64) - (call $log-f64 - (f64.const 72) - ) - (local.tee $4 - (local.tee $4 - (local.tee $4 - (br_if $label$29 - (block $label$30 (result i64) - (br_if $label$25 - (local.get $2) + (i32.const 1) + ) + (block $label$12 + (nop) + ) + ) + (br_if $label$4 + (if (result i32) + (local.get $3) + (block $label$13 (result i32) + (local.set $4 + (loop $label$14 (result f32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $0) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$15 (result f32) + (local.set $6 + (block $label$16 (result i32) + (if + (i32.const 1275596062) + (nop) + (local.set $5 + (local.get $5) ) - (i64.const 4294967229) ) - (i32.eqz - (i32.const 0) + (br_if $label$13 + (local.get $3) + (local.get $3) ) ) ) - ) - ) - ) - ) - ) - (br_if $label$25 - (i32.eqz - (local.tee $0 - (local.tee $2 - (local.tee $0 - (local.tee $0 - (local.tee $0 + (br_if $label$15 + (local.tee $4 (local.tee $0 - (local.tee $2 - (local.tee $0 - (i32.const 1215581264) + (local.get $0) + ) + ) + (i32.eqz + (loop $label$17 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 2176.25048828125) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$18 + (call $log-f32 + (local.get $0) + ) + ) + (br_if $label$17 + (local.tee $6 + (i32.const 32) + ) + ) + (local.tee $6 + (local.tee $3 + (local.get $3) + ) ) ) ) @@ -264,289 +690,85 @@ ) ) ) + (br $label$2) ) - ) - (local.tee $0 - (loop $label$31 - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$32 - (local.set $2 - (i32.const -127) - ) - (br $label$25) - ) - ) + (i32.const 286919692) ) ) + (i32.const 1701143815) ) ) - (i32.const 9282) - (block $label$33 (result i32) - (local.get $0) - ) ) + (f32.const -nan:0x7fffbd) ) - (br_if $label$1 - (i32.const -1) - ) - (v128.const i32x4 0x0b00c0b2 0x1f010200 0xff00ff01 0xff0fed00) ) ) - ) - ) - (local.set $5 - (v128.const i32x4 0x80190000 0xeb00021b 0x7f001a4a 0x005d1280) - ) - ) - ) - (func $func_8_invoker (; 9 ;) (type $FUNCSIG$v) - (call $func_8 - (i32.const 68) - (v128.const i32x4 0x25373870 0x313c793d 0x150c0902 0x1f4c030a) - (i32.const 420088586) - (v128.const i32x4 0xfffe1b09 0xfffe0000 0x5f0b1615 0x463dffe6) - (i64.const 2055) - (v128.const i32x4 0x00000000 0x43e00000 0x00000000 0x406c6000) - ) - ) - (func $func_10 (; 10 ;) (type $FUNCSIG$vd) (param $0 f64) - (local $1 i32) - (local $2 i64) - (local $3 f64) - (local $4 f64) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (nop) - (br_if $label$0 - (local.get $1) - ) - ) - ) - (func $func_10_invoker (; 11 ;) (type $FUNCSIG$v) - (call $func_10 - (f64.const -nan:0xfffffffffffac) - ) - (call $func_10 - (f64.const -81) - ) - (call $func_10 - (f64.const -91) - ) - ) - (func $func_12 (; 12 ;) (type $FUNCSIG$VVVVVii) (param $0 v128) (param $1 v128) (param $2 v128) (param $3 v128) (param $4 i32) (param $5 i32) (result v128) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (v128.const i32x4 0xff040000 0xff371d46 0x6f000002 0x00004318) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (call $log-i64 - (i64.const -17179869184) - ) - (return - (local.get $0) - ) - ) - ) - (func $func_13 (; 13 ;) (type $FUNCSIG$fddffj) (param $0 f64) (param $1 f64) (param $2 f32) (param $3 f32) (param $4 i64) (result f32) - (local $5 f32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (local.get $3) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (nop) - (return - (f32.const -562949953421312) - ) - ) - ) - (func $func_14 (; 14 ;) (type $FUNCSIG$j) (result i64) - (local $0 v128) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (i64.const -4294967295) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (call $log-f64 - (f64.const 3.0085765013203267e-46) - ) - (return - (i64.const 117901063) - ) - ) - ) - (func $func_15 (; 15 ;) - (local $0 v128) - (local $1 i64) - (local $2 i32) - (local $3 f64) - (local $4 f64) - (local $5 v128) - (local $6 i64) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (local.set $5 - (v128.const i32x4 0x5d1b5d4e 0x48481b54 0x00000000 0xf8000000) - ) - (nop) - ) - ) - (func $func_16 (; 16 ;) (type $FUNCSIG$i) (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (i32.const 0) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (loop $label$0 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) (return - (i32.const 32767) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (local.get $0) ) ) ) - (block (result i32) - (block $label$1 - (block $label$2 - (block $label$3 - (nop) - (nop) + (br_if $label$0 + (f32.const 4.6423336564924e-40) + (i32.eqz + (local.tee $3 + (loop $label$37 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (local.set $5 + (f64.const 151992138) + ) + (br_if $label$37 + (local.tee $3 + (local.tee $3 + (loop $label$38 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 185622288) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (local.get $6) + ) + ) + ) + ) + (local.tee $3 + (i32.const 112) + ) + ) ) - (nop) ) - (nop) - (nop) - ) - (br_if $label$0 - (i32.const 1147035403) ) - (i32.const 1024) - ) - ) - ) - (func $func_17 (; 17 ;) (type $FUNCSIG$f) (result f32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (f32.const 185009408) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (if (result f32) - (i32.const 1230459474) - (block $label$5 (result f32) - (f32.const 121) - ) - (block $label$6 (result f32) - (f32.const 1) ) ) ) - (func $hangLimitInitializer (; 18 ;) + (func $hangLimitInitializer (; 9 ;) (global.set $hangLimit (i32.const 10) ) diff --git a/test/passes/translate-to-fuzz.wast b/test/passes/translate-to-fuzz.wast index cbf25fde1..5b378f2b2 100644 --- a/test/passes/translate-to-fuzz.wast +++ b/test/passes/translate-to-fuzz.wast @@ -97,3 +97,5 @@ fire, walk with me (&!*^@$*&@!^*&@#^$*&@#$*&@#$^*&@^#$)(&)(!&$(*&^@&#*$ ) # this isn't really needed either + +bleh diff --git a/test/passes/translate-to-fuzz_no-fuzz-nans.txt b/test/passes/translate-to-fuzz_no-fuzz-nans.txt index f256d3bf4..ff8b1f26b 100644 --- a/test/passes/translate-to-fuzz_no-fuzz-nans.txt +++ b/test/passes/translate-to-fuzz_no-fuzz-nans.txt @@ -3,42 +3,28 @@ (type $FUNCSIG$vj (func (param i64))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$vjVdddV (func (param i64 v128 f64 f64 f64 v128))) (type $FUNCSIG$v (func)) - (type $FUNCSIG$jddfiV (func (param f64 f64 f32 i32 v128) (result i64))) - (type $FUNCSIG$viViVjV (func (param i32 v128 i32 v128 i64 v128))) - (type $FUNCSIG$VVVVVii (func (param v128 v128 v128 v128 i32 i32) (result v128))) - (type $FUNCSIG$fddffj (func (param f64 f64 f32 f32 i64) (result f32))) - (type $FUNCSIG$j (func (result i64))) - (type $FUNCSIG$i (func (result i32))) + (type $FUNCSIG$VidjVji (func (param i32 f64 i64 v128 i64 i32) (result v128))) (type $FUNCSIG$f (func (result f32))) (import "fuzzing-support" "log-i32" (func $log-i32 (param i32))) (import "fuzzing-support" "log-i64" (func $log-i64 (param i64))) (import "fuzzing-support" "log-f32" (func $log-f32 (param f32))) (import "fuzzing-support" "log-f64" (func $log-f64 (param f64))) - (memory $0 (shared 1 1)) - (data (i32.const 0) "n\00\05E\00\00\00\00") - (table $0 6 6 funcref) - (elem (i32.const 0) $func_6 $func_12 $func_12 $func_12 $func_15 $func_16) - (global $global$0 (mut f32) (f32.const 536870912)) - (global $global$1 (mut f32) (f32.const 2147483648)) - (global $global$2 (mut f64) (f64.const -1048576)) - (global $global$3 (mut f64) (f64.const 23643)) + (memory $0 1 1) + (data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3") + (table $0 1 1 funcref) + (elem (i32.const 0) $func_7) + (global $global$0 (mut i32) (i32.const 975664160)) + (global $global$1 (mut i32) (i32.const -536870912)) + (global $global$2 (mut f32) (f32.const 2147483648)) + (global $global$3 (mut f32) (f32.const 1448959360)) (global $hangLimit (mut i32) (i32.const 10)) (export "func_4" (func $func_4)) - (export "func_5" (func $func_5)) - (export "func_6_invoker" (func $func_6_invoker)) + (export "func_4_invoker" (func $func_4_invoker)) (export "func_8" (func $func_8)) - (export "func_8_invoker" (func $func_8_invoker)) - (export "func_10" (func $func_10)) - (export "func_10_invoker" (func $func_10_invoker)) - (export "func_12" (func $func_12)) - (export "func_13" (func $func_13)) - (export "func_14" (func $func_14)) - (export "func_16" (func $func_16)) - (export "func_17" (func $func_17)) (export "hangLimitInitializer" (func $hangLimitInitializer)) - (func $func_4 (; 4 ;) (type $FUNCSIG$v) - (local $0 f64) + (func $func_4 (; 4 ;) (type $FUNCSIG$vjVdddV) (param $0 i64) (param $1 v128) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 v128) (block (if (i32.eqz @@ -54,49 +40,38 @@ ) ) (block $label$0 - (call $log-i32 - (loop $label$22 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (call $log-i32 - (i32.const -16777216) - ) - (br_if $label$22 - (i32.const 520883468) + (call $log-f64 + (local.tee $3 + (local.tee $2 + (local.tee $4 + (f64.const -256) ) - (i32.const 925912624) ) ) ) - (local.set $0 - (local.tee $0 - (local.get $0) - ) + (call $log-i64 + (i64.const 79) ) ) ) - (func $func_5 (; 5 ;) (type $FUNCSIG$jddfiV) (param $0 f64) (param $1 f64) (param $2 f32) (param $3 i32) (param $4 v128) (result i64) - (local $5 i32) + (func $func_4_invoker (; 5 ;) (type $FUNCSIG$v) + (call $func_4 + (i64.const 73) + (v128.const i32x4 0x4e58f5cd 0x337c2b33 0xff7fffff 0xcf000000) + (f64.const 2598385990079483892015151e117) + (f64.const 1797693134862315708145274e284) + (f64.const -256) + (v128.const i32x4 0xff641a00 0x010008b9 0x80004d00 0x594000b3) + ) + ) + (func $func_6 (; 6 ;) (result i64) (block (if (i32.eqz (global.get $hangLimit) ) (return - (i64.const 1) + (i64.const 2825486730639530279) ) ) (global.set $hangLimit @@ -106,37 +81,20 @@ ) ) ) - (block $label$0 - (nop) - (return - (i64.const -16777216) - ) - ) + (i64.const 32) ) - (func $func_6 (; 6 ;) (param $0 i32) (result i64) - (local $1 v128) - (local $2 f64) - (local $3 i32) - (local $4 v128) - (local $5 f64) - (local $6 f32) - (local $7 i64) - (local $8 i64) - (local $9 f64) - (local $10 i64) - (local $11 i64) - (local $12 v128) - (local $13 f32) - (local $14 i32) - (local $15 f64) - (local $16 f32) + (func $func_7 (; 7 ;) (type $FUNCSIG$VidjVji) (param $0 i32) (param $1 f64) (param $2 i64) (param $3 v128) (param $4 i64) (param $5 i32) (result v128) + (local $6 v128) + (local $7 v128) + (local $8 f32) + (local $9 i64) (block (if (i32.eqz (global.get $hangLimit) ) (return - (local.get $7) + (local.get $3) ) ) (global.set $hangLimit @@ -146,22 +104,35 @@ ) ) ) - (i64.const 18014398509481984) - ) - (func $func_6_invoker (; 7 ;) (type $FUNCSIG$v) - (drop - (call $func_6 - (i32.const 225118223) + (local.tee $6 + (block $label$0 + (call $log-i64 + (local.tee $9 + (local.get $9) + ) + ) + (return + (local.get $3) + ) ) ) ) - (func $func_8 (; 8 ;) (type $FUNCSIG$viViVjV) (param $0 i32) (param $1 v128) (param $2 i32) (param $3 v128) (param $4 i64) (param $5 v128) + (func $func_8 (; 8 ;) (type $FUNCSIG$f) (result f32) + (local $0 f32) + (local $1 i64) + (local $2 v128) + (local $3 i32) + (local $4 f32) + (local $5 f64) + (local $6 i32) (block (if (i32.eqz (global.get $hangLimit) ) - (return) + (return + (local.get $4) + ) ) (global.set $hangLimit (i32.sub @@ -170,92 +141,140 @@ ) ) ) - (block $label$0 + (block $label$0 (result f32) (local.set $5 - (local.tee $5 - (loop $label$1 (result v128) - (block - (if - (i32.eqz - (global.get $hangLimit) + (block $label$1 (result f64) + (local.tee $4 + (loop $label$2 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 0) + ) ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) - ) - (block (result v128) - (drop - (if (result i32) - (i32.eqz - (loop $label$25 - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) + (block + (block $label$3 + (nop) + (local.set $5 + (local.get $5) + ) + ) + (br_if $label$2 + (loop $label$4 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) + (return + (f32.const -2147483648) ) ) - (block - (block $label$26 - (if - (local.get $0) - (nop) - (block $label$27 - (nop) - (nop) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$5 + (local.set $1 + (local.get $1) + ) + (block $label$12 + (local.set $5 + (br_if $label$1 + (f64.const 1.7669274412651046e-284) + (local.get $6) ) ) - (block $label$28 - (nop) - ) - (local.set $4 - (block $label$29 (result i64) - (call $log-f64 - (f64.const 72) - ) - (local.tee $4 - (local.tee $4 - (local.tee $4 - (br_if $label$29 - (block $label$30 (result i64) - (br_if $label$25 - (local.get $2) + ) + ) + (br_if $label$4 + (if + (local.get $3) + (block $label$13 + (local.set $4 + (loop $label$14 (result f32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$15 (result f32) + (local.set $6 + (block $label$16 (result i32) + (if + (i32.const 1275596062) + (nop) + (local.set $5 + (local.get $5) ) - (i64.const 4294967229) - ) - (i32.eqz - (i32.const 0) ) + (i32.const -2048) ) ) - ) - ) - ) - ) - ) - (br_if $label$25 - (i32.eqz - (local.tee $0 - (local.tee $2 - (local.tee $0 - (local.tee $0 - (local.tee $0 + (br_if $label$15 + (local.tee $4 (local.tee $0 - (local.tee $2 - (local.tee $0 - (i32.const 1215581264) + (local.get $0) + ) + ) + (i32.eqz + (loop $label$17 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $0) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$18 + (call $log-f32 + (f32.const 0) + ) + ) + (br_if $label$17 + (local.tee $6 + (i32.const 32) + ) + ) + (local.tee $6 + (local.tee $3 + (local.get $3) + ) ) ) ) @@ -264,16 +283,46 @@ ) ) ) + (br $label$2) + ) + (block $label$19 + (local.set $5 + (local.get $5) + ) + (br $label$4) ) ) - (local.tee $0 - (loop $label$31 + ) + (loop $label$20 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (local.get $4) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$21 (result i32) + (local.set $4 + (global.get $global$2) + ) + (loop $label$22 (result i32) (block (if (i32.eqz (global.get $hangLimit) ) - (return) + (return + (local.get $4) + ) ) (global.set $hangLimit (i32.sub @@ -282,282 +331,167 @@ ) ) ) - (block $label$32 - (local.set $2 - (i32.const -127) + (local.get $6) + ) + ) + ) + ) + ) + ) + (block + (loop $label$34 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const 1.61674249926627e-27) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$35 + (local.set $1 + (local.tee $1 + (local.tee $1 + (local.tee $1 + (local.tee $1 + (i64.const -512) + ) + ) + ) + ) + ) + (local.tee $4 + (local.tee $4 + (local.tee $0 + (block $label$36 + (local.set $1 + (local.get $1) ) - (br $label$25) + (br $label$2) ) ) ) ) ) ) - (i32.const 9282) - (block $label$33 (result i32) - (local.get $0) + (drop + (i32.eqz + (if (result i32) + (i32.const 1633371484) + (i32.const 36) + (local.get $3) + ) + ) ) ) ) - (br_if $label$1 - (i32.const -1) - ) - (v128.const i32x4 0x0b00c0b2 0x1f010200 0xff00ff01 0xff0fed00) ) ) - ) - ) - (local.set $5 - (v128.const i32x4 0x80190000 0xeb00021b 0x7f001a4a 0x005d1280) - ) - ) - ) - (func $func_8_invoker (; 9 ;) (type $FUNCSIG$v) - (call $func_8 - (i32.const 68) - (v128.const i32x4 0x25373870 0x313c793d 0x150c0902 0x1f4c030a) - (i32.const 420088586) - (v128.const i32x4 0xfffe1b09 0xfffe0000 0x5f0b1615 0x463dffe6) - (i64.const 2055) - (v128.const i32x4 0x00000000 0x43e00000 0x00000000 0x406c6000) - ) - ) - (func $func_10 (; 10 ;) (type $FUNCSIG$vd) (param $0 f64) - (local $1 i32) - (local $2 i64) - (local $3 f64) - (local $4 f64) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (nop) - (br_if $label$0 - (local.get $1) - ) - ) - ) - (func $func_10_invoker (; 11 ;) (type $FUNCSIG$v) - (call $func_10 - (f64.const 0) - ) - (call $func_10 - (f64.const -81) - ) - (call $func_10 - (f64.const -91) - ) - ) - (func $func_12 (; 12 ;) (type $FUNCSIG$VVVVVii) (param $0 v128) (param $1 v128) (param $2 v128) (param $3 v128) (param $4 i32) (param $5 i32) (result v128) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (v128.const i32x4 0xff040000 0xff371d46 0x6f000002 0x00004318) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (call $log-i64 - (i64.const -17179869184) - ) - (return - (local.get $0) - ) - ) - ) - (func $func_13 (; 13 ;) (type $FUNCSIG$fddffj) (param $0 f64) (param $1 f64) (param $2 f32) (param $3 f32) (param $4 i64) (result f32) - (local $5 f32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (local.get $3) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (nop) - (return - (f32.const -562949953421312) - ) - ) - ) - (func $func_14 (; 14 ;) (type $FUNCSIG$j) (result i64) - (local $0 v128) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (i64.const -4294967295) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (call $log-f64 - (f64.const 3.0085765013203267e-46) - ) - (return - (i64.const 117901063) - ) - ) - ) - (func $func_15 (; 15 ;) - (local $0 v128) - (local $1 i64) - (local $2 i32) - (local $3 f64) - (local $4 f64) - (local $5 v128) - (local $6 i64) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block $label$0 - (local.set $5 - (v128.const i32x4 0x5d1b5d4e 0x48481b54 0x00000000 0xf8000000) - ) - (nop) - ) - ) - (func $func_16 (; 16 ;) (type $FUNCSIG$i) (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (i32.const 0) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (loop $label$0 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) (return - (i32.const 32767) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (local.get $0) ) ) ) - (block (result i32) - (block $label$1 - (block $label$2 - (block $label$3 - (nop) - (nop) + (br_if $label$0 + (f32.const 4.6423336564924e-40) + (i32.eqz + (local.tee $3 + (loop $label$37 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const -536870912) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (local.set $5 + (f64.const 151992138) + ) + (br_if $label$37 + (local.tee $3 + (local.tee $3 + (loop $label$38 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f32.const -9223372036854775808) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$39 + (local.set $2 + (local.get $2) + ) + (block $label$43 + (local.set $0 + (f32.const -9223372036854775808) + ) + (local.set $5 + (local.tee $5 + (local.tee $5 + (local.tee $5 + (f64.const 740889648) + ) + ) + ) + ) + ) + ) + (local.set $4 + (f32.const -18446744073709551615) + ) + (i32.const 36) + ) + ) + ) + ) + ) + (local.tee $3 + (local.tee $6 + (i32.const 2147483647) + ) + ) + ) ) - (nop) ) - (nop) - (nop) - ) - (br_if $label$0 - (i32.const 1147035403) ) - (i32.const 1024) - ) - ) - ) - (func $func_17 (; 17 ;) (type $FUNCSIG$f) (result f32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (f32.const 865309568) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (if (result f32) - (i32.eqz - (if (result i32) - (i32.const 709182789) - (i32.const -4) - (i32.const 873467920) - ) - ) - (block $label$5 (result f32) - (f32.const 59953536565248) - ) - (block $label$6 (result f32) - (f32.const 1) ) ) ) - (func $hangLimitInitializer (; 18 ;) + (func $hangLimitInitializer (; 9 ;) (global.set $hangLimit (i32.const 10) ) ) - (func $deNan32 (; 19 ;) (param $0 f32) (result f32) + (func $deNan32 (; 10 ;) (param $0 f32) (result f32) (if (result f32) (f32.eq (local.get $0) @@ -567,7 +501,7 @@ (f32.const 0) ) ) - (func $deNan64 (; 20 ;) (param $0 f64) (result f64) + (func $deNan64 (; 11 ;) (param $0 f64) (result f64) (if (result f64) (f64.eq (local.get $0) diff --git a/test/unit/test_features.py b/test/unit/test_features.py index 2f9829a33..f9c410414 100644 --- a/test/unit/test_features.py +++ b/test/unit/test_features.py @@ -5,12 +5,13 @@ from scripts.test.shared import WASM_OPT, run_process, options class FeatureValidationTest(unittest.TestCase): def check_feature(self, module, error, flag): - p = run_process(WASM_OPT + ['--mvp-features', '--print'], + p = run_process(WASM_OPT + ['--mvp-features', '--print', '-o', os.devnull], input=module, check=False, capture_output=True) self.assertIn(error, p.stderr) self.assertIn('Fatal: error in validating input', p.stderr) self.assertNotEqual(p.returncode, 0) - p = run_process(WASM_OPT + ['--mvp-features', flag, '--print'], + p = run_process(WASM_OPT + ['--mvp-features', flag, '--print', + '-o', os.devnull], input=module, check=False, capture_output=True) self.assertEqual(p.returncode, 0) @@ -20,6 +21,9 @@ class FeatureValidationTest(unittest.TestCase): def check_sign_ext(self, module, error): self.check_feature(module, error, '--enable-sign-ext') + def check_bulk_mem(self, module, error): + self.check_feature(module, error, '--enable-bulk-memory') + def test_v128_signature(self): module = ''' (module @@ -89,6 +93,27 @@ class FeatureValidationTest(unittest.TestCase): ''' self.check_sign_ext(module, 'all used features should be allowed') + def test_bulk_mem_inst(self): + module = ''' + (module + (memory 1 1) + (func $foo + (memory.copy (i32.const 0) (i32.const 8) (i32.const 8)) + ) + ) + ''' + self.check_bulk_mem(module, + 'Bulk memory operation (bulk memory is disabled') + + def test_bulk_mem_segment(self): + module = ''' + (module + (memory 256 256) + (data passive "42") + ) + ''' + self.check_bulk_mem(module, 'nonzero segment flags (bulk memory is disabled)') + class TargetFeaturesSectionTest(unittest.TestCase): def disassemble(self, filename): |