summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/InputFiles.cpp5
-rw-r--r--lld/COFF/Symbols.cpp36
-rw-r--r--lld/COFF/Symbols.h25
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:
OpenPOWER on IntegriCloud