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)); 31c94d393aSSam Clegg File->parse(); 32c94d393aSSam Clegg 33c729c1b4SSam Clegg // LLVM bitcode file 34c729c1b4SSam Clegg if (auto *F = dyn_cast<BitcodeFile>(File)) 35c729c1b4SSam Clegg BitcodeFiles.push_back(F); 36c729c1b4SSam Clegg else if (auto *F = dyn_cast<ObjFile>(File)) 37c94d393aSSam Clegg ObjectFiles.push_back(F); 38c94d393aSSam Clegg } 39c94d393aSSam Clegg 40c729c1b4SSam Clegg // This function is where all the optimizations of link-time 41c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are 42c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format. 43c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files 44c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results. 45c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed 46c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization. 47c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() { 48c729c1b4SSam Clegg if (BitcodeFiles.empty()) 49c729c1b4SSam Clegg return; 50c729c1b4SSam Clegg 51c729c1b4SSam Clegg // Compile bitcode files and replace bitcode symbols. 52c729c1b4SSam Clegg LTO.reset(new BitcodeCompiler); 53c729c1b4SSam Clegg for (BitcodeFile *F : BitcodeFiles) 54c729c1b4SSam Clegg LTO->add(*F); 55c729c1b4SSam Clegg 56c729c1b4SSam Clegg for (StringRef Filename : LTO->compile()) { 57c729c1b4SSam Clegg auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp")); 58c729c1b4SSam Clegg Obj->parse(); 59c729c1b4SSam Clegg ObjectFiles.push_back(Obj); 60c729c1b4SSam Clegg } 61c729c1b4SSam Clegg } 62c729c1b4SSam Clegg 63c94d393aSSam Clegg void SymbolTable::reportRemainingUndefines() { 6474fe0ba1SSam Clegg for (Symbol *Sym : SymVector) { 65c729c1b4SSam Clegg if (!Sym->isUndefined() || Sym->isWeak()) 66c729c1b4SSam Clegg continue; 67c729c1b4SSam Clegg if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 68c729c1b4SSam Clegg continue; 69c729c1b4SSam Clegg if (!Sym->IsUsedInRegularObj) 70c729c1b4SSam Clegg continue; 7147e2b6b2SSam Clegg error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); 72c94d393aSSam Clegg } 73c94d393aSSam Clegg } 74c94d393aSSam Clegg 75c94d393aSSam Clegg Symbol *SymbolTable::find(StringRef Name) { 7667d6908fSRui Ueyama return SymMap.lookup(CachedHashStringRef(Name)); 77c94d393aSSam Clegg } 78c94d393aSSam Clegg 794c2cbfe6SSam Clegg std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { 804c2cbfe6SSam Clegg bool Inserted = false; 81a80d94d5SSam Clegg Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; 824c2cbfe6SSam Clegg if (!Sym) { 83dfb0b2c7SSam Clegg Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 84c729c1b4SSam Clegg Sym->IsUsedInRegularObj = false; 8574fe0ba1SSam Clegg SymVector.emplace_back(Sym); 864c2cbfe6SSam Clegg Inserted = true; 874c2cbfe6SSam Clegg } 884c2cbfe6SSam Clegg if (!File || File->kind() == InputFile::ObjectKind) 894c2cbfe6SSam Clegg Sym->IsUsedInRegularObj = true; 904c2cbfe6SSam Clegg return {Sym, Inserted}; 91c94d393aSSam Clegg } 92c94d393aSSam Clegg 93e3498ec5SRui Ueyama static void reportTypeError(const Symbol *Existing, const InputFile *File, 943876d89aSSam Clegg llvm::wasm::WasmSymbolType Type) { 95e3498ec5SRui Ueyama error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 96e3498ec5SRui Ueyama toString(Existing->getWasmType()) + " in " + 973876d89aSSam Clegg toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 983876d89aSSam Clegg " in " + toString(File)); 99e3498ec5SRui Ueyama } 100e3498ec5SRui Ueyama 1016f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing. 1026f4286fbSHeejin Ahn // For functions this can also involve verifying that the signatures match. 103cefbf9acSSam Clegg static void checkFunctionType(Symbol *Existing, const InputFile *File, 104e3498ec5SRui Ueyama const WasmSignature *NewSig) { 10565d6380cSSam Clegg auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); 10665d6380cSSam Clegg if (!ExistingFunction) { 1073876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION); 108e3498ec5SRui Ueyama return; 109e3498ec5SRui Ueyama } 110e3498ec5SRui Ueyama 111cefbf9acSSam Clegg if (!NewSig) 112cefbf9acSSam Clegg return; 113cefbf9acSSam Clegg 114e915a71fSHeejin Ahn const WasmSignature *OldSig = ExistingFunction->Signature; 115cefbf9acSSam Clegg if (!OldSig) { 116e915a71fSHeejin Ahn ExistingFunction->Signature = NewSig; 117cefbf9acSSam Clegg return; 118cefbf9acSSam Clegg } 119cefbf9acSSam Clegg 120cefbf9acSSam Clegg if (*NewSig != *OldSig) 121ffd0aaf8SSam Clegg warn("function signature mismatch: " + Existing->getName() + 122e3498ec5SRui Ueyama "\n>>> defined as " + toString(*OldSig) + " in " + 123e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined as " + 124ffd0aaf8SSam Clegg toString(*NewSig) + " in " + toString(File)); 125e3498ec5SRui Ueyama } 126e3498ec5SRui Ueyama 127e3498ec5SRui Ueyama static void checkGlobalType(const Symbol *Existing, const InputFile *File, 128e3498ec5SRui Ueyama const WasmGlobalType *NewType) { 129e3498ec5SRui Ueyama if (!isa<GlobalSymbol>(Existing)) { 1303876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 131b8621596SSam Clegg return; 132b8621596SSam Clegg } 133b8621596SSam Clegg 134e3498ec5SRui Ueyama const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 135e3498ec5SRui Ueyama if (*NewType != *OldType) { 136e3498ec5SRui Ueyama error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 137e3498ec5SRui Ueyama toString(*OldType) + " in " + toString(Existing->getFile()) + 138e3498ec5SRui Ueyama "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 139c94d393aSSam Clegg } 14024b3dcd4SSam Clegg } 14124b3dcd4SSam Clegg 142e915a71fSHeejin Ahn static void checkEventType(const Symbol *Existing, const InputFile *File, 143e915a71fSHeejin Ahn const WasmEventType *NewType, 144e915a71fSHeejin Ahn const WasmSignature *NewSig) { 145e915a71fSHeejin Ahn auto ExistingEvent = dyn_cast<EventSymbol>(Existing); 146e915a71fSHeejin Ahn if (!isa<EventSymbol>(Existing)) { 147e915a71fSHeejin Ahn reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); 148e915a71fSHeejin Ahn return; 149e915a71fSHeejin Ahn } 150e915a71fSHeejin Ahn 151e915a71fSHeejin Ahn const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); 152e915a71fSHeejin Ahn const WasmSignature *OldSig = ExistingEvent->Signature; 153e915a71fSHeejin Ahn if (NewType->Attribute != OldType->Attribute) 154e915a71fSHeejin Ahn error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + 155e915a71fSHeejin Ahn toString(*OldType) + " in " + toString(Existing->getFile()) + 156e915a71fSHeejin Ahn "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 157e915a71fSHeejin Ahn if (*NewSig != *OldSig) 158e915a71fSHeejin Ahn warn("Event signature mismatch: " + Existing->getName() + 159e915a71fSHeejin Ahn "\n>>> defined as " + toString(*OldSig) + " in " + 160e915a71fSHeejin Ahn toString(Existing->getFile()) + "\n>>> defined as " + 161e915a71fSHeejin Ahn toString(*NewSig) + " in " + toString(File)); 162e915a71fSHeejin Ahn } 163e915a71fSHeejin Ahn 164e3498ec5SRui Ueyama static void checkDataType(const Symbol *Existing, const InputFile *File) { 165e3498ec5SRui Ueyama if (!isa<DataSymbol>(Existing)) 1663876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 167e3498ec5SRui Ueyama } 168e3498ec5SRui Ueyama 169dfb0b2c7SSam Clegg DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 170ebda41f8SNicholas Wilson uint32_t Flags, 171ebda41f8SNicholas Wilson InputFunction *Function) { 172e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 173b961abc8SRui Ueyama assert(!find(Name)); 174ebda41f8SNicholas Wilson SyntheticFunctions.emplace_back(Function); 1754c2cbfe6SSam Clegg return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name, 1764c2cbfe6SSam Clegg Flags, nullptr, Function); 17750686856SSam Clegg } 17850686856SSam Clegg 17900245539SSam Clegg DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 18000245539SSam Clegg uint32_t Flags) { 181e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 182b961abc8SRui Ueyama assert(!find(Name)); 1834c2cbfe6SSam Clegg return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags); 184c94d393aSSam Clegg } 185c94d393aSSam Clegg 18693102974SSam Clegg DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 18793102974SSam Clegg InputGlobal *Global) { 188e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 189e7245b42SNicola Zaghen << "\n"); 190b961abc8SRui Ueyama assert(!find(Name)); 191ebda41f8SNicholas Wilson SyntheticGlobals.emplace_back(Global); 1924c2cbfe6SSam Clegg return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags, 1934c2cbfe6SSam Clegg nullptr, Global); 19493102974SSam Clegg } 19593102974SSam Clegg 196e3498ec5SRui Ueyama static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 197e3498ec5SRui Ueyama uint32_t NewFlags) { 198c03c9040SRui Ueyama // If existing symbol is undefined, replace it. 199e3498ec5SRui Ueyama if (!Existing->isDefined()) { 200e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 201e3498ec5SRui Ueyama << Existing->getName() << "\n"); 202c03c9040SRui Ueyama return true; 203c03c9040SRui Ueyama } 204c03c9040SRui Ueyama 205c03c9040SRui Ueyama // Now we have two defined symbols. If the new one is weak, we can ignore it. 206c03c9040SRui Ueyama if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 207e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 208c03c9040SRui Ueyama return false; 209c03c9040SRui Ueyama } 210c03c9040SRui Ueyama 211c03c9040SRui Ueyama // If the existing symbol is weak, we should replace it. 212e3498ec5SRui Ueyama if (Existing->isWeak()) { 213e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 214c03c9040SRui Ueyama return true; 215c03c9040SRui Ueyama } 216c03c9040SRui Ueyama 217c03c9040SRui Ueyama // Neither symbol is week. They conflict. 218e3498ec5SRui Ueyama error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 219e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined in " + 220e3498ec5SRui Ueyama toString(NewFile)); 221c03c9040SRui Ueyama return true; 222b8621596SSam Clegg } 22393e559b1SSam Clegg 22493e559b1SSam Clegg Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 225e3498ec5SRui Ueyama InputFile *File, 226e3498ec5SRui Ueyama InputFunction *Function) { 2278b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 2288b0b48f3SSam Clegg << (Function ? toString(Function->Signature) : "none") 2298b0b48f3SSam Clegg << "]\n"); 23093e559b1SSam Clegg Symbol *S; 23193e559b1SSam Clegg bool WasInserted; 2324c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 233c729c1b4SSam Clegg 234e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 235e3498ec5SRui Ueyama replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 236e3498ec5SRui Ueyama return S; 237e3498ec5SRui Ueyama } 238e3498ec5SRui Ueyama 239c729c1b4SSam Clegg if (Function) 240e3498ec5SRui Ueyama checkFunctionType(S, File, &Function->Signature); 241e3498ec5SRui Ueyama 2428b0b48f3SSam Clegg if (shouldReplace(S, File, Flags)) { 2438b0b48f3SSam Clegg // If the new defined function doesn't have signture (i.e. bitcode 24437b4ee52SSam Clegg // functions) but the old symbol does then preserve the old signature 2458b0b48f3SSam Clegg const WasmSignature *OldSig = nullptr; 2468b0b48f3SSam Clegg if (auto* F = dyn_cast<FunctionSymbol>(S)) 247e915a71fSHeejin Ahn OldSig = F->Signature; 24837b4ee52SSam Clegg if (auto *L = dyn_cast<LazySymbol>(S)) 24937b4ee52SSam Clegg OldSig = L->Signature; 2508b0b48f3SSam Clegg auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 251e915a71fSHeejin Ahn if (!NewSym->Signature) 252e915a71fSHeejin Ahn NewSym->Signature = OldSig; 2538b0b48f3SSam Clegg } 25493e559b1SSam Clegg return S; 25593e559b1SSam Clegg } 25693e559b1SSam Clegg 25700245539SSam Clegg Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 258e3498ec5SRui Ueyama InputFile *File, InputSegment *Segment, 25993102974SSam Clegg uint32_t Address, uint32_t Size) { 260e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 261e7245b42SNicola Zaghen << "\n"); 26293e559b1SSam Clegg Symbol *S; 26393e559b1SSam Clegg bool WasInserted; 2644c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 265c729c1b4SSam Clegg 266e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 267e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 268e3498ec5SRui Ueyama return S; 269e3498ec5SRui Ueyama } 270e3498ec5SRui Ueyama 271e3498ec5SRui Ueyama checkDataType(S, File); 272e3498ec5SRui Ueyama 273e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 274e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 275c94d393aSSam Clegg return S; 276c94d393aSSam Clegg } 277c94d393aSSam Clegg 27893102974SSam Clegg Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 279e3498ec5SRui Ueyama InputFile *File, InputGlobal *Global) { 280e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 2814c2cbfe6SSam Clegg 28293102974SSam Clegg Symbol *S; 28393102974SSam Clegg bool WasInserted; 2844c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 285c729c1b4SSam Clegg 286e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 287e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 28893102974SSam Clegg return S; 28993102974SSam Clegg } 29093102974SSam Clegg 291e3498ec5SRui Ueyama checkGlobalType(S, File, &Global->getType()); 292e3498ec5SRui Ueyama 293e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 294e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 295e3498ec5SRui Ueyama return S; 296e3498ec5SRui Ueyama } 297e3498ec5SRui Ueyama 298e915a71fSHeejin Ahn Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, 299e915a71fSHeejin Ahn InputFile *File, InputEvent *Event) { 300e915a71fSHeejin Ahn LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); 301e915a71fSHeejin Ahn 302e915a71fSHeejin Ahn Symbol *S; 303e915a71fSHeejin Ahn bool WasInserted; 304e915a71fSHeejin Ahn std::tie(S, WasInserted) = insert(Name, File); 305e915a71fSHeejin Ahn 306e915a71fSHeejin Ahn if (WasInserted || S->isLazy()) { 307e915a71fSHeejin Ahn replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 308e915a71fSHeejin Ahn return S; 309e915a71fSHeejin Ahn } 310e915a71fSHeejin Ahn 311e915a71fSHeejin Ahn checkEventType(S, File, &Event->getType(), &Event->Signature); 312e915a71fSHeejin Ahn 313e915a71fSHeejin Ahn if (shouldReplace(S, File, Flags)) 314e915a71fSHeejin Ahn replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 315e915a71fSHeejin Ahn return S; 316e915a71fSHeejin Ahn } 317e915a71fSHeejin Ahn 318*7cc07531SSam Clegg Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef Module, 319*7cc07531SSam Clegg uint32_t Flags, InputFile *File, 320e3498ec5SRui Ueyama const WasmSignature *Sig) { 3218b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << 3228b0b48f3SSam Clegg " [" << (Sig ? toString(*Sig) : "none") << "]\n"); 323c03c9040SRui Ueyama 324c94d393aSSam Clegg Symbol *S; 325c94d393aSSam Clegg bool WasInserted; 3264c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 327c729c1b4SSam Clegg 328e3498ec5SRui Ueyama if (WasInserted) 329*7cc07531SSam Clegg replaceSymbol<UndefinedFunction>(S, Name, Module, Flags, File, Sig); 330e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 331b961abc8SRui Ueyama Lazy->fetch(); 332cefbf9acSSam Clegg else 333e3498ec5SRui Ueyama checkFunctionType(S, File, Sig); 334cefbf9acSSam Clegg 335c03c9040SRui Ueyama return S; 336c03c9040SRui Ueyama } 337c03c9040SRui Ueyama 338e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 339e3498ec5SRui Ueyama InputFile *File) { 340e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 34193102974SSam Clegg 342e3498ec5SRui Ueyama Symbol *S; 343e3498ec5SRui Ueyama bool WasInserted; 3444c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 345f989a92dSSam Clegg 346e3498ec5SRui Ueyama if (WasInserted) 347e3498ec5SRui Ueyama replaceSymbol<UndefinedData>(S, Name, Flags, File); 348e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 349b961abc8SRui Ueyama Lazy->fetch(); 350e3498ec5SRui Ueyama else if (S->isDefined()) 351e3498ec5SRui Ueyama checkDataType(S, File); 352c94d393aSSam Clegg return S; 353c94d393aSSam Clegg } 354c94d393aSSam Clegg 355e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, 356e3498ec5SRui Ueyama InputFile *File, 357e3498ec5SRui Ueyama const WasmGlobalType *Type) { 358e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 359e3498ec5SRui Ueyama 360e3498ec5SRui Ueyama Symbol *S; 361e3498ec5SRui Ueyama bool WasInserted; 3624c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 363c729c1b4SSam Clegg 364e3498ec5SRui Ueyama if (WasInserted) 365e3498ec5SRui Ueyama replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); 366e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 367b961abc8SRui Ueyama Lazy->fetch(); 368e3498ec5SRui Ueyama else if (S->isDefined()) 369e3498ec5SRui Ueyama checkGlobalType(S, File, Type); 370e3498ec5SRui Ueyama return S; 371e3498ec5SRui Ueyama } 372e3498ec5SRui Ueyama 373e3498ec5SRui Ueyama void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 374e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 375c94d393aSSam Clegg StringRef Name = Sym->getName(); 376c03c9040SRui Ueyama 377c94d393aSSam Clegg Symbol *S; 378c94d393aSSam Clegg bool WasInserted; 3794c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, nullptr); 380c03c9040SRui Ueyama 381c94d393aSSam Clegg if (WasInserted) { 38237b4ee52SSam Clegg replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym); 383c03c9040SRui Ueyama return; 384c03c9040SRui Ueyama } 385c03c9040SRui Ueyama 38637b4ee52SSam Clegg if (!S->isUndefined()) 38737b4ee52SSam Clegg return; 38837b4ee52SSam Clegg 38937b4ee52SSam Clegg // The existing symbol is undefined, load a new one from the archive, 39037b4ee52SSam Clegg // unless the the existing symbol is weak in which case replace the undefined 39137b4ee52SSam Clegg // symbols with a LazySymbol. 39237b4ee52SSam Clegg if (S->isWeak()) { 39337b4ee52SSam Clegg const WasmSignature *OldSig = nullptr; 39437b4ee52SSam Clegg // In the case of an UndefinedFunction we need to preserve the expected 39537b4ee52SSam Clegg // signature. 39637b4ee52SSam Clegg if (auto *F = dyn_cast<UndefinedFunction>(S)) 39737b4ee52SSam Clegg OldSig = F->Signature; 39837b4ee52SSam Clegg LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 39937b4ee52SSam Clegg auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK, 40037b4ee52SSam Clegg File, *Sym); 40137b4ee52SSam Clegg NewSym->Signature = OldSig; 40237b4ee52SSam Clegg return; 40337b4ee52SSam Clegg } 40437b4ee52SSam Clegg 405e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 406e3498ec5SRui Ueyama File->addMember(Sym); 407c94d393aSSam Clegg } 408e0f6fcd0SSam Clegg 409c4d9aa1bSNicholas Wilson bool SymbolTable::addComdat(StringRef Name) { 410c4d9aa1bSNicholas Wilson return Comdats.insert(CachedHashStringRef(Name)).second; 411e0f6fcd0SSam Clegg } 412