Index: test/wasm/alias.ll =================================================================== --- test/wasm/alias.ll +++ test/wasm/alias.ll @@ -68,7 +68,7 @@ ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: start_alias +; CHECK-NEXT: Name: _start ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/archive.ll =================================================================== --- test/wasm/archive.ll +++ test/wasm/archive.ll @@ -27,11 +27,9 @@ ; correctly. ; CHECK: 00000003 T _start -; CHECK-NEXT: 00000003 T _start -; CHECK-NEXT: 00000001 T bar ; CHECK-NEXT: 00000001 T bar ; CHECK-NEXT: 00000002 T foo -; CHECK-NEXT: 00000002 T foo +; CHECK-NEXT: U missing_func ; Verify that symbols from unused objects don't appear in the symbol table ; CHECK-NOT: hello Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -45,7 +45,7 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x0000001F ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -62,8 +62,8 @@ ; CHECK-NEXT: - ElemType: ANYFUNC ; CHECK-NEXT: Limits: ; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x00000002 -; CHECK-NEXT: Maximum: 0x00000002 +; CHECK-NEXT: Initial: 0x00000003 +; CHECK-NEXT: Maximum: 0x00000003 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000001 @@ -129,7 +129,7 @@ ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 0 +; CHECK-NEXT: Value: 1 ; CHECK-NEXT: Functions: [ 3, 1 ] ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: @@ -158,7 +158,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x00000012 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 1 @@ -178,13 +178,13 @@ ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 -; CHECK-NEXT: Content: '00000000' +; CHECK-NEXT: Content: '01000000' ; CHECK-NEXT: - SectionOffset: 27 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 12 -; CHECK-NEXT: Content: '01000000' +; CHECK-NEXT: Content: '02000000' ; CHECK-NEXT: - SectionOffset: 36 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: @@ -231,12 +231,10 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: puts -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: foo_import ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: hello ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Name: my_func +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Name: func_comdat ; CHECK-NEXT: ... Index: test/wasm/weak-symbols.ll =================================================================== --- test/wasm/weak-symbols.ll +++ test/wasm/weak-symbols.ll @@ -105,8 +105,12 @@ ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: weakFn ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: exportWeak1 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: weakFn ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Name: exportWeak2 ; CHECK-NEXT: - Index: 5 Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -46,6 +46,7 @@ } uint32_t getOutputOffset() const { return OutputOffset; } + ArrayRef getRelocations() const { return Relocations; } virtual StringRef getComdat() const = 0; @@ -113,9 +114,11 @@ public: InputFunction(const WasmSignature &S, const WasmFunction *Func, const ObjFile *F) - : InputChunk(F), Signature(S), WrittenToNameSec(false), Function(Func) {} + : InputChunk(F), Signature(S), Function(Func) + { if (Func) Name = Func->Name; } uint32_t getSize() const override { return Function->Size; } + StringRef getName() const { return Name; } StringRef getComdat() const override { return Function->Comdat; } uint32_t getOutputIndex() const { return OutputIndex.getValue(); }; bool hasOutputIndex() const { return OutputIndex.hasValue(); }; @@ -123,8 +126,6 @@ const WasmSignature &Signature; - unsigned WrittenToNameSec : 1; - protected: ArrayRef data() const override { return File->CodeSection->Content.slice(getInputSectionOffset(), getSize()); @@ -133,14 +134,17 @@ return Function->CodeSectionOffset; } + StringRef Name; const WasmFunction *Function; llvm::Optional OutputIndex; }; class SyntheticFunction : public InputFunction { public: - SyntheticFunction(const WasmSignature &S, ArrayRef Body) - : InputFunction(S, nullptr, nullptr), Body(Body) {} + SyntheticFunction(const WasmSignature &S, ArrayRef Body, + StringRef Name_) + : InputFunction(S, nullptr, nullptr), Body(Body) + { Name = Name_; } uint32_t getSize() const override { return Body.size(); } Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -59,12 +59,6 @@ encodeULEB128(Reloc.Value, Buf, 5); break; case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - ExistingValue = decodeSLEB128(Buf); - if (ExistingValue != Reloc.Reloc.Index) { - DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n"); - assert(decodeSLEB128(Buf) == Reloc.Reloc.Index); - } - LLVM_FALLTHROUGH; case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: encodeSLEB128(static_cast(Reloc.Value), Buf, 5); break; @@ -110,17 +104,7 @@ if (Config->EmitRelocs) NewReloc.NewIndex = File->calcNewIndex(Reloc); - - switch (Reloc.Type) { - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - NewReloc.Value = File->getRelocatedAddress(Reloc.Index) + Reloc.Addend; - break; - default: - NewReloc.Value = File->calcNewIndex(Reloc); - break; - } + NewReloc.Value = File->calcNewValue(Reloc); OutRelocations.emplace_back(NewReloc); } Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -93,9 +93,9 @@ void dumpInfo() const; - uint32_t relocateFunctionIndex(uint32_t Original) const; - uint32_t getRelocatedAddress(uint32_t Index) const; + uint32_t relocateFunctionSymbolIndex(uint32_t Original) const; uint32_t calcNewIndex(const WasmRelocation &Reloc) const; + uint32_t calcNewValue(const WasmRelocation &Reloc) const; const WasmSection *CodeSection = nullptr; const WasmSection *DataSection = nullptr; @@ -104,12 +104,15 @@ std::vector Segments; std::vector Functions; - ArrayRef getSymbols() { return Symbols; } - ArrayRef getTableSymbols() { return TableSymbols; } + ArrayRef getSymbols() const { return Symbols; } + ArrayRef getFunctionSymbols() const { return FunctionSymbols; } private: + uint32_t getRelocatedAddress(uint32_t Index) const; uint32_t relocateTypeIndex(uint32_t Original) const; - uint32_t relocateGlobalIndex(uint32_t Original) const; + uint32_t relocateGlobalSymbolIndex(uint32_t Original) const; + uint32_t relocateFunctionWasmIndex(uint32_t Original) const; + uint32_t relocateGlobalWasmIndex(uint32_t Original) const; uint32_t relocateTableIndex(uint32_t Original) const; Symbol *createDefined(const WasmSymbol &Sym, Symbol::Kind Kind, @@ -128,17 +131,22 @@ // List of all symbols referenced or defined by this file. std::vector Symbols; - // List of all function symbols indexed by the function index space + // List of all function symbols indexed by the function Symbol index space, + // that is, function imports followed by function exports (not the Wasm + // function definition index space, function imports followed by function + // bodies). std::vector FunctionSymbols; - // List of all global symbols indexed by the global index space + // List of all global symbols indexed by the global Symbol index space, + // that is, global imports followed by global exports (not the Wasm + // global definition index space, global imports followed by global + // definitions). std::vector GlobalSymbols; - // List of all indirect symbols indexed by table index space. - std::vector TableSymbols; - uint32_t NumGlobalImports = 0; uint32_t NumFunctionImports = 0; + uint32_t NumGlobalExports = 0; + uint32_t NumFunctionExports = 0; std::unique_ptr WasmObj; }; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -47,38 +47,55 @@ " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" + " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" + " Function Imports : " + Twine(NumFunctionImports) + "\n" + - " Global Imports : " + Twine(NumGlobalImports) + "\n" + - " Table Entries : " + Twine(TableSymbols.size()) + "\n"); + " Global Imports : " + Twine(NumGlobalImports) + "\n"); } uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const { return GlobalSymbols[GlobalIndex]->getVirtualAddress(); } -uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const { - Symbol *Sym = FunctionSymbols[Original]; - uint32_t Index = Sym->getOutputIndex(); - DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": " - << Original << " -> " << Index << "\n"); - return Index; -} - uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const { return TypeMap[Original]; } -uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { - Symbol *Sym = TableSymbols[Original]; - uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; - DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original +uint32_t ObjFile::relocateFunctionSymbolIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; + uint32_t Index = Sym->getOutputSymbolIndex(); + DEBUG(dbgs() << "relocateFunctionSymbolIndex: " << toString(*Sym) << ": " + << Original << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateGlobalSymbolIndex(uint32_t Original) const { + Symbol *Sym = GlobalSymbols[Original]; + uint32_t Index = Sym->getOutputSymbolIndex(); + DEBUG(dbgs() << "relocateGlobalSymbolIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } -uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { - Symbol *Sym = GlobalSymbols[Original]; +uint32_t ObjFile::relocateFunctionWasmIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0; - DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original + DEBUG(dbgs() << "relocateFunctionWasmIndex: " << toString(*Sym) << ": " + << Original << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateGlobalWasmIndex(uint32_t Original) const { + Symbol *Sym = GlobalSymbols[Original]; + uint32_t Index = Sym->hasTableIndex() ? Sym->getOutputIndex() : 0; + DEBUG(dbgs() << "relocateGlobalWasmIndex: " << toString(*Sym) << ": " << Original + << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; + // The null case is possible, if you take the address of a weak function + // that's simply not supplied. + uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; + DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } @@ -92,15 +109,35 @@ case R_WEBASSEMBLY_TYPE_INDEX_LEB: return relocateTypeIndex(Reloc.Index); case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - return relocateFunctionIndex(Reloc.Index); case R_WEBASSEMBLY_TABLE_INDEX_I32: case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - return relocateTableIndex(Reloc.Index); + return relocateFunctionSymbolIndex(Reloc.Index); case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case R_WEBASSEMBLY_MEMORY_ADDR_I32: - return relocateGlobalIndex(Reloc.Index); + return relocateGlobalSymbolIndex(Reloc.Index); + default: + llvm_unreachable("unknown relocation type"); + } +} + +// Translate from the relocation's index into the final linked output value. +uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { + switch (Reloc.Type) { + case R_WEBASSEMBLY_TABLE_INDEX_I32: + case R_WEBASSEMBLY_TABLE_INDEX_SLEB: + return relocateTableIndex(Reloc.Index); + case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case R_WEBASSEMBLY_MEMORY_ADDR_I32: + case R_WEBASSEMBLY_MEMORY_ADDR_LEB: + return getRelocatedAddress(Reloc.Index) + Reloc.Addend; + case R_WEBASSEMBLY_TYPE_INDEX_LEB: + return relocateTypeIndex(Reloc.Index); + case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + return relocateFunctionWasmIndex(Reloc.Index); + case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + return relocateGlobalWasmIndex(Reloc.Index); default: llvm_unreachable("unknown relocation type"); } @@ -151,8 +188,9 @@ // Get the value stored in the wasm global represented by this symbol. // This represents the virtual address of the symbol in the input file. uint32_t ObjFile::getGlobalValue(const WasmSymbol &Sym) const { + assert(Sym.WasmIndex >= getWasmObj()->getNumImportedGlobals()); const WasmGlobal &Global = - getWasmObj()->globals()[Sym.ElementIndex - NumGlobalImports]; + getWasmObj()->globals()[Sym.WasmIndex - NumGlobalImports]; assert(Global.Type == llvm::wasm::WASM_TYPE_I32); return Global.InitExpr.Value.Int32; } @@ -166,7 +204,8 @@ } InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const { - uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports; + assert(Sym.WasmIndex >= NumFunctionImports); + uint32_t FunctionIndex = Sym.WasmIndex - NumFunctionImports; return Functions[FunctionIndex]; } @@ -178,16 +217,10 @@ void ObjFile::initializeSymbols() { Symbols.reserve(WasmObj->getNumberOfSymbols()); - for (const WasmImport &Import : WasmObj->imports()) { - switch (Import.Kind) { - case WASM_EXTERNAL_FUNCTION: - ++NumFunctionImports; - break; - case WASM_EXTERNAL_GLOBAL: - ++NumGlobalImports; - break; - } - } + NumFunctionImports = WasmObj->getNumImportedFunctions(); + NumGlobalImports = WasmObj->getNumImportedGlobals(); + NumFunctionExports = WasmObj->getNumExportedFunctions(); + NumGlobalExports = WasmObj->getNumExportedGlobals(); FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size()); GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size()); @@ -195,13 +228,12 @@ ArrayRef Funcs = WasmObj->functions(); ArrayRef FuncTypes = WasmObj->functionTypes(); ArrayRef Types = WasmObj->types(); - ArrayRef Globals = WasmObj->globals(); for (const auto &C : WasmObj->comdats()) Symtab->addComdat(C, this); - FunctionSymbols.resize(NumFunctionImports + Funcs.size()); - GlobalSymbols.resize(NumGlobalImports + Globals.size()); + FunctionSymbols.resize(NumFunctionImports + NumFunctionExports); + GlobalSymbols.resize(NumGlobalImports + NumGlobalExports); for (const WasmSegment &S : WasmObj->dataSegments()) { InputSegment *Seg = make(S, this); @@ -252,20 +284,13 @@ case WasmSymbol::SymbolType::GLOBAL_IMPORT: S = createUndefined(WasmSym, Symbol::Kind::UndefinedGlobalKind); break; - case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: - // These are for debugging only, no need to create linker symbols for them - continue; } Symbols.push_back(S); if (WasmSym.isFunction()) { - FunctionSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - FunctionSymbols[WasmSym.AltIndex] = S; + FunctionSymbols[WasmSym.SymbolIndex] = S; } else { - GlobalSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - GlobalSymbols[WasmSym.AltIndex] = S; + GlobalSymbols[WasmSym.SymbolIndex] = S; } } @@ -274,24 +299,6 @@ for (size_t I = 0; I < GlobalSymbols.size(); ++I) assert(GlobalSymbols[I] != nullptr);); - // Populate `TableSymbols` with all symbols that are called indirectly - uint32_t SegmentCount = WasmObj->elements().size(); - if (SegmentCount) { - if (SegmentCount > 1) - fatal(getName() + ": contains more than one element segment"); - const WasmElemSegment &Segment = WasmObj->elements()[0]; - if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST) - fatal(getName() + ": unsupported element segment"); - if (Segment.TableIndex != 0) - fatal(getName() + ": unsupported table index in elem segment"); - if (Segment.Offset.Value.Int32 != 0) - fatal(getName() + ": unsupported element segment offset"); - TableSymbols.reserve(Segment.Functions.size()); - for (uint64_t FunctionIndex : Segment.Functions) - TableSymbols.push_back(FunctionSymbols[FunctionIndex]); - } - - DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n"); DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n"); } Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -39,7 +39,7 @@ }; Symbol(StringRef Name, uint32_t Flags) - : WrittenToSymtab(0), WrittenToNameSec(0), Flags(Flags), Name(Name) {} + : Flags(Flags), Name(Name) {} Kind getKind() const { return SymbolKind; } @@ -74,10 +74,17 @@ // Returns true if an output index has been set for this symbol bool hasOutputIndex() const; - // Set the output index of the symbol (in the function or global index - // space of the output object. + // Set the output index of the symbol, in the function or global Wasm + // index space of the output object - that is, for defined symbols only, + // its position in the list of defined function bodies / global decls. void setOutputIndex(uint32_t Index); + // Get/set the output symbol index, in the function or global Symbol index + // space - that is, the position in the list of imports+exports. This is + // only used for relocatable output. + uint32_t getOutputSymbolIndex() const { return OutputSymbolIndex.getValue(); } + void setOutputSymbolIndex(uint32_t Index); + uint32_t getTableIndex() const { return TableIndex.getValue(); } // Returns true if a table index has been set for this symbol @@ -100,11 +107,6 @@ const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } InputFunction *getFunction() { return Function; } - // This bit is used by Writer::writeNameSection() to prevent - // symbols from being written to the symbol table more than once. - unsigned WrittenToSymtab : 1; - unsigned WrittenToNameSec : 1; - protected: uint32_t Flags; uint32_t VirtualAddress = 0; @@ -116,6 +118,7 @@ const InputSegment *Segment = nullptr; InputFunction *Function = nullptr; llvm::Optional OutputIndex; + llvm::Optional OutputSymbolIndex; llvm::Optional TableIndex; const WasmSignature *FunctionType = nullptr; }; Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -67,6 +67,12 @@ OutputIndex = Index; } +void Symbol::setOutputSymbolIndex(uint32_t Index) { + DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index << "\n"); + assert(!OutputSymbolIndex.hasValue()); + OutputSymbolIndex = Index; +} + void Symbol::setTableIndex(uint32_t Index) { DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); assert(!TableIndex.hasValue()); Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -76,7 +76,6 @@ void calculateInitFunctions(); void assignIndexes(); void calculateImports(); - void calculateOffsets(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -109,13 +108,13 @@ uint64_t FileSize = 0; uint32_t DataSize = 0; uint32_t NumMemoryPages = 0; - uint32_t InitialTableOffset = 0; + uint32_t InitialTableOffset = 1; std::vector Types; DenseMap TypeIndices; std::vector ImportedFunctions; std::vector ImportedGlobals; - std::vector DefinedGlobals; + std::vector DefinedGlobals; std::vector DefinedFunctions; std::vector IndirectFunctions; std::vector InitFunctions; @@ -266,25 +265,31 @@ uint32_t NumExports = ExportMemory ? 1 : 0; + unsigned FunctionIndex = ImportedFunctions.size(); std::vector SymbolExports; - if (ExportEntry) + if (ExportEntry) { + EntrySym->setOutputSymbolIndex(FunctionIndex++); SymbolExports.emplace_back(EntrySym); + } - for (const Symbol *Sym : Symtab->getSymbols()) { + for (Symbol *Sym : Symtab->getSymbols()) { if (Sym->isUndefined() || Sym->isGlobal()) continue; if (Sym->isHidden() && !ExportHidden) continue; if (ExportEntry && Sym == EntrySym) continue; + Sym->setOutputSymbolIndex(FunctionIndex++); SymbolExports.emplace_back(Sym); } - for (const Symbol *Sym : DefinedGlobals) { - // Can't export the SP right now because it mutable and mutable globals - // connot be exported. + unsigned GlobalIndex = ImportedGlobals.size(); + for (Symbol *Sym : DefinedGlobals) { + // Can't export the SP right now because it's mutable and mutable globals + // cannot be exported. if (Sym == Config->StackPointerSymbol) continue; + Sym->setOutputSymbolIndex(GlobalIndex++); SymbolExports.emplace_back(Sym); } @@ -420,7 +425,7 @@ if (!InitFunctions.empty()) { SubSection SubSection(WASM_INIT_FUNCS); writeUleb128(SubSection.getStream(), InitFunctions.size(), - "num init functionsw"); + "num init functions"); for (const WasmInitFunc &F : InitFunctions) { writeUleb128(SubSection.getStream(), F.Priority, "priority"); writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index"); @@ -470,58 +475,22 @@ // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { - // Create an array of all function sorted by function index space - std::vector Names; - - auto AddToNames = [&](Symbol* S) { - if (!S->isFunction() || S->WrittenToNameSec) - return; - // We also need to guard against two different symbols (two different - // names) for the same wasm function. While this is possible (aliases) - // it is not legal in the "name" section. - InputFunction *Function = S->getFunction(); - if (Function) { - if (Function->WrittenToNameSec) - return; - Function->WrittenToNameSec = true; - } - S->WrittenToNameSec = true; - Names.emplace_back(S); - }; - - for (ObjFile *File : Symtab->ObjectFiles) { - Names.reserve(Names.size() + File->getSymbols().size()); - DEBUG(dbgs() << "adding names from: " << File->getName() << "\n"); - for (Symbol *S : File->getSymbols()) { - if (S->isWeak()) - continue; - AddToNames(S); - } - } - - DEBUG(dbgs() << "adding symtab names\n"); - for (Symbol *S : Symtab->getSymbols()) { - DEBUG(dbgs() << "sym: " << S->getName() << "\n"); - if (S->getFile()) - continue; - AddToNames(S); - } + unsigned Names = 0; + for (const InputFunction *F : DefinedFunctions) + if (!F->getName().empty()) + ++Names; SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); - std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) { - return A->getOutputIndex() < B->getOutputIndex(); - }); - SubSection FunctionSubsection(WASM_NAMES_FUNCTION); raw_ostream &OS = FunctionSubsection.getStream(); - writeUleb128(OS, Names.size(), "name count"); + writeUleb128(OS, Names, "name count"); - // We have to iterate through the inputs twice so that all the imports - // appear first before any of the local function names. - for (const Symbol *S : Names) { - writeUleb128(OS, S->getOutputIndex(), "func index"); - writeStr(OS, S->getName(), "symbol name"); + for (const InputFunction *F : DefinedFunctions) { + if (!F->getName().empty()) { + writeUleb128(OS, F->getOutputIndex(), "func index"); + writeStr(OS, F->getName(), "symbol name"); + } } FunctionSubsection.finalizeContents(); @@ -622,9 +591,11 @@ if (Sym->isFunction()) { Sym->setOutputIndex(ImportedFunctions.size()); + Sym->setOutputSymbolIndex(ImportedFunctions.size()); ImportedFunctions.push_back(Sym); } else { Sym->setOutputIndex(ImportedGlobals.size()); + Sym->setOutputSymbolIndex(ImportedGlobals.size()); ImportedGlobals.push_back(Sym); } } @@ -702,11 +673,27 @@ for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n"); - for (Symbol *Sym : File->getTableSymbols()) { - if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + auto HandleRelocs = [&](ArrayRef Relocations) { + for (const WasmRelocation& Reloc : Relocations) { + if (Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_I32 && + Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_SLEB) + continue; + Symbol *Sym = File->getFunctionSymbols()[Reloc.Index]; + if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + continue; + Sym->setTableIndex(TableIndex++); + IndirectFunctions.emplace_back(Sym); + } + }; + for (InputFunction* Func : File->Functions) { + if (Func->Discarded) continue; - Sym->setTableIndex(TableIndex++); - IndirectFunctions.emplace_back(Sym); + HandleRelocs(Func->getRelocations()); + } + for (InputSegment* Seg : File->Segments) { + if (Seg->Discarded) + continue; + HandleRelocs(Seg->getRelocations()); } } } @@ -775,7 +762,9 @@ ArrayRef BodyArray( reinterpret_cast(CtorFunctionBody.data()), CtorFunctionBody.size()); - CtorFunction = llvm::make_unique(Signature, BodyArray); + CtorFunction = llvm::make_unique( + Signature, BodyArray, Config->CtorSymbol->getName()); + CtorFunction->setOutputIndex(FunctionIndex); DefinedFunctions.emplace_back(CtorFunction.get()); } @@ -788,7 +777,7 @@ InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); for (const WasmInitFunc &F : L.InitFunctions) InitFunctions.emplace_back(WasmInitFunc{ - F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); + F.Priority, File->relocateFunctionSymbolIndex(F.FunctionIndex)}); } // Sort in order of priority (lowest first) so that they are called // in the correct order. @@ -799,9 +788,6 @@ } void Writer::run() { - if (!Config->Relocatable) - InitialTableOffset = 1; - log("-- calculateTypes"); calculateTypes(); log("-- calculateImports");