145 lines · c
1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_WASM_SYMBOL_TABLE_H10#define LLD_WASM_SYMBOL_TABLE_H11 12#include "InputFiles.h"13#include "LTO.h"14#include "Symbols.h"15#include "lld/Common/LLVM.h"16#include "llvm/ADT/CachedHashString.h"17#include "llvm/ADT/DenseSet.h"18#include "llvm/BinaryFormat/WasmTraits.h"19#include <optional>20 21namespace lld::wasm {22 23class InputSegment;24 25// SymbolTable is a bucket of all known symbols, including defined,26// undefined, or lazy symbols (the last one is symbols in archive27// files whose archive members are not yet loaded).28//29// We put all symbols of all files to a SymbolTable, and the30// SymbolTable selects the "best" symbols if there are name31// conflicts. For example, obviously, a defined symbol is better than32// an undefined symbol. Or, if there's a conflict between a lazy and a33// undefined, it'll read an archive member to read a real definition34// to replace the lazy symbol. The logic is implemented in the35// add*() functions, which are called by input files as they are parsed.36// There is one add* function per symbol type.37class SymbolTable {38public:39 ArrayRef<Symbol *> symbols() const { return symVector; }40 41 void wrap(Symbol *sym, Symbol *real, Symbol *wrap);42 43 void addFile(InputFile *file, StringRef symName = {});44 45 void compileBitcodeFiles();46 47 Symbol *find(StringRef name);48 49 void replace(StringRef name, Symbol* sym);50 51 void trace(StringRef name);52 53 Symbol *addSharedFunction(StringRef name, uint32_t flags, InputFile *file,54 const WasmSignature *sig);55 Symbol *addSharedData(StringRef name, uint32_t flags, InputFile *file);56 Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file,57 InputFunction *function);58 Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file,59 InputChunk *segment, uint64_t address, uint64_t size);60 Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file,61 InputGlobal *g);62 Symbol *addDefinedTag(StringRef name, uint32_t flags, InputFile *file,63 InputTag *t);64 Symbol *addDefinedTable(StringRef name, uint32_t flags, InputFile *file,65 InputTable *t);66 67 Symbol *addUndefinedFunction(StringRef name,68 std::optional<StringRef> importName,69 std::optional<StringRef> importModule,70 uint32_t flags, InputFile *file,71 const WasmSignature *signature,72 bool isCalledDirectly);73 Symbol *addUndefinedData(StringRef name, uint32_t flags, InputFile *file);74 Symbol *addUndefinedGlobal(StringRef name,75 std::optional<StringRef> importName,76 std::optional<StringRef> importModule,77 uint32_t flags, InputFile *file,78 const WasmGlobalType *type);79 Symbol *addUndefinedTable(StringRef name, std::optional<StringRef> importName,80 std::optional<StringRef> importModule,81 uint32_t flags, InputFile *file,82 const WasmTableType *type);83 Symbol *addUndefinedTag(StringRef name, std::optional<StringRef> importName,84 std::optional<StringRef> importModule, uint32_t flags,85 InputFile *file, const WasmSignature *sig);86 87 TableSymbol *resolveIndirectFunctionTable(bool required);88 89 void addLazy(StringRef name, InputFile *f);90 91 bool addComdat(StringRef name);92 93 DefinedData *addSyntheticDataSymbol(StringRef name, uint32_t flags);94 DefinedGlobal *addSyntheticGlobal(StringRef name, uint32_t flags,95 InputGlobal *global);96 DefinedFunction *addSyntheticFunction(StringRef name, uint32_t flags,97 InputFunction *function);98 DefinedData *addOptionalDataSymbol(StringRef name, uint64_t value = 0);99 DefinedGlobal *addOptionalGlobalSymbol(StringRef name, InputGlobal *global);100 DefinedTable *addSyntheticTable(StringRef name, uint32_t flags,101 InputTable *global);102 103 void handleSymbolVariants();104 void handleWeakUndefines();105 DefinedFunction *createUndefinedStub(const WasmSignature &sig);106 107private:108 std::pair<Symbol *, bool> insert(StringRef name, const InputFile *file);109 std::pair<Symbol *, bool> insertName(StringRef name);110 111 bool getFunctionVariant(Symbol* sym, const WasmSignature *sig,112 const InputFile *file, Symbol **out);113 InputFunction *replaceWithUnreachable(Symbol *sym, const WasmSignature &sig,114 StringRef debugName);115 void replaceWithUndefined(Symbol *sym);116 117 TableSymbol *createDefinedIndirectFunctionTable(StringRef name);118 TableSymbol *createUndefinedIndirectFunctionTable(StringRef name);119 120 // Maps symbol names to index into the symVector. -1 means that symbols121 // is to not yet in the vector but it should have tracing enabled if it is122 // ever added.123 llvm::DenseMap<llvm::CachedHashStringRef, int> symMap;124 std::vector<Symbol *> symVector;125 126 // For certain symbols types, e.g. function symbols, we allow for multiple127 // variants of the same symbol with different signatures.128 llvm::DenseMap<llvm::CachedHashStringRef, std::vector<Symbol *>> symVariants;129 llvm::DenseMap<WasmSignature, DefinedFunction *> stubFunctions;130 131 // Comdat groups define "link once" sections. If two comdat groups have the132 // same name, only one of them is linked, and the other is ignored. This set133 // is used to uniquify them.134 llvm::DenseSet<llvm::CachedHashStringRef> comdatGroups;135 136 // For LTO.137 std::unique_ptr<BitcodeCompiler> lto;138};139 140extern SymbolTable *symtab;141 142} // namespace lld::wasm143 144#endif145