Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -20,6 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" @@ -261,7 +262,10 @@ uint32_t ImportSection = 0; uint32_t ExportSection = 0; - StringMap SymbolMap; + // Map symbol name -> symbol index + StringMap SymbolNames; + // Map pair(kind,index) -> symbol index + DenseMap, uint32_t> 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 WasmSymInfo { + uint32_t Kind; + uint32_t Index; + uint32_t Flags; +}; + // Information about a single relocation. struct WasmRelocationEntry { uint64_t Offset; // Where is the relocation. @@ -293,7 +300,7 @@ void writeDataRelocSection(); void writeLinkingMetaDataSection( ArrayRef Segments, uint32_t DataSize, - ArrayRef> SymbolFlags, + ArrayRef SymbolInfo, ArrayRef> InitFuncs, const std::map>& Comdats); @@ -921,19 +928,20 @@ void WasmObjectWriter::writeLinkingMetaDataSection( ArrayRef Segments, uint32_t DataSize, - ArrayRef> SymbolFlags, + ArrayRef SymbolInfo, ArrayRef> InitFuncs, const std::map>& Comdats) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); SectionBookkeeping SubSection; - if (SymbolFlags.size() != 0) { + if (!SymbolInfo.empty()) { startSection(SubSection, wasm::WASM_SYMBOL_INFO); - encodeULEB128(SymbolFlags.size(), getStream()); - for (auto Pair: SymbolFlags) { - writeString(Pair.first); - encodeULEB128(Pair.second, getStream()); + encodeULEB128(SymbolInfo.size(), getStream()); + for (const auto &SI : SymbolInfo) { + encodeULEB128(SI.Kind, getStream()); + encodeULEB128(SI.Index, getStream()); + encodeULEB128(SI.Flags, getStream()); } endSection(SubSection); } @@ -1019,12 +1027,24 @@ SmallVector TableElems; SmallVector Imports; SmallVector Exports; - SmallVector, 4> SymbolFlags; + SmallVector SymbolInfo; SmallVector, 2> InitFuncs; std::map> Comdats; SmallVector DataSegments; uint32_t DataSize = 0; + auto SetIndex = [&](const MCSymbolWasm &WS, uint32_t Index) { + SymbolIndices[&WS] = Index; + uint32_t Kind = WS.isFunction() ? wasm::WASM_EXTERNAL_FUNCTION + : wasm::WASM_EXTERNAL_GLOBAL; + uint32_t Flags = WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0; + Flags |= WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0; + Flags |= !WS.isExternal() && WS.isDefined() + ? wasm::WASM_SYMBOL_BINDING_LOCAL + : 0; + SymbolInfo.emplace_back(WasmSymInfo{Kind, Index, Flags}); + }; + // In the special .global_variables section, we've encoded global // variables used by the function. Translate them into the Globals // list. @@ -1128,13 +1148,13 @@ if (WS.isFunction()) { Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.Type = getFunctionType(WS); - SymbolIndices[&WS] = NumFunctionImports; + SetIndex(WS, NumFunctionImports); ++NumFunctionImports; } else { Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Type = int32_t(PtrType); Import.IsMutable = false; - SymbolIndices[&WS] = NumGlobalImports; + SetIndex(WS, NumGlobalImports); // If this global is the stack pointer, make it mutable. if (WS.getName() == "__stack_pointer") @@ -1191,12 +1211,6 @@ << " 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; @@ -1219,7 +1233,7 @@ WasmFunction Func; Func.Type = getFunctionType(WS); Func.Sym = &WS; - SymbolIndices[&WS] = Index; + SetIndex(WS, Index); Functions.push_back(Func); } else { // An import; the index was assigned above. @@ -1254,7 +1268,7 @@ Global.HasImport = false; Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS); Global.ImportIndex = 0; - SymbolIndices[&WS] = Index; + SetIndex(WS, Index); DEBUG(dbgs() << " -> global index: " << Index << "\n"); Globals.push_back(Global); } @@ -1271,9 +1285,6 @@ 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()); if (const MCSymbolWasm *C = Section.getGroup()) @@ -1309,9 +1320,6 @@ 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); } { @@ -1410,8 +1418,8 @@ writeNameSection(Functions, Imports); writeCodeRelocSection(); writeDataRelocSection(); - writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags, - InitFuncs, Comdats); + writeLinkingMetaDataSection(DataSegments, DataSize, SymbolInfo, InitFuncs, + Comdats); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -325,14 +325,16 @@ switch (Import.Kind) { case wasm::WASM_EXTERNAL_GLOBAL: assert(Import.Global.Type == wasm::WASM_TYPE_I32); - SymbolMap.try_emplace(Import.Field, Symbols.size()); + SymbolNames.try_emplace(Import.Field, Symbols.size()); + SymbolMap.try_emplace({Import.Kind, GlobalIndex}, Symbols.size()); Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, ImportSection, GlobalIndex++); DEBUG(dbgs() << "Adding import: " << Symbols.back() << " sym index:" << Symbols.size() << "\n"); break; case wasm::WASM_EXTERNAL_FUNCTION: - SymbolMap.try_emplace(Import.Field, Symbols.size()); + SymbolNames.try_emplace(Import.Field, Symbols.size()); + SymbolMap.try_emplace({Import.Kind, FunctionIndex}, Symbols.size()); Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT, ImportSection, FunctionIndex++, Import.SigIndex); @@ -352,8 +354,11 @@ Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ? WasmSymbol::SymbolType::FUNCTION_EXPORT : WasmSymbol::SymbolType::GLOBAL_EXPORT; - auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size()); + auto Pair = SymbolNames.try_emplace(Export.Name, Symbols.size()); + DEBUG(dbgs() << "export: " << Export.Kind << "\n"); + DEBUG(dbgs() << "export: " << Export.Index << "\n"); if (Pair.second) { + SymbolMap.try_emplace({Export.Kind, Export.Index}, Symbols.size()); Symbols.emplace_back(Export.Name, ExportType, ExportSection, Export.Index); DEBUG(dbgs() << "Adding export: " << Symbols.back() @@ -364,6 +369,7 @@ WasmSymbol NewSym(Export.Name, ExportType, ExportSection, Export.Index); NewSym.setAltIndex(OldSym.ElementIndex); Symbols[SymIndex] = NewSym; + SymbolMap.try_emplace({Export.Kind, Export.Index}, SymIndex); DEBUG(dbgs() << "Replacing existing symbol: " << NewSym << " sym index:" << SymIndex << "\n"); @@ -401,21 +407,20 @@ case wasm::WASM_SYMBOL_INFO: { uint32_t Count = readVaruint32(Ptr); while (Count--) { - StringRef Symbol = readString(Ptr); + uint32_t Kind = readVaruint32(Ptr); + uint32_t Index = readVaruint32(Ptr); uint32_t Flags = readVaruint32(Ptr); - auto iter = SymbolMap.find(Symbol); + auto iter = SymbolMap.find({Kind, Index}); if (iter == SymbolMap.end()) { return make_error( - "Invalid symbol name in linking section: " + Symbol, + "Invalid symbol in SYM_INFO: " + Twine(Kind) + ":" + Twine(Index), 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"); + DEBUG(dbgs() << "Set symbol flags index:" << SymIndex << " name:" + << Symbols[SymIndex].Name << " flags: " << Flags << "\n"); } break; } 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/array-fill.ll =================================================================== --- test/MC/WebAssembly/array-fill.ll +++ test/MC/WebAssembly/array-fill.ll @@ -16,7 +16,8 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 2 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: gBd +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 Index: test/MC/WebAssembly/comdat.ll =================================================================== --- test/MC/WebAssembly/comdat.ll +++ test/MC/WebAssembly/comdat.ll @@ -108,11 +108,14 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 3 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: basicInlineFn +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: sharedFn +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: constantData +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ BINDING_WEAK ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 Index: test/MC/WebAssembly/global-ctor-dtor.ll =================================================================== --- test/MC/WebAssembly/global-ctor-dtor.ll +++ test/MC/WebAssembly/global-ctor-dtor.ll @@ -161,15 +161,20 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 4 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: __dso_handle +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: .Lcall_dtors.42 +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] -; CHECK-NEXT: - Name: .Lregister_call_dtors.42 +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 6 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] -; CHECK-NEXT: - Name: .Lcall_dtors +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 7 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] -; CHECK-NEXT: - Name: .Lregister_call_dtors +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 8 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 Index: test/MC/WebAssembly/unnamed-data.ll =================================================================== --- test/MC/WebAssembly/unnamed-data.ll +++ test/MC/WebAssembly/unnamed-data.ll @@ -84,9 +84,11 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 28 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: .L.str1 +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] -; CHECK-NEXT: - Name: .L.str2 +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 Index: test/MC/WebAssembly/visibility.ll =================================================================== --- test/MC/WebAssembly/visibility.ll +++ test/MC/WebAssembly/visibility.ll @@ -18,6 +18,7 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: hiddenVis +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: ... Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -209,19 +209,26 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 20 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: foo_alias +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: bar_alias +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: foo +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: call_direct +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: call_alias +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: call_direct_ptr +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: call_alias_ptr +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 Index: test/MC/WebAssembly/weak.ll =================================================================== --- test/MC/WebAssembly/weak.ll +++ test/MC/WebAssembly/weak.ll @@ -32,8 +32,10 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: weak_external_data +; CHECK-NEXT: - Kind: GLOBAL +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: weak_function +; CHECK-NEXT: - Kind: FUNCTION +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: ... 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 @@ -38,9 +38,11 @@ Name: linking DataSize: 10 SymbolInfo: - - Name: function_export + - Kind: FUNCTION + Index: 1 Flags: [ BINDING_WEAK ] - - Name: global_export + - Kind: GLOBAL + Index: 0 Flags: [ BINDING_WEAK ] ... # CHECK: --- !WASM @@ -59,7 +61,9 @@ # CHECK: Name: linking # CHECK: DataSize: 10 # CHECK: SymbolInfo: -# CHECK: - Name: function_export +# CHECK: - Kind: FUNCTION +# CHECK: Index: 1 # 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 @@ -50,10 +50,10 @@ Exports: - Name: weak_global_func Kind: FUNCTION - Index: 0x00000004 + Index: 4 - Name: weak_global_data Kind: GLOBAL - Index: 0x00000003 + Index: 3 - Type: CODE Functions: - Index: 1 @@ -72,13 +72,17 @@ Name: linking DataSize: 0 SymbolInfo: - - Name: weak_global_func + - Kind: FUNCTION + Index: 4 Flags: [ BINDING_WEAK ] - - Name: weak_global_data + - Kind: GLOBAL + Index: 3 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: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -94,7 +94,10 @@ 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.ElementIndex, Symbol.Flags}; LinkingSec->SymbolInfos.emplace_back(Info); } } 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()); }