summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-c.cpp34
-rw-r--r--src/ir/ReFinalize.cpp3
-rw-r--r--src/ir/memory-utils.cpp26
-rw-r--r--src/ir/memory-utils.h75
-rw-r--r--src/ir/module-utils.h30
-rw-r--r--src/ir/utils.h2
-rw-r--r--src/passes/Memory64Lowering.cpp15
-rw-r--r--src/passes/MemoryPacking.cpp120
-rw-r--r--src/passes/Metrics.cpp22
-rw-r--r--src/passes/Print.cpp97
-rw-r--r--src/passes/RemoveMemory.cpp2
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp10
-rw-r--r--src/tools/fuzzing/fuzzing.cpp40
-rw-r--r--src/tools/wasm-ctor-eval.cpp15
-rw-r--r--src/tools/wasm-metadce.cpp7
-rw-r--r--src/tools/wasm-reduce.cpp14
-rw-r--r--src/wasm-binary.h11
-rw-r--r--src/wasm-builder.h15
-rw-r--r--src/wasm-interpreter.h19
-rw-r--r--src/wasm-s-parser.h9
-rw-r--r--src/wasm-traversal.h17
-rw-r--r--src/wasm.h43
-rw-r--r--src/wasm/wasm-binary.cpp67
-rw-r--r--src/wasm/wasm-emscripten.cpp44
-rw-r--r--src/wasm/wasm-s-parser.cpp37
-rw-r--r--src/wasm/wasm-validator.cpp40
-rw-r--r--src/wasm/wasm.cpp23
-rw-r--r--src/wasm2js.h30
-rw-r--r--test/dylib.wasm.fromBinary2
-rw-r--r--test/lit/passes/O4_disable-bulk-memory.wast8
-rw-r--r--test/lit/passes/inlining-optimizing_optimize-level=3.wast4
-rw-r--r--test/lld/em_asm_pthread.wasm.out10
-rw-r--r--test/lld/em_asm_shared.wat.out2
-rw-r--r--test/lld/em_js_O0.wat.out6
-rw-r--r--test/lld/main_module.wat.out2
-rw-r--r--test/lld/shared.wat.out2
-rw-r--r--test/lld/shared_add_to_table.wasm.out2
-rw-r--r--test/lld/shared_longjmp.wat.out2
-rw-r--r--test/metadce/outside.wast.dced4
-rw-r--r--test/passes/O3_low-memory-unused_metrics.txt1
-rw-r--r--test/passes/converge_O3_metrics.bin.txt14
-rw-r--r--test/passes/fannkuch0_dwarf.bin.txt2
-rw-r--r--test/passes/fannkuch3_dwarf.bin.txt2
-rw-r--r--test/passes/fannkuch3_manyopts_dwarf.bin.txt2
-rw-r--r--test/passes/ignore_missing_func_dwarf.bin.txt8
-rw-r--r--test/passes/inlined_to_start_dwarf.bin.txt2
-rw-r--r--test/passes/print-call-graph.txt2
-rw-r--r--test/passes/remove-unused-module-elements_all-features.txt4
-rw-r--r--test/passes/remove-unused-nonfunction-module-elements_all-features.txt4
-rw-r--r--test/passes/reverse_dwarf_abbrevs.bin.txt12
50 files changed, 534 insertions, 430 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index d70f31912..8a5756f6e 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -3768,23 +3768,25 @@ void BinaryenSetMemory(BinaryenModuleRef module,
wasm->addExport(memoryExport.release());
}
for (BinaryenIndex i = 0; i < numSegments; i++) {
- wasm->memory.segments.emplace_back(Name(),
- segmentPassive[i],
- (Expression*)segmentOffsets[i],
- segments[i],
- segmentSizes[i]);
+ auto curr = Builder::makeDataSegment(Name::fromInt(i),
+ segmentPassive[i],
+ (Expression*)segmentOffsets[i],
+ segments[i],
+ segmentSizes[i]);
+ curr->hasExplicitName = false;
+ wasm->dataSegments.push_back(std::move(curr));
}
}
// Memory segments
uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) {
- return ((Module*)module)->memory.segments.size();
+ return ((Module*)module)->dataSegments.size();
}
uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
BinaryenIndex id) {
auto* wasm = (Module*)module;
- if (wasm->memory.segments.size() <= id) {
+ if (wasm->dataSegments.size() <= id) {
Fatal() << "invalid segment id.";
}
@@ -3797,13 +3799,13 @@ uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
return false;
};
- const auto& segment = wasm->memory.segments[id];
+ const auto& segment = wasm->dataSegments[id];
int64_t ret;
- if (globalOffset(segment.offset, ret)) {
+ if (globalOffset(segment->offset, ret)) {
return ret;
}
- if (auto* get = segment.offset->dynCast<GlobalGet>()) {
+ if (auto* get = segment->offset->dynCast<GlobalGet>()) {
Global* global = wasm->getGlobal(get->name);
if (globalOffset(global->init, ret)) {
return ret;
@@ -3846,29 +3848,29 @@ bool BinaryenMemoryIsShared(BinaryenModuleRef module) {
}
size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
BinaryenIndex id) {
- const auto& segments = ((Module*)module)->memory.segments;
+ const auto& segments = ((Module*)module)->dataSegments;
if (segments.size() <= id) {
Fatal() << "invalid segment id.";
}
- return segments[id].data.size();
+ return segments[id]->data.size();
}
bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module,
BinaryenIndex id) {
- const auto& segments = ((Module*)module)->memory.segments;
+ const auto& segments = ((Module*)module)->dataSegments;
if (segments.size() <= id) {
Fatal() << "invalid segment id.";
}
- return segments[id].isPassive;
+ return segments[id]->isPassive;
}
void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
BinaryenIndex id,
char* buffer) {
- const auto& segments = ((Module*)module)->memory.segments;
+ const auto& segments = ((Module*)module)->dataSegments;
if (segments.size() <= id) {
Fatal() << "invalid segment id.";
}
const auto& segment = segments[id];
- std::copy(segment.data.cbegin(), segment.data.cend(), buffer);
+ std::copy(segment->data.cbegin(), segment->data.cend(), buffer);
}
// Start function. One per module
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 79a4c9386..ef09ddbae 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -189,6 +189,9 @@ void ReFinalize::visitElementSegment(ElementSegment* curr) {
WASM_UNREACHABLE("unimp");
}
void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); }
+void ReFinalize::visitDataSegment(DataSegment* curr) {
+ WASM_UNREACHABLE("unimp");
+}
void ReFinalize::visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); }
diff --git a/src/ir/memory-utils.cpp b/src/ir/memory-utils.cpp
index b7c92fe9e..8dc3baeb9 100644
--- a/src/ir/memory-utils.cpp
+++ b/src/ir/memory-utils.cpp
@@ -37,34 +37,36 @@ bool flatten(Module& wasm) {
}
}
- auto& memory = wasm.memory;
+ auto& dataSegments = wasm.dataSegments;
- if (memory.segments.size() == 0) {
+ if (dataSegments.size() == 0) {
return true;
}
std::vector<char> data;
- for (auto& segment : memory.segments) {
- if (segment.isPassive) {
+ for (auto& segment : dataSegments) {
+ if (segment->isPassive) {
return false;
}
- auto* offset = segment.offset->dynCast<Const>();
+ auto* offset = segment->offset->dynCast<Const>();
if (!offset) {
return false;
}
}
- for (auto& segment : memory.segments) {
- auto* offset = segment.offset->dynCast<Const>();
+ for (auto& segment : dataSegments) {
+ auto* offset = segment->offset->dynCast<Const>();
Index start = offset->value.getInteger();
- Index end = start + segment.data.size();
+ Index end = start + segment->data.size();
if (end > data.size()) {
data.resize(end);
}
- std::copy(segment.data.begin(), segment.data.end(), data.begin() + start);
+ std::copy(segment->data.begin(), segment->data.end(), data.begin() + start);
}
- memory.segments.resize(1);
- memory.segments[0].offset->cast<Const>()->value = Literal(int32_t(0));
- memory.segments[0].data.swap(data);
+ dataSegments.resize(1);
+ dataSegments[0]->offset->cast<Const>()->value = Literal(int32_t(0));
+ dataSegments[0]->data.swap(data);
+ wasm.removeDataSegments(
+ [&](DataSegment* curr) { return curr->name != dataSegments[0]->name; });
return true;
}
diff --git a/src/ir/memory-utils.h b/src/ir/memory-utils.h
index 9b3325329..5e9086ca4 100644
--- a/src/ir/memory-utils.h
+++ b/src/ir/memory-utils.h
@@ -43,8 +43,8 @@ inline void ensureExists(Memory& memory) {
// Try to merge segments until they fit into web limitations.
// Return true if successful.
inline bool ensureLimitedSegments(Module& module) {
- Memory& memory = module.memory;
- if (memory.segments.size() <= WebLimitations::MaxDataSegments) {
+ auto& dataSegments = module.dataSegments;
+ if (dataSegments.size() <= WebLimitations::MaxDataSegments) {
return true;
}
@@ -54,25 +54,23 @@ inline bool ensureLimitedSegments(Module& module) {
return false;
}
- auto isEmpty = [](Memory::Segment& segment) {
- return segment.data.size() == 0;
- };
+ auto isEmpty = [](DataSegment& segment) { return segment.data.size() == 0; };
- auto isConstantOffset = [](Memory::Segment& segment) {
+ auto isConstantOffset = [](DataSegment& segment) {
return segment.offset && segment.offset->is<Const>();
};
Index numConstant = 0, numDynamic = 0;
bool hasPassiveSegments = false;
- for (auto& segment : memory.segments) {
- if (!isEmpty(segment)) {
- if (isConstantOffset(segment)) {
+ for (auto& segment : dataSegments) {
+ if (!isEmpty(*segment)) {
+ if (isConstantOffset(*segment)) {
numConstant++;
} else {
numDynamic++;
}
}
- hasPassiveSegments |= segment.isPassive;
+ hasPassiveSegments |= segment->isPassive;
}
if (hasPassiveSegments) {
@@ -93,43 +91,43 @@ inline bool ensureLimitedSegments(Module& module) {
assert(num == WebLimitations::MaxDataSegments - 1);
}
- std::vector<Memory::Segment> mergedSegments;
+ std::vector<std::unique_ptr<wasm::DataSegment>> mergedSegments;
mergedSegments.reserve(WebLimitations::MaxDataSegments);
// drop empty segments and pass through dynamic-offset segments
- for (auto& segment : memory.segments) {
- if (isEmpty(segment)) {
+ for (auto& segment : dataSegments) {
+ if (isEmpty(*segment)) {
continue;
}
- if (isConstantOffset(segment)) {
+ if (isConstantOffset(*segment)) {
continue;
}
- mergedSegments.push_back(segment);
+ mergedSegments.push_back(std::move(segment));
}
// from here on, we concern ourselves with non-empty constant-offset
// segments, the ones which we may need to merge
- auto isRelevant = [&](Memory::Segment& segment) {
+ auto isRelevant = [&](DataSegment& segment) {
return !isEmpty(segment) && isConstantOffset(segment);
};
- for (Index i = 0; i < memory.segments.size(); i++) {
- auto& segment = memory.segments[i];
- if (!isRelevant(segment)) {
+ for (Index i = 0; i < dataSegments.size(); i++) {
+ auto& segment = dataSegments[i];
+ if (!isRelevant(*segment)) {
continue;
}
if (mergedSegments.size() + 2 < WebLimitations::MaxDataSegments) {
- mergedSegments.push_back(segment);
+ mergedSegments.push_back(std::move(segment));
continue;
}
// we can emit only one more segment! merge everything into one
// start the combined segment at the bottom of them all
- auto start = segment.offset->cast<Const>()->value.getInteger();
- for (Index j = i + 1; j < memory.segments.size(); j++) {
- auto& segment = memory.segments[j];
- if (!isRelevant(segment)) {
+ auto start = segment->offset->cast<Const>()->value.getInteger();
+ for (Index j = i + 1; j < dataSegments.size(); j++) {
+ auto& segment = dataSegments[j];
+ if (!isRelevant(*segment)) {
continue;
}
- auto offset = segment.offset->cast<Const>()->value.getInteger();
+ auto offset = segment->offset->cast<Const>()->value.getInteger();
start = std::min(start, offset);
}
// create the segment and add in all the data
@@ -137,26 +135,27 @@ inline bool ensureLimitedSegments(Module& module) {
c->value = Literal(int32_t(start));
c->type = Type::i32;
- Memory::Segment combined(c);
- for (Index j = i; j < memory.segments.size(); j++) {
- auto& segment = memory.segments[j];
- if (!isRelevant(segment)) {
+ auto combined = Builder::makeDataSegment();
+ combined->offset = c;
+ for (Index j = i; j < dataSegments.size(); j++) {
+ auto& segment = dataSegments[j];
+ if (!isRelevant(*segment)) {
continue;
}
- auto offset = segment.offset->cast<Const>()->value.getInteger();
- auto needed = offset + segment.data.size() - start;
- if (combined.data.size() < needed) {
- combined.data.resize(needed);
+ auto offset = segment->offset->cast<Const>()->value.getInteger();
+ auto needed = offset + segment->data.size() - start;
+ if (combined->data.size() < needed) {
+ combined->data.resize(needed);
}
- std::copy(segment.data.begin(),
- segment.data.end(),
- combined.data.begin() + (offset - start));
+ std::copy(segment->data.begin(),
+ segment->data.end(),
+ combined->data.begin() + (offset - start));
}
- mergedSegments.push_back(combined);
+ mergedSegments.push_back(std::move(combined));
break;
}
- memory.segments.swap(mergedSegments);
+ dataSegments.swap(mergedSegments);
return true;
}
} // namespace wasm::MemoryUtils
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 5030bf84f..4f731748e 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -106,6 +106,20 @@ inline Table* copyTable(const Table* table, Module& out) {
return out.addTable(std::move(ret));
}
+inline DataSegment* copyDataSegment(const DataSegment* segment, Module& out) {
+ auto ret = Builder::makeDataSegment();
+ ret->name = segment->name;
+ ret->hasExplicitName = segment->hasExplicitName;
+ ret->isPassive = segment->isPassive;
+ if (!segment->isPassive) {
+ auto offset = ExpressionManipulator::copy(segment->offset, out);
+ ret->offset = offset;
+ }
+ ret->data = segment->data;
+
+ return out.addDataSegment(std::move(ret));
+}
+
inline void copyModule(const Module& in, Module& out) {
// we use names throughout, not raw pointers, so simple copying is fine
// for everything *but* expressions
@@ -127,11 +141,10 @@ inline void copyModule(const Module& in, Module& out) {
for (auto& curr : in.tables) {
copyTable(curr.get(), out);
}
-
- out.memory = in.memory;
- for (auto& segment : out.memory.segments) {
- segment.offset = ExpressionManipulator::copy(segment.offset, out);
+ for (auto& curr : in.dataSegments) {
+ copyDataSegment(curr.get(), out);
}
+ out.memory = in.memory;
out.start = in.start;
out.userSections = in.userSections;
out.debugInfoFileNames = in.debugInfoFileNames;
@@ -205,6 +218,15 @@ template<typename T> inline void iterDefinedMemories(Module& wasm, T visitor) {
}
}
+template<typename T>
+inline void iterActiveDataSegments(Module& wasm, T visitor) {
+ for (auto& segment : wasm.dataSegments) {
+ if (!segment->isPassive) {
+ visitor(segment.get());
+ }
+ }
+}
+
template<typename T> inline void iterImportedTables(Module& wasm, T visitor) {
for (auto& import : wasm.tables) {
if (import->imported()) {
diff --git a/src/ir/utils.h b/src/ir/utils.h
index 7abc87b5e..cad4a78aa 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -139,6 +139,7 @@ struct ReFinalize
void visitTable(Table* curr);
void visitElementSegment(ElementSegment* curr);
void visitMemory(Memory* curr);
+ void visitDataSegment(DataSegment* curr);
void visitTag(Tag* curr);
void visitModule(Module* curr);
@@ -163,6 +164,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); }
void visitElementSegment(ElementSegment* curr) { WASM_UNREACHABLE("unimp"); }
void visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); }
+ void visitDataSegment(DataSegment* curr) { WASM_UNREACHABLE("unimp"); }
void visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); }
void visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); }
diff --git a/src/passes/Memory64Lowering.cpp b/src/passes/Memory64Lowering.cpp
index 95dbf4f17..4c2770e3a 100644
--- a/src/passes/Memory64Lowering.cpp
+++ b/src/passes/Memory64Lowering.cpp
@@ -99,19 +99,20 @@ struct Memory64Lowering : public WalkerPass<PostWalker<Memory64Lowering>> {
void visitAtomicNotify(AtomicNotify* curr) { wrapAddress64(curr->ptr); }
void visitMemory(Memory* memory) {
- for (auto& segment : memory->segments) {
- if (!segment.isPassive) {
- auto* c = segment.offset->cast<Const>();
- c->value = Literal(static_cast<uint32_t>(c->value.geti64()));
- c->type = Type::i32;
- }
- }
// This is visited last.
memory->indexType = Type::i32;
if (memory->hasMax() && memory->max > Memory::kMaxSize32) {
memory->max = Memory::kMaxSize32;
}
}
+
+ void visitDataSegment(DataSegment* segment) {
+ if (!segment->isPassive) {
+ auto* c = segment->offset->cast<Const>();
+ c->value = Literal(static_cast<uint32_t>(c->value.geti64()));
+ c->type = Type::i32;
+ }
+ }
};
Pass* createMemory64LoweringPass() { return new Memory64Lowering(); }
diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp
index 7b4caf11e..3be08e7b9 100644
--- a/src/passes/MemoryPacking.cpp
+++ b/src/passes/MemoryPacking.cpp
@@ -95,19 +95,22 @@ makeGtShiftedMemorySize(Builder& builder, Module& module, MemoryInit* curr) {
struct MemoryPacking : public Pass {
void run(PassRunner* runner, Module* module) override;
- bool canOptimize(const Memory& memory, const PassOptions& passOptions);
+ bool canOptimize(const Memory& memory,
+ std::vector<std::unique_ptr<DataSegment>>& dataSegments,
+ const PassOptions& passOptions);
void optimizeBulkMemoryOps(PassRunner* runner, Module* module);
void getSegmentReferrers(Module* module, ReferrersMap& referrers);
- void dropUnusedSegments(std::vector<Memory::Segment>& segments,
+ void dropUnusedSegments(std::vector<std::unique_ptr<DataSegment>>& segments,
ReferrersMap& referrers);
- bool canSplit(const Memory::Segment& segment, const Referrers& referrers);
- void calculateRanges(const Memory::Segment& segment,
+ bool canSplit(const std::unique_ptr<DataSegment>& segment,
+ const Referrers& referrers);
+ void calculateRanges(const std::unique_ptr<DataSegment>& segment,
const Referrers& referrers,
std::vector<Range>& ranges);
void createSplitSegments(Builder& builder,
- const Memory::Segment& segment,
+ const DataSegment* segment,
std::vector<Range>& ranges,
- std::vector<Memory::Segment>& packed,
+ std::vector<std::unique_ptr<DataSegment>>& packed,
size_t segmentsRemaining);
void createReplacements(Module* module,
const std::vector<Range>& ranges,
@@ -120,11 +123,11 @@ struct MemoryPacking : public Pass {
};
void MemoryPacking::run(PassRunner* runner, Module* module) {
- if (!canOptimize(module->memory, runner->options)) {
+ if (!canOptimize(module->memory, module->dataSegments, runner->options)) {
return;
}
- auto& segments = module->memory.segments;
+ auto& segments = module->dataSegments;
// For each segment, a list of bulk memory instructions that refer to it
ReferrersMap referrers;
@@ -141,7 +144,7 @@ void MemoryPacking::run(PassRunner* runner, Module* module) {
}
// The new, split memory segments
- std::vector<Memory::Segment> packed;
+ std::vector<std::unique_ptr<DataSegment>> packed;
Replacements replacements;
Builder builder(*module);
@@ -156,12 +159,13 @@ void MemoryPacking::run(PassRunner* runner, Module* module) {
} else {
// A single range covers the entire segment. Set isZero to false so the
// original memory.init will be used even if segment is all zeroes.
- ranges.push_back({false, 0, segment.data.size()});
+ ranges.push_back({false, 0, segment->data.size()});
}
Index firstNewIndex = packed.size();
size_t segmentsRemaining = segments.size() - origIndex;
- createSplitSegments(builder, segment, ranges, packed, segmentsRemaining);
+ createSplitSegments(
+ builder, segment.get(), ranges, packed, segmentsRemaining);
createReplacements(
module, ranges, currReferrers, replacements, firstNewIndex);
}
@@ -173,8 +177,10 @@ void MemoryPacking::run(PassRunner* runner, Module* module) {
}
}
-bool MemoryPacking::canOptimize(const Memory& memory,
- const PassOptions& passOptions) {
+bool MemoryPacking::canOptimize(
+ const Memory& memory,
+ std::vector<std::unique_ptr<DataSegment>>& dataSegments,
+ const PassOptions& passOptions) {
if (!memory.exists) {
return false;
}
@@ -186,18 +192,16 @@ bool MemoryPacking::canOptimize(const Memory& memory,
return false;
}
- auto& segments = memory.segments;
-
// One segment is always ok to optimize, as it does not have the potential
// problems handled below.
- if (segments.size() <= 1) {
+ if (dataSegments.size() <= 1) {
return true;
}
// Check if it is ok for us to optimize.
Address maxAddress = 0;
- for (auto& segment : segments) {
- if (!segment.isPassive) {
- auto* c = segment.offset->dynCast<Const>();
+ for (auto& segment : dataSegments) {
+ if (!segment->isPassive) {
+ auto* c = segment->offset->dynCast<Const>();
// If an active segment has a non-constant offset, then what gets written
// cannot be known until runtime. That is, the active segments are written
// out at startup, in order, and one may trample the data of another, like
@@ -222,7 +226,7 @@ bool MemoryPacking::canOptimize(const Memory& memory,
}
// Note the maximum address so far.
maxAddress = std::max(
- maxAddress, Address(c->value.getUnsigned() + segment.data.size()));
+ maxAddress, Address(c->value.getUnsigned() + segment->data.size()));
}
}
// All active segments have constant offsets, known at this time, so we may be
@@ -230,11 +234,11 @@ bool MemoryPacking::canOptimize(const Memory& memory,
// earlier.
// TODO: optimize in the trampling case
DisjointSpans space;
- for (auto& segment : segments) {
- if (!segment.isPassive) {
- auto* c = segment.offset->cast<Const>();
+ for (auto& segment : dataSegments) {
+ if (!segment->isPassive) {
+ auto* c = segment->offset->cast<Const>();
Address start = c->value.getUnsigned();
- DisjointSpans::Span span{start, start + segment.data.size()};
+ DisjointSpans::Span span{start, start + segment->data.size()};
if (space.addAndCheckOverlap(span)) {
std::cerr << "warning: active memory segments have overlap, which "
<< "prevents some optimizations.\n";
@@ -245,17 +249,17 @@ bool MemoryPacking::canOptimize(const Memory& memory,
return true;
}
-bool MemoryPacking::canSplit(const Memory::Segment& segment,
+bool MemoryPacking::canSplit(const std::unique_ptr<DataSegment>& segment,
const Referrers& referrers) {
// Don't mess with segments related to llvm coverage tools such as
// __llvm_covfun. There segments are expected/parsed by external downstream
// tools (llvm-cov) so they need to be left intact.
// See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
- if (segment.name.is() && segment.name.startsWith("__llvm")) {
+ if (segment->name.is() && segment->name.startsWith("__llvm")) {
return false;
}
- if (segment.isPassive) {
+ if (segment->isPassive) {
for (auto* referrer : referrers) {
if (auto* init = referrer->dynCast<MemoryInit>()) {
// Do not try to split if there is a nonconstant offset or size
@@ -268,13 +272,13 @@ bool MemoryPacking::canSplit(const Memory::Segment& segment,
}
// Active segments can only be split if they have constant offsets
- return segment.offset->is<Const>();
+ return segment->offset->is<Const>();
}
-void MemoryPacking::calculateRanges(const Memory::Segment& segment,
+void MemoryPacking::calculateRanges(const std::unique_ptr<DataSegment>& segment,
const Referrers& referrers,
std::vector<Range>& ranges) {
- auto& data = segment.data;
+ auto& data = segment->data;
if (data.size() == 0) {
return;
}
@@ -304,7 +308,7 @@ void MemoryPacking::calculateRanges(const Memory::Segment& segment,
// entire segment and that all its arguments are constants. These assumptions
// are true of all memory.inits generated by the tools.
size_t threshold = 0;
- if (segment.isPassive) {
+ if (segment->isPassive) {
// Passive segment metadata size
threshold += 2;
// Zeroes on the edge do not increase the number of segments or data.drops,
@@ -375,8 +379,8 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) {
void visitMemoryInit(MemoryInit* curr) {
Builder builder(*getModule());
- Memory::Segment& segment = getModule()->memory.segments[curr->segment];
- size_t maxRuntimeSize = segment.isPassive ? segment.data.size() : 0;
+ auto& segment = getModule()->dataSegments[curr->segment];
+ size_t maxRuntimeSize = segment->isPassive ? segment->data.size() : 0;
bool mustNop = false;
bool mustTrap = false;
auto* offset = curr->offset->dynCast<Const>();
@@ -409,7 +413,7 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) {
builder.makeDrop(curr->size),
builder.makeUnreachable()));
needsRefinalizing = true;
- } else if (!segment.isPassive) {
+ } else if (!segment->isPassive) {
// trap if (dest > memory.size | offset | size) != 0
replaceCurrent(builder.makeIf(
builder.makeBinary(
@@ -420,7 +424,7 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) {
}
}
void visitDataDrop(DataDrop* curr) {
- if (!getModule()->memory.segments[curr->segment].isPassive) {
+ if (!getModule()->dataSegments[curr->segment]->isPassive) {
ExpressionManipulator::nop(curr);
}
}
@@ -467,9 +471,10 @@ void MemoryPacking::getSegmentReferrers(Module* module,
}
}
-void MemoryPacking::dropUnusedSegments(std::vector<Memory::Segment>& segments,
- ReferrersMap& referrers) {
- std::vector<Memory::Segment> usedSegments;
+void MemoryPacking::dropUnusedSegments(
+ std::vector<std::unique_ptr<DataSegment>>& segments,
+ ReferrersMap& referrers) {
+ std::vector<std::unique_ptr<DataSegment>> usedSegments;
ReferrersMap usedReferrers;
// Remove segments that are never used
// TODO: remove unused portions of partially used segments as well
@@ -477,7 +482,7 @@ void MemoryPacking::dropUnusedSegments(std::vector<Memory::Segment>& segments,
bool used = false;
auto referrersIt = referrers.find(i);
bool hasReferrers = referrersIt != referrers.end();
- if (segments[i].isPassive) {
+ if (segments[i]->isPassive) {
if (hasReferrers) {
for (auto* referrer : referrersIt->second) {
if (referrer->is<MemoryInit>()) {
@@ -506,20 +511,22 @@ void MemoryPacking::dropUnusedSegments(std::vector<Memory::Segment>& segments,
std::swap(referrers, usedReferrers);
}
-void MemoryPacking::createSplitSegments(Builder& builder,
- const Memory::Segment& segment,
- std::vector<Range>& ranges,
- std::vector<Memory::Segment>& packed,
- size_t segmentsRemaining) {
+void MemoryPacking::createSplitSegments(
+ Builder& builder,
+ const DataSegment* segment,
+ std::vector<Range>& ranges,
+ std::vector<std::unique_ptr<DataSegment>>& packed,
+ size_t segmentsRemaining) {
size_t segmentCount = 0;
+ bool hasExplicitName = false;
for (size_t i = 0; i < ranges.size(); ++i) {
Range& range = ranges[i];
if (range.isZero) {
continue;
}
Expression* offset = nullptr;
- if (!segment.isPassive) {
- if (auto* c = segment.offset->dynCast<Const>()) {
+ if (!segment->isPassive) {
+ if (auto* c = segment->offset->dynCast<Const>()) {
if (c->value.type == Type::i32) {
offset = builder.makeConst(int32_t(c->value.geti32() + range.start));
} else {
@@ -528,7 +535,7 @@ void MemoryPacking::createSplitSegments(Builder& builder,
}
} else {
assert(ranges.size() == 1);
- offset = segment.offset;
+ offset = segment->offset;
}
}
if (WebLimitations::MaxDataSegments <= packed.size() + segmentsRemaining) {
@@ -541,24 +548,27 @@ void MemoryPacking::createSplitSegments(Builder& builder,
ranges.erase(ranges.begin() + i + 1, lastNonzero + 1);
}
Name name;
- if (segment.name.is()) {
+ if (segment->name.is()) {
// Name the first range after the original segment and all following
// ranges get numbered accordingly. This means that for segments that
// canot be split (segments that contains a single range) the input and
// output segment have the same name.
if (!segmentCount) {
- name = segment.name;
+ name = segment->name;
+ hasExplicitName = segment->hasExplicitName;
} else {
- name = std::string(segment.name.c_str()) + "." +
+ name = std::string(segment->name.c_str()) + "." +
std::to_string(segmentCount);
}
segmentCount++;
}
- packed.emplace_back(name,
- segment.isPassive,
- offset,
- &segment.data[range.start],
- range.end - range.start);
+ auto curr = Builder::makeDataSegment(name,
+ segment->isPassive,
+ offset,
+ &segment->data[range.start],
+ range.end - range.start);
+ curr->hasExplicitName = hasExplicitName;
+ packed.push_back(std::move(curr));
}
}
diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp
index 566738161..70d79c12c 100644
--- a/src/passes/Metrics.cpp
+++ b/src/passes/Metrics.cpp
@@ -53,7 +53,6 @@ struct Metrics
}
ModuleUtils::iterDefinedGlobals(*module,
[&](Global* curr) { walkGlobal(curr); });
- walkMemory(&module->memory);
// add imports / funcs / globals / exports / tables
counts["[imports]"] = imports.getNumImports();
@@ -62,23 +61,26 @@ struct Metrics
counts["[tags]"] = imports.getNumDefinedTags();
counts["[exports]"] = module->exports.size();
counts["[tables]"] = imports.getNumDefinedTables();
- // add memory and table
- if (module->memory.exists) {
- Index size = 0;
- for (auto& segment : module->memory.segments) {
- size += segment.data.size();
- }
+
+ // add memory
+ walkMemory(&module->memory);
+ Index size = 0;
+ for (auto& segment : module->dataSegments) {
+ walkDataSegment(segment.get());
+ size += segment->data.size();
+ }
+ if (!module->dataSegments.empty()) {
counts["[memory-data]"] = size;
}
- Index size = 0;
- ModuleUtils::iterActiveElementSegments(
- *module, [&](ElementSegment* segment) { size += segment->data.size(); });
+ // add table
+ size = 0;
for (auto& table : module->tables) {
walkTable(table.get());
}
for (auto& segment : module->elementSegments) {
walkElementSegment(segment.get());
+ size += segment->data.size();
}
if (!module->tables.empty()) {
counts["[table-data]"] = size;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index a87b2e643..7260d7161 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -3006,57 +3006,57 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
printMemoryHeader(curr);
o << '\n';
}
- for (auto segment : curr->segments) {
- doIndent(o, indent);
- o << '(';
- printMajor(o, "data ");
- if (segment.name.is()) {
- printName(segment.name, o);
- o << ' ';
- }
- if (!segment.isPassive) {
- visit(segment.offset);
- o << ' ';
- }
- o << "\"";
- for (size_t i = 0; i < segment.data.size(); i++) {
- unsigned char c = segment.data[i];
- switch (c) {
- case '\n':
- o << "\\n";
- break;
- case '\r':
- o << "\\0d";
- break;
- case '\t':
- o << "\\t";
- break;
- case '\f':
- o << "\\0c";
- break;
- case '\b':
- o << "\\08";
- break;
- case '\\':
- o << "\\\\";
- break;
- case '"':
- o << "\\\"";
- break;
- case '\'':
- o << "\\'";
- break;
- default: {
- if (c >= 32 && c < 127) {
- o << c;
- } else {
- o << std::hex << '\\' << (c / 16) << (c % 16) << std::dec;
- }
+ }
+ void visitDataSegment(DataSegment* curr) {
+ doIndent(o, indent);
+ o << '(';
+ printMajor(o, "data ");
+ if (curr->hasExplicitName) {
+ printName(curr->name, o);
+ o << ' ';
+ }
+ if (!curr->isPassive) {
+ visit(curr->offset);
+ o << ' ';
+ }
+ o << "\"";
+ for (size_t i = 0; i < curr->data.size(); i++) {
+ unsigned char c = curr->data[i];
+ switch (c) {
+ case '\n':
+ o << "\\n";
+ break;
+ case '\r':
+ o << "\\0d";
+ break;
+ case '\t':
+ o << "\\t";
+ break;
+ case '\f':
+ o << "\\0c";
+ break;
+ case '\b':
+ o << "\\08";
+ break;
+ case '\\':
+ o << "\\\\";
+ break;
+ case '"':
+ o << "\\\"";
+ break;
+ case '\'':
+ o << "\\'";
+ break;
+ default: {
+ if (c >= 32 && c < 127) {
+ o << c;
+ } else {
+ o << std::hex << '\\' << (c / 16) << (c % 16) << std::dec;
}
}
}
- o << "\")" << maybeNewLine;
}
+ o << "\")" << maybeNewLine;
}
void printDylinkSection(const std::unique_ptr<DylinkSection>& dylinkSection) {
doIndent(o, indent) << ";; dylink section\n";
@@ -3134,6 +3134,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
*curr, [&](Global* global) { visitGlobal(global); });
ModuleUtils::iterDefinedMemories(
*curr, [&](Memory* memory) { visitMemory(memory); });
+ for (auto& segment : curr->dataSegments) {
+ visitDataSegment(segment.get());
+ }
ModuleUtils::iterDefinedTables(*curr,
[&](Table* table) { visitTable(table); });
for (auto& segment : curr->elementSegments) {
diff --git a/src/passes/RemoveMemory.cpp b/src/passes/RemoveMemory.cpp
index 399a32933..6f2f9aee7 100644
--- a/src/passes/RemoveMemory.cpp
+++ b/src/passes/RemoveMemory.cpp
@@ -25,7 +25,7 @@ namespace wasm {
struct RemoveMemory : public Pass {
void run(PassRunner* runner, Module* module) override {
- module->memory.segments.clear();
+ module->removeDataSegments([&](DataSegment* curr) { return true; });
}
};
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp
index 686a95032..9268232b4 100644
--- a/src/passes/RemoveUnusedModuleElements.cpp
+++ b/src/passes/RemoveUnusedModuleElements.cpp
@@ -70,9 +70,9 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> {
: module(module) {
queue = roots;
// Globals used in memory/table init expressions are also roots
- for (auto& segment : module->memory.segments) {
- if (!segment.isPassive) {
- walk(segment.offset);
+ for (auto& segment : module->dataSegments) {
+ if (!segment->isPassive) {
+ walk(segment->offset);
}
}
for (auto& segment : module->elementSegments) {
@@ -365,9 +365,9 @@ struct RemoveUnusedModuleElements : public Pass {
if (!importsMemory) {
// The memory is unobservable to the outside, we can remove the
// contents.
- module->memory.segments.clear();
+ module->dataSegments.clear();
}
- if (module->memory.segments.empty()) {
+ if (module->dataSegments.empty()) {
module->memory.exists = false;
module->memory.module = module->memory.base = Name();
module->memory.initial = 0;
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index e5afbf559..c828c84d0 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -191,26 +191,30 @@ void TranslateToFuzzReader::setupMemory() {
// 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));
+ auto segment = builder.makeDataSegment();
+ segment->setName(Name::fromInt(i), false);
+ segment->isPassive = bool(upTo(2));
size_t segSize = upTo(USABLE_MEMORY * 2);
- segment.data.resize(segSize);
+ segment->data.resize(segSize);
for (size_t j = 0; j < segSize; j++) {
- segment.data[j] = upTo(512);
+ segment->data[j] = upTo(512);
}
- if (!segment.isPassive) {
- segment.offset = builder.makeConst(int32_t(memCovered));
+ if (!segment->isPassive) {
+ segment->offset = builder.makeConst(int32_t(memCovered));
memCovered += segSize;
}
- wasm.memory.segments.push_back(segment);
+ wasm.dataSegments.push_back(std::move(segment));
}
} else {
// init some data
- wasm.memory.segments.emplace_back(builder.makeConst(int32_t(0)));
+ auto segment = builder.makeDataSegment();
+ segment->offset = builder.makeConst(int32_t(0));
+ segment->setName(Name::fromInt(0), false);
+ wasm.dataSegments.push_back(std::move(segment));
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));
+ wasm.dataSegments[0]->data.push_back(value >= 256 ? 0 : (value & 0xff));
}
}
// Add memory hasher helper (for the hash, see hash.h). The function looks
@@ -326,10 +330,10 @@ void TranslateToFuzzReader::setupTags() {
}
void TranslateToFuzzReader::finalizeMemory() {
- for (auto& segment : wasm.memory.segments) {
- Address maxOffset = segment.data.size();
- if (!segment.isPassive) {
- if (auto* offset = segment.offset->dynCast<GlobalGet>()) {
+ for (auto& segment : wasm.dataSegments) {
+ Address maxOffset = segment->data.size();
+ if (!segment->isPassive) {
+ if (auto* offset = segment->offset->dynCast<GlobalGet>()) {
// Using a non-imported global in a segment offset is not valid in
// wasm. This can occur due to us making what used to be an imported
// global, in initial contents, be not imported any more. To fix that,
@@ -342,11 +346,11 @@ void TranslateToFuzzReader::finalizeMemory() {
if (!wasm.getGlobal(offset->name)->imported()) {
// TODO: It would be better to avoid segment overlap so that
// MemoryPacking can run.
- segment.offset =
+ segment->offset =
builder.makeConst(Literal::makeFromInt32(0, Type::i32));
}
}
- if (auto* offset = segment.offset->dynCast<Const>()) {
+ if (auto* offset = segment->offset->dynCast<Const>()) {
maxOffset = maxOffset + offset->value.getInteger();
}
}
@@ -2905,8 +2909,8 @@ Expression* TranslateToFuzzReader::makeMemoryInit() {
if (!allowMemory) {
return makeTrivial(Type::none);
}
- uint32_t segment = upTo(wasm.memory.segments.size());
- size_t totalSize = wasm.memory.segments[segment].data.size();
+ uint32_t segment = upTo(wasm.dataSegments.size());
+ size_t totalSize = wasm.dataSegments[segment]->data.size();
size_t offsetVal = upTo(totalSize);
size_t sizeVal = upTo(totalSize - offsetVal);
Expression* dest = makePointer();
@@ -2919,7 +2923,7 @@ Expression* TranslateToFuzzReader::makeDataDrop() {
if (!allowMemory) {
return makeTrivial(Type::none);
}
- return builder.makeDataDrop(upTo(wasm.memory.segments.size()));
+ return builder.makeDataDrop(upTo(wasm.dataSegments.size()));
}
Expression* TranslateToFuzzReader::makeMemoryCopy() {
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index 59e54d4f7..22fa87633 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -426,18 +426,19 @@ private:
void applyMemoryToModule() {
// Memory must have already been flattened into the standard form: one
// segment at offset 0, or none.
- if (wasm->memory.segments.empty()) {
+ if (wasm->dataSegments.empty()) {
Builder builder(*wasm);
- std::vector<char> empty;
- wasm->memory.segments.push_back(
- Memory::Segment(builder.makeConst(int32_t(0)), empty));
+ auto curr = builder.makeDataSegment();
+ curr->offset = builder.makeConst(int32_t(0));
+ curr->setName(Name::fromInt(0), false);
+ wasm->dataSegments.push_back(std::move(curr));
}
- auto& segment = wasm->memory.segments[0];
- assert(segment.offset->cast<Const>()->value.getInteger() == 0);
+ auto& segment = wasm->dataSegments[0];
+ assert(segment->offset->cast<Const>()->value.getInteger() == 0);
// Copy the current memory contents after execution into the Module's
// memory.
- segment.data = memory;
+ segment->data = memory;
}
// Serializing GC data requires more work than linear memory, because
diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp
index 4b12446f4..741afb22f 100644
--- a/src/tools/wasm-metadce.cpp
+++ b/src/tools/wasm-metadce.cpp
@@ -235,11 +235,8 @@ struct MetaDCEGraph {
});
rooter.walk(segment->offset);
});
- for (auto& segment : wasm.memory.segments) {
- if (!segment.isPassive) {
- rooter.walk(segment.offset);
- }
- }
+ ModuleUtils::iterActiveDataSegments(
+ wasm, [&](DataSegment* segment) { rooter.walk(segment->offset); });
// A parallel scanner for function bodies
struct Scanner : public WalkerPass<PostWalker<Scanner>> {
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index 3cfc0bb11..2276f66a4 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -752,20 +752,14 @@ struct Reducer
// TODO: bisection on segment shrinking?
- void visitMemory(Memory* curr) {
- std::cerr << "| try to simplify memory\n";
-
+ void visitDataSegment(DataSegment* curr) {
// try to reduce to first function. first, shrink segment elements.
// while we are shrinking successfully, keep going exponentially.
bool shrank = false;
- for (auto& segment : curr->segments) {
- shrank = shrinkByReduction(&segment, 2);
- }
+ shrank = shrinkByReduction(curr, 2);
// the "opposite" of shrinking: copy a 'zero' element
- for (auto& segment : curr->segments) {
- reduceByZeroing(
- &segment, 0, [](char item) { return item == 0; }, 2, shrank);
- }
+ reduceByZeroing(
+ curr, 0, [](char item) { return item == 0; }, 2, shrank);
}
template<typename T, typename U, typename C>
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 96927b10e..659e0f58b 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1158,6 +1158,7 @@ class WasmBinaryWriter {
std::unordered_map<Name, Index> globalIndexes;
std::unordered_map<Name, Index> tableIndexes;
std::unordered_map<Name, Index> elemIndexes;
+ std::unordered_map<Name, Index> dataIndexes;
BinaryIndexes(Module& wasm) {
auto addIndexes = [&](auto& source, auto& indexes) {
@@ -1185,6 +1186,11 @@ class WasmBinaryWriter {
elemIndexes[curr->name] = index;
}
+ for (auto& curr : wasm.dataSegments) {
+ auto index = dataIndexes.size();
+ dataIndexes[curr->name] = index;
+ }
+
// Globals may have tuple types in the IR, in which case they lower to
// multiple globals, one for each tuple element, in the binary. Tuple
// globals therefore occupy multiple binary indices, and we have to take
@@ -1486,6 +1492,9 @@ public:
// names
std::vector<std::unique_ptr<ElementSegment>> elementSegments;
+ // we store data here after being read from binary, before we know their names
+ std::vector<std::unique_ptr<DataSegment>> dataSegments;
+
// we store globals here before wasm.addGlobal after we know their names
std::vector<std::unique_ptr<Global>> globals;
// we store global imports here before wasm.addGlobalImport after we know
@@ -1590,7 +1599,7 @@ public:
bool hasDataCount = false;
void readDataSegments();
- void readDataCount();
+ void readDataSegmentCount();
void readTableDeclarations();
void readElementSegments();
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 86de1f7db..20babacf1 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -106,6 +106,21 @@ public:
return seg;
}
+ static std::unique_ptr<DataSegment>
+ makeDataSegment(Name name = "",
+ bool isPassive = false,
+ Expression* offset = nullptr,
+ const char* init = "",
+ Address size = 0) {
+ auto seg = std::make_unique<DataSegment>();
+ seg->name = name;
+ seg->isPassive = isPassive;
+ seg->offset = offset;
+ seg->data.resize(size);
+ std::copy_n(init, size, seg->data.begin());
+ return seg;
+ }
+
static std::unique_ptr<Export>
makeExport(Name name, Name value, ExternalKind kind) {
auto export_ = std::make_unique<Export>();
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 7b17e344b..f682e89a2 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2604,19 +2604,18 @@ private:
offset.finalize();
// apply active memory segments
- for (size_t i = 0, e = wasm.memory.segments.size(); i < e; ++i) {
- Memory::Segment& segment = wasm.memory.segments[i];
- if (segment.isPassive) {
+ for (size_t i = 0, e = wasm.dataSegments.size(); i < e; ++i) {
+ auto& segment = wasm.dataSegments[i];
+ if (segment->isPassive) {
continue;
}
-
Const size;
- size.value = Literal(uint32_t(segment.data.size()));
+ size.value = Literal(uint32_t(segment->data.size()));
size.finalize();
MemoryInit init;
init.segment = i;
- init.dest = segment.offset;
+ init.dest = segment->offset;
init.offset = &offset;
init.size = &size;
init.finalize();
@@ -3303,8 +3302,8 @@ public:
NOTE_EVAL1(offset);
NOTE_EVAL1(size);
- assert(curr->segment < wasm.memory.segments.size());
- Memory::Segment& segment = wasm.memory.segments[curr->segment];
+ assert(curr->segment < wasm.dataSegments.size());
+ auto& segment = wasm.dataSegments[curr->segment];
Address destVal(dest.getSingleValue().getUnsigned());
Address offsetVal(uint32_t(offset.getSingleValue().geti32()));
@@ -3313,7 +3312,7 @@ public:
if (offsetVal + sizeVal > 0 && droppedSegments.count(curr->segment)) {
trap("out of bounds segment access in memory.init");
}
- if ((uint64_t)offsetVal + sizeVal > segment.data.size()) {
+ if ((uint64_t)offsetVal + sizeVal > segment->data.size()) {
trap("out of bounds segment access in memory.init");
}
auto* inst = getMemoryInstance();
@@ -3324,7 +3323,7 @@ public:
Literal addr(destVal + i);
inst->externalInterface->store8(
inst->getFinalAddressWithoutOffset(addr, 1),
- segment.data[offsetVal + i]);
+ segment->data[offsetVal + i]);
}
return {};
}
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 61383f084..75c4f0dec 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -134,6 +134,7 @@ class SExpressionWasmBuilder {
int tableCounter = 0;
int elemCounter = 0;
int memoryCounter = 0;
+ int dataCounter = 0;
// we need to know function return types before we parse their contents
std::map<Name, HeapType> functionTypes;
std::unordered_map<cashew::IString, Index> debugInfoFileIndices;
@@ -320,8 +321,12 @@ 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, Name name, Expression* offset, bool isPassive);
+ void parseInnerData(Element& s,
+ Index i,
+ Name name,
+ bool hasExplicitName,
+ 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 7a803e2b2..7c10be3a9 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -50,6 +50,7 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
ReturnType visitTable(Table* curr) { return ReturnType(); }
ReturnType visitElementSegment(ElementSegment* curr) { return ReturnType(); }
ReturnType visitMemory(Memory* curr) { return ReturnType(); }
+ ReturnType visitDataSegment(DataSegment* curr) { return ReturnType(); }
ReturnType visitTag(Tag* curr) { return ReturnType(); }
ReturnType visitModule(Module* curr) { return ReturnType(); }
@@ -204,12 +205,15 @@ struct Walker : public VisitorType {
static_cast<SubType*>(this)->visitTable(table);
}
- void walkMemory(Memory* memory) {
- for (auto& segment : memory->segments) {
- if (!segment.isPassive) {
- walk(segment.offset);
- }
+ void walkDataSegment(DataSegment* segment) {
+ if (!segment->isPassive) {
+ walk(segment->offset);
}
+ static_cast<SubType*>(this)->visitDataSegment(segment);
+ }
+
+ void walkMemory(Memory* memory) {
+ // TODO: This method and walkTable should walk children too, or be renamed.
static_cast<SubType*>(this)->visitMemory(memory);
}
@@ -255,6 +259,9 @@ struct Walker : public VisitorType {
self->walkElementSegment(curr.get());
}
self->walkMemory(&module->memory);
+ for (auto& curr : module->dataSegments) {
+ self->walkDataSegment(curr.get());
+ }
}
// Walks module-level code, that is, code that is not in functions.
diff --git a/src/wasm.h b/src/wasm.h
index 3f2a83460..a466acdbe 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1862,6 +1862,13 @@ public:
}
};
+class DataSegment : public Named {
+public:
+ bool isPassive = false;
+ Expression* offset = nullptr;
+ std::vector<char> data; // TODO: optimize
+};
+
class Memory : public Importable {
public:
static const Address::address32_t kPageSize = 64 * 1024;
@@ -1870,37 +1877,9 @@ public:
static const Address::address32_t kMaxSize32 =
(uint64_t(4) * 1024 * 1024 * 1024) / kPageSize;
- struct Segment {
- // For use in name section only
- Name name;
- bool isPassive = false;
- Expression* offset = nullptr;
- std::vector<char> data; // TODO: optimize
- Segment() = default;
- Segment(Expression* offset) : offset(offset) {}
- Segment(Expression* offset, const char* init, Address size)
- : offset(offset) {
- data.resize(size);
- std::copy_n(init, size, data.begin());
- }
- Segment(Expression* offset, std::vector<char>& init) : offset(offset) {
- data.swap(init);
- }
- Segment(Name name,
- bool isPassive,
- Expression* offset,
- const char* init,
- Address size)
- : name(name), isPassive(isPassive), offset(offset) {
- data.resize(size);
- std::copy_n(init, size, data.begin());
- }
- };
-
bool exists = false;
Address initial = 0; // sizes are in pages
Address max = kMaxSize32;
- std::vector<Segment> segments;
bool shared = false;
Type indexType = Type::i32;
@@ -1913,7 +1892,6 @@ public:
name = "";
initial = 0;
max = kMaxSize32;
- segments.clear();
shared = false;
indexType = Type::i32;
}
@@ -1957,6 +1935,7 @@ public:
std::vector<std::unique_ptr<Global>> globals;
std::vector<std::unique_ptr<Tag>> tags;
std::vector<std::unique_ptr<ElementSegment>> elementSegments;
+ std::vector<std::unique_ptr<DataSegment>> dataSegments;
std::vector<std::unique_ptr<Table>> tables;
Memory memory;
@@ -1992,6 +1971,7 @@ private:
std::unordered_map<Name, Function*> functionsMap;
std::unordered_map<Name, Table*> tablesMap;
std::unordered_map<Name, ElementSegment*> elementSegmentsMap;
+ std::unordered_map<Name, DataSegment*> dataSegmentsMap;
std::unordered_map<Name, Global*> globalsMap;
std::unordered_map<Name, Tag*> tagsMap;
@@ -2002,12 +1982,14 @@ public:
Function* getFunction(Name name);
Table* getTable(Name name);
ElementSegment* getElementSegment(Name name);
+ DataSegment* getDataSegment(Name name);
Global* getGlobal(Name name);
Tag* getTag(Name name);
Export* getExportOrNull(Name name);
Table* getTableOrNull(Name name);
ElementSegment* getElementSegmentOrNull(Name name);
+ DataSegment* getDataSegmentOrNull(Name name);
Function* getFunctionOrNull(Name name);
Global* getGlobalOrNull(Name name);
Tag* getTagOrNull(Name name);
@@ -2021,6 +2003,7 @@ public:
Function* addFunction(std::unique_ptr<Function>&& curr);
Table* addTable(std::unique_ptr<Table>&& curr);
ElementSegment* addElementSegment(std::unique_ptr<ElementSegment>&& curr);
+ DataSegment* addDataSegment(std::unique_ptr<DataSegment>&& curr);
Global* addGlobal(std::unique_ptr<Global>&& curr);
Tag* addTag(std::unique_ptr<Tag>&& curr);
@@ -2030,6 +2013,7 @@ public:
void removeFunction(Name name);
void removeTable(Name name);
void removeElementSegment(Name name);
+ void removeDataSegment(Name name);
void removeGlobal(Name name);
void removeTag(Name name);
@@ -2037,6 +2021,7 @@ public:
void removeFunctions(std::function<bool(Function*)> pred);
void removeTables(std::function<bool(Table*)> pred);
void removeElementSegments(std::function<bool(ElementSegment*)> pred);
+ void removeDataSegments(std::function<bool(DataSegment*)> pred);
void removeGlobals(std::function<bool(Global*)> pred);
void removeTags(std::function<bool(Tag*)> pred);
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index c161a623b..b74331aed 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -517,36 +517,36 @@ void WasmBinaryWriter::writeExports() {
}
void WasmBinaryWriter::writeDataCount() {
- if (!wasm->features.hasBulkMemory() || !wasm->memory.segments.size()) {
+ if (!wasm->features.hasBulkMemory() || !wasm->dataSegments.size()) {
return;
}
auto start = startSection(BinaryConsts::Section::DataCount);
- o << U32LEB(wasm->memory.segments.size());
+ o << U32LEB(wasm->dataSegments.size());
finishSection(start);
}
void WasmBinaryWriter::writeDataSegments() {
- if (wasm->memory.segments.size() == 0) {
+ if (wasm->dataSegments.size() == 0) {
return;
}
- if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) {
+ if (wasm->dataSegments.size() > WebLimitations::MaxDataSegments) {
std::cerr << "Some VMs may not accept this binary because it has a large "
<< "number of data segments. Run the limit-segments pass to "
<< "merge segments.\n";
}
auto start = startSection(BinaryConsts::Section::Data);
- o << U32LEB(wasm->memory.segments.size());
- for (auto& segment : wasm->memory.segments) {
+ o << U32LEB(wasm->dataSegments.size());
+ for (auto& segment : wasm->dataSegments) {
uint32_t flags = 0;
- if (segment.isPassive) {
+ if (segment->isPassive) {
flags |= BinaryConsts::IsPassive;
}
o << U32LEB(flags);
- if (!segment.isPassive) {
- writeExpression(segment.offset);
+ if (!segment->isPassive) {
+ writeExpression(segment->offset);
o << int8_t(BinaryConsts::End);
}
- writeInlineBuffer(segment.data.data(), segment.data.size());
+ writeInlineBuffer(segment->data.data(), segment->data.size());
}
finishSection(start);
}
@@ -919,8 +919,8 @@ void WasmBinaryWriter::writeNames() {
// data segment names
if (wasm->memory.exists) {
Index count = 0;
- for (auto& seg : wasm->memory.segments) {
- if (seg.name.is()) {
+ for (auto& seg : wasm->dataSegments) {
+ if (seg->hasExplicitName) {
count++;
}
}
@@ -929,11 +929,11 @@ void WasmBinaryWriter::writeNames() {
auto substart =
startSubsection(BinaryConsts::UserSections::Subsection::NameData);
o << U32LEB(count);
- for (Index i = 0; i < wasm->memory.segments.size(); i++) {
- auto& seg = wasm->memory.segments[i];
- if (seg.name.is()) {
+ for (Index i = 0; i < wasm->dataSegments.size(); i++) {
+ auto& seg = wasm->dataSegments[i];
+ if (seg->name.is()) {
o << U32LEB(i);
- writeEscapedName(seg.name.str);
+ writeEscapedName(seg->name.str);
}
}
finishSubsection(substart);
@@ -1482,7 +1482,7 @@ void WasmBinaryBuilder::read() {
readDataSegments();
break;
case BinaryConsts::Section::DataCount:
- readDataCount();
+ readDataSegmentCount();
break;
case BinaryConsts::Section::Table:
readTableDeclarations();
@@ -2791,7 +2791,7 @@ Expression* WasmBinaryBuilder::popTypedExpression(Type type) {
}
void WasmBinaryBuilder::validateBinary() {
- if (hasDataCount && wasm.memory.segments.size() != dataCount) {
+ if (hasDataCount && dataSegments.size() != dataCount) {
throwError("Number of segments does not agree with DataCount section");
}
}
@@ -2809,7 +2809,9 @@ void WasmBinaryBuilder::processNames() {
for (auto& segment : elementSegments) {
wasm.addElementSegment(std::move(segment));
}
-
+ for (auto& segment : dataSegments) {
+ wasm.addDataSegment(std::move(segment));
+ }
// now that we have names, apply things
if (startIndex != static_cast<Index>(-1)) {
@@ -2888,8 +2890,8 @@ void WasmBinaryBuilder::processNames() {
wasm.updateMaps();
}
-void WasmBinaryBuilder::readDataCount() {
- BYN_TRACE("== readDataCount\n");
+void WasmBinaryBuilder::readDataSegmentCount() {
+ BYN_TRACE("== readDataSegmentCount\n");
hasDataCount = true;
dataCount = getU32LEB();
}
@@ -2898,26 +2900,27 @@ void WasmBinaryBuilder::readDataSegments() {
BYN_TRACE("== readDataSegments\n");
auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
- Memory::Segment curr;
+ auto curr = Builder::makeDataSegment();
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;
+ curr->setName(Name::fromInt(i), false);
+ curr->isPassive = flags & BinaryConsts::IsPassive;
if (flags & BinaryConsts::HasIndex) {
auto memIndex = getU32LEB();
if (memIndex != 0) {
throwError("nonzero memory index");
}
}
- if (!curr.isPassive) {
- curr.offset = readExpression();
+ if (!curr->isPassive) {
+ curr->offset = readExpression();
}
auto size = getU32LEB();
auto data = getByteView(size);
- curr.data = {data.first, data.second};
- wasm.memory.segments.push_back(std::move(curr));
+ curr->data = {data.first, data.second};
+ dataSegments.push_back(std::move(curr));
}
}
@@ -3254,14 +3257,16 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) {
}
} else if (nameType == BinaryConsts::UserSections::Subsection::NameData) {
auto num = getU32LEB();
+ NameProcessor processor;
for (size_t i = 0; i < num; i++) {
auto index = getU32LEB();
auto rawName = getInlineString();
- if (index < wasm.memory.segments.size()) {
- wasm.memory.segments[i].name = rawName;
+ auto name = processor.process(rawName);
+ if (index < dataSegments.size()) {
+ dataSegments[i]->setExplicitName(name);
} else {
- std::cerr << "warning: memory index out of bounds in name section, "
- "memory subsection: "
+ std::cerr << "warning: data index out of bounds in name section, "
+ "data subsection: "
<< std::string(rawName.str) << " at index "
<< std::to_string(index) << std::endl;
}
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index fea5048f6..3416c731d 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -111,12 +111,12 @@ public:
StringConstantTracker(Module& wasm) : wasm(wasm) { calcSegmentOffsets(); }
const char* stringAtAddr(Address address) {
- for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) {
- Memory::Segment& segment = wasm.memory.segments[i];
+ for (unsigned i = 0; i < wasm.dataSegments.size(); ++i) {
+ auto& segment = wasm.dataSegments[i];
Address offset = segmentOffsets[i];
if (offset != UNKNOWN_OFFSET && address >= offset &&
- address < offset + segment.data.size()) {
- return &segment.data[address - offset];
+ address < offset + segment->data.size()) {
+ return &segment->data[address - offset];
}
}
Fatal() << "unable to find data for ASM/EM_JS const at: " << address;
@@ -159,9 +159,9 @@ private:
} searcher(passiveOffsets);
searcher.walkModule(&wasm);
}
- for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) {
- auto& segment = wasm.memory.segments[i];
- if (segment.isPassive) {
+ for (unsigned i = 0; i < wasm.dataSegments.size(); ++i) {
+ auto& segment = wasm.dataSegments[i];
+ if (segment->isPassive) {
auto it = passiveOffsets.find(i);
if (it != passiveOffsets.end()) {
segmentOffsets.push_back(it->second);
@@ -169,7 +169,7 @@ private:
// This was a non-constant offset (perhaps TLS)
segmentOffsets.push_back(UNKNOWN_OFFSET);
}
- } else if (auto* addrConst = segment.offset->dynCast<Const>()) {
+ } else if (auto* addrConst = segment->offset->dynCast<Const>()) {
auto address = addrConst->value.getUnsigned();
segmentOffsets.push_back(address);
} else {
@@ -220,7 +220,7 @@ static void removeSegment(Module& wasm, Index segment) {
// Resize the segment to zero. In theory we should completely remove it
// but that would mean re-numbering the segments that follow which is
// non-trivial.
- wasm.memory.segments[segment].data.resize(0);
+ wasm.dataSegments[segment]->data.resize(0);
}
static Address getExportedAddress(Module& wasm, Export* export_) {
@@ -250,9 +250,9 @@ static std::vector<AsmConst> findEmAsmConsts(Module& wasm,
StringConstantTracker stringTracker(wasm);
Address startAddress = getExportedAddress(wasm, start);
Address endAddress = getExportedAddress(wasm, end);
- for (Index i = 0; i < wasm.memory.segments.size(); i++) {
+ for (Index i = 0; i < wasm.dataSegments.size(); i++) {
Address segmentStart = stringTracker.segmentOffsets[i];
- size_t segmentSize = wasm.memory.segments[i].data.size();
+ size_t segmentSize = wasm.dataSegments[i]->data.size();
if (segmentStart <= startAddress &&
segmentStart + segmentSize >= endAddress) {
Address address = startAddress;
@@ -269,7 +269,7 @@ static std::vector<AsmConst> findEmAsmConsts(Module& wasm,
// If we can't remove the whole segment then just set the string
// data to zero.
size_t segmentOffset = startAddress - segmentStart;
- char* startElem = &wasm.memory.segments[i].data[segmentOffset];
+ char* startElem = &wasm.dataSegments[i]->data[segmentOffset];
memset(startElem, 0, endAddress - startAddress);
}
break;
@@ -343,18 +343,18 @@ EmJsWalker findEmJsFuncsAndReturnWalker(Module& wasm) {
// single segment.
// We can detect this by checking for segments that contain only JS strings.
// When we find such segements we remove them from the final binary.
- for (Index i = 0; i < wasm.memory.segments.size(); i++) {
+ for (Index i = 0; i < wasm.dataSegments.size(); i++) {
Address start = walker.stringTracker.segmentOffsets[i];
Address cur = start;
- while (cur < start + wasm.memory.segments[i].data.size()) {
+ while (cur < start + wasm.dataSegments[i]->data.size()) {
if (walker.codeAddresses.count(cur) == 0) {
break;
}
cur.addr += walker.codeAddresses[cur];
}
- if (cur == start + wasm.memory.segments[i].data.size()) {
+ if (cur == start + wasm.dataSegments[i]->data.size()) {
// Entire segment is contains JS strings. Remove it.
removeSegment(wasm, i);
}
@@ -509,24 +509,24 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata() {
void EmscriptenGlueGenerator::separateDataSegments(Output* outfile,
Address base) {
size_t lastEnd = 0;
- for (Memory::Segment& seg : wasm.memory.segments) {
- if (seg.isPassive) {
+ for (auto& seg : wasm.dataSegments) {
+ if (seg->isPassive) {
Fatal() << "separating passive segments not implemented";
}
- if (!seg.offset->is<Const>()) {
+ if (!seg->offset->is<Const>()) {
Fatal() << "separating relocatable segments not implemented";
}
- size_t offset = seg.offset->cast<Const>()->value.getInteger();
+ size_t offset = seg->offset->cast<Const>()->value.getInteger();
offset -= base;
size_t fill = offset - lastEnd;
if (fill > 0) {
std::vector<char> buf(fill);
outfile->write(buf.data(), fill);
}
- outfile->write(seg.data.data(), seg.data.size());
- lastEnd = offset + seg.data.size();
+ outfile->write(seg->data.data(), seg->data.size());
+ lastEnd = offset + seg->data.size();
}
- wasm.memory.segments.clear();
+ wasm.dataSegments.clear();
}
} // namespace wasm
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index dd92278c6..b59319be2 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -3038,8 +3038,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
} else {
offset->set(Literal(int32_t(0)));
}
- parseInnerData(inner, j, {}, offset, false);
- wasm.memory.initial = wasm.memory.segments[0].data.size();
+ parseInnerData(
+ inner, j, Name::fromInt(dataCounter++), false, offset, false);
+ wasm.memory.initial = wasm.dataSegments[0]->data.size();
return;
}
}
@@ -3073,9 +3074,15 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (auto size = strlen(input)) {
std::vector<char> data;
stringToBinary(input, size, data);
- wasm.memory.segments.emplace_back(offset, data.data(), data.size());
+ auto segment = Builder::makeDataSegment(
+ Name::fromInt(dataCounter++), false, offset, data.data(), data.size());
+ segment->hasExplicitName = false;
+ wasm.dataSegments.push_back(std::move(segment));
} else {
- wasm.memory.segments.emplace_back(offset, "", 0);
+ auto segment =
+ Builder::makeDataSegment(Name::fromInt(dataCounter++), false, offset);
+ segment->hasExplicitName = false;
+ wasm.dataSegments.push_back(std::move(segment));
}
i++;
}
@@ -3085,13 +3092,15 @@ void SExpressionWasmBuilder::parseData(Element& s) {
if (!wasm.memory.exists) {
throw ParseException("data but no memory", s.line, s.col);
}
+ Index i = 1;
+ Name name = Name::fromInt(dataCounter++);
+ bool hasExplicitName = false;
bool isPassive = true;
Expression* offset = nullptr;
- Index i = 1;
- Name name;
if (s[i]->isStr() && s[i]->dollared()) {
name = s[i++]->str();
+ hasExplicitName = true;
}
if (s[i]->isList()) {
@@ -3112,11 +3121,15 @@ void SExpressionWasmBuilder::parseData(Element& s) {
isPassive = false;
}
- parseInnerData(s, i, name, offset, isPassive);
+ parseInnerData(s, i, name, hasExplicitName, offset, isPassive);
}
-void SExpressionWasmBuilder::parseInnerData(
- Element& s, Index i, Name name, Expression* offset, bool isPassive) {
+void SExpressionWasmBuilder::parseInnerData(Element& s,
+ Index i,
+ Name name,
+ bool hasExplicitName,
+ Expression* offset,
+ bool isPassive) {
std::vector<char> data;
while (i < s.size()) {
const char* input = s[i++]->c_str();
@@ -3124,8 +3137,10 @@ void SExpressionWasmBuilder::parseInnerData(
stringToBinary(input, size, data);
}
}
- wasm.memory.segments.emplace_back(
- name, isPassive, offset, data.data(), data.size());
+ auto curr =
+ Builder::makeDataSegment(name, isPassive, offset, data.data(), data.size());
+ curr->hasExplicitName = hasExplicitName;
+ wasm.dataSegments.push_back(std::move(curr));
}
void SExpressionWasmBuilder::parseExport(Element& s) {
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 54bc2f9d4..4c6e8e929 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1301,7 +1301,7 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
"Memory operations require a memory")) {
return;
}
- shouldBeTrue(curr->segment < getModule()->memory.segments.size(),
+ shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
curr,
"memory.init segment index out of bounds");
}
@@ -1317,7 +1317,7 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) {
"Memory operations require a memory")) {
return;
}
- shouldBeTrue(curr->segment < getModule()->memory.segments.size(),
+ shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
curr,
"data.drop segment index out of bounds");
}
@@ -3068,53 +3068,53 @@ static void validateMemory(Module& module, ValidationInfo& info) {
"memory",
"memory is shared, but atomics are disabled");
}
- for (auto& segment : curr.segments) {
- auto size = segment.data.size();
- if (segment.isPassive) {
+ for (auto& segment : module.dataSegments) {
+ auto size = segment->data.size();
+ if (segment->isPassive) {
info.shouldBeTrue(module.features.hasBulkMemory(),
- segment.offset,
+ segment->offset,
"nonzero segment flags (bulk memory is disabled)");
- info.shouldBeEqual(segment.offset,
+ info.shouldBeEqual(segment->offset,
(Expression*)nullptr,
- segment.offset,
+ segment->offset,
"passive segment should not have an offset");
} else {
if (curr.is64()) {
- if (!info.shouldBeEqual(segment.offset->type,
+ if (!info.shouldBeEqual(segment->offset->type,
Type(Type::i64),
- segment.offset,
+ segment->offset,
"segment offset should be i64")) {
continue;
}
} else {
- if (!info.shouldBeEqual(segment.offset->type,
+ if (!info.shouldBeEqual(segment->offset->type,
Type(Type::i32),
- segment.offset,
+ segment->offset,
"segment offset should be i32")) {
continue;
}
}
- info.shouldBeTrue(checkSegmentOffset(segment.offset,
- segment.data.size(),
+ info.shouldBeTrue(checkSegmentOffset(segment->offset,
+ segment->data.size(),
curr.initial * Memory::kPageSize,
module.features),
- segment.offset,
+ segment->offset,
"memory segment offset should be reasonable");
- if (segment.offset->is<Const>()) {
- auto start = segment.offset->cast<Const>()->value.getUnsigned();
+ if (segment->offset->is<Const>()) {
+ auto start = segment->offset->cast<Const>()->value.getUnsigned();
auto end = start + size;
info.shouldBeTrue(end <= curr.initial * Memory::kPageSize,
- segment.data.size(),
+ segment->data.size(),
"segment size should fit in memory (end)");
}
- FunctionValidator(module, &info).validate(segment.offset);
+ FunctionValidator(module, &info).validate(segment->offset);
}
// 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->data.size(),
"segment size should fit in memory (initial)");
}
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index ca9691346..8d4f1dcee 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1275,6 +1275,10 @@ ElementSegment* Module::getElementSegment(Name name) {
return getModuleElement(elementSegmentsMap, name, "getElementSegment");
}
+DataSegment* Module::getDataSegment(Name name) {
+ return getModuleElement(dataSegmentsMap, name, "getDataSegment");
+}
+
Global* Module::getGlobal(Name name) {
return getModuleElement(globalsMap, name, "getGlobal");
}
@@ -1308,6 +1312,10 @@ ElementSegment* Module::getElementSegmentOrNull(Name name) {
return getModuleElementOrNull(elementSegmentsMap, name);
}
+DataSegment* Module::getDataSegmentOrNull(Name name) {
+ return getModuleElementOrNull(dataSegmentsMap, name);
+}
+
Global* Module::getGlobalOrNull(Name name) {
return getModuleElementOrNull(globalsMap, name);
}
@@ -1383,6 +1391,11 @@ Module::addElementSegment(std::unique_ptr<ElementSegment>&& curr) {
elementSegments, elementSegmentsMap, std::move(curr), "addElementSegment");
}
+DataSegment* Module::addDataSegment(std::unique_ptr<DataSegment>&& curr) {
+ return addModuleElement(
+ dataSegments, dataSegmentsMap, std::move(curr), "addDataSegment");
+}
+
Global* Module::addGlobal(std::unique_ptr<Global>&& curr) {
return addModuleElement(globals, globalsMap, std::move(curr), "addGlobal");
}
@@ -1416,6 +1429,9 @@ void Module::removeTable(Name name) {
void Module::removeElementSegment(Name name) {
removeModuleElement(elementSegments, elementSegmentsMap, name);
}
+void Module::removeDataSegment(Name name) {
+ removeModuleElement(dataSegments, dataSegmentsMap, name);
+}
void Module::removeGlobal(Name name) {
removeModuleElement(globals, globalsMap, name);
}
@@ -1449,6 +1465,9 @@ void Module::removeTables(std::function<bool(Table*)> pred) {
void Module::removeElementSegments(std::function<bool(ElementSegment*)> pred) {
removeModuleElements(elementSegments, elementSegmentsMap, pred);
}
+void Module::removeDataSegments(std::function<bool(DataSegment*)> pred) {
+ removeModuleElements(dataSegments, dataSegmentsMap, pred);
+}
void Module::removeGlobals(std::function<bool(Global*)> pred) {
removeModuleElements(globals, globalsMap, pred);
}
@@ -1473,6 +1492,10 @@ void Module::updateMaps() {
for (auto& curr : elementSegments) {
elementSegmentsMap[curr->name] = curr.get();
}
+ dataSegmentsMap.clear();
+ for (auto& curr : dataSegments) {
+ dataSegmentsMap[curr->name] = curr.get();
+ }
globalsMap.clear();
for (auto& curr : globals) {
globalsMap[curr->name] = curr.get();
diff --git a/src/wasm2js.h b/src/wasm2js.h
index b74572cfe..5b98362ad 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -94,8 +94,8 @@ bool isTableExported(Module& wasm) {
}
bool hasActiveSegments(Module& wasm) {
- for (Index i = 0; i < wasm.memory.segments.size(); i++) {
- if (!wasm.memory.segments[i].isPassive) {
+ for (Index i = 0; i < wasm.dataSegments.size(); i++) {
+ if (!wasm.dataSegments[i]->isPassive) {
return true;
}
}
@@ -2665,13 +2665,13 @@ void Wasm2JSGlue::emitMemory() {
// If there are no memory segments, we don't need to emit any support code for
// segment creation.
- if ((!wasm.memory.exists) || wasm.memory.segments.empty()) {
+ if ((!wasm.memory.exists) || wasm.dataSegments.empty()) {
return;
}
// If we have passive memory segments, we need to store those.
- for (auto& seg : wasm.memory.segments) {
- if (seg.isPassive) {
+ for (auto& seg : wasm.dataSegments) {
+ if (seg->isPassive) {
out << " var memorySegments = {};\n";
break;
}
@@ -2706,20 +2706,20 @@ void Wasm2JSGlue::emitMemory() {
}
)";
- for (Index i = 0; i < wasm.memory.segments.size(); i++) {
- auto& seg = wasm.memory.segments[i];
- if (seg.isPassive) {
+ for (Index i = 0; i < wasm.dataSegments.size(); i++) {
+ auto& seg = wasm.dataSegments[i];
+ if (seg->isPassive) {
// Fancy passive segments are decoded into typed arrays on the side, for
// later copying.
out << "memorySegments[" << i
<< "] = base64DecodeToExistingUint8Array(new Uint8Array("
- << seg.data.size() << ")"
- << ", 0, \"" << base64Encode(seg.data) << "\");\n";
+ << seg->data.size() << ")"
+ << ", 0, \"" << base64Encode(seg->data) << "\");\n";
}
}
if (hasActiveSegments(wasm)) {
- auto globalOffset = [&](const Memory::Segment& segment) {
+ auto globalOffset = [&](const DataSegment& segment) {
if (auto* c = segment.offset->dynCast<Const>()) {
return std::to_string(c->value.getInteger());
}
@@ -2732,12 +2732,12 @@ void Wasm2JSGlue::emitMemory() {
};
out << "function initActiveSegments(imports) {\n";
- for (Index i = 0; i < wasm.memory.segments.size(); i++) {
- auto& seg = wasm.memory.segments[i];
- if (!seg.isPassive) {
+ for (Index i = 0; i < wasm.dataSegments.size(); i++) {
+ auto& seg = wasm.dataSegments[i];
+ if (!seg->isPassive) {
// Plain active segments are decoded directly into the main memory.
out << " base64DecodeToExistingUint8Array(bufferView, "
- << globalOffset(seg) << ", \"" << base64Encode(seg.data)
+ << globalOffset(*seg) << ", \"" << base64Encode(seg->data)
<< "\");\n";
}
}
diff --git a/test/dylib.wasm.fromBinary b/test/dylib.wasm.fromBinary
index 8c8a517d9..51b9c245d 100644
--- a/test/dylib.wasm.fromBinary
+++ b/test/dylib.wasm.fromBinary
@@ -4,7 +4,6 @@
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 0))
- (data (global.get $gimport$0) "*\00\00\00")
(import "env" "__memory_base" (global $gimport$0 i32))
(import "env" "g$waka_mine" (func $fimport$0 (result i32)))
(import "env" "g$waka_others" (func $fimport$1 (result i32)))
@@ -16,6 +15,7 @@
(global $global$3 (mut i32) (i32.const 0))
(global $global$4 i32 (i32.const 0))
(global $global$5 i32 (i32.const 0))
+ (data (global.get $gimport$0) "*\00\00\00")
(export "__wasm_apply_relocs" (func $0))
(export "_Z14waka_func_minei" (func $1))
(export "__original_main" (func $2))
diff --git a/test/lit/passes/O4_disable-bulk-memory.wast b/test/lit/passes/O4_disable-bulk-memory.wast
index 4ab403159..76a264075 100644
--- a/test/lit/passes/O4_disable-bulk-memory.wast
+++ b/test/lit/passes/O4_disable-bulk-memory.wast
@@ -58,16 +58,16 @@
(data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00")
(data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00")
(import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32)))
- ;; CHECK: (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00")
-
- ;; CHECK: (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00")
-
;; CHECK: (global $global$0 (mut i32) (i32.const 0))
;; CHECK: (global $global$1 (mut i32) (i32.const 0))
;; CHECK: (global $global$5 (mut i32) (i32.const 0))
+ ;; CHECK: (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00")
+
+ ;; CHECK: (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00")
+
;; CHECK: (table $0 1 funcref)
(table $0 1 funcref)
(elem (i32.const 0) $null)
diff --git a/test/lit/passes/inlining-optimizing_optimize-level=3.wast b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
index 632ec16ec..301f23de2 100644
--- a/test/lit/passes/inlining-optimizing_optimize-level=3.wast
+++ b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
@@ -35,8 +35,6 @@
;; CHECK: (import "env" "memory" (memory $0 256 256))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
- ;; CHECK: (data (i32.const 1024) "emcc_hello_world.asm.js")
-
;; CHECK: (import "env" "table" (table $timport$0 18 18 funcref))
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
;; CHECK: (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
@@ -99,6 +97,8 @@
(global $tempRet0 (mut i32) (i32.const 0))
(elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
(data (i32.const 1024) "emcc_hello_world.asm.js")
+ ;; CHECK: (data (i32.const 1024) "emcc_hello_world.asm.js")
+
;; CHECK: (elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
;; CHECK: (export "_i64Subtract" (func $_i64Subtract))
diff --git a/test/lld/em_asm_pthread.wasm.out b/test/lld/em_asm_pthread.wasm.out
index 45d76f5fc..d1913d655 100644
--- a/test/lld/em_asm_pthread.wasm.out
+++ b/test/lld/em_asm_pthread.wasm.out
@@ -39,11 +39,6 @@
(type $i32_i32_i32_i32_=>_f64 (func (param i32 i32 i32 i32) (result f64)))
(type $i32_i32_i64_i32_=>_i64 (func (param i32 i32 i64 i32) (result i64)))
(import "env" "memory" (memory $mimport$0 (shared 256 256)))
- (data "\00/home/azakai/Dev/emscripten/system/lib/pthread/library_pthread.c\00call\00_emscripten_do_dispatch_to_thread\00target_thread\00num_args+1 <= EM_QUEUED_JS_CALL_MAX_ARGS\00emscripten_run_in_main_runtime_thread_js\00q\00_emscripten_call_on_thread\00EM_FUNC_SIG_NUM_FUNC_ARGUMENTS(q->functionEnum) <= EM_QUEUED_CALL_MAX_ARGS\00_do_call\000 && \"Invalid Emscripten pthread _do_call opcode!\"\00target\00GetQueue\00em_queued_call_malloc\00")
- (data "\01\00\00\00\d0\0fP\00\05\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\04\00\00\00x\t\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\a0\05\00\00")
- (data "")
- (data "")
- (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(import "env" "emscripten_asm_const_int" (func $fimport$0 (param i32 i32 i32) (result i32)))
(import "env" "world" (func $fimport$1))
(import "env" "__cxa_thread_atexit" (func $fimport$2 (param i32 i32 i32) (result i32)))
@@ -75,6 +70,11 @@
(global $global$11 i32 (i32.const 1836))
(global $global$12 i32 (i32.const 1658))
(global $global$13 i32 (i32.const 1782))
+ (data "\00/home/azakai/Dev/emscripten/system/lib/pthread/library_pthread.c\00call\00_emscripten_do_dispatch_to_thread\00target_thread\00num_args+1 <= EM_QUEUED_JS_CALL_MAX_ARGS\00emscripten_run_in_main_runtime_thread_js\00q\00_emscripten_call_on_thread\00EM_FUNC_SIG_NUM_FUNC_ARGUMENTS(q->functionEnum) <= EM_QUEUED_CALL_MAX_ARGS\00_do_call\000 && \"Invalid Emscripten pthread _do_call opcode!\"\00target\00GetQueue\00em_queued_call_malloc\00")
+ (data "\01\00\00\00\d0\0fP\00\05\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\04\00\00\00x\t\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\a0\05\00\00")
+ (data "")
+ (data "")
+ (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(table $0 5 5 funcref)
(elem (i32.const 1) $6 $73 $72 $74)
(export "__wasm_call_ctors" (func $0))
diff --git a/test/lld/em_asm_shared.wat.out b/test/lld/em_asm_shared.wat.out
index b1911bca7..171f6b10c 100644
--- a/test/lld/em_asm_shared.wat.out
+++ b/test/lld/em_asm_shared.wat.out
@@ -4,7 +4,6 @@
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 1))
- (data $.data (global.get $__memory_base) "\00ii\00i\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(import "env" "__indirect_function_table" (table $timport$0 0 funcref))
(import "env" "__stack_pointer" (global $__stack_pointer (mut i32)))
(import "env" "__memory_base" (global $__memory_base i32))
@@ -18,6 +17,7 @@
(global $global$2 i32 (i32.const 4))
(global $global$3 i32 (i32.const 6))
(global $global$4 i32 (i32.const 90))
+ (data $.data (global.get $__memory_base) "\00ii\00i\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "__original_main" (func $__original_main))
(export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $global$0))
diff --git a/test/lld/em_js_O0.wat.out b/test/lld/em_js_O0.wat.out
index d0a4febe6..6f36ce6bc 100644
--- a/test/lld/em_js_O0.wat.out
+++ b/test/lld/em_js_O0.wat.out
@@ -1,11 +1,11 @@
(module
(import "env" "memory" (memory $0 256 256))
- (data (i32.const 1024) "(void)<::>{ out(\"no args works\"); }\00(void)<::>{ out(\"no args returning int\"); return 12; }\00(void)<::>{ out(\"no args returning double\"); return 12.25; }\00(int x)<::>{ out(\" takes ints: \" + x);}\00(double d)<::>{ out(\" takes doubles: \" + d);}\00(char* str)<::>{ out(\" takes strings: \" + UTF8ToString(str)); return 7.75; }\00(int x, int y)<::>{ out(\" takes multiple ints: \" + x + \", \" + y); return 6; }\00(int x, const char* str, double d)<::>{ out(\" mixed arg types: \" + x + \", \" + UTF8ToString(str) + \", \" + d); return 8.125; }\00(int unused)<::>{ out(\" ignores unused args\"); return 5.5; }\00(int x, int y)<::>{ out(\" skips unused args: \" + y); return 6; }\00(double x, double y, double z)<::>{ out(\" \" + x + \" + \" + z); return x + z; }\00(void)<::>{ out(\" can use <::> separator in user code\"); return 15; }\00(void)<::>{ var x, y; x = {}; y = 3; x[y] = [1, 2, 3]; out(\" can have commas in user code: \" + x[y]); return x[y][1]; }\00(void)<::>{ var jsString = \'\e3\81\93\e3\82\93\e3\81\ab\e3\81\a1\e3\81\af\'; var lengthBytes = lengthBytesUTF8(jsString); var stringOnWasmHeap = _malloc(lengthBytes); stringToUTF8(jsString, stringOnWasmHeap, lengthBytes+1); return stringOnWasmHeap; }\00(void)<::>{ var jsString = \'hello from js\'; var lengthBytes = jsString.length+1; var stringOnWasmHeap = _malloc(lengthBytes); stringToUTF8(jsString, stringOnWasmHeap, lengthBytes+1); return stringOnWasmHeap; }\00BEGIN\n\00 noarg_int returned: %d\n\00 noarg_double returned: %f\n\00 stringarg returned: %f\n\00string arg\00 multi_intarg returned: %d\n\00 multi_mixedarg returned: %f\n\00hello\00 unused_args returned: %d\n\00 skip_args returned: %f\n\00 add_outer returned: %f\n\00 user_separator returned: %d\n\00 user_comma returned: %d\n\00 return_str returned: %s\n\00 return_utf8_str returned: %s\n\00END\n\00\00\cc\1a\00\00\00\00\00\00\00\00\00\00\00\00\00\00T!\"\19\0d\01\02\03\11K\1c\0c\10\04\0b\1d\12\1e\'hnopqb \05\06\0f\13\14\15\1a\08\16\07($\17\18\t\n\0e\1b\1f%#\83\82}&*+<=>?CGJMXYZ[\\]^_`acdefgijklrstyz{|\00\00\00\00\00\00\00\00\00Illegal byte sequence\00Domain error\00Result not representable\00Not a tty\00Permission denied\00Operation not permitted\00No such file or directory\00No such process\00File exists\00Value too large for data type\00No space left on device\00Out of memory\00Resource busy\00Interrupted system call\00Resource temporarily unavailable\00Invalid seek\00Cross-device link\00Read-only file system\00Directory not empty\00Connection reset by peer\00Operation timed out\00Connection refused\00Host is down\00Host is unreachable\00Address in use\00Broken pipe\00I/O error\00No such device or address\00Block device required\00No such device\00Not a directory\00Is a directory\00Text file busy\00Exec format error\00Invalid argument\00Argument list too long\00Symbolic link loop\00Filename too long\00Too many open files in system\00No file descriptors available\00Bad file descriptor\00No child process\00Bad address\00File too large\00Too many links\00No locks available\00Resource deadlock would occur\00State not recoverable\00Previous owner died\00Operation canceled\00Function not implemented\00No message of desired type\00Identifier removed\00Device not a stream\00No data available\00Device timeout\00Out of streams resources\00Link has been severed\00Protocol error\00Bad message\00File descriptor in bad state\00Not a socket\00Destination address required\00Message too large\00Protocol wrong type for socket\00Protocol not available\00Protocol not supported\00Socket type not supported\00Not supported\00Protocol family not supported\00Address family not supported by protocol\00Address not available\00Network is down\00Network unreachable\00Connection reset by network\00Connection aborted\00No buffer space available\00Socket is connected\00Socket not connected\00Cannot send after socket shutdown\00Operation already in progress\00Operation in progress\00Stale file handle\00Remote I/O error\00Quota exceeded\00No medium found\00Wrong medium type\00No error information\00\00-+ 0X0x\00(null)\00\00\00\00\11\00\n\00\11\11\11\00\00\00\00\05\00\00\00\00\00\00\t\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\0f\n\11\11\11\03\n\07\00\01\13\t\0b\0b\00\00\t\06\0b\00\00\0b\00\06\11\00\00\00\11\11\11\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\n\n\11\11\11\00\n\00\00\02\00\t\0b\00\00\00\t\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\0d\00\00\00\04\0d\00\00\00\00\t\0e\00\00\00\00\00\0e\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\00\00\00\00\0f\00\00\00\00\0f\00\00\00\00\t\10\00\00\00\00\00\10\00\00\10\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\t\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\n\00\00\00\00\n\00\00\00\00\t\0b\00\00\00\00\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\000123456789ABCDEF-0X+0X 0X-0x+0x 0x\00inf\00INF\00nan\00NAN\00.\00")
- (data (i32.const 5232) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
- (data (i32.const 6860) "\05\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\04\00\00\00\88\14\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\cc\1a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\b0\18\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(global $global$0 (mut i32) (i32.const 5250112))
(global $global$1 i32 (i32.const 5250112))
(global $global$2 i32 (i32.const 7232))
+ (data (i32.const 1024) "(void)<::>{ out(\"no args works\"); }\00(void)<::>{ out(\"no args returning int\"); return 12; }\00(void)<::>{ out(\"no args returning double\"); return 12.25; }\00(int x)<::>{ out(\" takes ints: \" + x);}\00(double d)<::>{ out(\" takes doubles: \" + d);}\00(char* str)<::>{ out(\" takes strings: \" + UTF8ToString(str)); return 7.75; }\00(int x, int y)<::>{ out(\" takes multiple ints: \" + x + \", \" + y); return 6; }\00(int x, const char* str, double d)<::>{ out(\" mixed arg types: \" + x + \", \" + UTF8ToString(str) + \", \" + d); return 8.125; }\00(int unused)<::>{ out(\" ignores unused args\"); return 5.5; }\00(int x, int y)<::>{ out(\" skips unused args: \" + y); return 6; }\00(double x, double y, double z)<::>{ out(\" \" + x + \" + \" + z); return x + z; }\00(void)<::>{ out(\" can use <::> separator in user code\"); return 15; }\00(void)<::>{ var x, y; x = {}; y = 3; x[y] = [1, 2, 3]; out(\" can have commas in user code: \" + x[y]); return x[y][1]; }\00(void)<::>{ var jsString = \'\e3\81\93\e3\82\93\e3\81\ab\e3\81\a1\e3\81\af\'; var lengthBytes = lengthBytesUTF8(jsString); var stringOnWasmHeap = _malloc(lengthBytes); stringToUTF8(jsString, stringOnWasmHeap, lengthBytes+1); return stringOnWasmHeap; }\00(void)<::>{ var jsString = \'hello from js\'; var lengthBytes = jsString.length+1; var stringOnWasmHeap = _malloc(lengthBytes); stringToUTF8(jsString, stringOnWasmHeap, lengthBytes+1); return stringOnWasmHeap; }\00BEGIN\n\00 noarg_int returned: %d\n\00 noarg_double returned: %f\n\00 stringarg returned: %f\n\00string arg\00 multi_intarg returned: %d\n\00 multi_mixedarg returned: %f\n\00hello\00 unused_args returned: %d\n\00 skip_args returned: %f\n\00 add_outer returned: %f\n\00 user_separator returned: %d\n\00 user_comma returned: %d\n\00 return_str returned: %s\n\00 return_utf8_str returned: %s\n\00END\n\00\00\cc\1a\00\00\00\00\00\00\00\00\00\00\00\00\00\00T!\"\19\0d\01\02\03\11K\1c\0c\10\04\0b\1d\12\1e\'hnopqb \05\06\0f\13\14\15\1a\08\16\07($\17\18\t\n\0e\1b\1f%#\83\82}&*+<=>?CGJMXYZ[\\]^_`acdefgijklrstyz{|\00\00\00\00\00\00\00\00\00Illegal byte sequence\00Domain error\00Result not representable\00Not a tty\00Permission denied\00Operation not permitted\00No such file or directory\00No such process\00File exists\00Value too large for data type\00No space left on device\00Out of memory\00Resource busy\00Interrupted system call\00Resource temporarily unavailable\00Invalid seek\00Cross-device link\00Read-only file system\00Directory not empty\00Connection reset by peer\00Operation timed out\00Connection refused\00Host is down\00Host is unreachable\00Address in use\00Broken pipe\00I/O error\00No such device or address\00Block device required\00No such device\00Not a directory\00Is a directory\00Text file busy\00Exec format error\00Invalid argument\00Argument list too long\00Symbolic link loop\00Filename too long\00Too many open files in system\00No file descriptors available\00Bad file descriptor\00No child process\00Bad address\00File too large\00Too many links\00No locks available\00Resource deadlock would occur\00State not recoverable\00Previous owner died\00Operation canceled\00Function not implemented\00No message of desired type\00Identifier removed\00Device not a stream\00No data available\00Device timeout\00Out of streams resources\00Link has been severed\00Protocol error\00Bad message\00File descriptor in bad state\00Not a socket\00Destination address required\00Message too large\00Protocol wrong type for socket\00Protocol not available\00Protocol not supported\00Socket type not supported\00Not supported\00Protocol family not supported\00Address family not supported by protocol\00Address not available\00Network is down\00Network unreachable\00Connection reset by network\00Connection aborted\00No buffer space available\00Socket is connected\00Socket not connected\00Cannot send after socket shutdown\00Operation already in progress\00Operation in progress\00Stale file handle\00Remote I/O error\00Quota exceeded\00No medium found\00Wrong medium type\00No error information\00\00-+ 0X0x\00(null)\00\00\00\00\11\00\n\00\11\11\11\00\00\00\00\05\00\00\00\00\00\00\t\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\0f\n\11\11\11\03\n\07\00\01\13\t\0b\0b\00\00\t\06\0b\00\00\0b\00\06\11\00\00\00\11\11\11\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\n\n\11\11\11\00\n\00\00\02\00\t\0b\00\00\00\t\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\0d\00\00\00\04\0d\00\00\00\00\t\0e\00\00\00\00\00\0e\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\00\00\00\00\0f\00\00\00\00\0f\00\00\00\00\t\10\00\00\00\00\00\10\00\00\10\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\t\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\n\00\00\00\00\n\00\00\00\00\t\0b\00\00\00\00\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\000123456789ABCDEF-0X+0X 0X-0x+0x 0x\00inf\00INF\00nan\00NAN\00.\00")
+ (data (i32.const 5232) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
+ (data (i32.const 6860) "\05\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\04\00\00\00\88\14\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\cc\1a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\b0\18\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
(export "__heap_base" (global $global$1))
(export "__data_end" (global $global$2))
)
diff --git a/test/lld/main_module.wat.out b/test/lld/main_module.wat.out
index fb1b13127..1c27ba34f 100644
--- a/test/lld/main_module.wat.out
+++ b/test/lld/main_module.wat.out
@@ -3,7 +3,6 @@
(type $0 (func (param i32) (result i32)))
(type $2 (func (result i32)))
(import "env" "memory" (memory $0 0))
- (data (global.get $gimport$2) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00")
(import "env" "__indirect_function_table" (table $timport$1 0 funcref))
(import "env" "__stack_pointer" (global $sp (mut i32)))
(import "env" "__memory_base" (global $gimport$2 i32))
@@ -15,6 +14,7 @@
(global $global$0 i32 (i32.const 16))
(global $global$1 i32 (i32.const 20))
(global $global i32 (i32.const 42))
+ (data (global.get $gimport$2) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "_Z13print_messagev" (func $print_message\28\29))
(export "ptr_puts" (global $global$0))
diff --git a/test/lld/shared.wat.out b/test/lld/shared.wat.out
index 209c3db82..66000827d 100644
--- a/test/lld/shared.wat.out
+++ b/test/lld/shared.wat.out
@@ -3,7 +3,6 @@
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $none_=>_i32 (func (result i32)))
(import "env" "memory" (memory $mimport$0 1))
- (data $.data (global.get $__memory_base) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00")
(import "env" "__indirect_function_table" (table $timport$0 0 funcref))
(import "env" "__memory_base" (global $__memory_base i32))
(import "env" "__table_base" (global $__table_base i32))
@@ -13,6 +12,7 @@
(import "env" "puts" (func $puts (param i32) (result i32)))
(global $global$0 i32 (i32.const 16))
(global $global$1 i32 (i32.const 20))
+ (data $.data (global.get $__memory_base) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "_Z13print_messagev" (func $print_message\28\29))
(export "ptr_puts" (global $global$0))
diff --git a/test/lld/shared_add_to_table.wasm.out b/test/lld/shared_add_to_table.wasm.out
index 82d41654b..f4551d34a 100644
--- a/test/lld/shared_add_to_table.wasm.out
+++ b/test/lld/shared_add_to_table.wasm.out
@@ -4,7 +4,6 @@
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 0))
- (data (global.get $gimport$1) "*\00\00\00")
(import "env" "__indirect_function_table" (table $timport$0 0 funcref))
(import "env" "__stack_pointer" (global $gimport$0 (mut i32)))
(import "env" "__memory_base" (global $gimport$1 i32))
@@ -16,6 +15,7 @@
(import "env" "_Z16waka_func_theirsi" (func $waka_func_theirs\28int\29 (param i32) (result i32)))
(global $global$0 i32 (i32.const 0))
(global $global$1 i32 (i32.const 0))
+ (data (global.get $gimport$1) "*\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "__wasm_apply_relocs" (func $__wasm_apply_relocs))
(export "_Z14waka_func_minei" (func $waka_func_mine\28int\29))
diff --git a/test/lld/shared_longjmp.wat.out b/test/lld/shared_longjmp.wat.out
index 9515c9606..400af5af0 100644
--- a/test/lld/shared_longjmp.wat.out
+++ b/test/lld/shared_longjmp.wat.out
@@ -8,7 +8,6 @@
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 1))
- (data $.bss (global.get $__memory_base) "\00\00\00\00\00\00\00\00")
(import "env" "__indirect_function_table" (table $timport$0 0 funcref))
(import "env" "__memory_base" (global $__memory_base i32))
(import "env" "__table_base" (global $__table_base i32))
@@ -25,6 +24,7 @@
(import "env" "free" (func $free (param i32)))
(global $global$0 i32 (i32.const 0))
(global $global$1 i32 (i32.const 4))
+ (data $.bss (global.get $__memory_base) "\00\00\00\00\00\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "_start" (func $_start))
(export "__THREW__" (global $global$0))
diff --git a/test/metadce/outside.wast.dced b/test/metadce/outside.wast.dced
index a1c74c8d9..246019dc9 100644
--- a/test/metadce/outside.wast.dced
+++ b/test/metadce/outside.wast.dced
@@ -1,13 +1,13 @@
(module
(type $none_=>_none (func))
(import "env" "memory" (memory $0 256 256))
- (data (i32.const 1024) "abcd")
- (data (global.get $from_segment) "abcd")
(import "env" "table" (table $timport$0 10 10 funcref))
(import "env" "js_func" (func $a_js_func))
(global $__THREW__ (mut i32) (i32.const 0))
(global $from_segment (mut i32) (i32.const 0))
(global $from_segment_2 (mut i32) (i32.const 0))
+ (data (i32.const 1024) "abcd")
+ (data (global.get $from_segment) "abcd")
(elem (global.get $from_segment_2) $table_func)
(export "wasm_func" (func $a_wasm_func))
(func $table_func
diff --git a/test/passes/O3_low-memory-unused_metrics.txt b/test/passes/O3_low-memory-unused_metrics.txt
index 617b03a6d..d33277eb6 100644
--- a/test/passes/O3_low-memory-unused_metrics.txt
+++ b/test/passes/O3_low-memory-unused_metrics.txt
@@ -3,7 +3,6 @@ total
[funcs] : 1
[globals] : 0
[imports] : 10
- [memory-data] : 0
[table-data] : 0
[tables] : 0
[tags] : 0
diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt
index 8b17e64f5..fbf978433 100644
--- a/test/passes/converge_O3_metrics.bin.txt
+++ b/test/passes/converge_O3_metrics.bin.txt
@@ -31,6 +31,9 @@ total
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $none_=>_i32 (func (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
+ (import "env" "table" (table $timport$0 478 478 funcref))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
+ (global $global$0 (mut i32) (i32.const 1))
(data (i32.const 2948) "\03")
(data (i32.const 6828) "\04")
(data (i32.const 7028) "\0d\00\00\00\06")
@@ -39,9 +42,6 @@ total
(data (i32.const 18128) ",I")
(data (i32.const 18732) "D\1b")
(data (i32.const 18764) "`\0b")
- (import "env" "table" (table $timport$0 478 478 funcref))
- (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
- (global $global$0 (mut i32) (i32.const 1))
(elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
(export "_main" (func $_main))
(export "_malloc" (func $_malloc))
@@ -256,6 +256,8 @@ total
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $none_=>_i32 (func (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
+ (import "env" "table" (table $timport$0 478 478 funcref))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
(data (i32.const 2948) "\03")
(data (i32.const 6828) "\04")
(data (i32.const 7028) "\0d\00\00\00\06")
@@ -264,8 +266,6 @@ total
(data (i32.const 18128) ",I")
(data (i32.const 18732) "D\1b")
(data (i32.const 18764) "`\0b")
- (import "env" "table" (table $timport$0 478 478 funcref))
- (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
(elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
(export "_main" (func $_main))
(export "_malloc" (func $_malloc))
@@ -475,6 +475,8 @@ total
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $none_=>_i32 (func (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
+ (import "env" "table" (table $timport$0 478 478 funcref))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
(data (i32.const 2948) "\03")
(data (i32.const 6828) "\04")
(data (i32.const 7028) "\0d\00\00\00\06")
@@ -483,8 +485,6 @@ total
(data (i32.const 18128) ",I")
(data (i32.const 18732) "D\1b")
(data (i32.const 18764) "`\0b")
- (import "env" "table" (table $timport$0 478 478 funcref))
- (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
(elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
(export "_main" (func $_main))
(export "_malloc" (func $_malloc))
diff --git a/test/passes/fannkuch0_dwarf.bin.txt b/test/passes/fannkuch0_dwarf.bin.txt
index 8fb6f821d..aab7c229c 100644
--- a/test/passes/fannkuch0_dwarf.bin.txt
+++ b/test/passes/fannkuch0_dwarf.bin.txt
@@ -5196,7 +5196,6 @@ file_names[ 3]:
(type $i32_=>_none (func (param i32)))
(type $none_=>_none (func))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "Wrong argument.\n\00Pfannkuchen(%d) = %d.\n\00%d\00\n\00")
(import "env" "__indirect_function_table" (table $timport$0 1 funcref))
(import "env" "malloc" (func $malloc (param i32) (result i32)))
(import "env" "free" (func $free (param i32)))
@@ -5204,6 +5203,7 @@ file_names[ 3]:
(import "env" "printf" (func $printf (param i32 i32) (result i32)))
(global $global$0 (mut i32) (i32.const 5243952))
(global $global$1 i32 (i32.const 1069))
+ (data (i32.const 1024) "Wrong argument.\n\00Pfannkuchen(%d) = %d.\n\00%d\00\n\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "main" (func $main))
(export "__data_end" (global $global$1))
diff --git a/test/passes/fannkuch3_dwarf.bin.txt b/test/passes/fannkuch3_dwarf.bin.txt
index 3cfa2121a..3b98476e2 100644
--- a/test/passes/fannkuch3_dwarf.bin.txt
+++ b/test/passes/fannkuch3_dwarf.bin.txt
@@ -4796,7 +4796,6 @@ file_names[ 4]:
(type $i32_=>_none (func (param i32)))
(type $none_=>_none (func))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00")
(import "env" "__indirect_function_table" (table $timport$0 1 funcref))
(import "env" "malloc" (func $malloc (param i32) (result i32)))
(import "env" "memcpy" (func $memcpy (param i32 i32 i32) (result i32)))
@@ -4807,6 +4806,7 @@ file_names[ 4]:
(import "env" "putchar" (func $putchar (param i32) (result i32)))
(global $global$0 (mut i32) (i32.const 5243952))
(global $global$1 i32 (i32.const 1066))
+ (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "main" (func $main))
(export "__data_end" (global $global$1))
diff --git a/test/passes/fannkuch3_manyopts_dwarf.bin.txt b/test/passes/fannkuch3_manyopts_dwarf.bin.txt
index 00fed4beb..b9750d21e 100644
--- a/test/passes/fannkuch3_manyopts_dwarf.bin.txt
+++ b/test/passes/fannkuch3_manyopts_dwarf.bin.txt
@@ -4704,7 +4704,6 @@ file_names[ 4]:
(type $i32_=>_none (func (param i32)))
(type $none_=>_none (func))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00")
(import "env" "malloc" (func $malloc (param i32) (result i32)))
(import "env" "memcpy" (func $memcpy (param i32 i32 i32) (result i32)))
(import "env" "free" (func $free (param i32)))
@@ -4714,6 +4713,7 @@ file_names[ 4]:
(import "env" "putchar" (func $putchar (param i32) (result i32)))
(global $global$0 (mut i32) (i32.const 5243952))
(global $global$1 i32 (i32.const 1066))
+ (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "main" (func $main))
(export "__data_end" (global $global$1))
diff --git a/test/passes/ignore_missing_func_dwarf.bin.txt b/test/passes/ignore_missing_func_dwarf.bin.txt
index c1ff4d76b..2ac641448 100644
--- a/test/passes/ignore_missing_func_dwarf.bin.txt
+++ b/test/passes/ignore_missing_func_dwarf.bin.txt
@@ -4,11 +4,11 @@
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00")
- (data (i32.const 1168) "\00\04\00\00")
(import "env" "__indirect_function_table" (table $timport$0 1 funcref))
(global $global$0 (mut i32) (i32.const 5244064))
(global $global$1 i32 (i32.const 1172))
+ (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00")
+ (data (i32.const 1168) "\00\04\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "main" (func $main))
(export "__data_end" (global $global$1))
@@ -827,11 +827,11 @@ file_names[ 1]:
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00")
- (data (i32.const 1168) "\00\04\00\00")
(import "env" "__indirect_function_table" (table $timport$0 1 funcref))
(global $global$0 (mut i32) (i32.const 5244064))
(global $global$1 i32 (i32.const 1172))
+ (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00")
+ (data (i32.const 1168) "\00\04\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "main" (func $main))
(export "__data_end" (global $global$1))
diff --git a/test/passes/inlined_to_start_dwarf.bin.txt b/test/passes/inlined_to_start_dwarf.bin.txt
index 8eff2c8f1..44b4cf2b0 100644
--- a/test/passes/inlined_to_start_dwarf.bin.txt
+++ b/test/passes/inlined_to_start_dwarf.bin.txt
@@ -415,9 +415,9 @@ file_names[ 1]:
(type $i32_=>_none (func (param i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "\00\00\00\00")
(global $global$0 (mut i32) (i32.const 5243920))
(global $global$1 i32 (i32.const 1028))
+ (data (i32.const 1024) "\00\00\00\00")
(table $0 1 1 funcref)
(export "__indirect_function_table" (table $0))
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
diff --git a/test/passes/print-call-graph.txt b/test/passes/print-call-graph.txt
index df78a2c9e..4b2cefb81 100644
--- a/test/passes/print-call-graph.txt
+++ b/test/passes/print-call-graph.txt
@@ -121,7 +121,6 @@ digraph call {
(type $FUNCSIG$v (func))
(type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory $0 256 256))
- (data (global.get $memoryBase) "\05\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00\b0\04\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\04")
(import "env" "table" (table $timport$0 9 9 funcref))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
@@ -161,6 +160,7 @@ digraph call {
(global $tempRet0 (mut i32) (i32.const 0))
(global $tempFloat (mut f32) (f32.const 0))
(global $f0 (mut f32) (f32.const 0))
+ (data (global.get $memoryBase) "\05\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00\b0\04\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\04")
(elem (i32.const 0) $b0 $___stdio_close $b1 $___stdout_write $___stdio_seek $___stdio_write $b2 $_cleanup_387 $b3)
(export "_fflush" (func $_fflush))
(export "_main" (func $_main))
diff --git a/test/passes/remove-unused-module-elements_all-features.txt b/test/passes/remove-unused-module-elements_all-features.txt
index c2806d6e4..ecf303160 100644
--- a/test/passes/remove-unused-module-elements_all-features.txt
+++ b/test/passes/remove-unused-module-elements_all-features.txt
@@ -104,8 +104,8 @@
(module
(type $none_=>_none (func))
(import "env" "memory" (memory $0 256))
- (data (i32.const 1) "hello, world!")
(import "env" "table" (table $timport$0 1 funcref))
+ (data (i32.const 1) "hello, world!")
(elem (i32.const 0) $waka)
(func $waka
(nop)
@@ -219,10 +219,10 @@
(module
(type $none_=>_none (func))
(import "env" "memory" (memory $0 256))
- (data (global.get $memoryBase) "hello, world!")
(import "env" "table" (table $timport$0 0 funcref))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
+ (data (global.get $memoryBase) "hello, world!")
(elem (global.get $tableBase) $waka)
(func $waka
(nop)
diff --git a/test/passes/remove-unused-nonfunction-module-elements_all-features.txt b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt
index a767fccb1..28391b50d 100644
--- a/test/passes/remove-unused-nonfunction-module-elements_all-features.txt
+++ b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt
@@ -107,8 +107,8 @@
(module
(type $none_=>_none (func))
(import "env" "memory" (memory $0 256))
- (data (i32.const 1) "hello, world!")
(import "env" "table" (table $timport$0 1 funcref))
+ (data (i32.const 1) "hello, world!")
(elem (i32.const 0) $waka)
(func $waka
(nop)
@@ -222,10 +222,10 @@
(module
(type $none_=>_none (func))
(import "env" "memory" (memory $0 256))
- (data (global.get $memoryBase) "hello, world!")
(import "env" "table" (table $timport$0 0 funcref))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
+ (data (global.get $memoryBase) "hello, world!")
(elem (global.get $tableBase) $waka)
(func $waka
(nop)
diff --git a/test/passes/reverse_dwarf_abbrevs.bin.txt b/test/passes/reverse_dwarf_abbrevs.bin.txt
index 1bdfef239..a9874aa7b 100644
--- a/test/passes/reverse_dwarf_abbrevs.bin.txt
+++ b/test/passes/reverse_dwarf_abbrevs.bin.txt
@@ -121,18 +121,18 @@ file_names[ 1]:
(type $i32_i32_i64_i32_=>_i64 (func (param i32 i32 i64 i32) (result i64)))
(type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory $mimport$0 256 256))
- (data (i32.const 1024) "hello, world!\00\00\00\18\04")
- (data (i32.const 1048) "\05")
- (data (i32.const 1060) "\01")
- (data (i32.const 1084) "\02\00\00\00\03\00\00\00\c8\04\00\00\00\04")
- (data (i32.const 1108) "\01")
- (data (i32.const 1123) "\n\ff\ff\ff\ff")
(import "env" "__indirect_function_table" (table $timport$0 4 funcref))
(import "wasi_snapshot_preview1" "fd_write" (func $fimport$0 (param i32 i32 i32 i32) (result i32)))
(import "env" "emscripten_memcpy_big" (func $fimport$1 (param i32 i32 i32) (result i32)))
(import "env" "setTempRet0" (func $fimport$2 (param i32)))
(global $global$0 (mut i32) (i32.const 5245136))
(global $global$1 i32 (i32.const 2248))
+ (data (i32.const 1024) "hello, world!\00\00\00\18\04")
+ (data (i32.const 1048) "\05")
+ (data (i32.const 1060) "\01")
+ (data (i32.const 1084) "\02\00\00\00\03\00\00\00\c8\04\00\00\00\04")
+ (data (i32.const 1108) "\01")
+ (data (i32.const 1123) "\n\ff\ff\ff\ff")
(elem (i32.const 1) $6 $5 $7)
(export "__wasm_call_ctors" (func $0))
(export "main" (func $2))