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 2533c59abfSFangrui Song namespace lld { 2633c59abfSFangrui Song namespace wasm { 2733c59abfSFangrui Song SymbolTable *symtab; 28c94d393aSSam Clegg 29136d27abSRui Ueyama void SymbolTable::addFile(InputFile *file) { 30136d27abSRui Ueyama log("Processing: " + toString(file)); 31a282a61bSSam Clegg 32a282a61bSSam Clegg // .a file 33136d27abSRui Ueyama if (auto *f = dyn_cast<ArchiveFile>(file)) { 34136d27abSRui Ueyama f->parse(); 35a282a61bSSam Clegg return; 36a282a61bSSam Clegg } 37a282a61bSSam Clegg 38a282a61bSSam Clegg // .so file 39136d27abSRui Ueyama if (auto *f = dyn_cast<SharedFile>(file)) { 40136d27abSRui Ueyama sharedFiles.push_back(f); 41a282a61bSSam Clegg return; 42a282a61bSSam Clegg } 43a282a61bSSam Clegg 44136d27abSRui Ueyama if (config->trace) 45136d27abSRui Ueyama message(toString(file)); 46c94d393aSSam Clegg 47c729c1b4SSam Clegg // LLVM bitcode file 48136d27abSRui Ueyama if (auto *f = dyn_cast<BitcodeFile>(file)) { 49136d27abSRui Ueyama f->parse(); 50136d27abSRui Ueyama bitcodeFiles.push_back(f); 51a282a61bSSam Clegg return; 52a282a61bSSam Clegg } 53a282a61bSSam Clegg 54a282a61bSSam Clegg // Regular object file 55136d27abSRui Ueyama auto *f = cast<ObjFile>(file); 56136d27abSRui Ueyama f->parse(false); 57136d27abSRui Ueyama objectFiles.push_back(f); 58c94d393aSSam Clegg } 59c94d393aSSam Clegg 60c729c1b4SSam Clegg // This function is where all the optimizations of link-time 61c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are 62c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format. 63c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files 64c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results. 65c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed 66c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization. 67c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() { 68b062fe18SSam Clegg // Prevent further LTO objects being included 69b062fe18SSam Clegg BitcodeFile::doneLTO = true; 70b062fe18SSam Clegg 71136d27abSRui Ueyama if (bitcodeFiles.empty()) 72c729c1b4SSam Clegg return; 73c729c1b4SSam Clegg 74c729c1b4SSam Clegg // Compile bitcode files and replace bitcode symbols. 75136d27abSRui Ueyama lto.reset(new BitcodeCompiler); 76136d27abSRui Ueyama for (BitcodeFile *f : bitcodeFiles) 77136d27abSRui Ueyama lto->add(*f); 78c729c1b4SSam Clegg 79136d27abSRui Ueyama for (StringRef filename : lto->compile()) { 80136d27abSRui Ueyama auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), ""); 81136d27abSRui Ueyama obj->parse(true); 82136d27abSRui Ueyama objectFiles.push_back(obj); 83c729c1b4SSam Clegg } 84c729c1b4SSam Clegg } 85c729c1b4SSam Clegg 86136d27abSRui Ueyama Symbol *SymbolTable::find(StringRef name) { 87136d27abSRui Ueyama auto it = symMap.find(CachedHashStringRef(name)); 88136d27abSRui Ueyama if (it == symMap.end() || it->second == -1) 891f3f774fSSam Clegg return nullptr; 90136d27abSRui Ueyama return symVector[it->second]; 911f3f774fSSam Clegg } 921f3f774fSSam Clegg 93136d27abSRui Ueyama void SymbolTable::replace(StringRef name, Symbol* sym) { 94136d27abSRui Ueyama auto it = symMap.find(CachedHashStringRef(name)); 95136d27abSRui Ueyama symVector[it->second] = sym; 966540e570SSam Clegg } 976540e570SSam Clegg 98136d27abSRui Ueyama std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) { 99136d27abSRui Ueyama bool trace = false; 100136d27abSRui Ueyama auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 101136d27abSRui Ueyama int &symIndex = p.first->second; 102136d27abSRui Ueyama bool isNew = p.second; 103136d27abSRui Ueyama if (symIndex == -1) { 104136d27abSRui Ueyama symIndex = symVector.size(); 105136d27abSRui Ueyama trace = true; 106136d27abSRui Ueyama isNew = true; 1071f3f774fSSam Clegg } 1081f3f774fSSam Clegg 109136d27abSRui Ueyama if (!isNew) 110136d27abSRui Ueyama return {symVector[symIndex], false}; 1111f3f774fSSam Clegg 112136d27abSRui Ueyama Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 113136d27abSRui Ueyama sym->isUsedInRegularObj = false; 114136d27abSRui Ueyama sym->canInline = true; 115136d27abSRui Ueyama sym->traced = trace; 116064e9907SSam Clegg sym->forceExport = false; 117136d27abSRui Ueyama symVector.emplace_back(sym); 118136d27abSRui Ueyama return {sym, true}; 119c94d393aSSam Clegg } 120c94d393aSSam Clegg 121136d27abSRui Ueyama std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, 122136d27abSRui Ueyama const InputFile *file) { 123136d27abSRui Ueyama Symbol *s; 124136d27abSRui Ueyama bool wasInserted; 125136d27abSRui Ueyama std::tie(s, wasInserted) = insertName(name); 1261f3f774fSSam Clegg 127136d27abSRui Ueyama if (!file || file->kind() == InputFile::ObjectKind) 128136d27abSRui Ueyama s->isUsedInRegularObj = true; 1291f3f774fSSam Clegg 130136d27abSRui Ueyama return {s, wasInserted}; 131c94d393aSSam Clegg } 132c94d393aSSam Clegg 133136d27abSRui Ueyama static void reportTypeError(const Symbol *existing, const InputFile *file, 134136d27abSRui Ueyama llvm::wasm::WasmSymbolType type) { 135136d27abSRui Ueyama error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " + 136136d27abSRui Ueyama toString(existing->getWasmType()) + " in " + 137136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined as " + toString(type) + 138136d27abSRui Ueyama " in " + toString(file)); 139e3498ec5SRui Ueyama } 140e3498ec5SRui Ueyama 1416f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing. 1427c5fcb35SKazuaki Ishizaki // Returns true if the function types match, false is there is a signature 1436540e570SSam Clegg // mismatch. 144136d27abSRui Ueyama static bool signatureMatches(FunctionSymbol *existing, 145136d27abSRui Ueyama const WasmSignature *newSig) { 146136d27abSRui Ueyama const WasmSignature *oldSig = existing->signature; 147d506b0a4SSam Clegg 148d506b0a4SSam Clegg // If either function is missing a signature (this happend for bitcode 149d506b0a4SSam Clegg // symbols) then assume they match. Any mismatch will be reported later 150d506b0a4SSam Clegg // when the LTO objects are added. 151136d27abSRui Ueyama if (!newSig || !oldSig) 1526540e570SSam Clegg return true; 153cefbf9acSSam Clegg 154136d27abSRui Ueyama return *newSig == *oldSig; 155e3498ec5SRui Ueyama } 156e3498ec5SRui Ueyama 157136d27abSRui Ueyama static void checkGlobalType(const Symbol *existing, const InputFile *file, 158136d27abSRui Ueyama const WasmGlobalType *newType) { 159136d27abSRui Ueyama if (!isa<GlobalSymbol>(existing)) { 160136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL); 161b8621596SSam Clegg return; 162b8621596SSam Clegg } 163b8621596SSam Clegg 164136d27abSRui Ueyama const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType(); 165136d27abSRui Ueyama if (*newType != *oldType) { 166136d27abSRui Ueyama error("Global type mismatch: " + existing->getName() + "\n>>> defined as " + 167136d27abSRui Ueyama toString(*oldType) + " in " + toString(existing->getFile()) + 168136d27abSRui Ueyama "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 169c94d393aSSam Clegg } 17024b3dcd4SSam Clegg } 17124b3dcd4SSam Clegg 172136d27abSRui Ueyama static void checkEventType(const Symbol *existing, const InputFile *file, 173136d27abSRui Ueyama const WasmEventType *newType, 174136d27abSRui Ueyama const WasmSignature *newSig) { 175136d27abSRui Ueyama auto existingEvent = dyn_cast<EventSymbol>(existing); 176136d27abSRui Ueyama if (!isa<EventSymbol>(existing)) { 177136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT); 178e915a71fSHeejin Ahn return; 179e915a71fSHeejin Ahn } 180e915a71fSHeejin Ahn 181136d27abSRui Ueyama const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType(); 182136d27abSRui Ueyama const WasmSignature *oldSig = existingEvent->signature; 183136d27abSRui Ueyama if (newType->Attribute != oldType->Attribute) 184136d27abSRui Ueyama error("Event type mismatch: " + existing->getName() + "\n>>> defined as " + 185136d27abSRui Ueyama toString(*oldType) + " in " + toString(existing->getFile()) + 186136d27abSRui Ueyama "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 187136d27abSRui Ueyama if (*newSig != *oldSig) 188136d27abSRui Ueyama warn("Event signature mismatch: " + existing->getName() + 189136d27abSRui Ueyama "\n>>> defined as " + toString(*oldSig) + " in " + 190136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined as " + 191136d27abSRui Ueyama toString(*newSig) + " in " + toString(file)); 192e915a71fSHeejin Ahn } 193e915a71fSHeejin Ahn 194136d27abSRui Ueyama static void checkDataType(const Symbol *existing, const InputFile *file) { 195136d27abSRui Ueyama if (!isa<DataSymbol>(existing)) 196136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA); 197e3498ec5SRui Ueyama } 198e3498ec5SRui Ueyama 199136d27abSRui Ueyama DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, 200136d27abSRui Ueyama uint32_t flags, 201136d27abSRui Ueyama InputFunction *function) { 202136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n"); 203136d27abSRui Ueyama assert(!find(name)); 204136d27abSRui Ueyama syntheticFunctions.emplace_back(function); 205136d27abSRui Ueyama return replaceSymbol<DefinedFunction>(insertName(name).first, name, 206136d27abSRui Ueyama flags, nullptr, function); 20750686856SSam Clegg } 20850686856SSam Clegg 20929a3056bSSam Clegg // Adds an optional, linker generated, data symbol. The symbol will only be 2107ae3d335SKazuaki Ishizaki // added if there is an undefine reference to it, or if it is explicitly 2117ae3d335SKazuaki Ishizaki // exported via the --export flag. Otherwise we don't add the symbol and return 2127ae3d335SKazuaki Ishizaki // nullptr. 213caa0db13SSam Clegg DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, 214582fd474SWouter van Oortmerssen uint64_t value) { 215136d27abSRui Ueyama Symbol *s = find(name); 216136d27abSRui Ueyama if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) 217136d27abSRui Ueyama s = insertName(name).first; 218136d27abSRui Ueyama else if (!s || s->isDefined()) 2194bce63a0SSam Clegg return nullptr; 220136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); 221caa0db13SSam Clegg auto *rtn = replaceSymbol<DefinedData>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN); 222136d27abSRui Ueyama rtn->setVirtualAddress(value); 223136d27abSRui Ueyama rtn->referenced = true; 2244bce63a0SSam Clegg return rtn; 2254bce63a0SSam Clegg } 2264bce63a0SSam Clegg 227136d27abSRui Ueyama DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name, 228136d27abSRui Ueyama uint32_t flags) { 229136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n"); 230136d27abSRui Ueyama assert(!find(name)); 231136d27abSRui Ueyama return replaceSymbol<DefinedData>(insertName(name).first, name, flags); 232c94d393aSSam Clegg } 233c94d393aSSam Clegg 234136d27abSRui Ueyama DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags, 235136d27abSRui Ueyama InputGlobal *global) { 236136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global 237e7245b42SNicola Zaghen << "\n"); 238136d27abSRui Ueyama assert(!find(name)); 239136d27abSRui Ueyama syntheticGlobals.emplace_back(global); 240136d27abSRui Ueyama return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags, 241136d27abSRui Ueyama nullptr, global); 24293102974SSam Clegg } 24393102974SSam Clegg 24429a3056bSSam Clegg DefinedGlobal *SymbolTable::addOptionalGlobalSymbols(StringRef name, 24529a3056bSSam Clegg uint32_t flags, 24629a3056bSSam Clegg InputGlobal *global) { 24729a3056bSSam Clegg LLVM_DEBUG(dbgs() << "addOptionalGlobalSymbols: " << name << " -> " << global 24829a3056bSSam Clegg << "\n"); 24929a3056bSSam Clegg Symbol *s = find(name); 25029a3056bSSam Clegg if (!s || s->isDefined()) 25129a3056bSSam Clegg return nullptr; 25229a3056bSSam Clegg syntheticGlobals.emplace_back(global); 25329a3056bSSam Clegg return replaceSymbol<DefinedGlobal>(s, name, flags, nullptr, global); 25429a3056bSSam Clegg } 25529a3056bSSam Clegg 256136d27abSRui Ueyama static bool shouldReplace(const Symbol *existing, InputFile *newFile, 257136d27abSRui Ueyama uint32_t newFlags) { 258c03c9040SRui Ueyama // If existing symbol is undefined, replace it. 259136d27abSRui Ueyama if (!existing->isDefined()) { 260e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 261136d27abSRui Ueyama << existing->getName() << "\n"); 262c03c9040SRui Ueyama return true; 263c03c9040SRui Ueyama } 264c03c9040SRui Ueyama 265c03c9040SRui Ueyama // Now we have two defined symbols. If the new one is weak, we can ignore it. 266136d27abSRui Ueyama if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 267e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 268c03c9040SRui Ueyama return false; 269c03c9040SRui Ueyama } 270c03c9040SRui Ueyama 271c03c9040SRui Ueyama // If the existing symbol is weak, we should replace it. 272136d27abSRui Ueyama if (existing->isWeak()) { 273e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 274c03c9040SRui Ueyama return true; 275c03c9040SRui Ueyama } 276c03c9040SRui Ueyama 277c03c9040SRui Ueyama // Neither symbol is week. They conflict. 278136d27abSRui Ueyama error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " + 279136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined in " + 280136d27abSRui Ueyama toString(newFile)); 281c03c9040SRui Ueyama return true; 282b8621596SSam Clegg } 28393e559b1SSam Clegg 284136d27abSRui Ueyama Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags, 285136d27abSRui Ueyama InputFile *file, 286136d27abSRui Ueyama InputFunction *function) { 287136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " [" 288136d27abSRui Ueyama << (function ? toString(function->signature) : "none") 2898b0b48f3SSam Clegg << "]\n"); 290136d27abSRui Ueyama Symbol *s; 291136d27abSRui Ueyama bool wasInserted; 292136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 293c729c1b4SSam Clegg 294136d27abSRui Ueyama auto replaceSym = [&](Symbol *sym) { 2957c5fcb35SKazuaki Ishizaki // If the new defined function doesn't have signature (i.e. bitcode 2966540e570SSam Clegg // functions) but the old symbol does, then preserve the old signature 297136d27abSRui Ueyama const WasmSignature *oldSig = s->getSignature(); 298136d27abSRui Ueyama auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function); 299136d27abSRui Ueyama if (!newSym->signature) 300136d27abSRui Ueyama newSym->signature = oldSig; 3016540e570SSam Clegg }; 3026540e570SSam Clegg 303136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 304136d27abSRui Ueyama replaceSym(s); 305136d27abSRui Ueyama return s; 306e3498ec5SRui Ueyama } 307e3498ec5SRui Ueyama 308136d27abSRui Ueyama auto existingFunction = dyn_cast<FunctionSymbol>(s); 309136d27abSRui Ueyama if (!existingFunction) { 310136d27abSRui Ueyama reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 311136d27abSRui Ueyama return s; 3128b0b48f3SSam Clegg } 3136540e570SSam Clegg 314136d27abSRui Ueyama bool checkSig = true; 315136d27abSRui Ueyama if (auto ud = dyn_cast<UndefinedFunction>(existingFunction)) 316136d27abSRui Ueyama checkSig = ud->isCalledDirectly; 31759f959ffSSam Clegg 318136d27abSRui Ueyama if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) { 319136d27abSRui Ueyama Symbol* variant; 320136d27abSRui Ueyama if (getFunctionVariant(s, &function->signature, file, &variant)) 3216540e570SSam Clegg // New variant, always replace 322136d27abSRui Ueyama replaceSym(variant); 323136d27abSRui Ueyama else if (shouldReplace(s, file, flags)) 3246540e570SSam Clegg // Variant already exists, replace it after checking shouldReplace 325136d27abSRui Ueyama replaceSym(variant); 3266540e570SSam Clegg 3276540e570SSam Clegg // This variant we found take the place in the symbol table as the primary 3286540e570SSam Clegg // variant. 329136d27abSRui Ueyama replace(name, variant); 330136d27abSRui Ueyama return variant; 3316540e570SSam Clegg } 3326540e570SSam Clegg 3336540e570SSam Clegg // Existing function with matching signature. 334136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 335136d27abSRui Ueyama replaceSym(s); 3366540e570SSam Clegg 337136d27abSRui Ueyama return s; 33893e559b1SSam Clegg } 33993e559b1SSam Clegg 340136d27abSRui Ueyama Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, 341136d27abSRui Ueyama InputFile *file, InputSegment *segment, 3423b29376eSWouter van Oortmerssen uint64_t address, uint64_t size) { 343136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address 344e7245b42SNicola Zaghen << "\n"); 345136d27abSRui Ueyama Symbol *s; 346136d27abSRui Ueyama bool wasInserted; 347136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 348c729c1b4SSam Clegg 349136d27abSRui Ueyama auto replaceSym = [&]() { 350136d27abSRui Ueyama replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size); 3516540e570SSam Clegg }; 3526540e570SSam Clegg 353136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 354136d27abSRui Ueyama replaceSym(); 355136d27abSRui Ueyama return s; 356e3498ec5SRui Ueyama } 357e3498ec5SRui Ueyama 358136d27abSRui Ueyama checkDataType(s, file); 359e3498ec5SRui Ueyama 360136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 361136d27abSRui Ueyama replaceSym(); 362136d27abSRui Ueyama return s; 363c94d393aSSam Clegg } 364c94d393aSSam Clegg 365136d27abSRui Ueyama Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags, 366136d27abSRui Ueyama InputFile *file, InputGlobal *global) { 367136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n"); 3684c2cbfe6SSam Clegg 369136d27abSRui Ueyama Symbol *s; 370136d27abSRui Ueyama bool wasInserted; 371136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 372c729c1b4SSam Clegg 373136d27abSRui Ueyama auto replaceSym = [&]() { 374136d27abSRui Ueyama replaceSymbol<DefinedGlobal>(s, name, flags, file, global); 3756540e570SSam Clegg }; 3766540e570SSam Clegg 377136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 378136d27abSRui Ueyama replaceSym(); 379136d27abSRui Ueyama return s; 38093102974SSam Clegg } 38193102974SSam Clegg 382136d27abSRui Ueyama checkGlobalType(s, file, &global->getType()); 383e3498ec5SRui Ueyama 384136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 385136d27abSRui Ueyama replaceSym(); 386136d27abSRui Ueyama return s; 387e3498ec5SRui Ueyama } 388e3498ec5SRui Ueyama 389136d27abSRui Ueyama Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags, 390136d27abSRui Ueyama InputFile *file, InputEvent *event) { 391136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n"); 392e915a71fSHeejin Ahn 393136d27abSRui Ueyama Symbol *s; 394136d27abSRui Ueyama bool wasInserted; 395136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 396e915a71fSHeejin Ahn 397136d27abSRui Ueyama auto replaceSym = [&]() { 398136d27abSRui Ueyama replaceSymbol<DefinedEvent>(s, name, flags, file, event); 3996540e570SSam Clegg }; 4006540e570SSam Clegg 401136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 402136d27abSRui Ueyama replaceSym(); 403136d27abSRui Ueyama return s; 404e915a71fSHeejin Ahn } 405e915a71fSHeejin Ahn 406136d27abSRui Ueyama checkEventType(s, file, &event->getType(), &event->signature); 407e915a71fSHeejin Ahn 408136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 409136d27abSRui Ueyama replaceSym(); 410136d27abSRui Ueyama return s; 411e915a71fSHeejin Ahn } 412e915a71fSHeejin Ahn 41367b05584SSam Clegg // This function get called when an undefined symbol is added, and there is 41467b05584SSam Clegg // already an existing one in the symbols table. In this case we check that 41567b05584SSam Clegg // custom 'import-module' and 'import-field' symbol attributes agree. 4167ae3d335SKazuaki Ishizaki // With LTO these attributes are not available when the bitcode is read and only 41767b05584SSam Clegg // become available when the LTO object is read. In this case we silently 41867b05584SSam Clegg // replace the empty attributes with the valid ones. 41967b05584SSam Clegg template <typename T> 420bd481277SSam Clegg static void setImportAttributes(T *existing, Optional<StringRef> importName, 421bd481277SSam Clegg Optional<StringRef> importModule, 422a57f1a54SSam Clegg uint32_t flags, InputFile *file) { 423bd481277SSam Clegg if (importName) { 424bd481277SSam Clegg if (!existing->importName) 42567b05584SSam Clegg existing->importName = importName; 42667b05584SSam Clegg if (existing->importName != importName) 42767b05584SSam Clegg error("import name mismatch for symbol: " + toString(*existing) + 428bd481277SSam Clegg "\n>>> defined as " + *existing->importName + " in " + 429bd481277SSam Clegg toString(existing->getFile()) + "\n>>> defined as " + *importName + 43067b05584SSam Clegg " in " + toString(file)); 43167b05584SSam Clegg } 43267b05584SSam Clegg 433bd481277SSam Clegg if (importModule) { 434bd481277SSam Clegg if (!existing->importModule) 43567b05584SSam Clegg existing->importModule = importModule; 43667b05584SSam Clegg if (existing->importModule != importModule) 43767b05584SSam Clegg error("import module mismatch for symbol: " + toString(*existing) + 438bd481277SSam Clegg "\n>>> defined as " + *existing->importModule + " in " + 439bd481277SSam Clegg toString(existing->getFile()) + "\n>>> defined as " + 440bd481277SSam Clegg *importModule + " in " + toString(file)); 44167b05584SSam Clegg } 442a57f1a54SSam Clegg 443a57f1a54SSam Clegg // Update symbol binding, if the existing symbol is weak 444a57f1a54SSam Clegg uint32_t binding = flags & WASM_SYMBOL_BINDING_MASK; 445a57f1a54SSam Clegg if (existing->isWeak() && binding != WASM_SYMBOL_BINDING_WEAK) { 446a57f1a54SSam Clegg existing->flags = (existing->flags & ~WASM_SYMBOL_BINDING_MASK) | binding; 447a57f1a54SSam Clegg } 44867b05584SSam Clegg } 44967b05584SSam Clegg 450bd481277SSam Clegg Symbol *SymbolTable::addUndefinedFunction(StringRef name, 451bd481277SSam Clegg Optional<StringRef> importName, 452bd481277SSam Clegg Optional<StringRef> importModule, 453136d27abSRui Ueyama uint32_t flags, InputFile *file, 454136d27abSRui Ueyama const WasmSignature *sig, 455136d27abSRui Ueyama bool isCalledDirectly) { 456136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " [" 457136d27abSRui Ueyama << (sig ? toString(*sig) : "none") 458a57f1a54SSam Clegg << "] IsCalledDirectly:" << isCalledDirectly << " flags=0x" 459a57f1a54SSam Clegg << utohexstr(flags) << "\n"); 460f6f4b98fSSam Clegg assert(flags & WASM_SYMBOL_UNDEFINED); 461c03c9040SRui Ueyama 462136d27abSRui Ueyama Symbol *s; 463136d27abSRui Ueyama bool wasInserted; 464136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 465136d27abSRui Ueyama if (s->traced) 466136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 467c729c1b4SSam Clegg 468136d27abSRui Ueyama auto replaceSym = [&]() { 469136d27abSRui Ueyama replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags, 470136d27abSRui Ueyama file, sig, isCalledDirectly); 4716540e570SSam Clegg }; 4726540e570SSam Clegg 473b34ec596SSam Clegg if (wasInserted) { 474136d27abSRui Ueyama replaceSym(); 475b34ec596SSam Clegg } else if (auto *lazy = dyn_cast<LazySymbol>(s)) { 476b34ec596SSam Clegg if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 477b34ec596SSam Clegg lazy->setWeak(); 478b34ec596SSam Clegg lazy->signature = sig; 479b34ec596SSam Clegg } else { 480136d27abSRui Ueyama lazy->fetch(); 481b34ec596SSam Clegg } 482b34ec596SSam Clegg } else { 483136d27abSRui Ueyama auto existingFunction = dyn_cast<FunctionSymbol>(s); 484136d27abSRui Ueyama if (!existingFunction) { 485136d27abSRui Ueyama reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 486136d27abSRui Ueyama return s; 4876540e570SSam Clegg } 488136d27abSRui Ueyama if (!existingFunction->signature && sig) 489136d27abSRui Ueyama existingFunction->signature = sig; 490a57f1a54SSam Clegg auto *existingUndefined = dyn_cast<UndefinedFunction>(existingFunction); 491fecfc592SSam Clegg if (isCalledDirectly && !signatureMatches(existingFunction, sig)) { 492a57f1a54SSam Clegg // If the existing undefined functions is not called directly then let 493fecfc592SSam Clegg // this one take precedence. Otherwise the existing function is either 494a57f1a54SSam Clegg // directly called or defined, in which case we need a function variant. 495fecfc592SSam Clegg if (existingUndefined && !existingUndefined->isCalledDirectly) 496136d27abSRui Ueyama replaceSym(); 497fecfc592SSam Clegg else if (getFunctionVariant(s, sig, file, &s)) 498fecfc592SSam Clegg replaceSym(); 499fecfc592SSam Clegg } 50067b05584SSam Clegg if (existingUndefined) 501a57f1a54SSam Clegg setImportAttributes(existingUndefined, importName, importModule, flags, 502a57f1a54SSam Clegg file); 5036540e570SSam Clegg } 504cefbf9acSSam Clegg 505136d27abSRui Ueyama return s; 506c03c9040SRui Ueyama } 507c03c9040SRui Ueyama 508136d27abSRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags, 509136d27abSRui Ueyama InputFile *file) { 510136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n"); 511f6f4b98fSSam Clegg assert(flags & WASM_SYMBOL_UNDEFINED); 51293102974SSam Clegg 513136d27abSRui Ueyama Symbol *s; 514136d27abSRui Ueyama bool wasInserted; 515136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 516136d27abSRui Ueyama if (s->traced) 517136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 518f989a92dSSam Clegg 519b34ec596SSam Clegg if (wasInserted) { 520136d27abSRui Ueyama replaceSymbol<UndefinedData>(s, name, flags, file); 521b34ec596SSam Clegg } else if (auto *lazy = dyn_cast<LazySymbol>(s)) { 522b34ec596SSam Clegg if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) 523b34ec596SSam Clegg lazy->setWeak(); 524b34ec596SSam Clegg else 525136d27abSRui Ueyama lazy->fetch(); 526b34ec596SSam Clegg } else if (s->isDefined()) { 527136d27abSRui Ueyama checkDataType(s, file); 528b34ec596SSam Clegg } 529136d27abSRui Ueyama return s; 530c94d393aSSam Clegg } 531c94d393aSSam Clegg 532bd481277SSam Clegg Symbol *SymbolTable::addUndefinedGlobal(StringRef name, 533bd481277SSam Clegg Optional<StringRef> importName, 534bd481277SSam Clegg Optional<StringRef> importModule, 535bd481277SSam Clegg uint32_t flags, InputFile *file, 536136d27abSRui Ueyama const WasmGlobalType *type) { 537136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n"); 538f6f4b98fSSam Clegg assert(flags & WASM_SYMBOL_UNDEFINED); 539e3498ec5SRui Ueyama 540136d27abSRui Ueyama Symbol *s; 541136d27abSRui Ueyama bool wasInserted; 542136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 543136d27abSRui Ueyama if (s->traced) 544136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 545c729c1b4SSam Clegg 546136d27abSRui Ueyama if (wasInserted) 547136d27abSRui Ueyama replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags, 548136d27abSRui Ueyama file, type); 549136d27abSRui Ueyama else if (auto *lazy = dyn_cast<LazySymbol>(s)) 550136d27abSRui Ueyama lazy->fetch(); 551136d27abSRui Ueyama else if (s->isDefined()) 552136d27abSRui Ueyama checkGlobalType(s, file, type); 553136d27abSRui Ueyama return s; 554e3498ec5SRui Ueyama } 555e3498ec5SRui Ueyama 556136d27abSRui Ueyama void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) { 557136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n"); 558136d27abSRui Ueyama StringRef name = sym->getName(); 559c03c9040SRui Ueyama 560136d27abSRui Ueyama Symbol *s; 561136d27abSRui Ueyama bool wasInserted; 562136d27abSRui Ueyama std::tie(s, wasInserted) = insertName(name); 563c03c9040SRui Ueyama 564136d27abSRui Ueyama if (wasInserted) { 565136d27abSRui Ueyama replaceSymbol<LazySymbol>(s, name, 0, file, *sym); 566c03c9040SRui Ueyama return; 567c03c9040SRui Ueyama } 568c03c9040SRui Ueyama 569136d27abSRui Ueyama if (!s->isUndefined()) 57037b4ee52SSam Clegg return; 57137b4ee52SSam Clegg 57237b4ee52SSam Clegg // The existing symbol is undefined, load a new one from the archive, 5737ae3d335SKazuaki Ishizaki // unless the existing symbol is weak in which case replace the undefined 57437b4ee52SSam Clegg // symbols with a LazySymbol. 575136d27abSRui Ueyama if (s->isWeak()) { 576136d27abSRui Ueyama const WasmSignature *oldSig = nullptr; 57737b4ee52SSam Clegg // In the case of an UndefinedFunction we need to preserve the expected 57837b4ee52SSam Clegg // signature. 579136d27abSRui Ueyama if (auto *f = dyn_cast<UndefinedFunction>(s)) 580136d27abSRui Ueyama oldSig = f->signature; 58137b4ee52SSam Clegg LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 582136d27abSRui Ueyama auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK, 583136d27abSRui Ueyama file, *sym); 584136d27abSRui Ueyama newSym->signature = oldSig; 58537b4ee52SSam Clegg return; 58637b4ee52SSam Clegg } 58737b4ee52SSam Clegg 588e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 589136d27abSRui Ueyama file->addMember(sym); 590c94d393aSSam Clegg } 591e0f6fcd0SSam Clegg 592136d27abSRui Ueyama bool SymbolTable::addComdat(StringRef name) { 593136d27abSRui Ueyama return comdatGroups.insert(CachedHashStringRef(name)).second; 594e0f6fcd0SSam Clegg } 5951f3f774fSSam Clegg 5966540e570SSam Clegg // The new signature doesn't match. Create a variant to the symbol with the 5976540e570SSam Clegg // signature encoded in the name and return that instead. These symbols are 5986540e570SSam Clegg // then unified later in handleSymbolVariants. 599136d27abSRui Ueyama bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig, 600136d27abSRui Ueyama const InputFile *file, Symbol **out) { 601136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> " 602136d27abSRui Ueyama << " " << toString(*sig) << "\n"); 603136d27abSRui Ueyama Symbol *variant = nullptr; 6046540e570SSam Clegg 6056540e570SSam Clegg // Linear search through symbol variants. Should never be more than two 6066540e570SSam Clegg // or three entries here. 607136d27abSRui Ueyama auto &variants = symVariants[CachedHashStringRef(sym->getName())]; 608136d27abSRui Ueyama if (variants.empty()) 609136d27abSRui Ueyama variants.push_back(sym); 6106540e570SSam Clegg 611136d27abSRui Ueyama for (Symbol* v : variants) { 612136d27abSRui Ueyama if (*v->getSignature() == *sig) { 613136d27abSRui Ueyama variant = v; 6146540e570SSam Clegg break; 6156540e570SSam Clegg } 6166540e570SSam Clegg } 6176540e570SSam Clegg 618136d27abSRui Ueyama bool wasAdded = !variant; 619136d27abSRui Ueyama if (wasAdded) { 6206540e570SSam Clegg // Create a new variant; 6216540e570SSam Clegg LLVM_DEBUG(dbgs() << "added new variant\n"); 622136d27abSRui Ueyama variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 623064e9907SSam Clegg variant->isUsedInRegularObj = 624064e9907SSam Clegg !file || file->kind() == InputFile::ObjectKind; 625064e9907SSam Clegg variant->canInline = true; 626064e9907SSam Clegg variant->traced = false; 627064e9907SSam Clegg variant->forceExport = false; 628136d27abSRui Ueyama variants.push_back(variant); 6296540e570SSam Clegg } else { 630136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n"); 631136d27abSRui Ueyama assert(*variant->getSignature() == *sig); 6326540e570SSam Clegg } 6336540e570SSam Clegg 634136d27abSRui Ueyama *out = variant; 635136d27abSRui Ueyama return wasAdded; 6366540e570SSam Clegg } 6376540e570SSam Clegg 6381f3f774fSSam Clegg // Set a flag for --trace-symbol so that we can print out a log message 6391f3f774fSSam Clegg // if a new symbol with the same name is inserted into the symbol table. 640136d27abSRui Ueyama void SymbolTable::trace(StringRef name) { 641136d27abSRui Ueyama symMap.insert({CachedHashStringRef(name), -1}); 6421f3f774fSSam Clegg } 643230dc11dSSam Clegg 644136d27abSRui Ueyama void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { 645a5ca34e6SSam Clegg // Swap symbols as instructed by -wrap. 646136d27abSRui Ueyama int &origIdx = symMap[CachedHashStringRef(sym->getName())]; 647136d27abSRui Ueyama int &realIdx= symMap[CachedHashStringRef(real->getName())]; 648136d27abSRui Ueyama int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())]; 649136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n"); 650a5ca34e6SSam Clegg 651a5ca34e6SSam Clegg // Anyone looking up __real symbols should get the original 652136d27abSRui Ueyama realIdx = origIdx; 653a5ca34e6SSam Clegg // Anyone looking up the original should get the __wrap symbol 654136d27abSRui Ueyama origIdx = wrapIdx; 655a5ca34e6SSam Clegg } 656a5ca34e6SSam Clegg 657136d27abSRui Ueyama static const uint8_t unreachableFn[] = { 658230dc11dSSam Clegg 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 659230dc11dSSam Clegg 0x00 /* opcode unreachable */, 0x0b /* opcode end */ 660230dc11dSSam Clegg }; 661230dc11dSSam Clegg 662230dc11dSSam Clegg // Replace the given symbol body with an unreachable function. 663230dc11dSSam Clegg // This is used by handleWeakUndefines in order to generate a callable 6646540e570SSam Clegg // equivalent of an undefined function and also handleSymbolVariants for 6656540e570SSam Clegg // undefined functions that don't match the signature of the definition. 666136d27abSRui Ueyama InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym, 667136d27abSRui Ueyama const WasmSignature &sig, 668136d27abSRui Ueyama StringRef debugName) { 669136d27abSRui Ueyama auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName); 670136d27abSRui Ueyama func->setBody(unreachableFn); 671136d27abSRui Ueyama syntheticFunctions.emplace_back(func); 6724b8e2d8eSSam Clegg // Mark new symbols as local. For relocatable output we don't want them 6734b8e2d8eSSam Clegg // to be exported outside the object file. 6744b8e2d8eSSam Clegg replaceSymbol<DefinedFunction>(sym, debugName, WASM_SYMBOL_BINDING_LOCAL, 6754b8e2d8eSSam Clegg nullptr, func); 676*206884bfSSam Clegg // Ensure it compares equal to the null pointer, and so that table relocs 677*206884bfSSam Clegg // don't pull in the stub body (only call-operand relocs should do that). 678*206884bfSSam Clegg func->setTableIndex(0); 679136d27abSRui Ueyama return func; 680230dc11dSSam Clegg } 681230dc11dSSam Clegg 682*206884bfSSam Clegg void SymbolTable::replaceWithUndefined(Symbol *sym) { 683*206884bfSSam Clegg // Add a synthetic dummy for weak undefined functions. These dummies will 684*206884bfSSam Clegg // be GC'd if not used as the target of any "call" instructions. 685*206884bfSSam Clegg StringRef debugName = saver.save("undefined_weak:" + toString(*sym)); 686*206884bfSSam Clegg replaceWithUnreachable(sym, *sym->getSignature(), debugName); 687*206884bfSSam Clegg // Hide our dummy to prevent export. 688*206884bfSSam Clegg sym->setHidden(true); 689*206884bfSSam Clegg } 690*206884bfSSam Clegg 691230dc11dSSam Clegg // For weak undefined functions, there may be "call" instructions that reference 692230dc11dSSam Clegg // the symbol. In this case, we need to synthesise a dummy/stub function that 693230dc11dSSam Clegg // will abort at runtime, so that relocations can still provided an operand to 694230dc11dSSam Clegg // the call instruction that passes Wasm validation. 695230dc11dSSam Clegg void SymbolTable::handleWeakUndefines() { 696136d27abSRui Ueyama for (Symbol *sym : getSymbols()) { 697*206884bfSSam Clegg if (sym->isUndefWeak()) { 698*206884bfSSam Clegg if (sym->getSignature()) { 699*206884bfSSam Clegg replaceWithUndefined(sym); 700*206884bfSSam Clegg } else { 701*206884bfSSam Clegg // It is possible for undefined functions not to have a signature (eg. 702*206884bfSSam Clegg // if added via "--undefined"), but weak undefined ones do have a 703*206884bfSSam Clegg // signature. Lazy symbols may not be functions and therefore Sig can 704*206884bfSSam Clegg // still be null in some circumstance. 705136d27abSRui Ueyama assert(!isa<FunctionSymbol>(sym)); 706*206884bfSSam Clegg } 707*206884bfSSam Clegg } 708*206884bfSSam Clegg } 7096540e570SSam Clegg } 710230dc11dSSam Clegg 711*206884bfSSam Clegg DefinedFunction *SymbolTable::createUndefinedStub(const WasmSignature &sig) { 712*206884bfSSam Clegg if (stubFunctions.count(sig)) 713*206884bfSSam Clegg return stubFunctions[sig]; 714*206884bfSSam Clegg LLVM_DEBUG(dbgs() << "createUndefinedStub: " << toString(sig) << "\n"); 715*206884bfSSam Clegg auto *sym = reinterpret_cast<DefinedFunction *>(make<SymbolUnion>()); 716*206884bfSSam Clegg sym->isUsedInRegularObj = true; 717*206884bfSSam Clegg sym->canInline = true; 718*206884bfSSam Clegg sym->traced = false; 719*206884bfSSam Clegg sym->forceExport = false; 720*206884bfSSam Clegg sym->signature = &sig; 721*206884bfSSam Clegg replaceSymbol<DefinedFunction>( 722*206884bfSSam Clegg sym, "undefined_stub", WASM_SYMBOL_VISIBILITY_HIDDEN, nullptr, nullptr); 723*206884bfSSam Clegg replaceWithUnreachable(sym, sig, "undefined_stub"); 724*206884bfSSam Clegg stubFunctions[sig] = sym; 725*206884bfSSam Clegg return sym; 726230dc11dSSam Clegg } 7276540e570SSam Clegg 728136d27abSRui Ueyama static void reportFunctionSignatureMismatch(StringRef symName, 729136d27abSRui Ueyama FunctionSymbol *a, 730136d27abSRui Ueyama FunctionSymbol *b, bool isError) { 731136d27abSRui Ueyama std::string msg = ("function signature mismatch: " + symName + 732136d27abSRui Ueyama "\n>>> defined as " + toString(*a->signature) + " in " + 733136d27abSRui Ueyama toString(a->getFile()) + "\n>>> defined as " + 734136d27abSRui Ueyama toString(*b->signature) + " in " + toString(b->getFile())) 7356540e570SSam Clegg .str(); 736136d27abSRui Ueyama if (isError) 7376540e570SSam Clegg error(msg); 7386540e570SSam Clegg else 7396540e570SSam Clegg warn(msg); 7406540e570SSam Clegg } 7416540e570SSam Clegg 7426540e570SSam Clegg // Remove any variant symbols that were created due to function signature 7436540e570SSam Clegg // mismatches. 7446540e570SSam Clegg void SymbolTable::handleSymbolVariants() { 745136d27abSRui Ueyama for (auto pair : symVariants) { 7466540e570SSam Clegg // Push the initial symbol onto the list of variants. 747136d27abSRui Ueyama StringRef symName = pair.first.val(); 748136d27abSRui Ueyama std::vector<Symbol *> &variants = pair.second; 7496540e570SSam Clegg 7506540e570SSam Clegg #ifndef NDEBUG 751136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "symbol with (" << variants.size() 752136d27abSRui Ueyama << ") variants: " << symName << "\n"); 753136d27abSRui Ueyama for (auto *s: variants) { 754136d27abSRui Ueyama auto *f = cast<FunctionSymbol>(s); 755136d27abSRui Ueyama LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " " 756136d27abSRui Ueyama << toString(*f->signature) << "\n"); 7576540e570SSam Clegg } 7586540e570SSam Clegg #endif 7596540e570SSam Clegg 7606540e570SSam Clegg // Find the one definition. 761136d27abSRui Ueyama DefinedFunction *defined = nullptr; 762136d27abSRui Ueyama for (auto *symbol : variants) { 763136d27abSRui Ueyama if (auto f = dyn_cast<DefinedFunction>(symbol)) { 764136d27abSRui Ueyama defined = f; 7656540e570SSam Clegg break; 7666540e570SSam Clegg } 7676540e570SSam Clegg } 7686540e570SSam Clegg 7696540e570SSam Clegg // If there are no definitions, and the undefined symbols disagree on 7706540e570SSam Clegg // the signature, there is not we can do since we don't know which one 7716540e570SSam Clegg // to use as the signature on the import. 772136d27abSRui Ueyama if (!defined) { 773136d27abSRui Ueyama reportFunctionSignatureMismatch(symName, 774136d27abSRui Ueyama cast<FunctionSymbol>(variants[0]), 775136d27abSRui Ueyama cast<FunctionSymbol>(variants[1]), true); 7766540e570SSam Clegg return; 7776540e570SSam Clegg } 7786540e570SSam Clegg 779136d27abSRui Ueyama for (auto *symbol : variants) { 780136d27abSRui Ueyama if (symbol != defined) { 781136d27abSRui Ueyama auto *f = cast<FunctionSymbol>(symbol); 782136d27abSRui Ueyama reportFunctionSignatureMismatch(symName, f, defined, false); 78351b521c0SSam Clegg StringRef debugName = saver.save("signature_mismatch:" + toString(*f)); 784136d27abSRui Ueyama replaceWithUnreachable(f, *f->signature, debugName); 7856540e570SSam Clegg } 7866540e570SSam Clegg } 7876540e570SSam Clegg } 7886540e570SSam Clegg } 78933c59abfSFangrui Song 79033c59abfSFangrui Song } // namespace wasm 79133c59abfSFangrui Song } // namespace lld 792