summaryrefslogtreecommitdiffstats
path: root/lld/COFF/SymbolTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF/SymbolTable.cpp')
-rw-r--r--lld/COFF/SymbolTable.cpp66
1 files changed, 23 insertions, 43 deletions
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 5d999f18c49..538173d7554 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -24,36 +24,6 @@ using namespace llvm;
namespace lld {
namespace coff {
-enum SymbolPreference {
- SP_EXISTING = -1,
- SP_CONFLICT = 0,
- SP_NEW = 1,
-};
-
-/// Checks if an existing symbol S should be kept or replaced by a new symbol.
-/// Returns SP_EXISTING when S should be kept, SP_NEW when the new symbol
-/// should be kept, and SP_CONFLICT if no valid resolution exists.
-static SymbolPreference compareDefined(Symbol *S, bool WasInserted,
- bool NewIsCOMDAT) {
- // If the symbol wasn't previously known, the new symbol wins by default.
- if (WasInserted || !isa<Defined>(S))
- return SP_NEW;
-
- // If the existing symbol is a DefinedRegular, both it and the new symbol
- // must be comdats. In that case, we have no reason to prefer one symbol
- // over the other, and we keep the existing one. If one of the symbols
- // is not a comdat, we report a conflict.
- if (auto *R = dyn_cast<DefinedRegular>(S)) {
- if (NewIsCOMDAT && R->isCOMDAT())
- return SP_EXISTING;
- else
- return SP_CONFLICT;
- }
-
- // Existing symbol is not a DefinedRegular; new symbol wins.
- return SP_NEW;
-}
-
SymbolTable *Symtab;
void SymbolTable::addFile(InputFile *File) {
@@ -239,7 +209,7 @@ Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
return S;
}
-Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT,
+Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,
const coff_symbol_generic *Sym,
SectionChunk *C) {
Symbol *S;
@@ -247,22 +217,32 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT,
std::tie(S, WasInserted) = insert(N);
if (!isa<BitcodeFile>(F))
S->IsUsedInRegularObj = true;
- SymbolPreference SP = compareDefined(S, WasInserted, IsCOMDAT);
- if (SP == SP_CONFLICT) {
+ if (WasInserted || !isa<DefinedRegular>(S))
+ replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,
+ /*IsExternal*/ true, Sym, C);
+ else
reportDuplicate(S, F);
- } else if (SP == SP_NEW) {
- replaceSymbol<DefinedRegular>(S, F, N, IsCOMDAT, /*IsExternal*/ true, Sym,
- C);
- } else if (SP == SP_EXISTING && IsCOMDAT && C) {
- C->markDiscarded();
- // Discard associative chunks that we've parsed so far. No need to recurse
- // because an associative section cannot have children.
- for (SectionChunk *Child : C->children())
- Child->markDiscarded();
- }
return S;
}
+std::pair<Symbol *, bool>
+SymbolTable::addComdat(InputFile *F, StringRef N,
+ const coff_symbol_generic *Sym) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) = insert(N);
+ if (!isa<BitcodeFile>(F))
+ S->IsUsedInRegularObj = true;
+ if (WasInserted || !isa<DefinedRegular>(S)) {
+ replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,
+ /*IsExternal*/ true, Sym, nullptr);
+ return {S, true};
+ }
+ if (!cast<DefinedRegular>(S)->isCOMDAT())
+ reportDuplicate(S, F);
+ return {S, false};
+}
+
Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
const coff_symbol_generic *Sym, CommonChunk *C) {
Symbol *S;
OpenPOWER on IntegriCloud