summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp225
1 files changed, 146 insertions, 79 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 0f40cfd58..dacb6edbb 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -55,7 +55,7 @@ void WasmBinaryWriter::write() {
writeGlobals();
writeExports();
writeStart();
- writeTableElements();
+ writeElementSegments();
writeDataCount();
writeFunctions();
writeDataSegments();
@@ -552,11 +552,8 @@ void WasmBinaryWriter::writeTableDeclarations() {
finishSection(start);
}
-void WasmBinaryWriter::writeTableElements() {
- size_t elemCount = 0;
- for (auto& table : wasm->tables) {
- elemCount += table->segments.size();
- }
+void WasmBinaryWriter::writeElementSegments() {
+ size_t elemCount = wasm->elementSegments.size();
auto needingElemDecl = TableUtils::getFunctionsNeedingElemDeclare(*wasm);
if (!needingElemDecl.empty()) {
elemCount++;
@@ -565,40 +562,50 @@ void WasmBinaryWriter::writeTableElements() {
return;
}
- BYN_TRACE("== writeTableElements\n");
+ BYN_TRACE("== writeElementSegments\n");
auto start = startSection(BinaryConsts::Section::Element);
o << U32LEB(elemCount);
- for (auto& table : wasm->tables) {
- for (auto& segment : table->segments) {
- Index tableIdx = getTableIndex(table->name);
- // No support for passive element segments yet as they don't belong to a
- // table.
- bool isPassive = false;
- bool isDeclarative = false;
- bool hasTableIndex = tableIdx > 0;
- bool usesExpressions = false;
-
- uint32_t flags =
- (isPassive ? BinaryConsts::IsPassive |
- (isDeclarative ? BinaryConsts::IsDeclarative : 0)
- : (hasTableIndex ? BinaryConsts::HasIndex : 0)) |
- (usesExpressions ? BinaryConsts::UsesExpressions : 0);
-
- o << U32LEB(flags);
+ for (auto& segment : wasm->elementSegments) {
+ Index tableIdx = 0;
+
+ bool isPassive = segment->table.isNull();
+ // TODO(reference-types): add support for writing expressions instead of
+ // function indices.
+ bool usesExpressions = false;
+
+ bool hasTableIndex = false;
+ if (!isPassive) {
+ tableIdx = getTableIndex(segment->table);
+ hasTableIndex = tableIdx > 0;
+ }
+
+ uint32_t flags = 0;
+ if (usesExpressions) {
+ flags |= BinaryConsts::UsesExpressions;
+ }
+ if (isPassive) {
+ flags |= BinaryConsts::IsPassive;
+ } else if (hasTableIndex) {
+ flags |= BinaryConsts::HasIndex;
+ }
+
+ o << U32LEB(flags);
+ if (!isPassive) {
if (hasTableIndex) {
o << U32LEB(tableIdx);
}
- writeExpression(segment.offset);
+ writeExpression(segment->offset);
o << int8_t(BinaryConsts::End);
- if (!usesExpressions && (isPassive || hasTableIndex)) {
- // elemKind funcref
- o << U32LEB(0);
- }
- o << U32LEB(segment.data.size());
- for (auto name : segment.data) {
- o << U32LEB(getFunctionIndex(name));
- }
+ }
+
+ if (!usesExpressions && (isPassive || hasTableIndex)) {
+ // elemKind funcref
+ o << U32LEB(0);
+ }
+ o << U32LEB(segment->data.size());
+ for (auto& name : segment->data) {
+ o << U32LEB(getFunctionIndex(name));
}
}
@@ -765,6 +772,32 @@ void WasmBinaryWriter::writeNames() {
}
}
+ // elem names
+ {
+ std::vector<std::pair<Index, ElementSegment*>> elemsWithNames;
+ Index checked = 0;
+ for (auto& curr : wasm->elementSegments) {
+ if (curr->hasExplicitName) {
+ elemsWithNames.push_back({checked, curr.get()});
+ }
+ checked++;
+ }
+ assert(checked == indexes.elemIndexes.size());
+
+ if (elemsWithNames.size() > 0) {
+ auto substart =
+ startSubsection(BinaryConsts::UserSections::Subsection::NameElem);
+ o << U32LEB(elemsWithNames.size());
+
+ for (auto& indexedElem : elemsWithNames) {
+ o << U32LEB(indexedElem.first);
+ writeEscapedName(indexedElem.second->name.str);
+ }
+
+ finishSubsection(substart);
+ }
+ }
+
// memory names
if (wasm->memory.exists && wasm->memory.hasExplicitName) {
auto substart =
@@ -1337,7 +1370,7 @@ void WasmBinaryBuilder::read() {
readExports();
break;
case BinaryConsts::Section::Element:
- readTableElements();
+ readElementSegments();
break;
case BinaryConsts::Section::Global:
readGlobals();
@@ -1349,7 +1382,7 @@ void WasmBinaryBuilder::read() {
readDataCount();
break;
case BinaryConsts::Section::Table:
- readFunctionTableDeclaration();
+ readTableDeclarations();
break;
case BinaryConsts::Section::Event:
readEvents();
@@ -2549,6 +2582,9 @@ void WasmBinaryBuilder::processNames() {
for (auto& table : tables) {
wasm.addTable(std::move(table));
}
+ for (auto& segment : elementSegments) {
+ wasm.addElementSegment(std::move(segment));
+ }
// now that we have names, apply things
@@ -2607,14 +2643,11 @@ void WasmBinaryBuilder::processNames() {
}
}
- for (auto& table_pair : functionTable) {
- for (auto& pair : table_pair.second) {
- auto i = pair.first;
- auto& indices = pair.second;
- for (auto j : indices) {
- wasm.tables[table_pair.first]->segments[i].data.push_back(
- getFunctionName(j));
- }
+ for (auto& pair : functionTable) {
+ auto i = pair.first;
+ auto& indices = pair.second;
+ for (auto j : indices) {
+ wasm.elementSegments[i]->data.push_back(getFunctionName(j));
}
}
@@ -2670,8 +2703,8 @@ void WasmBinaryBuilder::readDataSegments() {
}
}
-void WasmBinaryBuilder::readFunctionTableDeclaration() {
- BYN_TRACE("== readFunctionTableDeclaration\n");
+void WasmBinaryBuilder::readTableDeclarations() {
+ BYN_TRACE("== readTableDeclarations\n");
auto numTables = getU32LEB();
for (size_t i = 0; i < numTables; i++) {
@@ -2695,8 +2728,8 @@ void WasmBinaryBuilder::readFunctionTableDeclaration() {
}
}
-void WasmBinaryBuilder::readTableElements() {
- BYN_TRACE("== readTableElements\n");
+void WasmBinaryBuilder::readElementSegments() {
+ BYN_TRACE("== readElementSegments\n");
auto numSegments = getU32LEB();
if (numSegments >= Table::kMaxSize) {
throwError("Too many segments");
@@ -2704,55 +2737,63 @@ void WasmBinaryBuilder::readTableElements() {
for (size_t i = 0; i < numSegments; i++) {
auto flags = getU32LEB();
bool isPassive = (flags & BinaryConsts::IsPassive) != 0;
- bool hasTableIdx = (flags & BinaryConsts::HasIndex) != 0;
+ bool hasTableIdx = !isPassive && ((flags & BinaryConsts::HasIndex) != 0);
+ bool isDeclarative =
+ isPassive && ((flags & BinaryConsts::IsDeclarative) != 0);
bool usesExpressions = (flags & BinaryConsts::UsesExpressions) != 0;
- if (isPassive) {
- bool isDeclarative = (flags & BinaryConsts::IsDeclarative) != 0;
- if (isDeclarative) {
- // "elem declare" is needed in wasm text and binary, but not in Binaryen
- // IR; read and ignore the contents.
- auto type = getU32LEB();
- WASM_UNUSED(type);
- auto num = getU32LEB();
- for (Index i = 0; i < num; i++) {
- getU32LEB();
- }
- continue;
+ if (isDeclarative) {
+ // Declared segments are needed in wasm text and binary, but not in
+ // Binaryen IR; skip over the segment
+ auto type = getU32LEB();
+ WASM_UNUSED(type);
+ auto num = getU32LEB();
+ for (Index i = 0; i < num; i++) {
+ getU32LEB();
}
-
- throwError("Only active elem segments are supported.");
+ continue;
}
if (usesExpressions) {
throwError("Only elem segments with function indexes are supported.");
}
- Index tableIdx = 0;
- if (hasTableIdx) {
- tableIdx = getU32LEB();
- }
+ if (!isPassive) {
+ Index tableIdx = 0;
+ if (hasTableIdx) {
+ tableIdx = getU32LEB();
+ }
- auto numTableImports = tableImports.size();
- if (tableIdx < numTableImports) {
- auto table = tableImports[tableIdx];
- table->segments.emplace_back(readExpression());
- } else if (tableIdx - numTableImports < tables.size()) {
- auto table = tables[tableIdx - numTableImports].get();
- table->segments.emplace_back(readExpression());
+ auto makeActiveElem = [&](Table* table) {
+ auto segment =
+ std::make_unique<ElementSegment>(table->name, readExpression());
+ segment->setName(Name::fromInt(i), false);
+ elementSegments.push_back(std::move(segment));
+ };
+
+ auto numTableImports = tableImports.size();
+ if (tableIdx < numTableImports) {
+ makeActiveElem(tableImports[tableIdx]);
+ } else if (tableIdx - numTableImports < tables.size()) {
+ makeActiveElem(tables[tableIdx - numTableImports].get());
+ } else {
+ throwError("Table index out of range.");
+ }
} else {
- throwError("Table index out of range.");
+ auto segment = std::make_unique<ElementSegment>();
+ segment->setName(Name::fromInt(i), false);
+ elementSegments.push_back(std::move(segment));
}
- if (hasTableIdx) {
+ if (isPassive || hasTableIdx) {
auto elemKind = getU32LEB();
if (elemKind != 0x0) {
throwError("Only funcref elem kinds are valid.");
}
}
- size_t segmentIndex = functionTable[tableIdx].size();
- auto& indexSegment = functionTable[tableIdx][segmentIndex];
+ size_t segmentIndex = functionTable.size();
+ auto& indexSegment = functionTable[segmentIndex];
auto size = getU32LEB();
for (Index j = 0; j < size; j++) {
indexSegment.push_back(getU32LEB());
@@ -2921,10 +2962,19 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) {
auto rawName = getInlineString();
auto name = processor.process(rawName);
auto numTableImports = tableImports.size();
+ auto setTableName = [&](Table* table) {
+ for (auto& segment : elementSegments) {
+ if (segment->table == table->name) {
+ segment->table = name;
+ }
+ }
+ table->setExplicitName(name);
+ };
+
if (index < numTableImports) {
- tableImports[index]->setExplicitName(name);
+ setTableName(tableImports[index]);
} else if (index - numTableImports < tables.size()) {
- tables[index - numTableImports]->setExplicitName(name);
+ setTableName(tables[index - numTableImports].get());
} else {
std::cerr << "warning: table index out of bounds in name section, "
"table subsection: "
@@ -2932,6 +2982,23 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) {
<< std::to_string(index) << std::endl;
}
}
+ } else if (nameType == BinaryConsts::UserSections::Subsection::NameElem) {
+ auto num = getU32LEB();
+ NameProcessor processor;
+ for (size_t i = 0; i < num; i++) {
+ auto index = getU32LEB();
+ auto rawName = getInlineString();
+ auto name = processor.process(rawName);
+
+ if (index < elementSegments.size()) {
+ elementSegments[index]->setExplicitName(name);
+ } else {
+ std::cerr << "warning: elem index out of bounds in name section, "
+ "elem subsection: "
+ << std::string(rawName.str) << " at index "
+ << std::to_string(index) << std::endl;
+ }
+ }
} else if (nameType == BinaryConsts::UserSections::Subsection::NameMemory) {
auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {