summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/COFF/InputFiles.cpp2
-rw-r--r--lld/COFF/InputFiles.h9
-rw-r--r--lld/COFF/Symbols.cpp34
-rw-r--r--lld/COFF/Symbols.h4
4 files changed, 39 insertions, 10 deletions
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 20cc25f6692..395d51067c7 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -32,6 +32,8 @@ using llvm::sys::fs::file_magic;
namespace lld {
namespace coff {
+int InputFile::NextIndex = 0;
+
// Returns the last element of a path, which is supposed to be a filename.
static StringRef getBasename(StringRef Path) {
size_t Pos = Path.find_last_of("\\/");
diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index d4f56aa8642..40df27aef79 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -62,8 +62,15 @@ public:
// Returns .drectve section contents if exist.
StringRef getDirectives() { return StringRef(Directives).trim(); }
+ // Each file has a unique index. The index number is used to
+ // resolve ties in symbol resolution.
+ int Index;
+ static int NextIndex;
+
protected:
- InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
+ InputFile(Kind K, MemoryBufferRef M)
+ : Index(NextIndex++), MB(M), FileKind(K) {}
+
MemoryBufferRef MB;
std::string Directives;
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index 58eb1908043..baf60e97932 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -47,7 +47,6 @@ int SymbolBody::compare(SymbolBody *Other) {
// First handle comparisons between two different kinds.
if (LK != RK) {
-
if (RK > LastDefinedKind) {
if (LK == LazyKind && cast<Undefined>(Other)->WeakAlias)
return -1;
@@ -94,12 +93,16 @@ int SymbolBody::compare(SymbolBody *Other) {
case DefinedRegularKind: {
auto *LHS = cast<DefinedRegular>(this);
auto *RHS = cast<DefinedRegular>(Other);
- return (LHS->isCOMDAT() && RHS->isCOMDAT()) ? 1 : 0;
+ if (LHS->isCOMDAT() && RHS->isCOMDAT())
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
+ return 0;
}
case DefinedCommonKind: {
auto *LHS = cast<DefinedCommon>(this);
auto *RHS = cast<DefinedCommon>(Other);
+ if (LHS->getSize() == RHS->getSize())
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
return LHS->getSize() > RHS->getSize() ? 1 : -1;
}
@@ -111,17 +114,30 @@ int SymbolBody::compare(SymbolBody *Other) {
return 0;
// Non-replaceable symbols win, but even two replaceable symboles don't
- // tie.
+ // tie. If both symbols are replaceable, choice is arbitrary.
+ if (RHS->IsReplaceable && LHS->IsReplaceable)
+ return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
return LHS->IsReplaceable ? -1 : 1;
}
- case LazyKind:
- // Don't tie, just pick the LHS.
- return 1;
+ case LazyKind: {
+ // Don't tie, pick the earliest.
+ auto *LHS = cast<Lazy>(this);
+ auto *RHS = cast<Lazy>(Other);
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
+ }
- case UndefinedKind:
- // Don't tie, just pick the LHS unless the RHS has a weak alias.
- return cast<Undefined>(Other)->WeakAlias ? -1 : 1;
+ case UndefinedKind: {
+ auto *LHS = cast<Undefined>(this);
+ auto *RHS = cast<Undefined>(Other);
+ // Tie if both undefined symbols have different weak aliases.
+ if (LHS->WeakAlias && RHS->WeakAlias) {
+ if (LHS->WeakAlias->repl() != RHS->WeakAlias->repl())
+ return 0;
+ return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
+ }
+ return LHS->WeakAlias ? 1 : -1;
+ }
case DefinedLocalImportKind:
case DefinedImportThunkKind:
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 7eac93dfc68..459d04c4734 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -139,6 +139,8 @@ public:
return S->kind() <= LastDefinedCOFFKind;
}
+ int getFileIndex() { return File->Index; }
+
protected:
ObjectFile *File;
const coff_symbol_generic *Sym;
@@ -231,6 +233,8 @@ public:
// was already returned.
ErrorOr<std::unique_ptr<InputFile>> getMember();
+ int getFileIndex() { return File->Index; }
+
private:
ArchiveFile *File;
const Archive::Symbol Sym;
OpenPOWER on IntegriCloud