1 //===- SymbolTable.cpp ----------------------------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SymbolTable.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputEvent.h" 13 #include "InputGlobal.h" 14 #include "WriterUtils.h" 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Memory.h" 17 #include "llvm/ADT/SetVector.h" 18 19 #define DEBUG_TYPE "lld" 20 21 using namespace llvm; 22 using namespace llvm::wasm; 23 using namespace llvm::object; 24 using namespace lld; 25 using namespace lld::wasm; 26 27 SymbolTable *lld::wasm::Symtab; 28 29 void SymbolTable::addFile(InputFile *File) { 30 log("Processing: " + toString(File)); 31 32 // .a file 33 if (auto *F = dyn_cast<ArchiveFile>(File)) { 34 F->parse(); 35 return; 36 } 37 38 // .so file 39 if (auto *F = dyn_cast<SharedFile>(File)) { 40 SharedFiles.push_back(F); 41 return; 42 } 43 44 if (Config->Trace) 45 message(toString(File)); 46 47 // LLVM bitcode file 48 if (auto *F = dyn_cast<BitcodeFile>(File)) { 49 F->parse(); 50 BitcodeFiles.push_back(F); 51 return; 52 } 53 54 // Regular object file 55 auto *F = cast<ObjFile>(File); 56 F->parse(false); 57 ObjectFiles.push_back(F); 58 } 59 60 // This function is where all the optimizations of link-time 61 // optimization happens. When LTO is in use, some input files are 62 // not in native object file format but in the LLVM bitcode format. 63 // This function compiles bitcode files into a few big native files 64 // using LLVM functions and replaces bitcode symbols with the results. 65 // Because all bitcode files that the program consists of are passed 66 // to the compiler at once, it can do whole-program optimization. 67 void SymbolTable::addCombinedLTOObject() { 68 if (BitcodeFiles.empty()) 69 return; 70 71 // Compile bitcode files and replace bitcode symbols. 72 LTO.reset(new BitcodeCompiler); 73 for (BitcodeFile *F : BitcodeFiles) 74 LTO->add(*F); 75 76 for (StringRef Filename : LTO->compile()) { 77 auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"), ""); 78 Obj->parse(true); 79 ObjectFiles.push_back(Obj); 80 } 81 } 82 83 Symbol *SymbolTable::find(StringRef Name) { 84 auto It = SymMap.find(CachedHashStringRef(Name)); 85 if (It == SymMap.end() || It->second == -1) 86 return nullptr; 87 return SymVector[It->second]; 88 } 89 90 void SymbolTable::replace(StringRef Name, Symbol* Sym) { 91 auto It = SymMap.find(CachedHashStringRef(Name)); 92 SymVector[It->second] = Sym; 93 } 94 95 std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { 96 bool Trace = false; 97 auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); 98 int &SymIndex = P.first->second; 99 bool IsNew = P.second; 100 if (SymIndex == -1) { 101 SymIndex = SymVector.size(); 102 Trace = true; 103 IsNew = true; 104 } 105 106 if (!IsNew) 107 return {SymVector[SymIndex], false}; 108 109 Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 110 Sym->IsUsedInRegularObj = false; 111 Sym->CanInline = true; 112 Sym->Traced = Trace; 113 SymVector.emplace_back(Sym); 114 return {Sym, true}; 115 } 116 117 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, 118 const InputFile *File) { 119 Symbol *S; 120 bool WasInserted; 121 std::tie(S, WasInserted) = insertName(Name); 122 123 if (!File || File->kind() == InputFile::ObjectKind) 124 S->IsUsedInRegularObj = true; 125 126 return {S, WasInserted}; 127 } 128 129 static void reportTypeError(const Symbol *Existing, const InputFile *File, 130 llvm::wasm::WasmSymbolType Type) { 131 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 132 toString(Existing->getWasmType()) + " in " + 133 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 134 " in " + toString(File)); 135 } 136 137 // Check the type of new symbol matches that of the symbol is replacing. 138 // Returns true if the function types match, false is there is a singature 139 // mismatch. 140 static bool signatureMatches(FunctionSymbol *Existing, 141 const WasmSignature *NewSig) { 142 const WasmSignature *OldSig = Existing->Signature; 143 144 // If either function is missing a signature (this happend for bitcode 145 // symbols) then assume they match. Any mismatch will be reported later 146 // when the LTO objects are added. 147 if (!NewSig || !OldSig) 148 return true; 149 150 return *NewSig == *OldSig; 151 } 152 153 static void checkGlobalType(const Symbol *Existing, const InputFile *File, 154 const WasmGlobalType *NewType) { 155 if (!isa<GlobalSymbol>(Existing)) { 156 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 157 return; 158 } 159 160 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 161 if (*NewType != *OldType) { 162 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 163 toString(*OldType) + " in " + toString(Existing->getFile()) + 164 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 165 } 166 } 167 168 static void checkEventType(const Symbol *Existing, const InputFile *File, 169 const WasmEventType *NewType, 170 const WasmSignature *NewSig) { 171 auto ExistingEvent = dyn_cast<EventSymbol>(Existing); 172 if (!isa<EventSymbol>(Existing)) { 173 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); 174 return; 175 } 176 177 const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); 178 const WasmSignature *OldSig = ExistingEvent->Signature; 179 if (NewType->Attribute != OldType->Attribute) 180 error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + 181 toString(*OldType) + " in " + toString(Existing->getFile()) + 182 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 183 if (*NewSig != *OldSig) 184 warn("Event signature mismatch: " + Existing->getName() + 185 "\n>>> defined as " + toString(*OldSig) + " in " + 186 toString(Existing->getFile()) + "\n>>> defined as " + 187 toString(*NewSig) + " in " + toString(File)); 188 } 189 190 static void checkDataType(const Symbol *Existing, const InputFile *File) { 191 if (!isa<DataSymbol>(Existing)) 192 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 193 } 194 195 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 196 uint32_t Flags, 197 InputFunction *Function) { 198 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 199 assert(!find(Name)); 200 SyntheticFunctions.emplace_back(Function); 201 return replaceSymbol<DefinedFunction>(insertName(Name).first, Name, 202 Flags, nullptr, Function); 203 } 204 205 // Adds an optional, linker generated, data symbols. The symbol will only be 206 // added if there is an undefine reference to it, or if it is explictly exported 207 // via the --export flag. Otherwise we don't add the symbol and return nullptr. 208 DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value, 209 uint32_t Flags) { 210 Symbol *S = find(Name); 211 if (!S && (Config->ExportAll || Config->ExportedSymbols.count(Name) != 0)) 212 S = insertName(Name).first; 213 else if (!S || S->isDefined()) 214 return nullptr; 215 LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n"); 216 auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags); 217 rtn->setVirtualAddress(Value); 218 rtn->Referenced = true; 219 return rtn; 220 } 221 222 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 223 uint32_t Flags) { 224 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 225 assert(!find(Name)); 226 return replaceSymbol<DefinedData>(insertName(Name).first, Name, Flags); 227 } 228 229 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 230 InputGlobal *Global) { 231 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 232 << "\n"); 233 assert(!find(Name)); 234 SyntheticGlobals.emplace_back(Global); 235 return replaceSymbol<DefinedGlobal>(insertName(Name).first, Name, Flags, 236 nullptr, Global); 237 } 238 239 static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 240 uint32_t NewFlags) { 241 // If existing symbol is undefined, replace it. 242 if (!Existing->isDefined()) { 243 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 244 << Existing->getName() << "\n"); 245 return true; 246 } 247 248 // Now we have two defined symbols. If the new one is weak, we can ignore it. 249 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 250 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 251 return false; 252 } 253 254 // If the existing symbol is weak, we should replace it. 255 if (Existing->isWeak()) { 256 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 257 return true; 258 } 259 260 // Neither symbol is week. They conflict. 261 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 262 toString(Existing->getFile()) + "\n>>> defined in " + 263 toString(NewFile)); 264 return true; 265 } 266 267 Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 268 InputFile *File, 269 InputFunction *Function) { 270 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 271 << (Function ? toString(Function->Signature) : "none") 272 << "]\n"); 273 Symbol *S; 274 bool WasInserted; 275 std::tie(S, WasInserted) = insert(Name, File); 276 277 auto ReplaceSym = [&](Symbol *Sym) { 278 // If the new defined function doesn't have signture (i.e. bitcode 279 // functions) but the old symbol does, then preserve the old signature 280 const WasmSignature *OldSig = S->getSignature(); 281 auto* NewSym = replaceSymbol<DefinedFunction>(Sym, Name, Flags, File, Function); 282 if (!NewSym->Signature) 283 NewSym->Signature = OldSig; 284 }; 285 286 if (WasInserted || S->isLazy()) { 287 ReplaceSym(S); 288 return S; 289 } 290 291 auto ExistingFunction = dyn_cast<FunctionSymbol>(S); 292 if (!ExistingFunction) { 293 reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); 294 return S; 295 } 296 297 bool CheckSig = true; 298 if (auto UD = dyn_cast<UndefinedFunction>(ExistingFunction)) 299 CheckSig = UD->IsCalledDirectly; 300 301 if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) { 302 Symbol* Variant; 303 if (getFunctionVariant(S, &Function->Signature, File, &Variant)) 304 // New variant, always replace 305 ReplaceSym(Variant); 306 else if (shouldReplace(S, File, Flags)) 307 // Variant already exists, replace it after checking shouldReplace 308 ReplaceSym(Variant); 309 310 // This variant we found take the place in the symbol table as the primary 311 // variant. 312 replace(Name, Variant); 313 return Variant; 314 } 315 316 // Existing function with matching signature. 317 if (shouldReplace(S, File, Flags)) 318 ReplaceSym(S); 319 320 return S; 321 } 322 323 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 324 InputFile *File, InputSegment *Segment, 325 uint32_t Address, uint32_t Size) { 326 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 327 << "\n"); 328 Symbol *S; 329 bool WasInserted; 330 std::tie(S, WasInserted) = insert(Name, File); 331 332 auto ReplaceSym = [&]() { 333 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 334 }; 335 336 if (WasInserted || S->isLazy()) { 337 ReplaceSym(); 338 return S; 339 } 340 341 checkDataType(S, File); 342 343 if (shouldReplace(S, File, Flags)) 344 ReplaceSym(); 345 return S; 346 } 347 348 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 349 InputFile *File, InputGlobal *Global) { 350 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 351 352 Symbol *S; 353 bool WasInserted; 354 std::tie(S, WasInserted) = insert(Name, File); 355 356 auto ReplaceSym = [&]() { 357 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 358 }; 359 360 if (WasInserted || S->isLazy()) { 361 ReplaceSym(); 362 return S; 363 } 364 365 checkGlobalType(S, File, &Global->getType()); 366 367 if (shouldReplace(S, File, Flags)) 368 ReplaceSym(); 369 return S; 370 } 371 372 Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, 373 InputFile *File, InputEvent *Event) { 374 LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); 375 376 Symbol *S; 377 bool WasInserted; 378 std::tie(S, WasInserted) = insert(Name, File); 379 380 auto ReplaceSym = [&]() { 381 replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 382 }; 383 384 if (WasInserted || S->isLazy()) { 385 ReplaceSym(); 386 return S; 387 } 388 389 checkEventType(S, File, &Event->getType(), &Event->Signature); 390 391 if (shouldReplace(S, File, Flags)) 392 ReplaceSym(); 393 return S; 394 } 395 396 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, 397 StringRef ImportModule, 398 uint32_t Flags, InputFile *File, 399 const WasmSignature *Sig, 400 bool IsCalledDirectly) { 401 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " [" 402 << (Sig ? toString(*Sig) : "none") 403 << "] IsCalledDirectly:" << IsCalledDirectly << "\n"); 404 405 Symbol *S; 406 bool WasInserted; 407 std::tie(S, WasInserted) = insert(Name, File); 408 if (S->Traced) 409 printTraceSymbolUndefined(Name, File); 410 411 auto ReplaceSym = [&]() { 412 replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags, 413 File, Sig, IsCalledDirectly); 414 }; 415 416 if (WasInserted) 417 ReplaceSym(); 418 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 419 Lazy->fetch(); 420 else { 421 auto ExistingFunction = dyn_cast<FunctionSymbol>(S); 422 if (!ExistingFunction) { 423 reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); 424 return S; 425 } 426 if (!ExistingFunction->Signature && Sig) 427 ExistingFunction->Signature = Sig; 428 if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig)) 429 if (getFunctionVariant(S, Sig, File, &S)) 430 ReplaceSym(); 431 } 432 433 return S; 434 } 435 436 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 437 InputFile *File) { 438 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 439 440 Symbol *S; 441 bool WasInserted; 442 std::tie(S, WasInserted) = insert(Name, File); 443 if (S->Traced) 444 printTraceSymbolUndefined(Name, File); 445 446 if (WasInserted) 447 replaceSymbol<UndefinedData>(S, Name, Flags, File); 448 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 449 Lazy->fetch(); 450 else if (S->isDefined()) 451 checkDataType(S, File); 452 return S; 453 } 454 455 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, 456 StringRef ImportModule, uint32_t Flags, 457 InputFile *File, 458 const WasmGlobalType *Type) { 459 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 460 461 Symbol *S; 462 bool WasInserted; 463 std::tie(S, WasInserted) = insert(Name, File); 464 if (S->Traced) 465 printTraceSymbolUndefined(Name, File); 466 467 if (WasInserted) 468 replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags, 469 File, Type); 470 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 471 Lazy->fetch(); 472 else if (S->isDefined()) 473 checkGlobalType(S, File, Type); 474 return S; 475 } 476 477 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 478 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 479 StringRef Name = Sym->getName(); 480 481 Symbol *S; 482 bool WasInserted; 483 std::tie(S, WasInserted) = insertName(Name); 484 485 if (WasInserted) { 486 replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym); 487 return; 488 } 489 490 if (!S->isUndefined()) 491 return; 492 493 // The existing symbol is undefined, load a new one from the archive, 494 // unless the the existing symbol is weak in which case replace the undefined 495 // symbols with a LazySymbol. 496 if (S->isWeak()) { 497 const WasmSignature *OldSig = nullptr; 498 // In the case of an UndefinedFunction we need to preserve the expected 499 // signature. 500 if (auto *F = dyn_cast<UndefinedFunction>(S)) 501 OldSig = F->Signature; 502 LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 503 auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK, 504 File, *Sym); 505 NewSym->Signature = OldSig; 506 return; 507 } 508 509 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 510 File->addMember(Sym); 511 } 512 513 bool SymbolTable::addComdat(StringRef Name) { 514 return ComdatGroups.insert(CachedHashStringRef(Name)).second; 515 } 516 517 // The new signature doesn't match. Create a variant to the symbol with the 518 // signature encoded in the name and return that instead. These symbols are 519 // then unified later in handleSymbolVariants. 520 bool SymbolTable::getFunctionVariant(Symbol* Sym, const WasmSignature *Sig, 521 const InputFile *File, Symbol **Out) { 522 LLVM_DEBUG(dbgs() << "getFunctionVariant: " << Sym->getName() << " -> " 523 << " " << toString(*Sig) << "\n"); 524 Symbol *Variant = nullptr; 525 526 // Linear search through symbol variants. Should never be more than two 527 // or three entries here. 528 auto &Variants = SymVariants[CachedHashStringRef(Sym->getName())]; 529 if (Variants.empty()) 530 Variants.push_back(Sym); 531 532 for (Symbol* V : Variants) { 533 if (*V->getSignature() == *Sig) { 534 Variant = V; 535 break; 536 } 537 } 538 539 bool WasAdded = !Variant; 540 if (WasAdded) { 541 // Create a new variant; 542 LLVM_DEBUG(dbgs() << "added new variant\n"); 543 Variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 544 Variants.push_back(Variant); 545 } else { 546 LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*Variant) << "\n"); 547 assert(*Variant->getSignature() == *Sig); 548 } 549 550 *Out = Variant; 551 return WasAdded; 552 } 553 554 // Set a flag for --trace-symbol so that we can print out a log message 555 // if a new symbol with the same name is inserted into the symbol table. 556 void SymbolTable::trace(StringRef Name) { 557 SymMap.insert({CachedHashStringRef(Name), -1}); 558 } 559 560 void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { 561 // Swap symbols as instructed by -wrap. 562 int &OrigIdx = SymMap[CachedHashStringRef(Sym->getName())]; 563 int &RealIdx= SymMap[CachedHashStringRef(Real->getName())]; 564 int &WrapIdx = SymMap[CachedHashStringRef(Wrap->getName())]; 565 LLVM_DEBUG(dbgs() << "wrap: " << Sym->getName() << "\n"); 566 567 // Anyone looking up __real symbols should get the original 568 RealIdx = OrigIdx; 569 // Anyone looking up the original should get the __wrap symbol 570 OrigIdx = WrapIdx; 571 } 572 573 static const uint8_t UnreachableFn[] = { 574 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 575 0x00 /* opcode unreachable */, 0x0b /* opcode end */ 576 }; 577 578 // Replace the given symbol body with an unreachable function. 579 // This is used by handleWeakUndefines in order to generate a callable 580 // equivalent of an undefined function and also handleSymbolVariants for 581 // undefined functions that don't match the signature of the definition. 582 InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, 583 const WasmSignature &Sig, 584 StringRef DebugName) { 585 auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName); 586 Func->setBody(UnreachableFn); 587 SyntheticFunctions.emplace_back(Func); 588 replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr, 589 Func); 590 return Func; 591 } 592 593 // For weak undefined functions, there may be "call" instructions that reference 594 // the symbol. In this case, we need to synthesise a dummy/stub function that 595 // will abort at runtime, so that relocations can still provided an operand to 596 // the call instruction that passes Wasm validation. 597 void SymbolTable::handleWeakUndefines() { 598 for (Symbol *Sym : getSymbols()) { 599 if (!Sym->isUndefWeak()) 600 continue; 601 602 const WasmSignature *Sig = Sym->getSignature(); 603 if (!Sig) { 604 // It is possible for undefined functions not to have a signature (eg. if 605 // added via "--undefined"), but weak undefined ones do have a signature. 606 // Lazy symbols may not be functions and therefore Sig can still be null 607 // in some circumstantce. 608 assert(!isa<FunctionSymbol>(Sym)); 609 continue; 610 } 611 612 // Add a synthetic dummy for weak undefined functions. These dummies will 613 // be GC'd if not used as the target of any "call" instructions. 614 StringRef DebugName = Saver.save("undefined:" + toString(*Sym)); 615 InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName); 616 // Ensure it compares equal to the null pointer, and so that table relocs 617 // don't pull in the stub body (only call-operand relocs should do that). 618 Func->setTableIndex(0); 619 // Hide our dummy to prevent export. 620 Sym->setHidden(true); 621 } 622 } 623 624 static void reportFunctionSignatureMismatch(StringRef SymName, 625 FunctionSymbol *A, 626 FunctionSymbol *B, bool IsError) { 627 std::string msg = ("function signature mismatch: " + SymName + 628 "\n>>> defined as " + toString(*A->Signature) + " in " + 629 toString(A->getFile()) + "\n>>> defined as " + 630 toString(*B->Signature) + " in " + toString(B->getFile())) 631 .str(); 632 if (IsError) 633 error(msg); 634 else 635 warn(msg); 636 } 637 638 // Remove any variant symbols that were created due to function signature 639 // mismatches. 640 void SymbolTable::handleSymbolVariants() { 641 for (auto Pair : SymVariants) { 642 // Push the initial symbol onto the list of variants. 643 StringRef SymName = Pair.first.val(); 644 std::vector<Symbol *> &Variants = Pair.second; 645 646 #ifndef NDEBUG 647 LLVM_DEBUG(dbgs() << "symbol with (" << Variants.size() 648 << ") variants: " << SymName << "\n"); 649 for (auto *S: Variants) { 650 auto *F = cast<FunctionSymbol>(S); 651 LLVM_DEBUG(dbgs() << " variant: " + F->getName() << " " 652 << toString(*F->Signature) << "\n"); 653 } 654 #endif 655 656 // Find the one definition. 657 DefinedFunction *Defined = nullptr; 658 for (auto *Symbol : Variants) { 659 if (auto F = dyn_cast<DefinedFunction>(Symbol)) { 660 Defined = F; 661 break; 662 } 663 } 664 665 // If there are no definitions, and the undefined symbols disagree on 666 // the signature, there is not we can do since we don't know which one 667 // to use as the signature on the import. 668 if (!Defined) { 669 reportFunctionSignatureMismatch(SymName, 670 cast<FunctionSymbol>(Variants[0]), 671 cast<FunctionSymbol>(Variants[1]), true); 672 return; 673 } 674 675 for (auto *Symbol : Variants) { 676 if (Symbol != Defined) { 677 auto *F = cast<FunctionSymbol>(Symbol); 678 reportFunctionSignatureMismatch(SymName, F, Defined, false); 679 StringRef DebugName = Saver.save("unreachable:" + toString(*F)); 680 replaceWithUnreachable(F, *F->Signature, DebugName); 681 } 682 } 683 } 684 } 685