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:
Rui Ueyama 2015-06-25 22:00:42 +00:00
parent 16238d90b2
commit 9b921e5dc9
6 changed files with 39 additions and 86 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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())