forked from OSchip/llvm-project
COFF: Merge DefinedRegular and DefinedCOMDAT.
I split them in r240319 because I thought they are different enough that we should treat them as different types. It turned out that that was not a good idea. They are so similar that we ended up having many duplicate code. llvm-svn: 240706
This commit is contained in:
parent
16238d90b2
commit
9b921e5dc9
|
@ -28,7 +28,7 @@ namespace lld {
|
|||
namespace coff {
|
||||
|
||||
SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
|
||||
: Chunk(SectionKind), File(F), Ptr(this), Header(H),
|
||||
: Chunk(SectionKind), Ptr(this), File(F), Header(H),
|
||||
Relocs(File->getCOFFObj()->getRelocations(Header)),
|
||||
NumRelocs(std::distance(Relocs.begin(), Relocs.end())) {
|
||||
// Initialize SectionName.
|
||||
|
@ -86,11 +86,8 @@ void SectionChunk::mark() {
|
|||
// Mark all symbols listed in the relocation table for this section.
|
||||
for (const coff_relocation &Rel : Relocs) {
|
||||
SymbolBody *B = File->getSymbolBody(Rel.SymbolTableIndex);
|
||||
if (auto *D = dyn_cast<DefinedRegular>(B)) {
|
||||
if (auto *D = dyn_cast<DefinedRegular>(B))
|
||||
D->markLive();
|
||||
} else if (auto *D = dyn_cast<DefinedCOMDAT>(B)) {
|
||||
D->markLive();
|
||||
}
|
||||
}
|
||||
|
||||
// Mark associative sections if any.
|
||||
|
@ -184,10 +181,10 @@ bool SectionChunk::equals(const SectionChunk *X) const {
|
|||
return false;
|
||||
SymbolBody *B1 = File->getSymbolBody(R1.SymbolTableIndex);
|
||||
SymbolBody *B2 = X->File->getSymbolBody(R2.SymbolTableIndex);
|
||||
if (auto *C1 = dyn_cast<DefinedCOMDAT>(B1))
|
||||
if (auto *C2 = dyn_cast<DefinedCOMDAT>(B2))
|
||||
if (C1->getChunk() == C2->getChunk())
|
||||
return true;
|
||||
auto *D1 = dyn_cast<DefinedRegular>(B1);
|
||||
auto *D2 = dyn_cast<DefinedRegular>(B2);
|
||||
if (D1 && D2 && D1->getChunk() == D2->getChunk())
|
||||
return true;
|
||||
return B1 == B2;
|
||||
};
|
||||
return std::equal(Relocs.begin(), Relocs.end(), X->Relocs.begin(), Eq);
|
||||
|
@ -199,15 +196,8 @@ ArrayRef<uint8_t> SectionChunk::getContents() const {
|
|||
return A;
|
||||
}
|
||||
|
||||
// Returns a pointer to this chunk or its replacement.
|
||||
SectionChunk *SectionChunk::repl() {
|
||||
while (Ptr != Ptr->Ptr)
|
||||
Ptr = Ptr->Ptr;
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
void SectionChunk::replaceWith(SectionChunk *Other) {
|
||||
Ptr = Other;
|
||||
Ptr = Other->Ptr;
|
||||
Live = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ using llvm::object::coff_section;
|
|||
using llvm::sys::fs::file_magic;
|
||||
|
||||
class Defined;
|
||||
class DefinedCOMDAT;
|
||||
class DefinedRegular;
|
||||
class DefinedImportData;
|
||||
class ObjectFile;
|
||||
class OutputSection;
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
void addAssociative(SectionChunk *Child);
|
||||
|
||||
StringRef getDebugName() override;
|
||||
void setSymbol(DefinedCOMDAT *S) { if (!Sym) Sym = S; }
|
||||
void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; }
|
||||
|
||||
// Used by the garbage collector.
|
||||
bool isRoot() { return Root; }
|
||||
|
@ -133,23 +133,22 @@ public:
|
|||
void markLive() { if (!Live) mark(); }
|
||||
|
||||
// Used for ICF (Identical COMDAT Folding)
|
||||
SectionChunk *repl();
|
||||
void replaceWith(SectionChunk *Other);
|
||||
uint64_t getHash() const;
|
||||
bool equals(const SectionChunk *Other) const;
|
||||
|
||||
private:
|
||||
ArrayRef<uint8_t> getContents() const;
|
||||
|
||||
// A file this chunk was created from.
|
||||
ObjectFile *File;
|
||||
|
||||
// A pointer pointing to a replacement for this chunk.
|
||||
// Initially it points to "this" object. If this chunk is merged
|
||||
// with other chunk by ICF, it points to another chunk,
|
||||
// and this chunk is considrered as dead.
|
||||
SectionChunk *Ptr;
|
||||
|
||||
private:
|
||||
ArrayRef<uint8_t> getContents() const;
|
||||
|
||||
// A file this chunk was created from.
|
||||
ObjectFile *File;
|
||||
|
||||
const coff_section *Header;
|
||||
StringRef SectionName;
|
||||
std::vector<Chunk *> AssocChildren;
|
||||
|
@ -163,7 +162,7 @@ private:
|
|||
|
||||
// Chunks are basically unnamed chunks of bytes.
|
||||
// Symbols are associated for debugging and logging purposs only.
|
||||
DefinedCOMDAT *Sym = nullptr;
|
||||
DefinedRegular *Sym = nullptr;
|
||||
};
|
||||
|
||||
// A chunk for common symbols. Common chunks don't have actual data.
|
||||
|
|
|
@ -215,10 +215,8 @@ SymbolBody *ObjectFile::createSymbolBody(COFFSymbolRef Sym, const void *AuxP,
|
|||
}
|
||||
Chunk *C = SparseChunks[Sym.getSectionNumber()];
|
||||
if (auto *SC = cast_or_null<SectionChunk>(C)) {
|
||||
if (!SC->isCOMDAT())
|
||||
return new (Alloc) DefinedRegular(COFFObj.get(), Sym, SC);
|
||||
auto *B = new (Alloc) DefinedCOMDAT(COFFObj.get(), Sym, SC);
|
||||
if (Sym.getValue() == 0 && !AuxP)
|
||||
auto *B = new (Alloc) DefinedRegular(COFFObj.get(), Sym, SC);
|
||||
if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP)
|
||||
SC->setSymbol(B);
|
||||
return B;
|
||||
}
|
||||
|
|
|
@ -26,16 +26,11 @@ namespace coff {
|
|||
int DefinedRegular::compare(SymbolBody *Other) {
|
||||
if (Other->kind() < kind())
|
||||
return -Other->compare(this);
|
||||
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))
|
||||
if (auto *D = dyn_cast<DefinedRegular>(Other)) {
|
||||
if (isCOMDAT() && D->isCOMDAT())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -67,9 +62,12 @@ 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 (isa<DefinedRegular>(Other) && Replaceable)
|
||||
return -1;
|
||||
if (isa<DefinedCommon>(Other) || isa<DefinedCOMDAT>(Other))
|
||||
if (auto *D = dyn_cast<DefinedRegular>(Other)) {
|
||||
if (Replaceable || D->isCOMDAT())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
if (isa<DefinedCommon>(Other))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -117,12 +115,6 @@ 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);
|
||||
|
|
|
@ -51,7 +51,6 @@ public:
|
|||
DefinedImportThunkKind,
|
||||
DefinedLocalImportKind,
|
||||
DefinedCommonKind,
|
||||
DefinedCOMDATKind,
|
||||
DefinedRegularKind,
|
||||
DefinedLast,
|
||||
LazyKind,
|
||||
|
@ -115,51 +114,31 @@ public:
|
|||
class DefinedRegular : public Defined {
|
||||
public:
|
||||
DefinedRegular(COFFObjectFile *F, COFFSymbolRef S, SectionChunk *C)
|
||||
: Defined(DefinedRegularKind), COFFFile(F), Sym(S), Data(C) {}
|
||||
: Defined(DefinedRegularKind), COFFFile(F), Sym(S), Data(&C->Ptr),
|
||||
IsCOMDAT(C->isCOMDAT()) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == DefinedRegularKind;
|
||||
}
|
||||
|
||||
StringRef getName() override;
|
||||
uint64_t getRVA() override { return Data->getRVA() + Sym.getValue(); }
|
||||
bool isExternal() override { return Sym.isExternal(); }
|
||||
uint64_t getFileOff() override { return Data->getFileOff() + Sym.getValue(); }
|
||||
int compare(SymbolBody *Other) override;
|
||||
void markLive() { Data->markLive(); }
|
||||
|
||||
private:
|
||||
StringRef Name;
|
||||
COFFObjectFile *COFFFile;
|
||||
COFFSymbolRef Sym;
|
||||
SectionChunk *Data;
|
||||
};
|
||||
|
||||
class DefinedCOMDAT : public Defined {
|
||||
public:
|
||||
DefinedCOMDAT(COFFObjectFile *F, COFFSymbolRef S, SectionChunk *C)
|
||||
: Defined(DefinedCOMDATKind), COFFFile(F), Sym(S), Data(C) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == DefinedCOMDATKind;
|
||||
}
|
||||
|
||||
uint64_t getFileOff() override {
|
||||
return Data->repl()->getFileOff() + Sym.getValue();
|
||||
return (*Data)->getFileOff() + Sym.getValue();
|
||||
}
|
||||
|
||||
StringRef getName() override;
|
||||
uint64_t getRVA() override { return Data->repl()->getRVA() + Sym.getValue(); }
|
||||
uint64_t getRVA() override { return (*Data)->getRVA() + Sym.getValue(); }
|
||||
bool isExternal() override { return Sym.isExternal(); }
|
||||
int compare(SymbolBody *Other) override;
|
||||
void markLive() { Data->repl()->markLive(); }
|
||||
Chunk *getChunk() { return Data->repl(); }
|
||||
bool isCOMDAT() { return IsCOMDAT; }
|
||||
void markLive() { (*Data)->markLive(); }
|
||||
Chunk *getChunk() { return *Data; }
|
||||
|
||||
private:
|
||||
StringRef Name;
|
||||
COFFObjectFile *COFFFile;
|
||||
COFFSymbolRef Sym;
|
||||
SectionChunk *Data;
|
||||
SectionChunk **Data;
|
||||
bool IsCOMDAT;
|
||||
};
|
||||
|
||||
class DefinedCommon : public Defined {
|
||||
|
|
|
@ -111,14 +111,9 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {
|
|||
void Writer::markLive() {
|
||||
if (!Config->DoGC)
|
||||
return;
|
||||
for (StringRef Name : Config->GCRoots) {
|
||||
SymbolBody *B = Symtab->find(Name);
|
||||
if (auto *D = dyn_cast<DefinedRegular>(B)) {
|
||||
for (StringRef Name : Config->GCRoots)
|
||||
if (auto *D = dyn_cast<DefinedRegular>(Symtab->find(Name)))
|
||||
D->markLive();
|
||||
} else if (auto *D = dyn_cast<DefinedCOMDAT>(B)) {
|
||||
D->markLive();
|
||||
}
|
||||
}
|
||||
for (Chunk *C : Symtab->getChunks())
|
||||
if (auto *SC = dyn_cast<SectionChunk>(C))
|
||||
if (SC->isRoot())
|
||||
|
|
Loading…
Reference in New Issue