Index: COFF/Symbols.h =================================================================== --- COFF/Symbols.h +++ COFF/Symbols.h @@ -45,14 +45,14 @@ public: enum Kind { DefinedFirst, - DefinedRegularKind, + DefinedBitcodeKind, DefinedAbsoluteKind, DefinedImportDataKind, DefinedImportThunkKind, - DefinedBitcodeKind, + DefinedRegularKind, DefinedLast, - UndefinedKind, LazyKind, + UndefinedKind, }; Kind kind() const { return SymbolKind; } @@ -128,6 +128,7 @@ 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; // Returns true if this is a common symbol. bool isCommon() const { return Sym.isCommon(); } @@ -278,7 +279,6 @@ uint64_t getRVA() override { llvm_unreachable("bitcode reached writer"); } uint64_t getFileOff() override { llvm_unreachable("bitcode reached writer"); } int compare(SymbolBody *Other) override; - bool isReplaceable() const { return Replaceable; } private: StringRef Name; Index: COFF/Symbols.cpp =================================================================== --- COFF/Symbols.cpp +++ COFF/Symbols.cpp @@ -21,67 +21,66 @@ namespace lld { namespace coff { -// As an approximation, regular symbols win over bitcode symbols, but we -// definitely have a conflict if the regular symbol is not replaceable and -// neither is the bitcode symbol. We do not replicate the rest of the symbol -// resolution logic here; symbol resolution will be done accurately after -// lowering bitcode symbols to regular symbols in addCombinedLTOObject(). -static int compareRegularBitcode(DefinedRegular *R, DefinedBitcode *B) { - if (!R->isCommon() && !R->isCOMDAT() && !B->isReplaceable()) - return 0; - return 1; -} - -// Returns 1, 0 or -1 if this symbol should take precedence over the -// Other in the symbol table, tie or lose, respectively. -int Defined::compare(SymbolBody *Other) { - if (!isa(Other)) +// Returns 1, 0 or -1 if this symbol should take precedence +// over the Other, tie or lose, respectively. +int DefinedRegular::compare(SymbolBody *Other) { + if (Other->kind() < kind()) + return -Other->compare(this); + auto *R = dyn_cast(Other); + if (!R) return 1; - auto *X = dyn_cast(this); - if (!X) - return 0; - - if (auto *B = dyn_cast(Other)) - return compareRegularBitcode(X, B); - - auto *Y = dyn_cast(Other); - if (!Y) - return 0; // Common symbols are weaker than other types of defined symbols. - if (X->isCommon() && Y->isCommon()) - return (X->getCommonSize() < Y->getCommonSize()) ? -1 : 1; + if (isCommon() && R->isCommon()) + return (getCommonSize() < R->getCommonSize()) ? -1 : 1; // TODO: we are not sure if regular defined symbol and common // symbols are allowed to have the same name. - if (X->isCommon()) + if (isCommon()) return -1; - if (Y->isCommon()) + if (R->isCommon()) return 1; - - if (X->isCOMDAT() && Y->isCOMDAT()) + if (isCOMDAT() && R->isCOMDAT()) return 1; return 0; } int DefinedBitcode::compare(SymbolBody *Other) { + assert(Other->kind() >= kind()); if (!isa(Other)) return 1; - if (auto *R = dyn_cast(Other)) - return -compareRegularBitcode(R, this); - if (auto *B = dyn_cast(Other)) { - if (!isReplaceable() && !B->isReplaceable()) + if (!Replaceable && !B->Replaceable) return 0; // Non-replaceable symbols win. - return isReplaceable() ? -1 : 1; + return Replaceable ? -1 : 1; + } + + // As an approximation, regular symbols win over bitcode symbols, + // but we definitely have a conflict if the regular symbol is not + // replaceable and neither is the bitcode symbol. We do not + // 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(Other)) { + if (!R->isCommon() && !R->isCOMDAT() && !Replaceable) + return 0; + return -1; } return 0; } -int Lazy::compare(SymbolBody *Other) { +int Defined::compare(SymbolBody *Other) { + if (Other->kind() < kind()) + return -Other->compare(this); if (isa(Other)) - return -1; + return 0; + return 1; +} + +int Lazy::compare(SymbolBody *Other) { + if (Other->kind() < kind()) + return -Other->compare(this); // Undefined symbols with weak aliases will turn into defined // symbols if they remain undefined, so we don't need to resolve @@ -93,10 +92,8 @@ } int Undefined::compare(SymbolBody *Other) { - if (isa(Other)) - return -1; - if (isa(Other)) - return getWeakAlias() ? 1 : -1; + if (Other->kind() < kind()) + return -Other->compare(this); if (cast(Other)->getWeakAlias()) return -1; return 1;