diff options
author | Thomas Lively <tlively@google.com> | 2024-11-13 14:29:36 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-13 11:29:36 -0800 |
commit | 24c81824c1d80c398c6adb27decc28048c5e8029 (patch) | |
tree | 2a0851a5311a18ee0a358867b4a365d86bf42019 /src | |
parent | 24b5bdfd1bf550dae38a7a990379b315d9f11bae (diff) | |
download | binaryen-24c81824c1d80c398c6adb27decc28048c5e8029.tar.gz binaryen-24c81824c1d80c398c6adb27decc28048c5e8029.tar.bz2 binaryen-24c81824c1d80c398c6adb27decc28048c5e8029.zip |
Read the names section first (#7074)
Rather than back-patching names when we get to the names section in the
binary reader, skip ahead to read the names section before anything else
so we can use the final names right away. This is a prerequisite for
using IRBuilder in the binary reader.
The only functional change is that we now allow empty local names. Empty
names are perfectly valid.
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-binary.h | 46 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 651 |
2 files changed, 342 insertions, 355 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 82f487085..67c1dec96 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1547,44 +1547,31 @@ public: Name getNextLabel(); - // We read functions and globals before we know their names, so we need to - // backpatch the names later + // We read the names section first so we know in advance what names various + // elements should have. Store the information for use when building + // expressions. + std::unordered_map<Index, Name> functionNames; + std::unordered_map<Index, std::unordered_map<Index, Name>> localNames; + std::unordered_map<Index, Name> typeNames; + std::unordered_map<Index, std::unordered_map<Index, Name>> fieldNames; + std::unordered_map<Index, Name> tableNames; + std::unordered_map<Index, Name> memoryNames; + std::unordered_map<Index, Name> globalNames; + std::unordered_map<Index, Name> tagNames; + std::unordered_map<Index, Name> dataNames; + std::unordered_map<Index, Name> elemNames; - // at index i we have all refs to the function i - std::map<Index, std::vector<Name*>> functionRefs; Function* currFunction = nullptr; // before we see a function (like global init expressions), there is no end of // function to check Index endOfFunction = -1; - // at index i we have all references to the table i - std::map<Index, std::vector<Name*>> tableRefs; - - std::map<Index, Name> elemTables; - - // at index i we have all references to the memory i - std::map<Index, std::vector<wasm::Name*>> memoryRefs; - - // at index i we have all refs to the global i - std::map<Index, std::vector<Name*>> globalRefs; - - // 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); void readFunctions(); void readVars(); - std::map<Export*, Index> exportIndices; - std::vector<std::unique_ptr<Export>> exportOrder; void readExports(); // The strings in the strings section (which are referred to by StringConst). @@ -1647,12 +1634,13 @@ public: Expression* popTuple(size_t numElems); Expression* popTypedExpression(Type type); - void validateBinary(); // validations that cannot be performed on the Module - void processNames(); + // validations that cannot be performed on the Module + void validateBinary(); size_t dataCount = 0; bool hasDataCount = false; + void createDataSegments(Index count); void readDataSegments(); void readDataSegmentCount(); @@ -1662,7 +1650,7 @@ public: void readTags(); static Name escape(Name name); - void readNames(size_t); + void findAndReadNames(); void readFeatures(size_t); void readDylink(size_t); void readDylink0(size_t); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 7e1daf0b1..57a01bb1c 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1780,10 +1780,16 @@ void WasmBinaryReader::read() { } } + // Skip ahead and read the name section so we know what names to use when we + // construct module elements. + if (debugInfo) { + findAndReadNames(); + } + readHeader(); readSourceMapHeader(); - // read sections until the end + // Read sections until the end while (more()) { uint8_t sectionCode = getInt8(); uint32_t payloadLen = getU32LEB(); @@ -1793,7 +1799,7 @@ void WasmBinaryReader::read() { auto oldPos = pos; - // note the section in the list of seen sections, as almost no sections can + // Note the section in the list of seen sections, as almost no sections can // appear more than once, and verify those that shouldn't do not. if (sectionCode != BinaryConsts::Section::Custom && !seenSections.insert(sectionCode).second) { @@ -1870,8 +1876,26 @@ void WasmBinaryReader::read() { } } + // Set local names for imported and declared functions. + for (auto& [index, locals] : localNames) { + if (index >= wasm.functions.size()) { + std::cerr << "warning: function index out of bounds in name section: " + "locals at index " + << index << '\n'; + continue; + } + for (auto& [local, name] : locals) { + if (local >= wasm.functions[index]->getNumLocals()) { + std::cerr << "warning: local index out of bounds in name section: " + << name << " at index " << local << " in function " << index + << '\n'; + continue; + } + wasm.functions[index]->setLocalName(local, name); + } + } + validateBinary(); - processNames(); } void WasmBinaryReader::readCustomSection(size_t payloadLen) { @@ -1883,11 +1907,8 @@ void WasmBinaryReader::readCustomSection(size_t payloadLen) { } payloadLen -= read; if (sectionName.equals(BinaryConsts::CustomSections::Name)) { - if (debugInfo) { - readNames(payloadLen); - } else { - pos += payloadLen; - } + // We already read the name section before anything else. + pos += payloadLen; } else if (sectionName.equals(BinaryConsts::CustomSections::TargetFeatures)) { readFeatures(payloadLen); } else if (sectionName.equals(BinaryConsts::CustomSections::Dylink)) { @@ -2233,16 +2254,47 @@ void WasmBinaryReader::readHeader() { } } -void WasmBinaryReader::readStart() { startIndex = getU32LEB(); } +void WasmBinaryReader::readStart() { + startIndex = getU32LEB(); + wasm.start = getFunctionName(startIndex); +} static Name makeName(std::string prefix, size_t counter) { return Name(prefix + std::to_string(counter)); } +// Look up a name from the names section or use a validated version of the +// provided name. Return the name and whether it is explicit in the input. +static std::pair<Name, bool> +getOrMakeName(const std::unordered_map<Index, Name>& nameMap, + Index i, + Name name, + std::unordered_set<Name>& usedNames) { + if (auto it = nameMap.find(i); it != nameMap.end()) { + return {it->second, true}; + } else { + auto valid = Names::getValidNameGivenExisting(name, usedNames); + usedNames.insert(valid); + return {valid, false}; + } +} + void WasmBinaryReader::readMemories() { auto num = getU32LEB(); + auto numImports = wasm.memories.size(); + std::unordered_set<Name> usedNames; + for (auto& [index, name] : memoryNames) { + if (index >= num + numImports) { + std::cerr << "warning: memory index out of bounds in name section: " + << name << " at index " << index << '\n'; + } + usedNames.insert(name); + } for (size_t i = 0; i < num; i++) { - auto memory = Builder::makeMemory(makeName("", i)); + auto [name, isExplicit] = + getOrMakeName(memoryNames, numImports + i, makeName("", i), usedNames); + auto memory = Builder::makeMemory(name); + memory->hasExplicitName = isExplicit; getResizableLimits(memory->initial, memory->max, memory->shared, @@ -2423,6 +2475,39 @@ void WasmBinaryReader::readTypes() { for (Index i = 0; i < types.size(); ++i) { wasm.typeIndices.insert({types[i], i}); } + + // Assign names from the names section. + for (auto& [index, name] : typeNames) { + if (index >= types.size()) { + std::cerr << "warning: type index out of bounds in name section: " << name + << " at index " << index << '\n'; + continue; + } + wasm.typeNames[types[index]].name = name; + } + for (auto& [index, fields] : fieldNames) { + if (index >= types.size()) { + std::cerr + << "warning: type index out of bounds in name section: fields at index " + << index << '\n'; + continue; + } + if (!types[index].isStruct()) { + std::cerr << "warning: field names applied to non-struct type at index " + << index << '\n'; + continue; + } + auto& names = wasm.typeNames[types[index]].fieldNames; + for (auto& [field, name] : fields) { + if (field >= types[index].getStruct().fields.size()) { + std::cerr << "warning: field index out of bounds in name section: " + << name << " at index " << field << " in type " << index + << '\n'; + continue; + } + names[field] = name; + } + } } Name WasmBinaryReader::getFunctionName(Index index) { @@ -2513,11 +2598,8 @@ void WasmBinaryReader::getResizableLimits(Address& initial, void WasmBinaryReader::readImports() { size_t num = getU32LEB(); Builder builder(wasm); - size_t tableCounter = 0; - size_t memoryCounter = 0; - size_t functionCounter = 0; - size_t globalCounter = 0; - size_t tagCounter = 0; + std::unordered_set<Name> usedFunctionNames, usedTableNames, usedMemoryNames, + usedGlobalNames, usedTagNames; for (size_t i = 0; i < num; i++) { auto module = getInlineString(); auto base = getInlineString(); @@ -2527,7 +2609,11 @@ void WasmBinaryReader::readImports() { // could occur later due to the names section. switch (kind) { case ExternalKind::Function: { - Name name = makeName("fimport$", functionCounter++); + auto [name, isExplicit] = + getOrMakeName(functionNames, + wasm.functions.size(), + makeName("fimport$", wasm.functions.size()), + usedFunctionNames); auto index = getU32LEB(); functionTypes.push_back(getTypeByIndex(index)); auto type = getTypeByIndex(index); @@ -2537,13 +2623,20 @@ void WasmBinaryReader::readImports() { "'s type must be a signature. Given: " + type.toString()); } auto curr = builder.makeFunction(name, type, {}); + curr->hasExplicitName = isExplicit; curr->module = module; curr->base = base; wasm.addFunction(std::move(curr)); break; } case ExternalKind::Table: { - auto table = builder.makeTable(makeName("timport$", tableCounter++)); + auto [name, isExplicit] = + getOrMakeName(tableNames, + wasm.tables.size(), + makeName("timport$", wasm.tables.size()), + usedTableNames); + auto table = builder.makeTable(name); + table->hasExplicitName = isExplicit; table->module = module; table->base = base; table->type = getType(); @@ -2562,7 +2655,13 @@ void WasmBinaryReader::readImports() { break; } case ExternalKind::Memory: { - auto memory = builder.makeMemory(makeName("mimport$", memoryCounter++)); + auto [name, isExplicit] = + getOrMakeName(memoryNames, + wasm.memories.size(), + makeName("mimport$", wasm.memories.size()), + usedMemoryNames); + auto memory = builder.makeMemory(name); + memory->hasExplicitName = isExplicit; memory->module = module; memory->base = base; getResizableLimits(memory->initial, @@ -2574,26 +2673,37 @@ void WasmBinaryReader::readImports() { break; } case ExternalKind::Global: { + auto [name, isExplicit] = + getOrMakeName(globalNames, + wasm.globals.size(), + makeName("gimport$", wasm.globals.size()), + usedGlobalNames); auto type = getConcreteType(); auto mutable_ = getU32LEB(); if (mutable_ & ~1) { throwError("Global mutability must be 0 or 1"); } auto curr = - builder.makeGlobal(makeName("gimport$", globalCounter++), + builder.makeGlobal(name, type, nullptr, mutable_ ? Builder::Mutable : Builder::Immutable); + curr->hasExplicitName = isExplicit; curr->module = module; curr->base = base; wasm.addGlobal(std::move(curr)); break; } case ExternalKind::Tag: { - Name name = makeName("eimport$", tagCounter++); + auto [name, isExplicit] = + getOrMakeName(tagNames, + wasm.tags.size(), + makeName("eimport$", wasm.tags.size()), + usedTagNames); getInt8(); // Reserved 'attribute' field auto index = getU32LEB(); auto curr = builder.makeTag(name, getSignatureByTypeIndex(index)); + curr->hasExplicitName = isExplicit; curr->module = module; curr->base = base; wasm.addTag(std::move(curr)); @@ -2620,14 +2730,26 @@ void WasmBinaryReader::requireFunctionContext(const char* error) { void WasmBinaryReader::readFunctionSignatures() { size_t num = getU32LEB(); + auto numImports = wasm.functions.size(); + std::unordered_set<Name> usedNames; + for (auto& [index, name] : functionNames) { + if (index >= num + numImports) { + std::cerr << "warning: function index out of bounds in name section: " + << name << " at index " << index << '\n'; + } + usedNames.insert(name); + } for (size_t i = 0; i < num; i++) { + auto [name, isExplicit] = + getOrMakeName(functionNames, numImports + i, makeName("", i), usedNames); auto index = getU32LEB(); HeapType type = getTypeByIndex(index); functionTypes.push_back(type); // Check that the type is a signature. getSignatureByTypeIndex(index); - wasm.addFunction( - Builder(wasm).makeFunction(makeName("", i), type, {}, nullptr)); + auto func = Builder(wasm).makeFunction(name, type, {}, nullptr); + func->hasExplicitName = isExplicit; + wasm.addFunction(std::move(func)); } } @@ -2779,9 +2901,28 @@ void WasmBinaryReader::readExports() { throwError("duplicate export name"); } curr->kind = (ExternalKind)getU32LEB(); + auto* ex = wasm.addExport(std::move(curr)); auto index = getU32LEB(); - exportIndices[curr.get()] = index; - exportOrder.push_back(std::move(curr)); + switch (ex->kind) { + case ExternalKind::Function: + ex->value = getFunctionName(index); + continue; + case ExternalKind::Table: + ex->value = getTableName(index); + continue; + case ExternalKind::Memory: + ex->value = getMemoryName(index); + continue; + case ExternalKind::Global: + ex->value = getGlobalName(index); + continue; + case ExternalKind::Tag: + ex->value = getTagName(index); + continue; + case ExternalKind::Invalid: + break; + } + throwError("invalid export kind"); } } @@ -3052,18 +3193,28 @@ void WasmBinaryReader::readStrings() { void WasmBinaryReader::readGlobals() { size_t num = getU32LEB(); + auto numImports = wasm.globals.size(); + std::unordered_set<Name> usedNames; + for (auto& [index, name] : globalNames) { + if (index >= num + numImports) { + std::cerr << "warning: global index out of bounds in name section: " + << name << " at index " << index << '\n'; + } + usedNames.insert(name); + } for (size_t i = 0; i < num; i++) { + auto [name, isExplicit] = getOrMakeName( + globalNames, numImports + i, makeName("global$", i), usedNames); auto type = getConcreteType(); auto mutable_ = getU32LEB(); if (mutable_ & ~1) { throwError("Global mutability must be 0 or 1"); } auto* init = readExpression(); - wasm.addGlobal( - Builder::makeGlobal(makeName("global$", i), - type, - init, - mutable_ ? Builder::Mutable : Builder::Immutable)); + auto global = Builder::makeGlobal( + name, type, init, mutable_ ? Builder::Mutable : Builder::Immutable); + global->hasExplicitName = isExplicit; + wasm.addGlobal(std::move(global)); } } @@ -3255,77 +3406,22 @@ void WasmBinaryReader::validateBinary() { } } -void WasmBinaryReader::processNames() { - // now that we have names, apply things - - if (startIndex != static_cast<Index>(-1)) { - wasm.start = getFunctionName(startIndex); - } - - for (auto& curr : exportOrder) { - auto index = exportIndices[curr.get()]; - switch (curr->kind) { - case ExternalKind::Function: { - curr->value = getFunctionName(index); - break; - } - case ExternalKind::Table: - curr->value = getTableName(index); - break; - case ExternalKind::Memory: - curr->value = getMemoryName(index); - break; - case ExternalKind::Global: - curr->value = getGlobalName(index); - break; - case ExternalKind::Tag: - curr->value = getTagName(index); - break; - default: - throwError("bad export kind"); - } - wasm.addExport(std::move(curr)); - } - - for (auto& [index, refs] : functionRefs) { - for (auto* ref : refs) { - *ref = getFunctionName(index); - } - } - for (auto& [index, refs] : tableRefs) { - for (auto* ref : refs) { - *ref = getTableName(index); - } - } - for (auto& [index, refs] : memoryRefs) { - for (auto ref : refs) { - *ref = getMemoryName(index); - } - } - for (auto& [index, refs] : globalRefs) { - for (auto* ref : refs) { - *ref = getGlobalName(index); - } - } - for (auto& [index, refs] : tagRefs) { - for (auto* ref : refs) { - *ref = getTagName(index); - } - } - for (auto& [index, refs] : dataRefs) { - for (auto* ref : refs) { - *ref = getDataName(index); +void WasmBinaryReader::createDataSegments(Index count) { + std::unordered_set<Name> usedNames; + for (auto& [index, name] : dataNames) { + if (index >= count) { + std::cerr << "warning: data index out of bounds in name section: " << name + << " at index " << index << '\n'; } + usedNames.insert(name); } - for (auto& [index, refs] : elemRefs) { - for (auto* ref : refs) { - *ref = getElemName(index); - } + for (size_t i = 0; i < count; ++i) { + auto [name, isExplicit] = + getOrMakeName(dataNames, i, makeName("", i), usedNames); + auto curr = Builder::makeDataSegment(name); + curr->hasExplicitName = isExplicit; + wasm.addDataSegment(std::move(curr)); } - - // Everything now has its proper name. - - wasm.updateMaps(); } void WasmBinaryReader::readDataSegmentCount() { @@ -3333,11 +3429,7 @@ void WasmBinaryReader::readDataSegmentCount() { dataCount = getU32LEB(); // Eagerly create the data segments so they are available during parsing of // the code section. - for (size_t i = 0; i < dataCount; ++i) { - auto curr = Builder::makeDataSegment(); - curr->setName(Name::fromInt(i), false); - wasm.addDataSegment(std::move(curr)); - } + createDataSegments(dataCount); } void WasmBinaryReader::readDataSegments() { @@ -3348,11 +3440,7 @@ void WasmBinaryReader::readDataSegments() { } } else { // We haven't already created the data segments, so create them now. - for (size_t i = 0; i < num; ++i) { - auto curr = Builder::makeDataSegment(); - curr->setName(Name::fromInt(i), false); - wasm.addDataSegment(std::move(curr)); - } + createDataSegments(num); } assert(wasm.dataSegments.size() == num); for (size_t i = 0; i < num; i++) { @@ -3371,7 +3459,7 @@ void WasmBinaryReader::readDataSegments() { if (flags & BinaryConsts::HasIndex) { memIdx = getU32LEB(); } - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->offset = readExpression(); } auto size = getU32LEB(); @@ -3381,14 +3469,25 @@ void WasmBinaryReader::readDataSegments() { } void WasmBinaryReader::readTableDeclarations() { - auto numTables = getU32LEB(); - - for (size_t i = 0; i < numTables; i++) { + auto num = getU32LEB(); + auto numImports = wasm.tables.size(); + std::unordered_set<Name> usedNames; + for (auto& [index, name] : tableNames) { + if (index >= num + numImports) { + std::cerr << "warning: table index out of bounds in name section: " + << name << " at index " << index << '\n'; + } + usedNames.insert(name); + } + for (size_t i = 0; i < num; i++) { + auto [name, isExplicit] = + getOrMakeName(tableNames, numImports + i, makeName("", i), usedNames); auto elemType = getType(); if (!elemType.isRef()) { throwError("Table type must be a reference type"); } - auto table = Builder::makeTable(makeName("", i), elemType); + auto table = Builder::makeTable(name, elemType); + table->hasExplicitName = isExplicit; bool is_shared; getResizableLimits(table->initial, table->max, @@ -3403,11 +3502,21 @@ void WasmBinaryReader::readTableDeclarations() { } void WasmBinaryReader::readElementSegments() { - auto numSegments = getU32LEB(); - if (numSegments >= Table::kMaxSize) { + auto num = getU32LEB(); + if (num >= Table::kMaxSize) { throwError("Too many segments"); } - for (size_t i = 0; i < numSegments; i++) { + std::unordered_set<Name> usedNames; + for (auto& [index, name] : elemNames) { + if (index >= num) { + std::cerr << "warning: elem index out of bounds in name section: " << name + << " at index " << index << '\n'; + } + usedNames.insert(name); + } + for (size_t i = 0; i < num; i++) { + auto [name, isExplicit] = + getOrMakeName(elemNames, i, makeName("", i), usedNames); auto flags = getU32LEB(); bool isPassive = (flags & BinaryConsts::IsPassive) != 0; bool hasTableIdx = !isPassive && ((flags & BinaryConsts::HasIndex) != 0); @@ -3431,7 +3540,7 @@ void WasmBinaryReader::readElementSegments() { } auto segment = std::make_unique<ElementSegment>(); - segment->setName(Name::fromInt(i), false); + segment->setName(name, isExplicit); if (!isPassive) { Index tableIdx = 0; @@ -3468,9 +3577,7 @@ void WasmBinaryReader::readElementSegments() { for (Index j = 0; j < size; j++) { Index index = getU32LEB(); auto sig = getTypeByFunctionIndex(index); - // Use a placeholder name for now - auto* refFunc = Builder(wasm).makeRefFunc(Name::fromInt(index), sig); - functionRefs[index].push_back(&refFunc->func); + auto* refFunc = Builder(wasm).makeRefFunc(getFunctionName(index), sig); segmentData.push_back(refFunc); } } @@ -3480,12 +3587,24 @@ void WasmBinaryReader::readElementSegments() { } void WasmBinaryReader::readTags() { - size_t numTags = getU32LEB(); - for (size_t i = 0; i < numTags; i++) { + size_t num = getU32LEB(); + auto numImports = wasm.tags.size(); + std::unordered_set<Name> usedNames; + for (auto& [index, name] : tagNames) { + if (index >= num + numImports) { + std::cerr << "warning: tag index out of bounds in name section: " << name + << " at index " << index << '\n'; + } + usedNames.insert(name); + } + for (size_t i = 0; i < num; i++) { getInt8(); // Reserved 'attribute' field + auto [name, isExplicit] = + getOrMakeName(tagNames, numImports + i, makeName("tag$", i), usedNames); auto typeIndex = getU32LEB(); - wasm.addTag(Builder::makeTag(makeName("tag$", i), - getSignatureByTypeIndex(typeIndex))); + auto tag = Builder::makeTag(name, getSignatureByTypeIndex(typeIndex)); + tag->hasExplicitName = isExplicit; + wasm.addTag(std::move(tag)); } } @@ -3531,19 +3650,6 @@ namespace { // Performs necessary processing of names from the name section before using // them. Specifically it escapes and deduplicates them. -// -// Deduplication is not trivial, since we can't only consider things in the name -// section itself. The issue is that we have already given everything a -// temporary name. Consider if we gave these two temp names: -// -// $foo$0 -// $foo$1 -// -// and imagine that the first appears in the name section, where it is given the -// the name $foo$1, and the second does not appear in the name section. In that -// case, we'd rename the second to the same name as the first. If we left things -// there that would be invalid, so we need to pick another temp name for the -// second item to resolve that. class NameProcessor { public: // Returns a unique, escaped name. Notes that name for the items to follow to @@ -3552,20 +3658,6 @@ public: return deduplicate(WasmBinaryReader::escape(name)); } - // After processing the names section entries, which set explicit names, we - // also handle the remaining items here, which handles the corner case - // described above. - // - // TODO: This handles vectors of Named objects; we should also do this for - // local names and type names etc. - template<typename T> void deduplicateUnexplicitlyNamed(std::vector<T>& vec) { - for (auto& x : vec) { - if (!x->hasExplicitName) { - x->name = deduplicate(x->name); - } - } - } - private: std::unordered_set<Name> usedNames; @@ -3578,8 +3670,33 @@ private: } // anonymous namespace -void WasmBinaryReader::readNames(size_t payloadLen) { - auto sectionPos = pos; +void WasmBinaryReader::findAndReadNames() { + // Find the names section. Skip the magic and version. + assert(pos == 0); + getInt32(); + getInt32(); + Index payloadLen, sectionPos; + bool found = false; + while (more()) { + uint8_t sectionCode = getInt8(); + payloadLen = getU32LEB(); + sectionPos = pos; + if (sectionCode == BinaryConsts::Section::Custom) { + auto sectionName = getInlineString(); + if (sectionName.equals(BinaryConsts::CustomSections::Name)) { + found = true; + break; + } + } + pos = sectionPos + payloadLen; + } + if (!found) { + // No names section to read. + pos = 0; + return; + } + + // Read the names. uint32_t lastType = 0; while (pos < sectionPos + payloadLen) { auto nameType = getU32LEB(); @@ -3600,51 +3717,19 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < wasm.functions.size()) { - wasm.functions[index]->setExplicitName(name); - } else { - std::cerr << "warning: function index out of bounds in name section, " - "function subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + functionNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.functions); } else if (nameType == Subsection::NameLocal) { auto numFuncs = getU32LEB(); for (size_t i = 0; i < numFuncs; i++) { auto funcIndex = getU32LEB(); - Function* func = nullptr; - if (funcIndex < wasm.functions.size()) { - func = wasm.functions[funcIndex].get(); - } else { - std::cerr - << "warning: function index out of bounds in name section, local " - "subsection: " - << std::to_string(funcIndex) << std::endl; - } auto numLocals = getU32LEB(); NameProcessor processor; for (size_t j = 0; j < numLocals; j++) { auto localIndex = getU32LEB(); - auto rawLocalName = getInlineString(); - if (!func) { - continue; // read and discard in case of prior error - } - auto localName = processor.process(rawLocalName); - if (localName.size() == 0) { - std::cerr << "warning: empty local name at index " - << std::to_string(localIndex) << " in function " - << std::string(func->name.str) << std::endl; - } else if (localIndex < func->getNumLocals()) { - func->localNames[localIndex] = localName; - } else { - std::cerr << "warning: local index out of bounds in name " - "section, local subsection: " - << std::string(rawLocalName.str) << " at index " - << std::to_string(localIndex) << " in function " - << std::string(func->name.str) << std::endl; - } + auto rawName = getInlineString(); + auto name = processor.process(rawName); + localNames[funcIndex][localIndex] = name; } } } else if (nameType == Subsection::NameType) { @@ -3654,14 +3739,7 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < types.size()) { - wasm.typeNames[types[index]].name = name; - } else { - std::cerr << "warning: type index out of bounds in name section, " - "type subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + typeNames[index] = name; } } else if (nameType == Subsection::NameTable) { auto num = getU32LEB(); @@ -3670,23 +3748,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - - if (index < wasm.tables.size()) { - auto* table = wasm.tables[index].get(); - for (auto& segment : wasm.elementSegments) { - if (segment->table == table->name) { - segment->table = name; - } - } - table->setExplicitName(name); - } else { - std::cerr << "warning: table index out of bounds in name section, " - "table subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + tableNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.tables); } else if (nameType == Subsection::NameElem) { auto num = getU32LEB(); NameProcessor processor; @@ -3694,17 +3757,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - - if (index < wasm.elementSegments.size()) { - wasm.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; - } + elemNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.elementSegments); } else if (nameType == Subsection::NameMemory) { auto num = getU32LEB(); NameProcessor processor; @@ -3712,16 +3766,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < wasm.memories.size()) { - wasm.memories[index]->setExplicitName(name); - } else { - std::cerr << "warning: memory index out of bounds in name section, " - "memory subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + memoryNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.memories); } else if (nameType == Subsection::NameData) { auto num = getU32LEB(); NameProcessor processor; @@ -3729,16 +3775,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < wasm.dataSegments.size()) { - wasm.dataSegments[index]->setExplicitName(name); - } else { - 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; - } + dataNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.dataSegments); } else if (nameType == Subsection::NameGlobal) { auto num = getU32LEB(); NameProcessor processor; @@ -3746,16 +3784,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < wasm.globals.size()) { - wasm.globals[index]->setExplicitName(name); - } else { - std::cerr << "warning: global index out of bounds in name section, " - "global subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + globalNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.globals); } else if (nameType == Subsection::NameField) { auto numTypes = getU32LEB(); for (size_t i = 0; i < numTypes; i++) { @@ -3771,9 +3801,7 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto fieldIndex = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (validType) { - wasm.typeNames[types[typeIndex]].fieldNames[fieldIndex] = name; - } + fieldNames[typeIndex][fieldIndex] = name; } } } else if (nameType == Subsection::NameTag) { @@ -3783,16 +3811,8 @@ void WasmBinaryReader::readNames(size_t payloadLen) { auto index = getU32LEB(); auto rawName = getInlineString(); auto name = processor.process(rawName); - if (index < wasm.tags.size()) { - wasm.tags[index]->setExplicitName(name); - } else { - std::cerr << "warning: tag index out of bounds in name section, " - "tag subsection: " - << std::string(rawName.str) << " at index " - << std::to_string(index) << std::endl; - } + tagNames[index] = name; } - processor.deduplicateUnexplicitlyNamed(wasm.tags); } else { std::cerr << "warning: unknown name subsection with id " << std::to_string(nameType) << " at " << pos << std::endl; @@ -3805,6 +3825,9 @@ void WasmBinaryReader::readNames(size_t payloadLen) { if (pos != sectionPos + payloadLen) { throwError("bad names section position change"); } + + // Reset the position; we were just reading ahead. + pos = 0; } void WasmBinaryReader::readFeatures(size_t payloadLen) { @@ -4614,8 +4637,7 @@ void WasmBinaryReader::visitCall(Call* curr) { curr->operands[num - i - 1] = popNonVoidExpression(); } curr->type = sig.results; - // We don't know function names yet. - functionRefs[index].push_back(&curr->target); + curr->target = getFunctionName(index); curr->finalize(); } @@ -4630,8 +4652,7 @@ void WasmBinaryReader::visitCallIndirect(CallIndirect* curr) { for (size_t i = 0; i < num; i++) { curr->operands[num - i - 1] = popNonVoidExpression(); } - // Defer setting the table name for later, when we know it. - tableRefs[tableIdx].push_back(&curr->table); + curr->table = getTableName(tableIdx); curr->finalize(); } @@ -4668,7 +4689,6 @@ void WasmBinaryReader::visitGlobalGet(GlobalGet* curr) { auto* global = wasm.globals[index].get(); curr->name = global->name; curr->type = global->type; - globalRefs[index].push_back(&curr->name); // we don't know the final name yet } void WasmBinaryReader::visitGlobalSet(GlobalSet* curr) { @@ -4678,7 +4698,6 @@ void WasmBinaryReader::visitGlobalSet(GlobalSet* curr) { } curr->name = wasm.globals[index]->name; curr->value = popNonVoidExpression(); - globalRefs[index].push_back(&curr->name); // we don't know the final name yet curr->finalize(); } @@ -4853,7 +4872,7 @@ bool WasmBinaryReader::maybeVisitLoad( curr->isAtomic = prefix == BinaryConsts::AtomicPrefix; Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->ptr = popNonVoidExpression(); curr->finalize(); out = curr; @@ -4971,7 +4990,7 @@ bool WasmBinaryReader::maybeVisitStore( curr->isAtomic = prefix == BinaryConsts::AtomicPrefix; Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->value = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); curr->finalize(); @@ -5031,7 +5050,7 @@ bool WasmBinaryReader::maybeVisitAtomicRMW(Expression*& out, uint8_t code) { Address readAlign; Index memIdx = readMemoryAccess(readAlign, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); if (readAlign != curr->bytes) { throwError("Align of AtomicRMW must match size"); } @@ -5082,7 +5101,7 @@ bool WasmBinaryReader::maybeVisitAtomicCmpxchg(Expression*& out, uint8_t code) { Address readAlign; Index memIdx = readMemoryAccess(readAlign, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); if (readAlign != curr->bytes) { throwError("Align of AtomicCpxchg must match size"); } @@ -5117,7 +5136,7 @@ bool WasmBinaryReader::maybeVisitAtomicWait(Expression*& out, uint8_t code) { curr->ptr = popNonVoidExpression(); Address readAlign; Index memIdx = readMemoryAccess(readAlign, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); if (readAlign != curr->expectedType.getByteSize()) { throwError("Align of AtomicWait must match size"); } @@ -5137,7 +5156,7 @@ bool WasmBinaryReader::maybeVisitAtomicNotify(Expression*& out, uint8_t code) { curr->ptr = popNonVoidExpression(); Address readAlign; Index memIdx = readMemoryAccess(readAlign, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); if (readAlign != curr->type.getByteSize()) { throwError("Align of AtomicNotify must match size"); } @@ -5464,9 +5483,9 @@ bool WasmBinaryReader::maybeVisitMemoryInit(Expression*& out, uint32_t code) { curr->offset = popNonVoidExpression(); curr->dest = popNonVoidExpression(); Index segIdx = getU32LEB(); - dataRefs[segIdx].push_back(&curr->segment); + curr->segment = getDataName(segIdx); Index memIdx = getU32LEB(); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->finalize(); out = curr; return true; @@ -5478,7 +5497,7 @@ bool WasmBinaryReader::maybeVisitDataDrop(Expression*& out, uint32_t code) { } auto* curr = allocator.alloc<DataDrop>(); Index segIdx = getU32LEB(); - dataRefs[segIdx].push_back(&curr->segment); + curr->segment = getDataName(segIdx); curr->finalize(); out = curr; return true; @@ -5495,8 +5514,8 @@ bool WasmBinaryReader::maybeVisitMemoryCopy(Expression*& out, uint32_t code) { Index destIdx = getU32LEB(); Index sourceIdx = getU32LEB(); curr->finalize(); - memoryRefs[destIdx].push_back(&curr->destMemory); - memoryRefs[sourceIdx].push_back(&curr->sourceMemory); + curr->destMemory = getMemoryName(destIdx); + curr->sourceMemory = getMemoryName(sourceIdx); out = curr; return true; } @@ -5511,7 +5530,7 @@ bool WasmBinaryReader::maybeVisitMemoryFill(Expression*& out, uint32_t code) { curr->dest = popNonVoidExpression(); Index memIdx = getU32LEB(); curr->finalize(); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); out = curr; return true; } @@ -5528,9 +5547,8 @@ bool WasmBinaryReader::maybeVisitTableSize(Expression*& out, uint32_t code) { if (getTable(tableIdx)->is64()) { curr->type = Type::i64; } + curr->table = getTableName(tableIdx); curr->finalize(); - // Defer setting the table name for later, when we know it. - tableRefs[tableIdx].push_back(&curr->table); out = curr; return true; } @@ -5549,9 +5567,8 @@ bool WasmBinaryReader::maybeVisitTableGrow(Expression*& out, uint32_t code) { if (getTable(tableIdx)->is64()) { curr->type = Type::i64; } + curr->table = getTableName(tableIdx); curr->finalize(); - // Defer setting the table name for later, when we know it. - tableRefs[tableIdx].push_back(&curr->table); out = curr; return true; } @@ -5568,7 +5585,7 @@ bool WasmBinaryReader::maybeVisitTableFill(Expression*& out, uint32_t code) { auto* value = popNonVoidExpression(); auto* dest = popNonVoidExpression(); auto* ret = Builder(wasm).makeTableFill(Name(), dest, value, size); - tableRefs[tableIdx].push_back(&ret->table); + ret->table = getTableName(tableIdx); out = ret; return true; } @@ -5589,8 +5606,8 @@ bool WasmBinaryReader::maybeVisitTableCopy(Expression*& out, uint32_t code) { auto* source = popNonVoidExpression(); auto* dest = popNonVoidExpression(); auto* ret = Builder(wasm).makeTableCopy(dest, source, size, Name(), Name()); - tableRefs[destTableIdx].push_back(&ret->destTable); - tableRefs[sourceTableIdx].push_back(&ret->sourceTable); + ret->destTable = getTableName(destTableIdx); + ret->sourceTable = getTableName(sourceTableIdx); out = ret; return true; } @@ -5604,9 +5621,9 @@ bool WasmBinaryReader::maybeVisitTableInit(Expression*& out, uint32_t code) { curr->offset = popNonVoidExpression(); curr->dest = popNonVoidExpression(); Index segIdx = getU32LEB(); - elemRefs[segIdx].push_back(&curr->segment); - Index memIdx = getU32LEB(); - tableRefs[memIdx].push_back(&curr->table); + curr->segment = getElemName(segIdx); + Index tableIdx = getU32LEB(); + curr->table = getTableName(tableIdx); curr->finalize(); out = curr; return true; @@ -6620,7 +6637,7 @@ bool WasmBinaryReader::maybeVisitSIMDStore(Expression*& out, uint32_t code) { curr->bytes = 16; curr->valueType = Type::v128; Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->isAtomic = false; curr->value = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); @@ -6878,7 +6895,7 @@ bool WasmBinaryReader::maybeVisitSIMDLoad(Expression*& out, uint32_t code) { curr->type = Type::v128; curr->bytes = 16; Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->isAtomic = false; curr->ptr = popNonVoidExpression(); curr->finalize(); @@ -6939,7 +6956,7 @@ bool WasmBinaryReader::maybeVisitSIMDLoad(Expression*& out, uint32_t code) { return false; } Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->ptr = popNonVoidExpression(); curr->finalize(); out = curr; @@ -6989,7 +7006,7 @@ bool WasmBinaryReader::maybeVisitSIMDLoadStoreLane(Expression*& out, auto* curr = allocator.alloc<SIMDLoadStoreLane>(); curr->op = op; Index memIdx = readMemoryAccess(curr->align, curr->offset); - memoryRefs[memIdx].push_back(&curr->memory); + curr->memory = getMemoryName(memIdx); curr->index = getLaneIndex(lanes); curr->vec = popNonVoidExpression(); curr->ptr = popNonVoidExpression(); @@ -7035,8 +7052,8 @@ void WasmBinaryReader::visitMemorySize(MemorySize* curr) { if (getMemory(index)->is64()) { curr->type = Type::i64; } + curr->memory = getMemoryName(index); curr->finalize(); - memoryRefs[index].push_back(&curr->memory); } void WasmBinaryReader::visitMemoryGrow(MemoryGrow* curr) { @@ -7045,7 +7062,7 @@ void WasmBinaryReader::visitMemoryGrow(MemoryGrow* curr) { if (getMemory(index)->is64()) { curr->type = Type::i64; } - memoryRefs[index].push_back(&curr->memory); + curr->memory = getMemoryName(index); } void WasmBinaryReader::visitNop(Nop* curr) {} @@ -7068,12 +7085,7 @@ void WasmBinaryReader::visitRefIsNull(RefIsNull* curr) { void WasmBinaryReader::visitRefFunc(RefFunc* curr) { Index index = getU32LEB(); - // We don't know function names yet, so record this use to be updated later. - // Note that we do not need to check that 'index' is in bounds, as that will - // be verified in the next line. (Also, note that functionRefs[index] may - // write to an odd place in the functionRefs map if index is invalid, but that - // is harmless.) - functionRefs[index].push_back(&curr->func); + curr->func = getFunctionName(index); // To support typed function refs, we give the reference not just a general // funcref, but a specific subtype with the actual signature. curr->finalize(Type(getTypeByFunctionIndex(index), NonNullable)); @@ -7092,9 +7104,8 @@ void WasmBinaryReader::visitTableGet(TableGet* curr) { } curr->index = popNonVoidExpression(); curr->type = wasm.tables[tableIdx]->type; + curr->table = getTableName(tableIdx); curr->finalize(); - // Defer setting the table name for later, when we know it. - tableRefs[tableIdx].push_back(&curr->table); } void WasmBinaryReader::visitTableSet(TableSet* curr) { @@ -7104,9 +7115,8 @@ void WasmBinaryReader::visitTableSet(TableSet* curr) { } curr->value = popNonVoidExpression(); curr->index = popNonVoidExpression(); + curr->table = getTableName(tableIdx); curr->finalize(); - // Defer setting the table name for later, when we know it. - tableRefs[tableIdx].push_back(&curr->table); } void WasmBinaryReader::visitTryOrTryInBlock(Expression*& out) { @@ -7169,8 +7179,7 @@ void WasmBinaryReader::visitTryOrTryInBlock(Expression*& out) { breakStack.pop_back(); for (Index i = 0; i < tagIndexes.size(); i++) { - // We don't know the final name yet. - tagRefs[tagIndexes[i]].push_back(&curr->catchTags[i]); + curr->catchTags[i] = getTagName(tagIndexes[i]); } if (lastSeparator == BinaryConsts::Delegate) { @@ -7293,8 +7302,7 @@ void WasmBinaryReader::visitTryTable(TryTable* curr) { for (Index i = 0; i < tagIndexes.size(); i++) { if (curr->catchTags[i]) { - // We don't know the final name yet. - tagRefs[tagIndexes[i]].push_back(&curr->catchTags[i]); + curr->catchTags[i] = getTagName(tagIndexes[i]); } } @@ -7312,7 +7320,6 @@ void WasmBinaryReader::visitThrow(Throw* curr) { } auto* tag = wasm.tags[index].get(); curr->tag = tag->name; - tagRefs[index].push_back(&curr->tag); // we don't know the final name yet size_t num = tag->sig.params.size(); curr->operands.resize(num); for (size_t i = 0; i < num; i++) { @@ -7563,14 +7570,12 @@ bool WasmBinaryReader::maybeVisitArrayNewElem(Expression*& out, uint32_t code) { auto* size = popNonVoidExpression(); auto* offset = popNonVoidExpression(); if (isData) { - auto* curr = - Builder(wasm).makeArrayNewData(heapType, Name(), offset, size); - dataRefs[segIdx].push_back(&curr->segment); + auto* curr = Builder(wasm).makeArrayNewData( + heapType, getDataName(segIdx), offset, size); out = curr; } else { - auto* curr = - Builder(wasm).makeArrayNewElem(heapType, Name(), offset, size); - elemRefs[segIdx].push_back(&curr->segment); + auto* curr = Builder(wasm).makeArrayNewElem( + heapType, getElemName(segIdx), offset, size); out = curr; } return true; @@ -7708,14 +7713,12 @@ bool WasmBinaryReader::maybeVisitArrayInit(Expression*& out, uint32_t code) { auto* ref = popNonVoidExpression(); validateHeapTypeUsingChild(ref, heapType); if (isData) { - auto* curr = - Builder(wasm).makeArrayInitData(Name(), ref, index, offset, size); - dataRefs[segIdx].push_back(&curr->segment); + auto* curr = Builder(wasm).makeArrayInitData( + getDataName(segIdx), ref, index, offset, size); out = curr; } else { - auto* curr = - Builder(wasm).makeArrayInitElem(Name(), ref, index, offset, size); - elemRefs[segIdx].push_back(&curr->segment); + auto* curr = Builder(wasm).makeArrayInitElem( + getElemName(segIdx), ref, index, offset, size); out = curr; } return true; @@ -7941,9 +7944,6 @@ void WasmBinaryReader::visitResume(Resume* curr) { curr->handlerTags[i] = tag; curr->handlerBlocks[i] = handler; - - // We don't know the final name yet - tagRefs[tagIndex].push_back(&curr->handlerTags[i]); } curr->cont = popNonVoidExpression(); @@ -7966,7 +7966,6 @@ void WasmBinaryReader::visitSuspend(Suspend* curr) { } auto* tag = wasm.tags[tagIndex].get(); curr->tag = tag->name; - tagRefs[tagIndex].push_back(&curr->tag); auto numArgs = tag->sig.params.size(); curr->operands.resize(numArgs); |