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