summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2019-04-05 19:48:54 -0700
committerGitHub <noreply@github.com>2019-04-05 19:48:54 -0700
commit37443aef8c22f100dc59e81aff6af5a252f3217d (patch)
treeae68bcc8b6bbc4f2b7fdd1f50349b9980e59f10f
parent5b24f039ba1f55520a61f6dd6bb8ca46556c592b (diff)
downloadbinaryen-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.
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/binaryen-c.cpp13
-rw-r--r--src/binaryen-c.h2
-rw-r--r--src/ir/memory-utils.h4
-rw-r--r--src/js/binaryen.js-post.js9
-rw-r--r--src/passes/MemoryPacking.cpp4
-rw-r--r--src/passes/Print.cpp6
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp4
-rw-r--r--src/shared-constants.h2
-rw-r--r--src/shell-interface.h3
-rw-r--r--src/tools/fuzzing.h86
-rw-r--r--src/tools/wasm-ctor-eval.cpp10
-rw-r--r--src/tools/wasm-metadce.cpp4
-rw-r--r--src/wasm-binary.h5
-rw-r--r--src/wasm-s-parser.h2
-rw-r--r--src/wasm-traversal.h4
-rw-r--r--src/wasm.h9
-rw-r--r--src/wasm/wasm-binary.cpp67
-rw-r--r--src/wasm/wasm-emscripten.cpp1
-rw-r--r--src/wasm/wasm-s-parser.cpp28
-rw-r--r--src/wasm/wasm-validator.cpp19
-rw-r--r--src/wasm/wasm.cpp2
-rw-r--r--src/wasm2js.h1
-rw-r--r--test/binaryen.js/kitchen-sink.js16
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt12
-rw-r--r--test/example/c-api-kitchen-sink.c9
-rw-r--r--test/example/c-api-kitchen-sink.txt12
-rw-r--r--test/example/c-api-kitchen-sink.txt.txt1
-rw-r--r--test/example/c-api-relooper-unreachable-if.cpp7
-rw-r--r--test/example/c-api-unused-mem.cpp7
-rw-r--r--test/example/relooper-fuzz.c2
-rw-r--r--test/example/relooper-fuzz1.c2
-rw-r--r--test/example/relooper-fuzz2.c2
-rw-r--r--test/example/relooper-merge1.c2
-rw-r--r--test/example/relooper-merge2.c2
-rw-r--r--test/example/relooper-merge3.c2
-rw-r--r--test/example/relooper-merge4.c2
-rw-r--r--test/example/relooper-merge5.c2
-rw-r--r--test/example/relooper-merge6.c2
-rw-r--r--test/passes/translate-to-fuzz.txt1064
-rw-r--r--test/passes/translate-to-fuzz.wast2
-rw-r--r--test/passes/translate-to-fuzz_no-fuzz-nans.txt762
-rw-r--r--test/unit/test_features.py29
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):