diff options
| -rw-r--r-- | lld/COFF/InputFiles.cpp | 5 | ||||
| -rw-r--r-- | lld/COFF/Symbols.cpp | 36 | ||||
| -rw-r--r-- | lld/COFF/Symbols.h | 25 |
3 files changed, 50 insertions, 16 deletions
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index d9cdd2fdd23..f2734ea7b1e 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -211,8 +211,11 @@ SymbolBody *ObjectFile::createSymbolBody(COFFSymbolRef Sym, const void *AuxP, } } } - if (Chunk *C = SparseChunks[Sym.getSectionNumber()]) + if (Chunk *C = SparseChunks[Sym.getSectionNumber()]) { + if (C->isCOMDAT()) + return new (Alloc) DefinedCOMDAT(COFFObj.get(), Sym, C); return new (Alloc) DefinedRegular(COFFObj.get(), Sym, C); + } return nullptr; } diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index af2cf0d8a83..02cf7322084 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -26,12 +26,17 @@ namespace coff { int DefinedRegular::compare(SymbolBody *Other) { if (Other->kind() < kind()) return -Other->compare(this); - auto *R = dyn_cast<DefinedRegular>(Other); - if (!R) - return 1; - if (isCOMDAT() && R->isCOMDAT()) - return 1; - return 0; + if (isa<DefinedRegular>(Other)) + return 0; + return 1; +} + +int DefinedCOMDAT::compare(SymbolBody *Other) { + if (Other->kind() < kind()) + return -Other->compare(this); + if (isa<DefinedRegular>(Other)) + return 0; + return 1; } int DefinedCommon::compare(SymbolBody *Other) { @@ -39,9 +44,9 @@ int DefinedCommon::compare(SymbolBody *Other) { return -Other->compare(this); if (auto *D = dyn_cast<DefinedCommon>(Other)) return getSize() > D->getSize() ? 1 : -1; - if (isa<DefinedRegular>(Other)) - return -1; - return 1; + if (isa<Lazy>(Other) || isa<Undefined>(Other)) + return 1; + return -1; } int DefinedBitcode::compare(SymbolBody *Other) { @@ -62,12 +67,9 @@ int DefinedBitcode::compare(SymbolBody *Other) { // replicate the rest of the symbol resolution logic here; symbol // resolution will be done accurately after lowering bitcode symbols // to regular symbols in addCombinedLTOObject(). - if (auto *R = dyn_cast<DefinedRegular>(Other)) { - if (!R->isCOMDAT() && !Replaceable) - return 0; + if (isa<DefinedRegular>(Other) && Replaceable) return -1; - } - if (isa<DefinedCommon>(Other)) + if (isa<DefinedCommon>(Other) || isa<DefinedCOMDAT>(Other)) return -1; return 0; } @@ -115,6 +117,12 @@ StringRef DefinedRegular::getName() { return Name; } +StringRef DefinedCOMDAT::getName() { + if (Name.empty()) + COFFFile->getSymbolName(Sym, Name); + return Name; +} + StringRef DefinedCommon::getName() { if (Name.empty()) COFFFile->getSymbolName(Sym, Name); diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 62fbd54bf7f..344c089df5f 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -50,6 +50,7 @@ public: DefinedImportDataKind, DefinedImportThunkKind, DefinedCommonKind, + DefinedCOMDATKind, DefinedRegularKind, DefinedLast, LazyKind, @@ -128,7 +129,29 @@ public: bool isExternal() override { return Sym.isExternal(); } void markLive() override { Data->markLive(); } uint64_t getFileOff() override { return Data->getFileOff() + Sym.getValue(); } - bool isCOMDAT() const { return Data->isCOMDAT(); } + int compare(SymbolBody *Other) override; + +private: + StringRef Name; + COFFObjectFile *COFFFile; + COFFSymbolRef Sym; + Chunk *Data; +}; + +class DefinedCOMDAT : public Defined { +public: + DefinedCOMDAT(COFFObjectFile *F, COFFSymbolRef S, Chunk *C) + : Defined(DefinedCOMDATKind), COFFFile(F), Sym(S), Data(C) {} + + static bool classof(const SymbolBody *S) { + return S->kind() == DefinedCOMDATKind; + } + + StringRef getName() override; + uint64_t getRVA() override { return Data->getRVA() + Sym.getValue(); } + bool isExternal() override { return Sym.isExternal(); } + void markLive() override { Data->markLive(); } + uint64_t getFileOff() override { return Data->getFileOff() + Sym.getValue(); } int compare(SymbolBody *Other) override; private: |

