summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp25
-rw-r--r--src/binaryen-c.h13
-rw-r--r--src/ir/possible-contents.cpp2
-rw-r--r--src/js/binaryen.js-post.js20
-rw-r--r--src/passes/MemoryPacking.cpp87
-rw-r--r--src/passes/MultiMemoryLowering.cpp2
-rw-r--r--src/passes/PostEmscripten.cpp28
-rw-r--r--src/passes/Print.cpp21
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp3
-rw-r--r--src/tools/fuzzing/fuzzing.cpp14
-rw-r--r--src/wasm-binary.h10
-rw-r--r--src/wasm-builder.h6
-rw-r--r--src/wasm-delegations-fields.def6
-rw-r--r--src/wasm-interpreter.h15
-rw-r--r--src/wasm-s-parser.h4
-rw-r--r--src/wasm.h6
-rw-r--r--src/wasm/wasm-binary.cpp55
-rw-r--r--src/wasm/wasm-emscripten.cpp8
-rw-r--r--src/wasm/wasm-s-parser.cpp42
-rw-r--r--src/wasm/wasm-stack.cpp17
-rw-r--r--src/wasm/wasm-validator.cpp18
-rw-r--r--src/wasm/wat-parser.cpp22
-rw-r--r--src/wasm2js.h30
23 files changed, 272 insertions, 182 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index fe067587a..01f14f924 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1553,14 +1553,14 @@ BinaryenExpressionRef BinaryenSIMDLoadStoreLane(BinaryenModuleRef module,
getMemoryName(module, memoryName)));
}
BinaryenExpressionRef BinaryenMemoryInit(BinaryenModuleRef module,
- uint32_t segment,
+ const char* segment,
BinaryenExpressionRef dest,
BinaryenExpressionRef offset,
BinaryenExpressionRef size,
const char* memoryName) {
return static_cast<Expression*>(
Builder(*(Module*)module)
- .makeMemoryInit(segment,
+ .makeMemoryInit(Name(segment),
(Expression*)dest,
(Expression*)offset,
(Expression*)size,
@@ -1568,9 +1568,9 @@ BinaryenExpressionRef BinaryenMemoryInit(BinaryenModuleRef module,
}
BinaryenExpressionRef BinaryenDataDrop(BinaryenModuleRef module,
- uint32_t segment) {
+ const char* segment) {
return static_cast<Expression*>(
- Builder(*(Module*)module).makeDataDrop(segment));
+ Builder(*(Module*)module).makeDataDrop(Name(segment)));
}
BinaryenExpressionRef BinaryenMemoryCopy(BinaryenModuleRef module,
@@ -3483,16 +3483,16 @@ bool BinaryenSIMDLoadStoreLaneIsStore(BinaryenExpressionRef expr) {
return static_cast<SIMDLoadStoreLane*>(expression)->isStore();
}
// MemoryInit
-uint32_t BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr) {
+const char* BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<MemoryInit>());
- return static_cast<MemoryInit*>(expression)->segment;
+ return static_cast<MemoryInit*>(expression)->segment.str.data();
}
void BinaryenMemoryInitSetSegment(BinaryenExpressionRef expr,
- uint32_t segment) {
+ const char* segment) {
auto* expression = (Expression*)expr;
assert(expression->is<MemoryInit>());
- static_cast<MemoryInit*>(expression)->segment = segment;
+ static_cast<MemoryInit*>(expression)->segment = Name(segment);
}
BinaryenExpressionRef BinaryenMemoryInitGetDest(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
@@ -3531,15 +3531,16 @@ void BinaryenMemoryInitSetSize(BinaryenExpressionRef expr,
static_cast<MemoryInit*>(expression)->size = (Expression*)sizeExpr;
}
// DataDrop
-uint32_t BinaryenDataDropGetSegment(BinaryenExpressionRef expr) {
+const char* BinaryenDataDropGetSegment(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<DataDrop>());
- return static_cast<DataDrop*>(expression)->segment;
+ return static_cast<DataDrop*>(expression)->segment.str.data();
}
-void BinaryenDataDropSetSegment(BinaryenExpressionRef expr, uint32_t segment) {
+void BinaryenDataDropSetSegment(BinaryenExpressionRef expr,
+ const char* segment) {
auto* expression = (Expression*)expr;
assert(expression->is<DataDrop>());
- static_cast<DataDrop*>(expression)->segment = segment;
+ static_cast<DataDrop*>(expression)->segment = Name(segment);
}
// MemoryCopy
BinaryenExpressionRef BinaryenMemoryCopyGetDest(BinaryenExpressionRef expr) {
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 1a54e311c..afbc13782 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -961,13 +961,13 @@ BinaryenSIMDLoadStoreLane(BinaryenModuleRef module,
const char* memoryName);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryInit(BinaryenModuleRef module,
- uint32_t segment,
+ const char* segment,
BinaryenExpressionRef dest,
BinaryenExpressionRef offset,
BinaryenExpressionRef size,
const char* memoryName);
BINARYEN_API BinaryenExpressionRef BinaryenDataDrop(BinaryenModuleRef module,
- uint32_t segment);
+ const char* segment);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryCopy(BinaryenModuleRef module,
BinaryenExpressionRef dest,
@@ -2031,11 +2031,12 @@ BINARYEN_API bool BinaryenSIMDLoadStoreLaneIsStore(BinaryenExpressionRef expr);
// Gets the index of the segment being initialized by a `memory.init`
// expression.
-BINARYEN_API uint32_t BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr);
+BINARYEN_API const char*
+BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr);
// Sets the index of the segment being initialized by a `memory.init`
// expression.
BINARYEN_API void BinaryenMemoryInitSetSegment(BinaryenExpressionRef expr,
- uint32_t segmentIndex);
+ const char* segment);
// Gets the destination expression of a `memory.init` expression.
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryInitGetDest(BinaryenExpressionRef expr);
@@ -2058,10 +2059,10 @@ BINARYEN_API void BinaryenMemoryInitSetSize(BinaryenExpressionRef expr,
// DataDrop
// Gets the index of the segment being dropped by a `data.drop` expression.
-BINARYEN_API uint32_t BinaryenDataDropGetSegment(BinaryenExpressionRef expr);
+BINARYEN_API const char* BinaryenDataDropGetSegment(BinaryenExpressionRef expr);
// Sets the index of the segment being dropped by a `data.drop` expression.
BINARYEN_API void BinaryenDataDropSetSegment(BinaryenExpressionRef expr,
- uint32_t segmentIndex);
+ const char* segment);
// MemoryCopy
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp
index d292529dc..05faf7b1e 100644
--- a/src/ir/possible-contents.cpp
+++ b/src/ir/possible-contents.cpp
@@ -903,7 +903,7 @@ struct InfoCollector
return;
}
case NewElem: {
- Type segType = getModule()->elementSegments[curr->segment]->type;
+ Type segType = getModule()->getElementSegment(curr->segment)->type;
addRoot(DataLocation{heapType, 0}, PossibleContents::fromType(segType));
return;
}
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 50cac2a1c..35f5d9a5c 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -758,7 +758,7 @@ function wrapModule(module, self = {}) {
return Module['_BinaryenMemoryGrow'](module, value, strToStack(name), memory64);
},
'init'(segment, dest, offset, size, name) {
- return Module['_BinaryenMemoryInit'](module, segment, dest, offset, size, strToStack(name));
+ return preserveStack(() => Module['_BinaryenMemoryInit'](module, strToStack(segment), dest, offset, size, strToStack(name)));
},
'copy'(dest, source, size, destMemory, sourceMemory) {
return Module['_BinaryenMemoryCopy'](module, dest, source, size, strToStack(destMemory), strToStack(sourceMemory));
@@ -781,7 +781,7 @@ function wrapModule(module, self = {}) {
self['data'] = {
'drop'(segment) {
- return Module['_BinaryenDataDrop'](module, segment);
+ return preserveStack(() => Module['_BinaryenDataDrop'](module, strToStack(segment)));
}
}
@@ -3172,7 +3172,7 @@ Module['getExpressionInfo'] = function(expr) {
case Module['MemoryInitId']:
return {
'id': id,
- 'segment': Module['_BinaryenMemoryInitGetSegment'](expr),
+ 'segment': UTF8ToString(Module['_BinaryenMemoryInitGetSegment'](expr)),
'dest': Module['_BinaryenMemoryInitGetDest'](expr),
'offset': Module['_BinaryenMemoryInitGetOffset'](expr),
'size': Module['_BinaryenMemoryInitGetSize'](expr)
@@ -3180,7 +3180,7 @@ Module['getExpressionInfo'] = function(expr) {
case Module['DataDropId']:
return {
'id': id,
- 'segment': Module['_BinaryenDataDropGetSegment'](expr),
+ 'segment': UTF8ToString(Module['_BinaryenDataDropGetSegment'](expr)),
};
case Module['MemoryCopyId']:
return {
@@ -4543,10 +4543,10 @@ Module['SIMDLoadStoreLane'] = makeExpressionWrapper({
Module['MemoryInit'] = makeExpressionWrapper({
'getSegment'(expr) {
- return Module['_BinaryenMemoryInitGetSegment'](expr);
+ return UTF8ToString(Module['_BinaryenMemoryInitGetSegment'](expr));
},
- 'setSegment'(expr, segmentIndex) {
- Module['_BinaryenMemoryInitSetSegment'](expr, segmentIndex);
+ 'setSegment'(expr, segment) {
+ preserveStack(() => Module['_BinaryenMemoryInitSetSegment'](expr, strToStack(segment)));
},
'getDest'(expr) {
return Module['_BinaryenMemoryInitGetDest'](expr);
@@ -4570,10 +4570,10 @@ Module['MemoryInit'] = makeExpressionWrapper({
Module['DataDrop'] = makeExpressionWrapper({
'getSegment'(expr) {
- return Module['_BinaryenDataDropGetSegment'](expr);
+ return UTF8ToString(Module['_BinaryenDataDropGetSegment'](expr));
},
- 'setSegment'(expr, segmentIndex) {
- Module['_BinaryenDataDropSetSegment'](expr, segmentIndex);
+ 'setSegment'(expr, segment) {
+ preserveStack(() => Module['_BinaryenDataDropSetSegment'](expr, strToStack(segment)));
}
});
diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp
index 7beed9a16..608bc1af2 100644
--- a/src/passes/MemoryPacking.cpp
+++ b/src/passes/MemoryPacking.cpp
@@ -69,7 +69,7 @@ using Replacements = std::unordered_map<Expression*, Replacement>;
using Referrers = std::vector<Expression*>;
// Map segment indices to referrers.
-using ReferrersMap = std::unordered_map<Index, Referrers>;
+using ReferrersMap = std::unordered_map<Name, Referrers>;
// memory.init: 2 byte opcode + 1 byte segment index + 1 byte memory index +
// 3 x 2 byte operands
@@ -119,9 +119,9 @@ struct MemoryPacking : public Pass {
size_t segmentsRemaining);
void createReplacements(Module* module,
const std::vector<Range>& ranges,
+ const std::vector<Name>& segments,
const Referrers& referrers,
- Replacements& replacements,
- const Index segmentIndex);
+ Replacements& replacements);
void replaceSegmentOps(Module* module, Replacements& replacements);
};
@@ -155,9 +155,9 @@ void MemoryPacking::run(Module* module) {
Replacements replacements;
Builder builder(*module);
- for (size_t origIndex = 0; origIndex < segments.size(); ++origIndex) {
- auto& segment = segments[origIndex];
- auto& currReferrers = referrers[origIndex];
+ for (size_t index = 0; index < segments.size(); ++index) {
+ auto& segment = segments[index];
+ auto& currReferrers = referrers[segment->name];
std::vector<Range> ranges;
@@ -169,12 +169,16 @@ void MemoryPacking::run(Module* module) {
ranges.push_back({false, 0, segment->data.size()});
}
- Index firstNewIndex = packed.size();
- size_t segmentsRemaining = segments.size() - origIndex;
+ size_t segmentsRemaining = segments.size() - index;
+ size_t currSegmentsStart = packed.size();
createSplitSegments(
builder, segment.get(), ranges, packed, segmentsRemaining);
+ std::vector<Name> currSegmentNames;
+ for (size_t i = currSegmentsStart; i < packed.size(); ++i) {
+ currSegmentNames.push_back(packed[i]->name);
+ }
createReplacements(
- module, ranges, currReferrers, replacements, firstNewIndex);
+ module, ranges, currSegmentNames, currReferrers, replacements);
}
segments.swap(packed);
@@ -394,7 +398,7 @@ void MemoryPacking::optimizeSegmentOps(Module* module) {
void visitMemoryInit(MemoryInit* curr) {
Builder builder(*getModule());
- auto& segment = getModule()->dataSegments[curr->segment];
+ auto* segment = getModule()->getDataSegment(curr->segment);
size_t maxRuntimeSize = segment->isPassive ? segment->data.size() : 0;
bool mustNop = false;
bool mustTrap = false;
@@ -439,7 +443,7 @@ void MemoryPacking::optimizeSegmentOps(Module* module) {
}
}
void visitDataDrop(DataDrop* curr) {
- if (!getModule()->dataSegments[curr->segment]->isPassive) {
+ if (!getModule()->getDataSegment(curr->segment)->isPassive) {
ExpressionManipulator::nop(curr);
}
}
@@ -496,12 +500,11 @@ 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
for (size_t i = 0; i < segments.size(); ++i) {
bool used = false;
- auto referrersIt = referrers.find(i);
+ auto referrersIt = referrers.find(segments[i]->name);
bool hasReferrers = referrersIt != referrers.end();
if (segments[i]->isPassive) {
if (hasReferrers) {
@@ -518,9 +521,6 @@ void MemoryPacking::dropUnusedSegments(
}
if (used) {
usedSegments.push_back(std::move(segments[i]));
- if (hasReferrers) {
- usedReferrers[usedSegments.size() - 1] = std::move(referrersIt->second);
- }
} else if (hasReferrers) {
// All referrers are data.drops. Make them nops.
for (auto* referrer : referrersIt->second) {
@@ -530,7 +530,6 @@ void MemoryPacking::dropUnusedSegments(
}
std::swap(segments, usedSegments);
module->updateDataSegmentsMap();
- std::swap(referrers, usedReferrers);
}
void MemoryPacking::createSplitSegments(
@@ -596,25 +595,11 @@ void MemoryPacking::createSplitSegments(
void MemoryPacking::createReplacements(Module* module,
const std::vector<Range>& ranges,
+ const std::vector<Name>& segments,
const Referrers& referrers,
- Replacements& replacements,
- const Index segmentIndex) {
- // If there was no transformation, only update the indices
+ Replacements& replacements) {
+ // If there was no transformation, we do not need to do anything.
if (ranges.size() == 1 && !ranges.front().isZero) {
- for (auto referrer : referrers) {
- replacements[referrer] = [referrer, segmentIndex](Function*) {
- if (auto* curr = referrer->dynCast<MemoryInit>()) {
- curr->segment = segmentIndex;
- } else if (auto* curr = referrer->dynCast<DataDrop>()) {
- curr->segment = segmentIndex;
- } else if (auto* curr = referrer->dynCast<ArrayNewSeg>()) {
- curr->segment = segmentIndex;
- } else {
- WASM_UNREACHABLE("Unexpected segment operation");
- }
- return referrer;
- };
- }
return;
}
@@ -649,8 +634,9 @@ void MemoryPacking::createReplacements(Module* module,
size_t start = init->offset->cast<Const>()->value.geti32();
size_t end = start + init->size->cast<Const>()->value.geti32();
- // Segment index used in emitted memory.init instructions
- size_t initIndex = segmentIndex;
+ // Index in `segments` of the segment used in emitted memory.init
+ // instructions
+ size_t initIndex = 0;
// Index of the range from which this memory.init starts reading
size_t firstRangeIdx = 0;
@@ -742,8 +728,8 @@ void MemoryPacking::createReplacements(Module* module,
size_t offsetBytes = std::max(start, range.start) - range.start;
Expression* offset = builder.makeConst(int32_t(offsetBytes));
Expression* size = builder.makeConst(int32_t(bytes));
- appendResult(
- builder.makeMemoryInit(initIndex, dest, offset, size, init->memory));
+ appendResult(builder.makeMemoryInit(
+ segments[initIndex], dest, offset, size, init->memory));
initIndex++;
}
}
@@ -779,10 +765,10 @@ void MemoryPacking::createReplacements(Module* module,
appendResult(
builder.makeGlobalSet(dropStateGlobal, builder.makeConst(int32_t(1))));
}
- size_t dropIndex = segmentIndex;
+ size_t dropIndex = 0;
for (auto range : ranges) {
if (!range.isZero) {
- appendResult(builder.makeDataDrop(dropIndex++));
+ appendResult(builder.makeDataDrop(segments[dropIndex++]));
}
}
replacements[drop] = [result, module](Function*) {
@@ -807,22 +793,25 @@ void MemoryPacking::replaceSegmentOps(Module* module,
}
void visitMemoryInit(MemoryInit* curr) {
- auto replacement = replacements.find(curr);
- assert(replacement != replacements.end());
- replaceCurrent(replacement->second(getFunction()));
+ if (auto replacement = replacements.find(curr);
+ replacement != replacements.end()) {
+ replaceCurrent(replacement->second(getFunction()));
+ }
}
void visitDataDrop(DataDrop* curr) {
- auto replacement = replacements.find(curr);
- assert(replacement != replacements.end());
- replaceCurrent(replacement->second(getFunction()));
+ if (auto replacement = replacements.find(curr);
+ replacement != replacements.end()) {
+ replaceCurrent(replacement->second(getFunction()));
+ }
}
void visitArrayNewSeg(ArrayNewSeg* curr) {
if (curr->op == NewData) {
- auto replacement = replacements.find(curr);
- assert(replacement != replacements.end());
- replaceCurrent(replacement->second(getFunction()));
+ if (auto replacement = replacements.find(curr);
+ replacement != replacements.end()) {
+ replaceCurrent(replacement->second(getFunction()));
+ }
}
}
} replacer(replacements);
diff --git a/src/passes/MultiMemoryLowering.cpp b/src/passes/MultiMemoryLowering.cpp
index 08e1622d5..f0a4be112 100644
--- a/src/passes/MultiMemoryLowering.cpp
+++ b/src/passes/MultiMemoryLowering.cpp
@@ -181,7 +181,7 @@ struct MultiMemoryLowering : public Pass {
Expression* makeDataSegmentBoundsCheck(MemoryInit* curr,
Index sizeIdx,
Index offsetIdx) {
- auto& segment = parent.wasm->dataSegments[curr->segment];
+ auto* segment = parent.wasm->getDataSegment(curr->segment);
Expression* addGtuTrap = makeAddGtuTrap(
builder.makeLocalGet(offsetIdx, parent.pointerType),
builder.makeLocalGet(sizeIdx, parent.pointerType),
diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp
index ea4922e3a..b569cd0e0 100644
--- a/src/passes/PostEmscripten.cpp
+++ b/src/passes/PostEmscripten.cpp
@@ -42,7 +42,7 @@ static bool isInvoke(Function* F) {
}
struct SegmentRemover : WalkerPass<PostWalker<SegmentRemover>> {
- SegmentRemover(Index segment) : segment(segment) {}
+ SegmentRemover(Name segment) : segment(segment) {}
bool isFunctionParallel() override { return true; }
@@ -66,19 +66,19 @@ struct SegmentRemover : WalkerPass<PostWalker<SegmentRemover>> {
}
}
- Index segment;
+ Name segment;
};
static void calcSegmentOffsets(Module& wasm,
std::vector<Address>& segmentOffsets) {
const Address UNKNOWN_OFFSET(uint32_t(-1));
- std::unordered_map<Index, Address> passiveOffsets;
+ std::unordered_map<Name, Address> passiveOffsets;
if (wasm.features.hasBulkMemory()) {
// Fetch passive segment offsets out of memory.init instructions
struct OffsetSearcher : PostWalker<OffsetSearcher> {
- std::unordered_map<Index, Address>& offsets;
- OffsetSearcher(std::unordered_map<unsigned, Address>& offsets)
+ std::unordered_map<Name, Address>& offsets;
+ OffsetSearcher(std::unordered_map<Name, Address>& offsets)
: offsets(offsets) {}
void visitMemoryInit(MemoryInit* curr) {
// The desitination of the memory.init is either a constant
@@ -108,7 +108,7 @@ static void calcSegmentOffsets(Module& wasm,
for (unsigned i = 0; i < wasm.dataSegments.size(); ++i) {
auto& segment = wasm.dataSegments[i];
if (segment->isPassive) {
- auto it = passiveOffsets.find(i);
+ auto it = passiveOffsets.find(segment->name);
if (it != passiveOffsets.end()) {
segmentOffsets.push_back(it->second);
} else {
@@ -126,13 +126,11 @@ static void calcSegmentOffsets(Module& wasm,
}
}
-static void removeSegment(Module& wasm, Index segment) {
+static void removeSegment(Module& wasm, Name segment) {
PassRunner runner(&wasm);
SegmentRemover(segment).run(&runner, &wasm);
- // 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.dataSegments[segment]->data.resize(0);
+ // Resize the segment to zero. TODO: Remove it entirely instead.
+ wasm.getDataSegment(segment)->data.resize(0);
}
static Address getExportedAddress(Module& wasm, Export* export_) {
@@ -160,21 +158,21 @@ static void removeData(Module& wasm,
Address startAddress = getExportedAddress(wasm, start);
Address endAddress = getExportedAddress(wasm, end);
for (Index i = 0; i < wasm.dataSegments.size(); i++) {
+ auto& segment = wasm.dataSegments[i];
Address segmentStart = segmentOffsets[i];
- size_t segmentSize = wasm.dataSegments[i]->data.size();
+ size_t segmentSize = segment->data.size();
if (segmentStart <= startAddress &&
segmentStart + segmentSize >= endAddress) {
-
if (segmentStart == startAddress &&
segmentStart + segmentSize == endAddress) {
BYN_TRACE("removeData: removing whole segment\n");
- removeSegment(wasm, i);
+ removeSegment(wasm, segment->name);
} else {
// If we can't remove the whole segment then just set the string
// data to zero.
BYN_TRACE("removeData: removing part of segment\n");
size_t segmentOffset = startAddress - segmentStart;
- char* startElem = &wasm.dataSegments[i]->data[segmentOffset];
+ char* startElem = &segment->data[segmentOffset];
memset(startElem, 0, endAddress - startAddress);
}
return;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index c9a717058..9f765bb79 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -929,13 +929,13 @@ struct PrintExpressionContents
o << "memory.init";
restoreNormalColor(o);
printMemoryName(curr->memory, o, wasm);
- o << ' ' << curr->segment;
+ o << " $" << curr->segment;
}
void visitDataDrop(DataDrop* curr) {
prepareColor(o);
o << "data.drop";
restoreNormalColor(o);
- o << ' ' << curr->segment;
+ o << " $" << curr->segment;
}
void visitMemoryCopy(MemoryCopy* curr) {
prepareColor(o);
@@ -2283,7 +2283,7 @@ struct PrintExpressionContents
}
o << ' ';
TypeNamePrinter(o, wasm).print(curr->type.getHeapType());
- o << ' ' << curr->segment;
+ o << " $" << curr->segment;
}
void visitArrayNewFixed(ArrayNewFixed* curr) {
if (printUnreachableReplacement(curr)) {
@@ -3246,13 +3246,8 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
doIndent(o, indent);
o << '(';
- printMedium(o, "elem");
- // If there is no explicit name, and there are multiple segments, use our
- // internal names to differentiate them.
- if (curr->hasExplicitName || currModule->elementSegments.size() > 1) {
- o << ' ';
- printName(curr->name, o);
- }
+ printMedium(o, "elem ");
+ printName(curr->name, o);
if (curr->table.is()) {
if (usesExpressions || currModule->tables.size() > 1) {
@@ -3325,10 +3320,8 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
doIndent(o, indent);
o << '(';
printMajor(o, "data ");
- if (curr->hasExplicitName) {
- printName(curr->name, o);
- o << ' ';
- }
+ printName(curr->name, o);
+ o << ' ';
if (!curr->isPassive) {
assert(!currModule || currModule->memories.size() > 0);
if (!currModule || curr->memory != currModule->memories[0]->name) {
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp
index 103be5e4a..8b9ed2a78 100644
--- a/src/passes/RemoveUnusedModuleElements.cpp
+++ b/src/passes/RemoveUnusedModuleElements.cpp
@@ -180,8 +180,7 @@ struct ReferenceFinder : public PostWalker<ReferenceFinder> {
usesMemory = true;
return;
case NewElem:
- auto segment = getModule()->elementSegments[curr->segment]->name;
- note({ModuleElementKind::ElementSegment, segment});
+ note({ModuleElementKind::ElementSegment, curr->segment});
return;
}
WASM_UNREACHABLE("unexpected op");
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 0a4f8e581..4a611345d 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -202,7 +202,8 @@ void TranslateToFuzzReader::setupMemory() {
size_t numSegments = upTo(8) + 1;
for (size_t i = 0; i < numSegments; i++) {
auto segment = builder.makeDataSegment();
- segment->setName(Name::fromInt(i), false);
+ segment->setName(Names::getValidDataSegmentName(wasm, Name::fromInt(i)),
+ false);
segment->isPassive = bool(upTo(2));
size_t segSize = upTo(USABLE_MEMORY * 2);
segment->data.resize(segSize);
@@ -214,7 +215,7 @@ void TranslateToFuzzReader::setupMemory() {
memCovered += segSize;
segment->memory = wasm.memories[0]->name;
}
- wasm.dataSegments.push_back(std::move(segment));
+ wasm.addDataSegment(std::move(segment));
}
} else {
// init some data
@@ -3196,8 +3197,9 @@ Expression* TranslateToFuzzReader::makeMemoryInit() {
if (!allowMemory) {
return makeTrivial(Type::none);
}
- uint32_t segment = upTo(wasm.dataSegments.size());
- size_t totalSize = wasm.dataSegments[segment]->data.size();
+ Index segIdx = upTo(wasm.dataSegments.size());
+ Name segment = wasm.dataSegments[segIdx]->name;
+ size_t totalSize = wasm.dataSegments[segIdx]->data.size();
size_t offsetVal = upTo(totalSize);
size_t sizeVal = upTo(totalSize - offsetVal);
Expression* dest = makePointer();
@@ -3211,7 +3213,9 @@ Expression* TranslateToFuzzReader::makeDataDrop() {
if (!allowMemory) {
return makeTrivial(Type::none);
}
- return builder.makeDataDrop(upTo(wasm.dataSegments.size()));
+ Index segIdx = upTo(wasm.dataSegments.size());
+ Name segment = wasm.dataSegments[segIdx]->name;
+ return builder.makeDataDrop(segment);
}
Expression* TranslateToFuzzReader::makeMemoryCopy() {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index e6092fbc9..4f224e1dd 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1325,6 +1325,8 @@ public:
uint32_t getMemoryIndex(Name name) const;
uint32_t getGlobalIndex(Name name) const;
uint32_t getTagIndex(Name name) const;
+ uint32_t getDataSegmentIndex(Name name) const;
+ uint32_t getElementSegmentIndex(Name name) const;
uint32_t getTypeIndex(HeapType type) const;
uint32_t getStringIndex(Name string) const;
@@ -1506,6 +1508,8 @@ public:
Name getMemoryName(Index index);
Name getGlobalName(Index index);
Name getTagName(Index index);
+ Name getDataName(Index index);
+ Name getElemName(Index index);
// gets a memory in the combined import+defined space
Memory* getMemory(Index index);
@@ -1556,6 +1560,12 @@ public:
// at index i we have all refs to the tag i
std::map<Index, std::vector<Name*>> tagRefs;
+ // at index i we have all refs to the data segment i
+ std::map<Index, std::vector<Name*>> dataRefs;
+
+ // at index i we have all refs to the element segment i
+ std::map<Index, std::vector<Name*>> elemRefs;
+
// Throws a parsing error if we are not in a function context
void requireFunctionContext(const char* error);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 73803e37d..dbddb248b 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -569,7 +569,7 @@ public:
ret->memory = memory;
return ret;
}
- MemoryInit* makeMemoryInit(uint32_t segment,
+ MemoryInit* makeMemoryInit(Name segment,
Expression* dest,
Expression* offset,
Expression* size,
@@ -583,7 +583,7 @@ public:
ret->finalize();
return ret;
}
- DataDrop* makeDataDrop(uint32_t segment) {
+ DataDrop* makeDataDrop(Name segment) {
auto* ret = wasm.allocator.alloc<DataDrop>();
ret->segment = segment;
ret->finalize();
@@ -930,7 +930,7 @@ public:
}
ArrayNewSeg* makeArrayNewSeg(ArrayNewSegOp op,
HeapType type,
- Index seg,
+ Name seg,
Expression* offset,
Expression* size) {
auto* ret = wasm.allocator.alloc<ArrayNewSeg>();
diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def
index 92ab4c9d3..480789ca3 100644
--- a/src/wasm-delegations-fields.def
+++ b/src/wasm-delegations-fields.def
@@ -400,14 +400,14 @@ switch (DELEGATE_ID) {
DELEGATE_FIELD_CHILD(MemoryInit, size);
DELEGATE_FIELD_CHILD(MemoryInit, offset);
DELEGATE_FIELD_CHILD(MemoryInit, dest);
- DELEGATE_FIELD_INT(MemoryInit, segment);
+ DELEGATE_FIELD_NAME(MemoryInit, segment);
DELEGATE_FIELD_NAME(MemoryInit, memory);
DELEGATE_END(MemoryInit);
break;
}
case Expression::Id::DataDropId: {
DELEGATE_START(DataDrop);
- DELEGATE_FIELD_INT(DataDrop, segment);
+ DELEGATE_FIELD_NAME(DataDrop, segment);
DELEGATE_END(DataDrop);
break;
}
@@ -666,7 +666,7 @@ switch (DELEGATE_ID) {
case Expression::Id::ArrayNewSegId: {
DELEGATE_START(ArrayNewSeg);
DELEGATE_FIELD_INT(ArrayNewSeg, op);
- DELEGATE_FIELD_INT(ArrayNewSeg, segment);
+ DELEGATE_FIELD_NAME(ArrayNewSeg, segment);
DELEGATE_FIELD_CHILD(ArrayNewSeg, size);
DELEGATE_FIELD_CHILD(ArrayNewSeg, offset);
DELEGATE_END(ArrayNewSeg);
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 75f2a8338..4b7d652b4 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2552,7 +2552,7 @@ private:
// stack traces.
std::vector<Name> functionStack;
- std::unordered_set<size_t> droppedSegments;
+ std::unordered_set<Name> droppedSegments;
struct TableInterfaceInfo {
// The external interface in which the table is defined.
@@ -2642,14 +2642,14 @@ private:
MemoryInit init;
init.memory = segment->memory;
- init.segment = i;
+ init.segment = segment->name;
init.dest = segment->offset;
init.offset = &offset;
init.size = &size;
init.finalize();
DataDrop drop;
- drop.segment = i;
+ drop.segment = segment->name;
drop.finalize();
self()->visit(&init);
@@ -3397,8 +3397,7 @@ public:
NOTE_EVAL1(offset);
NOTE_EVAL1(size);
- assert(curr->segment < wasm.dataSegments.size());
- auto& segment = wasm.dataSegments[curr->segment];
+ auto* segment = wasm.getDataSegment(curr->segment);
Address destVal(dest.getSingleValue().getUnsigned());
Address offsetVal(uint32_t(offset.getSingleValue().geti32()));
@@ -3543,9 +3542,8 @@ public:
switch (curr->op) {
case NewData: {
- assert(curr->segment < wasm.dataSegments.size());
assert(elemType.isNumber());
- const auto& seg = *wasm.dataSegments[curr->segment];
+ const auto& seg = *wasm.getDataSegment(curr->segment);
auto elemBytes = element.getByteSize();
auto end = offset + size * elemBytes;
if ((size != 0ull && droppedSegments.count(curr->segment)) ||
@@ -3560,8 +3558,7 @@ public:
break;
}
case NewElem: {
- assert(curr->segment < wasm.elementSegments.size());
- const auto& seg = *wasm.elementSegments[curr->segment];
+ const auto& seg = *wasm.getElementSegment(curr->segment);
auto end = offset + size;
// TODO: Handle dropped element segments once we support those.
if (end > seg.data.size()) {
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 5692df03d..c684ae58a 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -124,7 +124,9 @@ class SExpressionWasmBuilder {
std::vector<Name> functionNames;
std::vector<Name> tableNames;
+ std::vector<Name> elemSegmentNames;
std::vector<Name> memoryNames;
+ std::vector<Name> dataSegmentNames;
std::vector<Name> globalNames;
std::vector<Name> tagNames;
int functionCounter = 0;
@@ -170,7 +172,9 @@ private:
Name getFunctionName(Element& s);
Name getTableName(Element& s);
+ Name getElemSegmentName(Element& s);
Name getMemoryName(Element& s);
+ Name getDataSegmentName(Element& s);
Name getGlobalName(Element& s);
Name getTagName(Element& s);
void parseStart(Element& s) { wasm.addStart(getFunctionName(*s[1])); }
diff --git a/src/wasm.h b/src/wasm.h
index 0f188f7b0..d776ec9aa 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1176,7 +1176,7 @@ public:
MemoryInit() = default;
MemoryInit(MixedArena& allocator) : MemoryInit() {}
- Index segment;
+ Name segment;
Expression* dest;
Expression* offset;
Expression* size;
@@ -1190,7 +1190,7 @@ public:
DataDrop() = default;
DataDrop(MixedArena& allocator) : DataDrop() {}
- Index segment;
+ Name segment;
void finalize();
};
@@ -1608,7 +1608,7 @@ public:
ArrayNewSeg(MixedArena& allocator) {}
ArrayNewSegOp op;
- Index segment;
+ Name segment;
Expression* offset;
Expression* size;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 7de97eb64..f92f1ae26 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -651,6 +651,18 @@ uint32_t WasmBinaryWriter::getTagIndex(Name name) const {
return it->second;
}
+uint32_t WasmBinaryWriter::getDataSegmentIndex(Name name) const {
+ auto it = indexes.dataIndexes.find(name);
+ assert(it != indexes.dataIndexes.end());
+ return it->second;
+}
+
+uint32_t WasmBinaryWriter::getElementSegmentIndex(Name name) const {
+ auto it = indexes.elemIndexes.find(name);
+ assert(it != indexes.elemIndexes.end());
+ return it->second;
+}
+
uint32_t WasmBinaryWriter::getTypeIndex(HeapType type) const {
auto it = indexedTypes.indices.find(type);
#ifndef NDEBUG
@@ -2304,6 +2316,20 @@ Name WasmBinaryBuilder::getTagName(Index index) {
return wasm.tags[index]->name;
}
+Name WasmBinaryBuilder::getDataName(Index index) {
+ if (index >= wasm.dataSegments.size()) {
+ throwError("invalid data segment index");
+ }
+ return wasm.dataSegments[index]->name;
+}
+
+Name WasmBinaryBuilder::getElemName(Index index) {
+ if (index >= wasm.elementSegments.size()) {
+ throwError("invalid element segment index");
+ }
+ return wasm.elementSegments[index]->name;
+}
+
Memory* WasmBinaryBuilder::getMemory(Index index) {
if (index < wasm.memories.size()) {
return wasm.memories[index].get();
@@ -3115,6 +3141,16 @@ void WasmBinaryBuilder::processNames() {
*ref = getTagName(index);
}
}
+ for (auto& [index, refs] : dataRefs) {
+ for (auto* ref : refs) {
+ *ref = getDataName(index);
+ }
+ }
+ for (auto& [index, refs] : elemRefs) {
+ for (auto* ref : refs) {
+ *ref = getElemName(index);
+ }
+ }
// Everything now has its proper name.
@@ -5190,10 +5226,11 @@ bool WasmBinaryBuilder::maybeVisitMemoryInit(Expression*& out, uint32_t code) {
curr->size = popNonVoidExpression();
curr->offset = popNonVoidExpression();
curr->dest = popNonVoidExpression();
- curr->segment = getU32LEB();
+ Index segIdx = getU32LEB();
+ dataRefs[segIdx].push_back(&curr->segment);
Index memIdx = getU32LEB();
- curr->finalize();
memoryRefs[memIdx].push_back(&curr->memory);
+ curr->finalize();
out = curr;
return true;
}
@@ -5203,7 +5240,8 @@ bool WasmBinaryBuilder::maybeVisitDataDrop(Expression*& out, uint32_t code) {
return false;
}
auto* curr = allocator.alloc<DataDrop>();
- curr->segment = getU32LEB();
+ Index segIdx = getU32LEB();
+ dataRefs[segIdx].push_back(&curr->segment);
curr->finalize();
out = curr;
return true;
@@ -7080,10 +7118,17 @@ bool WasmBinaryBuilder::maybeVisitArrayNewSeg(Expression*& out, uint32_t code) {
code == BinaryConsts::ArrayNewElem) {
auto op = code == BinaryConsts::ArrayNewData ? NewData : NewElem;
auto heapType = getIndexedHeapType();
- auto seg = getU32LEB();
+ auto segIdx = getU32LEB();
auto* size = popNonVoidExpression();
auto* offset = popNonVoidExpression();
- out = Builder(wasm).makeArrayNewSeg(op, heapType, seg, offset, size);
+ auto* built =
+ Builder(wasm).makeArrayNewSeg(op, heapType, Name(), offset, size);
+ if (op == NewData) {
+ dataRefs[segIdx].push_back(&built->segment);
+ } else {
+ elemRefs[segIdx].push_back(&built->segment);
+ }
+ out = built;
return true;
}
return false;
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 9cc8b29f0..aef36d181 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -125,12 +125,12 @@ public:
private:
void calcSegmentOffsets() {
- std::unordered_map<Index, Address> passiveOffsets;
+ std::unordered_map<Name, Address> passiveOffsets;
if (wasm.features.hasBulkMemory()) {
// Fetch passive segment offsets out of memory.init instructions
struct OffsetSearcher : PostWalker<OffsetSearcher> {
- std::unordered_map<Index, Address>& offsets;
- OffsetSearcher(std::unordered_map<unsigned, Address>& offsets)
+ std::unordered_map<Name, Address>& offsets;
+ OffsetSearcher(std::unordered_map<Name, Address>& offsets)
: offsets(offsets) {}
void visitMemoryInit(MemoryInit* curr) {
// The desitination of the memory.init is either a constant
@@ -160,7 +160,7 @@ private:
for (unsigned i = 0; i < wasm.dataSegments.size(); ++i) {
auto& segment = wasm.dataSegments[i];
if (segment->isPassive) {
- auto it = passiveOffsets.find(i);
+ auto it = passiveOffsets.find(segment->name);
if (it != passiveOffsets.end()) {
segmentOffsets.push_back(it->second);
} else {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 1afdefe87..51df46544 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -510,6 +510,19 @@ Name SExpressionWasmBuilder::getTableName(Element& s) {
}
}
+Name SExpressionWasmBuilder::getElemSegmentName(Element& s) {
+ if (s.dollared()) {
+ return s.str();
+ } else {
+ // index
+ size_t offset = parseIndex(s);
+ if (offset >= elemSegmentNames.size()) {
+ throw ParseException("unknown elem segment", s.line, s.col);
+ }
+ return elemSegmentNames[offset];
+ }
+}
+
bool SExpressionWasmBuilder::isMemory64(Name memoryName) {
auto* memory = wasm.getMemoryOrNull(memoryName);
if (!memory) {
@@ -535,6 +548,19 @@ Name SExpressionWasmBuilder::getMemoryName(Element& s) {
}
}
+Name SExpressionWasmBuilder::getDataSegmentName(Element& s) {
+ if (s.dollared()) {
+ return s.str();
+ } else {
+ // index
+ size_t offset = parseIndex(s);
+ if (offset >= dataSegmentNames.size()) {
+ throw ParseException("unknown data segment", s.line, s.col);
+ }
+ return dataSegmentNames[offset];
+ }
+}
+
Name SExpressionWasmBuilder::getGlobalName(Element& s) {
if (s.dollared()) {
return s.str();
@@ -2289,7 +2315,7 @@ Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) {
memory = getMemoryNameAtIdx(0);
}
ret->memory = memory;
- ret->segment = parseIndex(*s[i++]);
+ ret->segment = getDataSegmentName(*s[i++]);
ret->dest = parseExpression(s[i++]);
ret->offset = parseExpression(s[i++]);
ret->size = parseExpression(s[i]);
@@ -2299,7 +2325,7 @@ Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) {
Expression* SExpressionWasmBuilder::makeDataDrop(Element& s) {
auto ret = allocator.alloc<DataDrop>();
- ret->segment = parseIndex(*s[1]);
+ ret->segment = getDataSegmentName(*s[1]);
ret->finalize();
return ret;
}
@@ -2951,7 +2977,8 @@ Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) {
Expression* SExpressionWasmBuilder::makeArrayNewSeg(Element& s,
ArrayNewSegOp op) {
auto heapType = parseHeapType(*s[1]);
- Index seg = parseIndex(*s[2]);
+ Name seg =
+ op == NewData ? getDataSegmentName(*s[2]) : getElemSegmentName(*s[2]);
Expression* offset = parseExpression(*s[3]);
Expression* size = parseExpression(*s[4]);
return Builder(wasm).makeArrayNewSeg(op, heapType, seg, offset, size);
@@ -3312,8 +3339,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
} else {
offset->set(Literal(int32_t(0)));
}
- auto seg = Builder::makeDataSegment(
- Name::fromInt(dataCounter++), memory->name, false, offset);
+ auto segName = Name::fromInt(dataCounter++);
+ auto seg = Builder::makeDataSegment(segName, memory->name, false, offset);
+ dataSegmentNames.push_back(segName);
parseInnerData(inner, j, seg);
memory->initial = seg->data.size();
wasm.addDataSegment(std::move(seg));
@@ -3358,6 +3386,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
data.data(),
data.size());
segment->hasExplicitName = false;
+ dataSegmentNames.push_back(segment->name);
wasm.addDataSegment(std::move(segment));
} else {
auto segment = Builder::makeDataSegment(
@@ -3382,6 +3411,7 @@ void SExpressionWasmBuilder::parseData(Element& s) {
name = s[i++]->str();
hasExplicitName = true;
}
+ dataSegmentNames.push_back(name);
if (s[i]->isList()) {
// Optional (memory <memoryidx>)
@@ -3764,6 +3794,7 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) {
Expression* offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
auto segment = std::make_unique<ElementSegment>(table->name, offset);
segment->setName(name, hasExplicitName);
+ elemSegmentNames.push_back(name);
parseElemFinish(s, segment, i, s[i]->isList());
return;
}
@@ -3772,6 +3803,7 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) {
name = s[i++]->str();
hasExplicitName = true;
}
+ elemSegmentNames.push_back(name);
if (s[i]->isStr() && s[i]->str() == DECLARE) {
// We don't store declared segments in the IR
return;
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 1d4e28116..9e22efc0c 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -687,26 +687,27 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
void BinaryInstWriter::visitMemoryInit(MemoryInit* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::MemoryInit);
- o << U32LEB(curr->segment) << int8_t(parent.getMemoryIndex(curr->memory));
+ o << U32LEB(parent.getDataSegmentIndex(curr->segment));
+ o << U32LEB(parent.getMemoryIndex(curr->memory));
}
void BinaryInstWriter::visitDataDrop(DataDrop* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::DataDrop);
- o << U32LEB(curr->segment);
+ o << U32LEB(parent.getDataSegmentIndex(curr->segment));
}
void BinaryInstWriter::visitMemoryCopy(MemoryCopy* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::MemoryCopy);
- o << int8_t(parent.getMemoryIndex(curr->destMemory))
- << int8_t(parent.getMemoryIndex(curr->sourceMemory));
+ o << U32LEB(parent.getMemoryIndex(curr->destMemory));
+ o << U32LEB(parent.getMemoryIndex(curr->sourceMemory));
}
void BinaryInstWriter::visitMemoryFill(MemoryFill* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::MemoryFill);
- o << int8_t(parent.getMemoryIndex(curr->memory));
+ o << U32LEB(parent.getMemoryIndex(curr->memory));
}
void BinaryInstWriter::visitConst(Const* curr) {
@@ -2122,15 +2123,17 @@ void BinaryInstWriter::visitArrayNewSeg(ArrayNewSeg* curr) {
switch (curr->op) {
case NewData:
o << U32LEB(BinaryConsts::ArrayNewData);
+ parent.writeIndexedHeapType(curr->type.getHeapType());
+ o << U32LEB(parent.getDataSegmentIndex(curr->segment));
break;
case NewElem:
o << U32LEB(BinaryConsts::ArrayNewElem);
+ parent.writeIndexedHeapType(curr->type.getHeapType());
+ o << U32LEB(parent.getElementSegmentIndex(curr->segment));
break;
default:
WASM_UNREACHABLE("unexpected op");
}
- parent.writeIndexedHeapType(curr->type.getHeapType());
- o << U32LEB(curr->segment);
}
void BinaryInstWriter::visitArrayNewFixed(ArrayNewFixed* curr) {
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 274e1fd1c..d8dba953f 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1425,9 +1425,9 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
if (!shouldBeTrue(!!memory, curr, "memory.init memory must exist")) {
return;
}
- shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
+ shouldBeTrue(getModule()->getDataSegmentOrNull(curr->segment),
curr,
- "memory.init segment index out of bounds");
+ "memory.init segment should exist");
}
void FunctionValidator::visitDataDrop(DataDrop* curr) {
@@ -1442,9 +1442,9 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) {
"Memory operations require a memory")) {
return;
}
- shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
+ shouldBeTrue(getModule()->getDataSegment(curr->segment),
curr,
- "data.drop segment index out of bounds");
+ "data.drop segment should exist");
}
void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
@@ -2722,16 +2722,16 @@ void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) {
"array.new_{data, elem} size must be an i32");
switch (curr->op) {
case NewData:
- if (!shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
+ if (!shouldBeTrue(getModule()->getDataSegment(curr->segment),
curr,
- "array.new_data segment index out of bounds")) {
+ "array.new_data segment should exist")) {
return;
}
break;
case NewElem:
- if (!shouldBeTrue(curr->segment < getModule()->elementSegments.size(),
+ if (!shouldBeTrue(getModule()->getElementSegment(curr->segment),
curr,
- "array.new_elem segment index out of bounds")) {
+ "array.new_elem segment should exist")) {
return;
}
break;
@@ -2762,7 +2762,7 @@ void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) {
"array.new_data result element type should be numeric");
break;
case NewElem:
- shouldBeSubType(getModule()->elementSegments[curr->segment]->type,
+ shouldBeSubType(getModule()->getElementSegment(curr->segment)->type,
elemType,
curr,
"array.new_elem segment type should be a subtype of the "
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 89e913ab5..567502c93 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -1284,7 +1284,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
using LocalIdxT = Index;
using GlobalIdxT = Name;
using MemoryIdxT = Name;
- using DataIdxT = uint32_t;
+ using DataIdxT = Name;
using MemargT = Memarg;
@@ -1550,20 +1550,18 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return name;
}
- Result<uint32_t> getDataFromIdx(uint32_t idx) {
+ Result<Name> getDataFromIdx(uint32_t idx) {
if (idx >= wasm.dataSegments.size()) {
return in.err("data index out of bounds");
}
- return idx;
+ return wasm.dataSegments[idx]->name;
}
- Result<uint32_t> getDataFromName(Name name) {
- for (uint32_t i = 0; i < wasm.dataSegments.size(); ++i) {
- if (wasm.dataSegments[i]->name == name) {
- return i;
- }
+ Result<Name> getDataFromName(Name name) {
+ if (!wasm.getDataSegmentOrNull(name)) {
+ return in.err("data $" + name.toString() + " does not exist");
}
- return in.err("data $" + name.toString() + " does not exist");
+ return name;
}
Result<TypeUseT> makeTypeUse(Index pos,
@@ -1984,7 +1982,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
op, memarg.offset, memarg.align, lane, *ptr, *vec, *m));
}
- Result<> makeMemoryInit(Index pos, Name* mem, uint32_t data) {
+ Result<> makeMemoryInit(Index pos, Name* mem, Name data) {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
auto size = pop(pos);
@@ -1996,7 +1994,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return push(pos, builder.makeMemoryInit(data, *dest, *offset, *size, *m));
}
- Result<> makeDataDrop(Index pos, uint32_t data) {
+ Result<> makeDataDrop(Index pos, Name data) {
return push(pos, builder.makeDataDrop(data));
}
@@ -2147,7 +2145,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return push(pos, builder.makeArrayNew(type, *size));
}
- Result<> makeArrayNewData(Index pos, HeapType type, uint32_t data) {
+ Result<> makeArrayNewData(Index pos, HeapType type, Name data) {
if (!type.isArray()) {
return in.err(pos, "expected array type annotation");
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 054f442dc..c86788e5a 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -168,6 +168,9 @@ public:
std::string symbolsFile;
};
+ // Map data segment names to indices.
+ std::unordered_map<Name, Index> dataIndices;
+
Wasm2JSBuilder(Flags f, PassOptions options_) : flags(f), options(options_) {
// We don't try to model wasm's trapping precisely - if we did, each load
// and store would need to do a check. Given that, we can just ignore
@@ -191,6 +194,12 @@ public:
// JS
Ref processFunctionBody(Module* m, Function* func, bool standalone);
+ Index getDataIndex(Name segment) {
+ auto it = dataIndices.find(segment);
+ assert(it != dataIndices.end());
+ return it->second;
+ }
+
// Get a temp var.
IString getTemp(Type type, Function* func) {
IString ret;
@@ -333,6 +342,11 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
ElementUtils::iterAllElementFunctionNames(
wasm, [&](Name name) { functionsCallableFromOutside.insert(name); });
+ // Collect passive data segment indices.
+ for (Index i = 0; i < wasm->dataSegments.size(); ++i) {
+ dataIndices[wasm->dataSegments[i]->name] = i;
+ }
+
// Ensure the scratch memory helpers.
// If later on they aren't needed, we'll clean them up.
ABI::wasm2js::ensureHelpers(wasm);
@@ -2178,16 +2192,18 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
}
Ref visitMemoryInit(MemoryInit* curr) {
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_INIT);
- return ValueBuilder::makeCall(ABI::wasm2js::MEMORY_INIT,
- ValueBuilder::makeNum(curr->segment),
- visit(curr->dest, EXPRESSION_RESULT),
- visit(curr->offset, EXPRESSION_RESULT),
- visit(curr->size, EXPRESSION_RESULT));
+ return ValueBuilder::makeCall(
+ ABI::wasm2js::MEMORY_INIT,
+ ValueBuilder::makeNum(parent->getDataIndex(curr->segment)),
+ visit(curr->dest, EXPRESSION_RESULT),
+ visit(curr->offset, EXPRESSION_RESULT),
+ visit(curr->size, EXPRESSION_RESULT));
}
Ref visitDataDrop(DataDrop* curr) {
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::DATA_DROP);
- return ValueBuilder::makeCall(ABI::wasm2js::DATA_DROP,
- ValueBuilder::makeNum(curr->segment));
+ return ValueBuilder::makeCall(
+ ABI::wasm2js::DATA_DROP,
+ ValueBuilder::makeNum(parent->getDataIndex(curr->segment)));
}
Ref visitMemoryCopy(MemoryCopy* curr) {
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_COPY);