1c94d393aSSam Clegg //===- SymbolTable.cpp ----------------------------------------------------===// 2c94d393aSSam Clegg // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c94d393aSSam Clegg // 7c94d393aSSam Clegg //===----------------------------------------------------------------------===// 8c94d393aSSam Clegg 9c94d393aSSam Clegg #include "SymbolTable.h" 10c94d393aSSam Clegg #include "Config.h" 115fa274beSSam Clegg #include "InputChunks.h" 12e915a71fSHeejin Ahn #include "InputEvent.h" 1393102974SSam Clegg #include "InputGlobal.h" 14b8621596SSam Clegg #include "WriterUtils.h" 15c94d393aSSam Clegg #include "lld/Common/ErrorHandler.h" 162017d52bSRui Ueyama #include "lld/Common/Memory.h" 177d67dd11SRui Ueyama #include "llvm/ADT/SetVector.h" 18c94d393aSSam Clegg 19c94d393aSSam Clegg #define DEBUG_TYPE "lld" 20c94d393aSSam Clegg 21c94d393aSSam Clegg using namespace llvm; 2220db381bSSam Clegg using namespace llvm::wasm; 2345218f4aSSam Clegg using namespace llvm::object; 24c94d393aSSam Clegg using namespace lld; 25c94d393aSSam Clegg using namespace lld::wasm; 26c94d393aSSam Clegg 27c94d393aSSam Clegg SymbolTable *lld::wasm::Symtab; 28c94d393aSSam Clegg 29c94d393aSSam Clegg void SymbolTable::addFile(InputFile *File) { 30c94d393aSSam Clegg log("Processing: " + toString(File)); 311f3f774fSSam Clegg if (Config->Trace) 321f3f774fSSam Clegg message(toString(File)); 33c94d393aSSam Clegg File->parse(); 34c94d393aSSam Clegg 35c729c1b4SSam Clegg // LLVM bitcode file 36c729c1b4SSam Clegg if (auto *F = dyn_cast<BitcodeFile>(File)) 37c729c1b4SSam Clegg BitcodeFiles.push_back(F); 38c729c1b4SSam Clegg else if (auto *F = dyn_cast<ObjFile>(File)) 39c94d393aSSam Clegg ObjectFiles.push_back(F); 40c94d393aSSam Clegg } 41c94d393aSSam Clegg 42c729c1b4SSam Clegg // This function is where all the optimizations of link-time 43c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are 44c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format. 45c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files 46c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results. 47c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed 48c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization. 49c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() { 50c729c1b4SSam Clegg if (BitcodeFiles.empty()) 51c729c1b4SSam Clegg return; 52c729c1b4SSam Clegg 53c729c1b4SSam Clegg // Compile bitcode files and replace bitcode symbols. 54c729c1b4SSam Clegg LTO.reset(new BitcodeCompiler); 55c729c1b4SSam Clegg for (BitcodeFile *F : BitcodeFiles) 56c729c1b4SSam Clegg LTO->add(*F); 57c729c1b4SSam Clegg 58c729c1b4SSam Clegg for (StringRef Filename : LTO->compile()) { 59c729c1b4SSam Clegg auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp")); 60c729c1b4SSam Clegg Obj->parse(); 61c729c1b4SSam Clegg ObjectFiles.push_back(Obj); 62c729c1b4SSam Clegg } 63c729c1b4SSam Clegg } 64c729c1b4SSam Clegg 65c94d393aSSam Clegg void SymbolTable::reportRemainingUndefines() { 6674fe0ba1SSam Clegg for (Symbol *Sym : SymVector) { 67c729c1b4SSam Clegg if (!Sym->isUndefined() || Sym->isWeak()) 68c729c1b4SSam Clegg continue; 69c729c1b4SSam Clegg if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 70c729c1b4SSam Clegg continue; 71c729c1b4SSam Clegg if (!Sym->IsUsedInRegularObj) 72c729c1b4SSam Clegg continue; 7347e2b6b2SSam Clegg error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); 74c94d393aSSam Clegg } 75c94d393aSSam Clegg } 76c94d393aSSam Clegg 77c94d393aSSam Clegg Symbol *SymbolTable::find(StringRef Name) { 781f3f774fSSam Clegg auto It = SymMap.find(CachedHashStringRef(Name)); 791f3f774fSSam Clegg if (It == SymMap.end() || It->second == -1) 801f3f774fSSam Clegg return nullptr; 811f3f774fSSam Clegg return SymVector[It->second]; 821f3f774fSSam Clegg } 831f3f774fSSam Clegg 841f3f774fSSam Clegg std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { 851f3f774fSSam Clegg bool Trace = false; 861f3f774fSSam Clegg auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); 871f3f774fSSam Clegg int &SymIndex = P.first->second; 881f3f774fSSam Clegg bool IsNew = P.second; 891f3f774fSSam Clegg if (SymIndex == -1) { 901f3f774fSSam Clegg SymIndex = SymVector.size(); 911f3f774fSSam Clegg Trace = true; 921f3f774fSSam Clegg IsNew = true; 931f3f774fSSam Clegg } 941f3f774fSSam Clegg 951f3f774fSSam Clegg if (!IsNew) 961f3f774fSSam Clegg return {SymVector[SymIndex], false}; 971f3f774fSSam Clegg 981f3f774fSSam Clegg Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 991f3f774fSSam Clegg Sym->IsUsedInRegularObj = false; 1001f3f774fSSam Clegg Sym->Traced = Trace; 1011f3f774fSSam Clegg SymVector.emplace_back(Sym); 1021f3f774fSSam Clegg return {Sym, true}; 103c94d393aSSam Clegg } 104c94d393aSSam Clegg 1054c2cbfe6SSam Clegg std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { 1061f3f774fSSam Clegg Symbol *S; 1071f3f774fSSam Clegg bool WasInserted; 1081f3f774fSSam Clegg std::tie(S, WasInserted) = insertName(Name); 1091f3f774fSSam Clegg 1104c2cbfe6SSam Clegg if (!File || File->kind() == InputFile::ObjectKind) 1111f3f774fSSam Clegg S->IsUsedInRegularObj = true; 1121f3f774fSSam Clegg 1131f3f774fSSam Clegg return {S, WasInserted}; 114c94d393aSSam Clegg } 115c94d393aSSam Clegg 116e3498ec5SRui Ueyama static void reportTypeError(const Symbol *Existing, const InputFile *File, 1173876d89aSSam Clegg llvm::wasm::WasmSymbolType Type) { 118e3498ec5SRui Ueyama error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 119e3498ec5SRui Ueyama toString(Existing->getWasmType()) + " in " + 1203876d89aSSam Clegg toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 1213876d89aSSam Clegg " in " + toString(File)); 122e3498ec5SRui Ueyama } 123e3498ec5SRui Ueyama 1246f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing. 1256f4286fbSHeejin Ahn // For functions this can also involve verifying that the signatures match. 126cefbf9acSSam Clegg static void checkFunctionType(Symbol *Existing, const InputFile *File, 127e3498ec5SRui Ueyama const WasmSignature *NewSig) { 12865d6380cSSam Clegg auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); 12965d6380cSSam Clegg if (!ExistingFunction) { 1303876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION); 131e3498ec5SRui Ueyama return; 132e3498ec5SRui Ueyama } 133e3498ec5SRui Ueyama 134cefbf9acSSam Clegg if (!NewSig) 135cefbf9acSSam Clegg return; 136cefbf9acSSam Clegg 137e915a71fSHeejin Ahn const WasmSignature *OldSig = ExistingFunction->Signature; 138cefbf9acSSam Clegg if (!OldSig) { 139e915a71fSHeejin Ahn ExistingFunction->Signature = NewSig; 140cefbf9acSSam Clegg return; 141cefbf9acSSam Clegg } 142cefbf9acSSam Clegg 143cefbf9acSSam Clegg if (*NewSig != *OldSig) 144ffd0aaf8SSam Clegg warn("function signature mismatch: " + Existing->getName() + 145e3498ec5SRui Ueyama "\n>>> defined as " + toString(*OldSig) + " in " + 146e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined as " + 147ffd0aaf8SSam Clegg toString(*NewSig) + " in " + toString(File)); 148e3498ec5SRui Ueyama } 149e3498ec5SRui Ueyama 150e3498ec5SRui Ueyama static void checkGlobalType(const Symbol *Existing, const InputFile *File, 151e3498ec5SRui Ueyama const WasmGlobalType *NewType) { 152e3498ec5SRui Ueyama if (!isa<GlobalSymbol>(Existing)) { 1533876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 154b8621596SSam Clegg return; 155b8621596SSam Clegg } 156b8621596SSam Clegg 157e3498ec5SRui Ueyama const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 158e3498ec5SRui Ueyama if (*NewType != *OldType) { 159e3498ec5SRui Ueyama error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 160e3498ec5SRui Ueyama toString(*OldType) + " in " + toString(Existing->getFile()) + 161e3498ec5SRui Ueyama "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 162c94d393aSSam Clegg } 16324b3dcd4SSam Clegg } 16424b3dcd4SSam Clegg 165e915a71fSHeejin Ahn static void checkEventType(const Symbol *Existing, const InputFile *File, 166e915a71fSHeejin Ahn const WasmEventType *NewType, 167e915a71fSHeejin Ahn const WasmSignature *NewSig) { 168e915a71fSHeejin Ahn auto ExistingEvent = dyn_cast<EventSymbol>(Existing); 169e915a71fSHeejin Ahn if (!isa<EventSymbol>(Existing)) { 170e915a71fSHeejin Ahn reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); 171e915a71fSHeejin Ahn return; 172e915a71fSHeejin Ahn } 173e915a71fSHeejin Ahn 174e915a71fSHeejin Ahn const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); 175e915a71fSHeejin Ahn const WasmSignature *OldSig = ExistingEvent->Signature; 176e915a71fSHeejin Ahn if (NewType->Attribute != OldType->Attribute) 177e915a71fSHeejin Ahn error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + 178e915a71fSHeejin Ahn toString(*OldType) + " in " + toString(Existing->getFile()) + 179e915a71fSHeejin Ahn "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 180e915a71fSHeejin Ahn if (*NewSig != *OldSig) 181e915a71fSHeejin Ahn warn("Event signature mismatch: " + Existing->getName() + 182e915a71fSHeejin Ahn "\n>>> defined as " + toString(*OldSig) + " in " + 183e915a71fSHeejin Ahn toString(Existing->getFile()) + "\n>>> defined as " + 184e915a71fSHeejin Ahn toString(*NewSig) + " in " + toString(File)); 185e915a71fSHeejin Ahn } 186e915a71fSHeejin Ahn 187e3498ec5SRui Ueyama static void checkDataType(const Symbol *Existing, const InputFile *File) { 188e3498ec5SRui Ueyama if (!isa<DataSymbol>(Existing)) 1893876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 190e3498ec5SRui Ueyama } 191e3498ec5SRui Ueyama 192dfb0b2c7SSam Clegg DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 193ebda41f8SNicholas Wilson uint32_t Flags, 194ebda41f8SNicholas Wilson InputFunction *Function) { 195e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 196b961abc8SRui Ueyama assert(!find(Name)); 197ebda41f8SNicholas Wilson SyntheticFunctions.emplace_back(Function); 1984c2cbfe6SSam Clegg return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name, 1994c2cbfe6SSam Clegg Flags, nullptr, Function); 20050686856SSam Clegg } 20150686856SSam Clegg 20200245539SSam Clegg DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 20300245539SSam Clegg uint32_t Flags) { 204e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 205b961abc8SRui Ueyama assert(!find(Name)); 2064c2cbfe6SSam Clegg return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags); 207c94d393aSSam Clegg } 208c94d393aSSam Clegg 20993102974SSam Clegg DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 21093102974SSam Clegg InputGlobal *Global) { 211e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 212e7245b42SNicola Zaghen << "\n"); 213b961abc8SRui Ueyama assert(!find(Name)); 214ebda41f8SNicholas Wilson SyntheticGlobals.emplace_back(Global); 2154c2cbfe6SSam Clegg return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags, 2164c2cbfe6SSam Clegg nullptr, Global); 21793102974SSam Clegg } 21893102974SSam Clegg 219e3498ec5SRui Ueyama static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 220e3498ec5SRui Ueyama uint32_t NewFlags) { 221c03c9040SRui Ueyama // If existing symbol is undefined, replace it. 222e3498ec5SRui Ueyama if (!Existing->isDefined()) { 223e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 224e3498ec5SRui Ueyama << Existing->getName() << "\n"); 225c03c9040SRui Ueyama return true; 226c03c9040SRui Ueyama } 227c03c9040SRui Ueyama 228c03c9040SRui Ueyama // Now we have two defined symbols. If the new one is weak, we can ignore it. 229c03c9040SRui Ueyama if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 230e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 231c03c9040SRui Ueyama return false; 232c03c9040SRui Ueyama } 233c03c9040SRui Ueyama 234c03c9040SRui Ueyama // If the existing symbol is weak, we should replace it. 235e3498ec5SRui Ueyama if (Existing->isWeak()) { 236e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 237c03c9040SRui Ueyama return true; 238c03c9040SRui Ueyama } 239c03c9040SRui Ueyama 240c03c9040SRui Ueyama // Neither symbol is week. They conflict. 241e3498ec5SRui Ueyama error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 242e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined in " + 243e3498ec5SRui Ueyama toString(NewFile)); 244c03c9040SRui Ueyama return true; 245b8621596SSam Clegg } 24693e559b1SSam Clegg 24793e559b1SSam Clegg Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 248e3498ec5SRui Ueyama InputFile *File, 249e3498ec5SRui Ueyama InputFunction *Function) { 2508b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 2518b0b48f3SSam Clegg << (Function ? toString(Function->Signature) : "none") 2528b0b48f3SSam Clegg << "]\n"); 25393e559b1SSam Clegg Symbol *S; 25493e559b1SSam Clegg bool WasInserted; 2554c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 256c729c1b4SSam Clegg 257e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 258e3498ec5SRui Ueyama replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 259e3498ec5SRui Ueyama return S; 260e3498ec5SRui Ueyama } 261e3498ec5SRui Ueyama 262c729c1b4SSam Clegg if (Function) 263e3498ec5SRui Ueyama checkFunctionType(S, File, &Function->Signature); 264e3498ec5SRui Ueyama 2658b0b48f3SSam Clegg if (shouldReplace(S, File, Flags)) { 2668b0b48f3SSam Clegg // If the new defined function doesn't have signture (i.e. bitcode 26737b4ee52SSam Clegg // functions) but the old symbol does then preserve the old signature 2688b0b48f3SSam Clegg const WasmSignature *OldSig = nullptr; 2698b0b48f3SSam Clegg if (auto* F = dyn_cast<FunctionSymbol>(S)) 270e915a71fSHeejin Ahn OldSig = F->Signature; 27137b4ee52SSam Clegg if (auto *L = dyn_cast<LazySymbol>(S)) 27237b4ee52SSam Clegg OldSig = L->Signature; 2738b0b48f3SSam Clegg auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 274e915a71fSHeejin Ahn if (!NewSym->Signature) 275e915a71fSHeejin Ahn NewSym->Signature = OldSig; 2768b0b48f3SSam Clegg } 27793e559b1SSam Clegg return S; 27893e559b1SSam Clegg } 27993e559b1SSam Clegg 28000245539SSam Clegg Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 281e3498ec5SRui Ueyama InputFile *File, InputSegment *Segment, 28293102974SSam Clegg uint32_t Address, uint32_t Size) { 283e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 284e7245b42SNicola Zaghen << "\n"); 28593e559b1SSam Clegg Symbol *S; 28693e559b1SSam Clegg bool WasInserted; 2874c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 288c729c1b4SSam Clegg 289e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 290e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 291e3498ec5SRui Ueyama return S; 292e3498ec5SRui Ueyama } 293e3498ec5SRui Ueyama 294e3498ec5SRui Ueyama checkDataType(S, File); 295e3498ec5SRui Ueyama 296e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 297e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 298c94d393aSSam Clegg return S; 299c94d393aSSam Clegg } 300c94d393aSSam Clegg 30193102974SSam Clegg Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 302e3498ec5SRui Ueyama InputFile *File, InputGlobal *Global) { 303e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 3044c2cbfe6SSam Clegg 30593102974SSam Clegg Symbol *S; 30693102974SSam Clegg bool WasInserted; 3074c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 308c729c1b4SSam Clegg 309e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 310e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 31193102974SSam Clegg return S; 31293102974SSam Clegg } 31393102974SSam Clegg 314e3498ec5SRui Ueyama checkGlobalType(S, File, &Global->getType()); 315e3498ec5SRui Ueyama 316e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 317e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 318e3498ec5SRui Ueyama return S; 319e3498ec5SRui Ueyama } 320e3498ec5SRui Ueyama 321e915a71fSHeejin Ahn Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, 322e915a71fSHeejin Ahn InputFile *File, InputEvent *Event) { 323e915a71fSHeejin Ahn LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); 324e915a71fSHeejin Ahn 325e915a71fSHeejin Ahn Symbol *S; 326e915a71fSHeejin Ahn bool WasInserted; 327e915a71fSHeejin Ahn std::tie(S, WasInserted) = insert(Name, File); 328e915a71fSHeejin Ahn 329e915a71fSHeejin Ahn if (WasInserted || S->isLazy()) { 330e915a71fSHeejin Ahn replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 331e915a71fSHeejin Ahn return S; 332e915a71fSHeejin Ahn } 333e915a71fSHeejin Ahn 334e915a71fSHeejin Ahn checkEventType(S, File, &Event->getType(), &Event->Signature); 335e915a71fSHeejin Ahn 336e915a71fSHeejin Ahn if (shouldReplace(S, File, Flags)) 337e915a71fSHeejin Ahn replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 338e915a71fSHeejin Ahn return S; 339e915a71fSHeejin Ahn } 340e915a71fSHeejin Ahn 341*9b84eeaaSDan Gohman Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, 342*9b84eeaaSDan Gohman StringRef ImportModule, 3437cc07531SSam Clegg uint32_t Flags, InputFile *File, 344e3498ec5SRui Ueyama const WasmSignature *Sig) { 3458b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << 3468b0b48f3SSam Clegg " [" << (Sig ? toString(*Sig) : "none") << "]\n"); 347c03c9040SRui Ueyama 348c94d393aSSam Clegg Symbol *S; 349c94d393aSSam Clegg bool WasInserted; 3504c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 351c729c1b4SSam Clegg 352e3498ec5SRui Ueyama if (WasInserted) 353*9b84eeaaSDan Gohman replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags, 354*9b84eeaaSDan Gohman File, Sig); 355e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 356b961abc8SRui Ueyama Lazy->fetch(); 357cefbf9acSSam Clegg else 358e3498ec5SRui Ueyama checkFunctionType(S, File, Sig); 359cefbf9acSSam Clegg 360c03c9040SRui Ueyama return S; 361c03c9040SRui Ueyama } 362c03c9040SRui Ueyama 363e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 364e3498ec5SRui Ueyama InputFile *File) { 365e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 36693102974SSam Clegg 367e3498ec5SRui Ueyama Symbol *S; 368e3498ec5SRui Ueyama bool WasInserted; 3694c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 370f989a92dSSam Clegg 371e3498ec5SRui Ueyama if (WasInserted) 372e3498ec5SRui Ueyama replaceSymbol<UndefinedData>(S, Name, Flags, File); 373e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 374b961abc8SRui Ueyama Lazy->fetch(); 375e3498ec5SRui Ueyama else if (S->isDefined()) 376e3498ec5SRui Ueyama checkDataType(S, File); 377c94d393aSSam Clegg return S; 378c94d393aSSam Clegg } 379c94d393aSSam Clegg 380*9b84eeaaSDan Gohman Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, 381*9b84eeaaSDan Gohman StringRef ImportModule, uint32_t Flags, 382e3498ec5SRui Ueyama InputFile *File, 383e3498ec5SRui Ueyama const WasmGlobalType *Type) { 384e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 385e3498ec5SRui Ueyama 386e3498ec5SRui Ueyama Symbol *S; 387e3498ec5SRui Ueyama bool WasInserted; 3884c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 389c729c1b4SSam Clegg 390e3498ec5SRui Ueyama if (WasInserted) 391*9b84eeaaSDan Gohman replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags, 392*9b84eeaaSDan Gohman File, Type); 393e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 394b961abc8SRui Ueyama Lazy->fetch(); 395e3498ec5SRui Ueyama else if (S->isDefined()) 396e3498ec5SRui Ueyama checkGlobalType(S, File, Type); 397e3498ec5SRui Ueyama return S; 398e3498ec5SRui Ueyama } 399e3498ec5SRui Ueyama 400e3498ec5SRui Ueyama void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 401e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 402c94d393aSSam Clegg StringRef Name = Sym->getName(); 403c03c9040SRui Ueyama 404c94d393aSSam Clegg Symbol *S; 405c94d393aSSam Clegg bool WasInserted; 4064c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, nullptr); 407c03c9040SRui Ueyama 408c94d393aSSam Clegg if (WasInserted) { 40937b4ee52SSam Clegg replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym); 410c03c9040SRui Ueyama return; 411c03c9040SRui Ueyama } 412c03c9040SRui Ueyama 41337b4ee52SSam Clegg if (!S->isUndefined()) 41437b4ee52SSam Clegg return; 41537b4ee52SSam Clegg 41637b4ee52SSam Clegg // The existing symbol is undefined, load a new one from the archive, 41737b4ee52SSam Clegg // unless the the existing symbol is weak in which case replace the undefined 41837b4ee52SSam Clegg // symbols with a LazySymbol. 41937b4ee52SSam Clegg if (S->isWeak()) { 42037b4ee52SSam Clegg const WasmSignature *OldSig = nullptr; 42137b4ee52SSam Clegg // In the case of an UndefinedFunction we need to preserve the expected 42237b4ee52SSam Clegg // signature. 42337b4ee52SSam Clegg if (auto *F = dyn_cast<UndefinedFunction>(S)) 42437b4ee52SSam Clegg OldSig = F->Signature; 42537b4ee52SSam Clegg LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 42637b4ee52SSam Clegg auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK, 42737b4ee52SSam Clegg File, *Sym); 42837b4ee52SSam Clegg NewSym->Signature = OldSig; 42937b4ee52SSam Clegg return; 43037b4ee52SSam Clegg } 43137b4ee52SSam Clegg 432e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 433e3498ec5SRui Ueyama File->addMember(Sym); 434c94d393aSSam Clegg } 435e0f6fcd0SSam Clegg 436c4d9aa1bSNicholas Wilson bool SymbolTable::addComdat(StringRef Name) { 437c4d9aa1bSNicholas Wilson return Comdats.insert(CachedHashStringRef(Name)).second; 438e0f6fcd0SSam Clegg } 4391f3f774fSSam Clegg 4401f3f774fSSam Clegg // Set a flag for --trace-symbol so that we can print out a log message 4411f3f774fSSam Clegg // if a new symbol with the same name is inserted into the symbol table. 4421f3f774fSSam Clegg void SymbolTable::trace(StringRef Name) { 4431f3f774fSSam Clegg SymMap.insert({CachedHashStringRef(Name), -1}); 4441f3f774fSSam Clegg } 445