Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -90,12 +90,13 @@ }; struct WasmFunction { - uint32_t Index; + uint32_t WasmIndex; // index into code array + num imported fns std::vector Locals; ArrayRef Body; uint32_t CodeSectionOffset; uint32_t Size; - StringRef Comdat; + StringRef Name; // from the "names" or "export" section + StringRef Comdat; // from the "comdat info" section }; struct WasmDataSegment { Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -39,39 +39,45 @@ FUNCTION_EXPORT, GLOBAL_IMPORT, GLOBAL_EXPORT, - DEBUG_FUNCTION_NAME, }; WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section, - uint32_t ElementIndex, uint32_t FunctionType = 0) - : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex), - FunctionType(FunctionType) {} + uint32_t SymbolIndex, uint32_t WasmIndex, + uint32_t FunctionType = 0) + : Name(Name), Type(Type), Section(Section), SymbolIndex(SymbolIndex), + WasmIndex(WasmIndex), FunctionType(FunctionType) {} StringRef Name; SymbolType Type; uint32_t Section; uint32_t Flags = 0; - // Index into either the function or global index space. - uint32_t ElementIndex; + // Index into either the function or global Symbol index space. The Symbol + // index space consists of the imports followed by the exports (each of + // which creates a Symbol). + uint32_t SymbolIndex; + // Index into the the function or global Wasm index space. This is the + // index space used by the Wasm format for referring to a function or + // global, and consists of the imports followed by the function/global + // definitions. + // To be crystal clear, the following Wasm file has three linker symbols, + // and two Wasm callable items: + // (import "env" "externalFn" ...) + // (export "exportedFn" (func $exportedFnBody)) + // (export "exportedFnAlias" (func $exportedFnBody)) + // (func $exportedFnBody ...) + // Symbol index space = + // [ 0: import externalFn, 1: export exportedFn, 2: export exportedFnAlias ] + // Wasm index space = + // [ 0: import externalFn, 1: definition exportedFnBody ] + uint32_t WasmIndex; // For function, the type index uint32_t FunctionType; - // Symbols can be both exported and imported (in the case of the weakly - // defined symbol). In this the import index is stored as AltIndex. - uint32_t AltIndex = 0; - bool HasAltIndex = false; - - void setAltIndex(uint32_t Index) { - HasAltIndex = true; - AltIndex = Index; - } - bool isFunction() const { return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT || - Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || - Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME; + Type == WasmSymbol::SymbolType::FUNCTION_EXPORT; } @@ -101,7 +107,8 @@ void print(raw_ostream &Out) const { Out << "Name=" << Name << ", Type=" << static_cast(Type) - << ", Flags=" << Flags << " ElemIndex=" << ElementIndex; + << ", Flags=" << Flags << " SymbolIndex=" << SymbolIndex + << ", WasmIndex=" << WasmIndex; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -145,12 +152,17 @@ ArrayRef globals() const { return Globals; } ArrayRef exports() const { return Exports; } const wasm::WasmLinkingData& linkingData() const { return LinkingData; } - uint32_t getNumberOfSymbols() const { return Symbols.size(); } + uint32_t getNumberOfSymbols() const + { return FunctionSymbols.size() + GlobalSymbols.size(); } ArrayRef elements() const { return ElemSegments; } ArrayRef dataSegments() const { return DataSegments; } ArrayRef functions() const { return Functions; } ArrayRef comdats() const { return Comdats; } uint32_t startFunction() const { return StartFunction; } + uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } + uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } + uint32_t getNumExportedGlobals() const { return NumExportedGlobals; } + uint32_t getNumExportedFunctions() const { return NumExportedFunctions; } void moveSymbolNext(DataRefImpl &Symb) const override; @@ -205,7 +217,8 @@ bool isRelocatableObject() const override; private: - bool isValidFunctionIndex(uint32_t Index) const; + bool isValidFunctionWasmIndex(uint32_t Index) const; + bool isValidFunctionSymbolIndex(uint32_t Index) const; const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; @@ -237,7 +250,7 @@ Error parseRelocSection(StringRef Name, const uint8_t *Ptr, const uint8_t *End); - void populateSymbolTable(); + Error populateSymbolTable(); wasm::WasmObjectHeader Header; std::vector Sections; @@ -251,17 +264,18 @@ std::vector ElemSegments; std::vector DataSegments; std::vector Functions; - std::vector Symbols; + std::vector FunctionSymbols; + std::vector GlobalSymbols; std::vector Comdats; uint32_t StartFunction = -1; bool HasLinkingSection = false; wasm::WasmLinkingData LinkingData; uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; + uint32_t NumExportedGlobals = 0; + uint32_t NumExportedFunctions = 0; uint32_t ImportSection = 0; uint32_t ExportSection = 0; - - StringMap SymbolMap; }; } // end namespace object Index: include/llvm/ObjectYAML/WasmYAML.h =================================================================== --- include/llvm/ObjectYAML/WasmYAML.h +++ include/llvm/ObjectYAML/WasmYAML.h @@ -130,7 +130,8 @@ }; struct SymbolInfo { - StringRef Name; + ExportKind Kind; + uint32_t Index; SymbolFlags Flags; }; Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -146,6 +146,13 @@ uint32_t Index; }; +// Information about a single symbol to be written into the linking metadata +struct WasmSymEntry { + uint32_t Kind; + uint32_t Index; + uint32_t Flags; +}; + // Information about a single relocation. struct WasmRelocationEntry { uint64_t Offset; // Where is the relocation. @@ -211,17 +218,21 @@ // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; - // Maps function symbols to the table element index space. Used - // for TABLE_INDEX relocation types (i.e. address taken functions). - DenseMap IndirectSymbolIndices; - // Maps function/global symbols to the function/global index space. + // Maps function/global symbols to the function/global Symbol index space. DenseMap SymbolIndices; + // Maps function/global symbols to the function/global Wasm index space. + DenseMap WasmIndices; + // Maps function symbol indices to the table element index space. Used + // for TABLE_INDEX relocation types (i.e. address taken functions). + SmallVector TableIndices; DenseMap FunctionTypeIndices; SmallVector FunctionTypes; SmallVector Globals; + unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; + unsigned InitialTableOffset = 1; // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -247,11 +258,12 @@ DataRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); - IndirectSymbolIndices.clear(); + TableIndices.clear(); FunctionTypeIndices.clear(); FunctionTypes.clear(); Globals.clear(); MCObjectWriter::reset(); + NumFunctionImports = 0; NumGlobalImports = 0; } @@ -285,18 +297,17 @@ void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, ArrayRef Functions); void writeDataSection(ArrayRef Segments); - void writeNameSection(ArrayRef Functions, - ArrayRef Imports, - uint32_t NumFuncImports); + void writeNameSection(ArrayRef Functions); void writeCodeRelocSection(); void writeDataRelocSection(); void writeLinkingMetaDataSection( ArrayRef Segments, uint32_t DataSize, - ArrayRef> SymbolFlags, + ArrayRef SymbolFlags, ArrayRef> InitFuncs, const std::map>& Comdats); uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); + uint32_t getProvisionalTableIndex(const WasmRelocationEntry &RelEntry); void applyRelocations(ArrayRef Relocations, uint64_t ContentsOffset); @@ -505,7 +516,7 @@ if (!Sym->isDefined(/*SetUsed=*/false)) return 0; - uint32_t GlobalIndex = SymbolIndices[Sym]; + uint32_t GlobalIndex = WasmIndices[Sym]; const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports]; uint64_t Address = Global.InitialValue + RelEntry.Addend; @@ -515,6 +526,28 @@ return Value; } +// Get a provisional table index. For table relocations, the relocation +// entry contains the actual function symbol index, and that's all that's +// used by the linker. However, as a nice touch so that the object files +// "work", we create provisional table and table indexes just for show. +uint32_t WasmObjectWriter::getProvisionalTableIndex( + const WasmRelocationEntry &RelEntry) { + const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); + assert(Sym->isFunction()); + if (!WasmIndices.count(Sym)) + report_fatal_error("symbol not found in function/global index space: " + + RelEntry.Symbol->getName()); + uint32_t WasmIndex = WasmIndices[Sym]; + // For address-taken imports, simply insert a placeholder null pointer + if (WasmIndex < NumFunctionImports) + return 0; + int32_t TableIndex = TableIndices[WasmIndex - NumFunctionImports]; + if (TableIndex < 0) + report_fatal_error("symbol not found in table index space: " + + Sym->getName()); + return TableIndex; +} + static void addData(SmallVectorImpl &DataBytes, MCSectionWasm &DataSection) { DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n"); @@ -564,10 +597,6 @@ switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - if (!IndirectSymbolIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in table index space: " + - RelEntry.Symbol->getName()); - return IndirectSymbolIndices[RelEntry.Symbol]; case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: @@ -599,7 +628,6 @@ DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { @@ -607,9 +635,14 @@ WritePatchableSLEB(Stream, Index, Offset); break; } + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: { + uint32_t TableIndex = getProvisionalTableIndex(RelEntry); + WritePatchableSLEB(Stream, TableIndex, Offset); + break; + } case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { - uint32_t Index = getRelocationIndexValue(RelEntry); - WriteI32(Stream, Index, Offset); + uint32_t TableIndex = getProvisionalTableIndex(RelEntry); + WriteI32(Stream, TableIndex, Offset); break; } case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { @@ -788,7 +821,7 @@ // init expr for starting offset write8(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(0, getStream()); + encodeSLEB128(InitialTableOffset, getStream()); write8(wasm::WASM_OPCODE_END); encodeULEB128(TableElems.size(), getStream()); @@ -852,12 +885,8 @@ endSection(Section); } -void WasmObjectWriter::writeNameSection( - ArrayRef Functions, - ArrayRef Imports, - unsigned NumFuncImports) { - uint32_t TotalFunctions = NumFuncImports + Functions.size(); - if (TotalFunctions == 0) +void WasmObjectWriter::writeNameSection(ArrayRef Functions) { + if (Functions.size() == 0) return; SectionBookkeeping Section; @@ -865,15 +894,8 @@ SectionBookkeeping SubSection; startSection(SubSection, wasm::WASM_NAMES_FUNCTION); - encodeULEB128(TotalFunctions, getStream()); - uint32_t Index = 0; - for (const WasmImport &Import : Imports) { - if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { - encodeULEB128(Index, getStream()); - writeString(Import.FieldName); - ++Index; - } - } + encodeULEB128(Functions.size(), getStream()); + uint32_t Index = NumFunctionImports; for (const WasmFunction &Func : Functions) { encodeULEB128(Index, getStream()); writeString(Func.Sym->getName()); @@ -922,19 +944,20 @@ void WasmObjectWriter::writeLinkingMetaDataSection( ArrayRef Segments, uint32_t DataSize, - ArrayRef> SymbolFlags, + ArrayRef SymbolFlags, ArrayRef> InitFuncs, const std::map>& Comdats) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); SectionBookkeeping SubSection; - if (SymbolFlags.size() != 0) { + if (!SymbolFlags.empty()) { startSection(SubSection, wasm::WASM_SYMBOL_INFO); encodeULEB128(SymbolFlags.size(), getStream()); - for (auto Pair: SymbolFlags) { - writeString(Pair.first); - encodeULEB128(Pair.second, getStream()); + for (const auto &SI : SymbolFlags) { + encodeULEB128(SI.Kind, getStream()); + encodeULEB128(SI.Index, getStream()); + encodeULEB128(SI.Flags, getStream()); } endSection(SubSection); } @@ -1009,6 +1032,18 @@ return Pair.first->second; } +static void addFlags(SmallVector &SymbolFlags, + uint32_t SymbolIndex, const MCSymbolWasm &WS) { + uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) | + (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0) | + (!WS.isExternal() ? wasm::WASM_SYMBOL_BINDING_LOCAL : 0); + if (Flags != 0) { + uint32_t Kind = WS.isFunction() ? wasm::WASM_EXTERNAL_FUNCTION + : wasm::WASM_EXTERNAL_GLOBAL; + SymbolFlags.emplace_back(WasmSymEntry{Kind, SymbolIndex, Flags}); + } +} + void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); @@ -1020,10 +1055,11 @@ SmallVector TableElems; SmallVector Imports; SmallVector Exports; - SmallVector, 4> SymbolFlags; + SmallVector SymbolFlags; SmallVector, 2> InitFuncs; std::map> Comdats; - unsigned NumFuncImports = 0; + unsigned NumFuncExports = 0; + unsigned NumGlobalExports = 0; SmallVector DataSegments; uint32_t DataSize = 0; @@ -1113,8 +1149,7 @@ const auto &WS = static_cast(S); // Register types for all functions, including those with private linkage - // (making them - // because wasm always needs a type signature. + // (because wasm always needs a type signature). if (WS.isFunction()) registerFunctionType(WS); @@ -1122,7 +1157,7 @@ continue; // If the symbol is not defined in this translation unit, import it. - if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) { + if (!WS.isDefined(/*SetUsed=*/false)) { WasmImport Import; Import.ModuleName = WS.getModuleName(); Import.FieldName = WS.getName(); @@ -1130,13 +1165,13 @@ if (WS.isFunction()) { Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.Type = getFunctionType(WS); - SymbolIndices[&WS] = NumFuncImports; - ++NumFuncImports; + WasmIndices[&WS] = SymbolIndices[&WS] = NumFunctionImports; + ++NumFunctionImports; } else { Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Type = int32_t(PtrType); Import.IsMutable = false; - SymbolIndices[&WS] = NumGlobalImports; + WasmIndices[&WS] = SymbolIndices[&WS] = NumGlobalImports; // If this global is the stack pointer, make it mutable. if (WS.getName() == "__stack_pointer") @@ -1186,23 +1221,18 @@ const auto &WS = static_cast(S); DEBUG(dbgs() << "MCSymbol: '" << S << "'" - << " isDefined=" << S.isDefined() << " isExternal=" - << S.isExternal() << " isTemporary=" << S.isTemporary() + << " isDefined=" << S.isDefined() + << " isExternal=" << S.isExternal() + << " isTemporary=" << S.isTemporary() << " isFunction=" << WS.isFunction() << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() << " isVariable=" << WS.isVariable() << "\n"); - if (WS.isWeak() || WS.isHidden()) { - uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) | - (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0); - SymbolFlags.emplace_back(WS.getName(), Flags); - } - if (WS.isVariable()) continue; - unsigned Index; + unsigned WasmIndex, SymbolIndex; if (WS.isFunction()) { if (WS.isDefined(/*SetUsed=*/false)) { @@ -1215,21 +1245,24 @@ "function symbols must have a size set with .size"); // A definition. Take the next available index. - Index = NumFuncImports + Functions.size(); + WasmIndex = NumFunctionImports + Functions.size(); + SymbolIndex = NumFunctionImports + NumFuncExports; + ++NumFuncExports; // Prepare the function. WasmFunction Func; Func.Type = getFunctionType(WS); Func.Sym = &WS; - SymbolIndices[&WS] = Index; + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; Functions.push_back(Func); } else { // An import; the index was assigned above. - Index = SymbolIndices.find(&WS)->second; + WasmIndex = SymbolIndex = SymbolIndices.find(&WS)->second; } - DEBUG(dbgs() << " -> function index: " << Index << "\n"); - } else { + DEBUG(dbgs() << " -> function index: " << WasmIndex << "\n"); + } else { if (WS.isTemporary() && !WS.getSize()) continue; @@ -1246,7 +1279,9 @@ // For each global, prepare a corresponding wasm global holding its // address. For externals these will also be named exports. - Index = NumGlobalImports + Globals.size(); + WasmIndex = NumGlobalImports + Globals.size(); + SymbolIndex = NumGlobalImports + NumGlobalExports; + ++NumGlobalExports; auto &DataSection = static_cast(WS.getSection()); assert(DataSection.isWasmData()); @@ -1256,16 +1291,19 @@ Global.HasImport = false; Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS); Global.ImportIndex = 0; - SymbolIndices[&WS] = Index; - DEBUG(dbgs() << " -> global index: " << Index << "\n"); + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; + DEBUG(dbgs() << " -> global index: " << WasmIndex << "\n"); Globals.push_back(Global); } + addFlags(SymbolFlags, SymbolIndex, WS); + // If the symbol is visible outside this translation unit, export it. if (WS.isDefined(/*SetUsed=*/false)) { WasmExport Export; Export.FieldName = WS.getName(); - Export.Index = Index; + Export.Index = WasmIndex; if (WS.isFunction()) Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; else @@ -1273,14 +1311,11 @@ DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); Exports.push_back(Export); - if (!WS.isExternal()) - SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL); - if (WS.isFunction()) { auto &Section = static_cast(WS.getSection(false)); if (const MCSymbolWasm *C = Section.getGroup()) Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); + WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, WasmIndex}); } } } @@ -1298,45 +1333,53 @@ const auto &WS = static_cast(S); const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS); DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n"); - assert(SymbolIndices.count(ResolvedSym) > 0); - uint32_t Index = SymbolIndices.find(ResolvedSym)->second; - DEBUG(dbgs() << " -> index:" << Index << "\n"); + assert(WasmIndices.count(ResolvedSym) > 0); + uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second; + DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); + + unsigned SymbolIndex; + if (WS.isFunction()) { + SymbolIndex = NumFunctionImports + NumFuncExports; + ++NumFuncExports; + } else { + SymbolIndex = NumGlobalImports + NumGlobalExports; + ++NumGlobalExports; + } + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; + + addFlags(SymbolFlags, SymbolIndex, WS); WasmExport Export; Export.FieldName = WS.getName(); - Export.Index = Index; + Export.Index = WasmIndex; if (WS.isFunction()) Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; else Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); Exports.push_back(Export); - - if (!WS.isExternal()) - SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL); } { + TableIndices.resize(Functions.size(), -1); auto HandleReloc = [&](const WasmRelocationEntry &Rel) { - // Functions referenced by a relocation need to prepared to be called - // indirectly. - const MCSymbolWasm& WS = *Rel.Symbol; - if (WS.isFunction() && IndirectSymbolIndices.count(&WS) == 0) { - switch (Rel.Type) { - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { - uint32_t Index = SymbolIndices.find(&WS)->second; - IndirectSymbolIndices[&WS] = TableElems.size(); - DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); - TableElems.push_back(Index); - registerFunctionType(WS); - break; - } - default: - break; - } + // Functions referenced by a relocation need to put in the table. This is + // purely to make the object file's provisional values readable, and is + // ignored by the linker, which re-calculates the relocations itself. + if (Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 && + Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB) + return; + assert(Rel.Symbol->isFunction()); + const MCSymbolWasm* WS = ResolveSymbol(*Rel.Symbol); + uint32_t WasmIndex = WasmIndices[WS]; + if (WasmIndex < NumFunctionImports) + return; // Can't put imports in the table XXX test this, surely not?!? + uint32_t FuncIndex = WasmIndex - NumFunctionImports; + if (TableIndices[FuncIndex] == -1) { + TableIndices[FuncIndex] = TableElems.size() + InitialTableOffset; + DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); + TableElems.push_back(FuncIndex); } }; @@ -1409,7 +1452,7 @@ writeElemSection(TableElems); writeCodeSection(Asm, Layout, Functions); writeDataSection(DataSegments); - writeNameSection(Functions, Imports, NumFuncImports); + writeNameSection(Functions); writeCodeRelocSection(); writeDataRelocSection(); writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags, Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -278,10 +278,11 @@ while (Count--) { uint32_t Index = readVaruint32(Ptr); StringRef Name = readString(Ptr); - if (!Name.empty()) - Symbols.emplace_back(Name, - WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME, - Sections.size(), Index); + if (Index >= Functions.size() + NumImportedFunctions || Name.empty()) + return make_error("Invalid name entry", + object_error::parse_failed); + if (Index >= NumImportedFunctions) + Functions[Index].Name = Name; // Override any existing name } break; } @@ -302,59 +303,79 @@ return Error::success(); } -void WasmObjectFile::populateSymbolTable() { +Error WasmObjectFile::populateSymbolTable() { + FunctionSymbols.reserve(NumImportedFunctions + NumExportedFunctions); + GlobalSymbols.reserve(NumImportedGlobals + NumExportedGlobals); + StringSet<> SymbolNames; + // Add imports to symbol table - size_t GlobalIndex = 0; - size_t FunctionIndex = 0; for (const wasm::WasmImport& Import : Imports) { + WasmSymbol::SymbolType ImportType; + std::vector *Symbols; + unsigned FunctionType = 0; switch (Import.Kind) { case wasm::WASM_EXTERNAL_GLOBAL: assert(Import.Global.Type == wasm::WASM_TYPE_I32); - SymbolMap.try_emplace(Import.Field, Symbols.size()); - Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, - ImportSection, GlobalIndex++); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); + Symbols = &GlobalSymbols; + ImportType = WasmSymbol::SymbolType::GLOBAL_IMPORT; break; case wasm::WASM_EXTERNAL_FUNCTION: - SymbolMap.try_emplace(Import.Field, Symbols.size()); - Symbols.emplace_back(Import.Field, - WasmSymbol::SymbolType::FUNCTION_IMPORT, - ImportSection, FunctionIndex++, Import.SigIndex); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); + Symbols = &FunctionSymbols; + ImportType = WasmSymbol::SymbolType::FUNCTION_IMPORT; + FunctionType = Import.SigIndex; break; default: - break; + continue; } + if (!SymbolNames.insert(Import.Field).second) + return make_error( + "Duplicate symbol name " + Import.Field, + object_error::parse_failed); + unsigned SymbolIndex = Symbols->size(); + unsigned WasmIndex = SymbolIndex; + Symbols->emplace_back(Import.Field, ImportType, ImportSection, SymbolIndex, + WasmIndex, FunctionType); + DEBUG(dbgs() << "Adding import: " << Symbols->back() + << " sym index:" << SymbolIndex << "\n"); } // Add exports to symbol table for (const wasm::WasmExport& Export : Exports) { - if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION || - Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) { - WasmSymbol::SymbolType ExportType = - Export.Kind == wasm::WASM_EXTERNAL_FUNCTION - ? WasmSymbol::SymbolType::FUNCTION_EXPORT - : WasmSymbol::SymbolType::GLOBAL_EXPORT; - auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size()); - if (Pair.second) { - Symbols.emplace_back(Export.Name, ExportType, - ExportSection, Export.Index); - DEBUG(dbgs() << "Adding export: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); - } else { - uint32_t SymIndex = Pair.first->second; - const WasmSymbol &OldSym = Symbols[SymIndex]; - WasmSymbol NewSym(Export.Name, ExportType, ExportSection, Export.Index); - NewSym.setAltIndex(OldSym.ElementIndex); - Symbols[SymIndex] = NewSym; - - DEBUG(dbgs() << "Replacing existing symbol: " << NewSym - << " sym index:" << SymIndex << "\n"); - } + WasmSymbol::SymbolType ExportType; + std::vector *Symbols; + unsigned FunctionType = 0; + switch (Export.Kind) { + case wasm::WASM_EXTERNAL_GLOBAL: + assert(Export.Index >= NumImportedGlobals); + Symbols = &GlobalSymbols; + ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT; + break; + case wasm::WASM_EXTERNAL_FUNCTION: { + assert(Export.Index >= NumImportedFunctions); + Symbols = &FunctionSymbols; + ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT; + FunctionType = FunctionTypes[Export.Index - NumImportedFunctions]; + wasm::WasmFunction &Func = Functions[Export.Index - NumImportedFunctions]; + if (Func.Name.empty()) + Func.Name = Export.Name; + break; } + default: + continue; + } + if (!SymbolNames.insert(Export.Name).second) + return make_error( + "Duplicate symbol name " + Export.Name, + object_error::parse_failed); + unsigned SymbolIndex = Symbols->size(); + unsigned WasmIndex = Export.Index; + Symbols->emplace_back(Export.Name, ExportType, ExportSection, SymbolIndex, + WasmIndex, FunctionType); + DEBUG(dbgs() << "Adding export: " << Symbols->back() + << " sym index:" << SymbolIndex << "\n"); } + + return Error::success(); } Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, @@ -364,7 +385,8 @@ // Only populate the symbol table with imports and exports if the object // has a linking section (i.e. its a relocatable object file). Otherwise // the global might not represent symbols at all. - populateSymbolTable(); + if (Error Err = populateSymbolTable()) + return Err; while (Ptr < End) { uint8_t Type = readVarint7(Ptr); @@ -374,22 +396,28 @@ case wasm::WASM_SYMBOL_INFO: { uint32_t Count = readVaruint32(Ptr); while (Count--) { - StringRef Symbol = readString(Ptr); - DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n"); - uint32_t Flags = readVaruint32(Ptr); - auto iter = SymbolMap.find(Symbol); - if (iter == SymbolMap.end()) { - return make_error( - "Invalid symbol name in linking section: " + Symbol, - object_error::parse_failed); + uint32_t Kind = readVaruint32(Ptr); + std::vector *Symbols; + switch (Kind) { + case wasm::WASM_EXTERNAL_GLOBAL: + Symbols = &GlobalSymbols; + break; + case wasm::WASM_EXTERNAL_FUNCTION: + Symbols = &FunctionSymbols; + break; + default: + return make_error("Unexpected syminfo kind", + object_error::parse_failed); } - uint32_t SymIndex = iter->second; - assert(SymIndex < Symbols.size()); - Symbols[SymIndex].Flags = Flags; - DEBUG(dbgs() << "Set symbol flags index:" - << SymIndex << " name:" - << Symbols[SymIndex].Name << " expected:" - << Symbol << " flags: " << Flags << "\n"); + uint32_t SymIndex = readVaruint32(Ptr); + if (SymIndex >= Symbols->size()) + return make_error("Invalid syminfo index", + object_error::parse_failed); + uint32_t Flags = readVaruint32(Ptr); + (*Symbols)[SymIndex].Flags = Flags; + DEBUG(dbgs() << "Set symbol flags index:" << SymIndex + << " name:" << (*Symbols)[SymIndex].Name + << " flags: " << Flags << "\n"); } break; } @@ -415,7 +443,7 @@ wasm::WasmInitFunc Init; Init.Priority = readVaruint32(Ptr); Init.FunctionIndex = readVaruint32(Ptr); - if (!isValidFunctionIndex(Init.FunctionIndex)) + if (!isValidFunctionSymbolIndex(Init.FunctionIndex)) return make_error("Invalid function index: " + Twine(Init.FunctionIndex), object_error::parse_failed); @@ -475,7 +503,7 @@ DataSegments[Index].Data.Comdat = Name; break; case wasm::WASM_COMDAT_FUNCTION: - if (Index < NumImportedFunctions || !isValidFunctionIndex(Index)) + if (Index < NumImportedFunctions || !isValidFunctionWasmIndex(Index)) return make_error("COMDAT function index out of range", object_error::parse_failed); Index -= NumImportedFunctions; @@ -710,16 +738,19 @@ Ex.Index = readVaruint32(Ptr); switch (Ex.Kind) { case wasm::WASM_EXTERNAL_FUNCTION: - if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions) + ++NumExportedFunctions; + if (Ex.Index < NumImportedFunctions || + Ex.Index >= FunctionTypes.size() + NumImportedFunctions) return make_error("Invalid function export", object_error::parse_failed); break; - case wasm::WASM_EXTERNAL_GLOBAL: { - if (Ex.Index >= Globals.size() + NumImportedGlobals) + case wasm::WASM_EXTERNAL_GLOBAL: + ++NumExportedGlobals; + if (Ex.Index < NumImportedGlobals || + Ex.Index >= Globals.size() + NumImportedGlobals) return make_error("Invalid global export", object_error::parse_failed); break; - } case wasm::WASM_EXTERNAL_MEMORY: case wasm::WASM_EXTERNAL_TABLE: break; @@ -735,13 +766,17 @@ return Error::success(); } -bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { - return Index < FunctionTypes.size() + NumImportedFunctions; +bool WasmObjectFile::isValidFunctionWasmIndex(uint32_t Index) const { + return Index < NumImportedFunctions + FunctionTypes.size(); +} + +bool WasmObjectFile::isValidFunctionSymbolIndex(uint32_t Index) const { + return Index < NumImportedFunctions + NumExportedFunctions; } Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { StartFunction = readVaruint32(Ptr); - if (!isValidFunctionIndex(StartFunction)) + if (!isValidFunctionWasmIndex(StartFunction)) return make_error("Invalid start function", object_error::parse_failed); return Error::success(); @@ -761,7 +796,7 @@ uint32_t Size = readVaruint32(Ptr); const uint8_t *FunctionEnd = Ptr + Size; - Function.Index = NumImportedFunctions + Functions.size(); + Function.WasmIndex = NumImportedFunctions + Functions.size(); Function.CodeSectionOffset = FunctionStart - CodeSectionStart; Function.Size = FunctionEnd - FunctionStart; @@ -862,10 +897,6 @@ case WasmSymbol::SymbolType::FUNCTION_EXPORT: Result |= SymbolRef::SF_Executable; break; - case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: - Result |= SymbolRef::SF_Executable; - Result |= SymbolRef::SF_FormatSpecific; - break; case WasmSymbol::SymbolType::GLOBAL_IMPORT: Result |= SymbolRef::SF_Undefined; break; @@ -884,12 +915,15 @@ basic_symbol_iterator WasmObjectFile::symbol_end() const { DataRefImpl Ref; - Ref.d.a = Symbols.size(); + Ref.d.a = FunctionSymbols.size() + GlobalSymbols.size(); return BasicSymbolRef(Ref, this); } const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { - return Symbols[Symb.d.a]; + unsigned Index = Symb.d.a; + return Index >= FunctionSymbols.size() + ? GlobalSymbols[Index - FunctionSymbols.size()] + : FunctionSymbols[Index]; } const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { @@ -909,10 +943,9 @@ case WasmSymbol::SymbolType::FUNCTION_IMPORT: case WasmSymbol::SymbolType::GLOBAL_IMPORT: case WasmSymbol::SymbolType::FUNCTION_EXPORT: - case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: - return Sym.ElementIndex; + return Sym.WasmIndex; case WasmSymbol::SymbolType::GLOBAL_EXPORT: { - uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals; + uint32_t GlobalIndex = Sym.WasmIndex - NumImportedGlobals; assert(GlobalIndex < Globals.size()); const wasm::WasmGlobal &Global = Globals[GlobalIndex]; // WasmSymbols correspond only to I32_CONST globals @@ -944,7 +977,6 @@ switch (Sym.Type) { case WasmSymbol::SymbolType::FUNCTION_IMPORT: case WasmSymbol::SymbolType::FUNCTION_EXPORT: - case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: return SymbolRef::ST_Function; case WasmSymbol::SymbolType::GLOBAL_IMPORT: case WasmSymbol::SymbolType::GLOBAL_EXPORT: Index: lib/ObjectYAML/WasmYAML.cpp =================================================================== --- lib/ObjectYAML/WasmYAML.cpp +++ lib/ObjectYAML/WasmYAML.cpp @@ -391,7 +391,8 @@ void MappingTraits::mapping(IO &IO, WasmYAML::SymbolInfo &Info) { - IO.mapRequired("Name", Info.Name); + IO.mapRequired("Kind", Info.Kind); + IO.mapRequired("Index", Info.Index); IO.mapRequired("Flags", Info.Flags); } Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -98,77 +98,24 @@ ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: foo ; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: foo +; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: call_direct -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 2 -; CHECK-NEXT: - Name: call_alias -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Name: call_direct_ptr -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 4 -; CHECK-NEXT: - Name: direct_address -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: call_alias_ptr -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: - Name: alias_address -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: bar ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: bar_alias_address +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: foo_alias ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: bar_alias ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Type: ELEM -; CHECK-NEXT: Segments: -; CHECK-NEXT: - Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 0 -; CHECK-NEXT: Functions: [ 1, 0 ] -; CHECK-NEXT: - Type: CODE -; CHECK-NEXT: Relocations: -; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Offset: 0x00000009 -; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x00000012 -; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Offset: 0x0000001E -; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x00000024 -; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 2 -; CHECK-NEXT: Offset: 0x00000031 -; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x00000037 -; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 41000B -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 1081808080000B -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 1080808080000B -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 410028028880808000118080808000000B -; CHECK-NEXT: - Index: 5 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 410028029080808000118080808000000B -; CHECK-NEXT: - Type: DATA + +; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 0 @@ -194,7 +141,7 @@ ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: foo_alias +; CHECK-NEXT: Name: call_alias ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: foo ; CHECK-NEXT: - Index: 2 @@ -208,21 +155,17 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 20 -; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: foo_alias -; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: bar_alias -; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: foo -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: call_direct -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: SymbolInfo: ; CHECK-NEXT: - Name: call_alias ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: call_direct_ptr ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: call_alias_ptr ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: foo_alias +; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: bar_alias +; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.bar @@ -239,19 +182,11 @@ ; CHECK-NEXT: ... ; CHECK-SYMS: SYMBOL TABLE: -; CHECK-SYMS-NEXT: 00000000 g F name foo_alias +; CHECK-SYMS-NEXT: 00000000 g F name call_alias ; CHECK-SYMS-NEXT: 00000001 g F name foo -; CHECK-SYMS-NEXT: 00000002 g F name call_direct -; CHECK-SYMS-NEXT: 00000003 g F name call_alias -; CHECK-SYMS-NEXT: 00000004 g F name call_direct_ptr -; CHECK-SYMS-NEXT: 00000005 g F name call_alias_ptr +; CHECK-SYMS-NEXT: 00000000 g F EXPORT .hidden call_alias +; CHECK-SYMS-NEXT: 00000001 g F EXPORT .hidden foo +; CHECK-SYMS-NEXT: 00000000 g EXPORT bar +; CHECK-SYMS-NEXT: 00000008 g EXPORT bar_alias_address ; CHECK-SYMS-NEXT: 00000001 gw F EXPORT .hidden foo_alias ; CHECK-SYMS-NEXT: 00000000 gw EXPORT .hidden bar_alias -; CHECK-SYMS-NEXT: 00000001 g F EXPORT .hidden foo -; CHECK-SYMS-NEXT: 00000002 g F EXPORT .hidden call_direct -; CHECK-SYMS-NEXT: 00000003 g F EXPORT .hidden call_alias -; CHECK-SYMS-NEXT: 00000004 g F EXPORT .hidden call_direct_ptr -; CHECK-SYMS-NEXT: 00000008 g EXPORT direct_address -; CHECK-SYMS-NEXT: 00000005 g F EXPORT .hidden call_alias_ptr -; CHECK-SYMS-NEXT: 00000010 g EXPORT alias_address -; CHECK-SYMS-NEXT: 00000000 g EXPORT bar Index: test/ObjectYAML/wasm/linking_section.yaml =================================================================== --- test/ObjectYAML/wasm/linking_section.yaml +++ test/ObjectYAML/wasm/linking_section.yaml @@ -31,7 +31,8 @@ Name: linking DataSize: 999 SymbolInfo: - - Name: bar + - Kind: FUNCTION + Index: 0 Flags: [ BINDING_WEAK ] SegmentInfo: - Index: 0 @@ -50,7 +51,8 @@ # CHECK-NEXT: Name: linking # CHECK-NEXT: DataSize: 999 # CHECK-NEXT: SymbolInfo: -# CHECK-NEXT: - Name: bar +# CHECK-NEXT: - Kind: FUNCTION +# CHECK-NEXT: Index: 0 # CHECK-NEXT: Flags: [ BINDING_WEAK ] # CHECK-NEXT: SegmentInfo: # CHECK-NEXT: - Index: 0 Index: test/ObjectYAML/wasm/weak_symbols.yaml =================================================================== --- test/ObjectYAML/wasm/weak_symbols.yaml +++ test/ObjectYAML/wasm/weak_symbols.yaml @@ -30,9 +30,11 @@ Name: linking DataSize: 10 SymbolInfo: - - Name: function_export + - Kind: FUNCTION + Index: 0 Flags: [ BINDING_WEAK ] - - Name: global_export + - Kind: GLOBAL + Index: 0 Flags: [ BINDING_WEAK ] ... # CHECK: --- !WASM @@ -51,7 +53,9 @@ # CHECK: Name: linking # CHECK: DataSize: 10 # CHECK: SymbolInfo: -# CHECK: - Name: function_export +# CHECK: - Kind: FUNCTION +# CHECK: Index: 0 # CHECK: Flags: [ BINDING_WEAK ] -# CHECK: - Name: global_export +# CHECK: - Kind: GLOBAL +# CHECK: Index: 0 # CHECK: Flags: [ BINDING_WEAK ] Index: test/tools/llvm-nm/wasm/weak-symbols.yaml =================================================================== --- test/tools/llvm-nm/wasm/weak-symbols.yaml +++ test/tools/llvm-nm/wasm/weak-symbols.yaml @@ -58,13 +58,17 @@ Name: linking DataSize: 0 SymbolInfo: - - Name: weak_global_func + - Kind: FUNCTION + Index: 1 Flags: [ BINDING_WEAK ] - - Name: weak_global_data + - Kind: GLOBAL + Index: 1 Flags: [ BINDING_WEAK ] - - Name: weak_import_func + - Kind: FUNCTION + Index: 0 Flags: [ BINDING_WEAK ] - - Name: weak_import_data + - Kind: GLOBAL + Index: 0 Flags: [ BINDING_WEAK ] # CHECK: 00000400 W weak_global_data Index: test/tools/llvm-objdump/WebAssembly/symbol-table.test =================================================================== --- test/tools/llvm-objdump/WebAssembly/symbol-table.test +++ test/tools/llvm-objdump/WebAssembly/symbol-table.test @@ -1,9 +1,6 @@ RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s CHECK: SYMBOL TABLE: -CHECK-NEXT: 00000000 g F name puts -CHECK-NEXT: 00000001 g F name SomeOtherFunction -CHECK-NEXT: 00000002 g F name main CHECK-NEXT: 00000000 g F IMPORT puts CHECK-NEXT: 00000000 g F IMPORT SomeOtherFunction CHECK-NEXT: 00000002 g F EXPORT main Index: test/tools/llvm-readobj/symbols.test =================================================================== --- test/tools/llvm-readobj/symbols.test +++ test/tools/llvm-readobj/symbols.test @@ -74,21 +74,6 @@ WASM: Symbols [ WASM-NEXT: Symbol { WASM-NEXT: Name: puts -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) -WASM-NEXT: Flags: 0x0 -WASM-NEXT: } -WASM-NEXT: Symbol { -WASM-NEXT: Name: SomeOtherFunction -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) -WASM-NEXT: Flags: 0x0 -WASM-NEXT: } -WASM-NEXT: Symbol { -WASM-NEXT: Name: main -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) -WASM-NEXT: Flags: 0x0 -WASM-NEXT: } -WASM-NEXT: Symbol { -WASM-NEXT: Name: puts WASM-NEXT: Type: FUNCTION_IMPORT (0x0) WASM-NEXT: Flags: 0x0 WASM-NEXT: } Index: tools/llvm-readobj/WasmDumper.cpp =================================================================== --- tools/llvm-readobj/WasmDumper.cpp +++ tools/llvm-readobj/WasmDumper.cpp @@ -28,7 +28,6 @@ ENUM_ENTRY(FUNCTION_EXPORT), ENUM_ENTRY(GLOBAL_IMPORT), ENUM_ENTRY(GLOBAL_EXPORT), - ENUM_ENTRY(DEBUG_FUNCTION_NAME), #undef ENUM_ENTRY }; Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -53,13 +53,12 @@ std::unique_ptr CustomSec; if (WasmSec.Name == "name") { std::unique_ptr NameSec = make_unique(); - for (const object::SymbolRef& Sym: Obj.symbols()) { - const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym); - if (Symbol.Type != object::WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME) + for (const llvm::wasm::WasmFunction &Func: Obj.functions()) { + if (Func.Name.empty()) continue; WasmYAML::NameEntry NameEntry; - NameEntry.Name = Symbol.Name; - NameEntry.Index = Sym.getValue(); + NameEntry.Name = Func.Name; + NameEntry.Index = Func.WasmIndex; NameSec->FunctionNames.push_back(NameEntry); } CustomSec = std::move(NameSec); @@ -74,7 +73,8 @@ if (!Func.Comdat.empty()) { auto &Comdat = LinkingSec->Comdats[ComdatIndexes[Func.Comdat]]; Comdat.Entries.emplace_back( - WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index}); + WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, + Func.WasmIndex}); } } uint32_t SegmentIndex = 0; @@ -97,7 +97,9 @@ for (const object::SymbolRef& Sym: Obj.symbols()) { const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym); if (Symbol.Flags != 0) { - WasmYAML::SymbolInfo Info{Symbol.Name, Symbol.Flags}; + WasmYAML::SymbolInfo Info{Symbol.isFunction() ? wasm::WASM_EXTERNAL_FUNCTION + : wasm::WASM_EXTERNAL_GLOBAL, + Symbol.SymbolIndex, Symbol.Flags}; LinkingSec->SymbolInfos.emplace_back(Info); } } @@ -248,7 +250,7 @@ auto CodeSec = make_unique(); for (auto &Func : Obj.functions()) { WasmYAML::Function Function; - Function.Index = Func.Index; + Function.Index = Func.WasmIndex; for (auto &Local : Func.Locals) { WasmYAML::LocalDecl LocalDecl; LocalDecl.Type = Local.Type; Index: tools/yaml2obj/yaml2wasm.cpp =================================================================== --- tools/yaml2obj/yaml2wasm.cpp +++ tools/yaml2obj/yaml2wasm.cpp @@ -146,7 +146,8 @@ encodeULEB128(Section.SymbolInfos.size(), SubSection.GetStream()); for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) { - writeStringRef(Info.Name, SubSection.GetStream()); + encodeULEB128(Info.Kind, SubSection.GetStream()); + encodeULEB128(Info.Index, SubSection.GetStream()); encodeULEB128(Info.Flags, SubSection.GetStream()); }