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