//===- SymbolTable.h --------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLD_WASM_SYMBOL_TABLE_H #define LLD_WASM_SYMBOL_TABLE_H #include "InputFiles.h" #include "LTO.h" #include "Symbols.h" #include "lld/Common/LLVM.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/BinaryFormat/WasmTraits.h" #include namespace lld::wasm { class InputSegment; // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive // files whose archive members are not yet loaded). // // We put all symbols of all files to a SymbolTable, and the // SymbolTable selects the "best" symbols if there are name // conflicts. For example, obviously, a defined symbol is better than // an undefined symbol. Or, if there's a conflict between a lazy and a // undefined, it'll read an archive member to read a real definition // to replace the lazy symbol. The logic is implemented in the // add*() functions, which are called by input files as they are parsed. // There is one add* function per symbol type. class SymbolTable { public: ArrayRef symbols() const { return symVector; } void wrap(Symbol *sym, Symbol *real, Symbol *wrap); void addFile(InputFile *file, StringRef symName = {}); void compileBitcodeFiles(); Symbol *find(StringRef name); void replace(StringRef name, Symbol* sym); void trace(StringRef name); Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file, InputFunction *function); Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file, InputChunk *segment, uint64_t address, uint64_t size); Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file, InputGlobal *g); Symbol *addDefinedTag(StringRef name, uint32_t flags, InputFile *file, InputTag *t); Symbol *addDefinedTable(StringRef name, uint32_t flags, InputFile *file, InputTable *t); Symbol *addUndefinedFunction(StringRef name, std::optional importName, std::optional importModule, uint32_t flags, InputFile *file, const WasmSignature *signature, bool isCalledDirectly); Symbol *addUndefinedData(StringRef name, uint32_t flags, InputFile *file); Symbol *addUndefinedGlobal(StringRef name, std::optional importName, std::optional importModule, uint32_t flags, InputFile *file, const WasmGlobalType *type); Symbol *addUndefinedTable(StringRef name, std::optional importName, std::optional importModule, uint32_t flags, InputFile *file, const WasmTableType *type); Symbol *addUndefinedTag(StringRef name, std::optional importName, std::optional importModule, uint32_t flags, InputFile *file, const WasmSignature *sig); TableSymbol *resolveIndirectFunctionTable(bool required); void addLazy(ArchiveFile *f, const llvm::object::Archive::Symbol *sym); bool addComdat(StringRef name); DefinedData *addSyntheticDataSymbol(StringRef name, uint32_t flags); DefinedGlobal *addSyntheticGlobal(StringRef name, uint32_t flags, InputGlobal *global); DefinedFunction *addSyntheticFunction(StringRef name, uint32_t flags, InputFunction *function); DefinedData *addOptionalDataSymbol(StringRef name, uint64_t value = 0); DefinedGlobal *addOptionalGlobalSymbol(StringRef name, InputGlobal *global); DefinedTable *addSyntheticTable(StringRef name, uint32_t flags, InputTable *global); void handleSymbolVariants(); void handleWeakUndefines(); DefinedFunction *createUndefinedStub(const WasmSignature &sig); std::vector objectFiles; std::vector stubFiles; std::vector sharedFiles; std::vector bitcodeFiles; std::vector syntheticFunctions; std::vector syntheticGlobals; std::vector syntheticTables; private: std::pair insert(StringRef name, const InputFile *file); std::pair insertName(StringRef name); bool getFunctionVariant(Symbol* sym, const WasmSignature *sig, const InputFile *file, Symbol **out); InputFunction *replaceWithUnreachable(Symbol *sym, const WasmSignature &sig, StringRef debugName); void replaceWithUndefined(Symbol *sym); TableSymbol *createDefinedIndirectFunctionTable(StringRef name); TableSymbol *createUndefinedIndirectFunctionTable(StringRef name); // Maps symbol names to index into the symVector. -1 means that symbols // is to not yet in the vector but it should have tracing enabled if it is // ever added. llvm::DenseMap symMap; std::vector symVector; // For certain symbols types, e.g. function symbols, we allow for multiple // variants of the same symbol with different signatures. llvm::DenseMap> symVariants; llvm::DenseMap stubFunctions; // Comdat groups define "link once" sections. If two comdat groups have the // same name, only one of them is linked, and the other is ignored. This set // is used to uniquify them. llvm::DenseSet comdatGroups; // For LTO. std::unique_ptr lto; }; extern SymbolTable *symtab; } // namespace lld::wasm #endif