COFF: Use atomic pointers in preparation for parallelizing.

In the new design, mutation of Symbol pointers is the name resolution
operation. This patch makes them atomic pointers so that they can
be mutated by multiple threads safely. I'm going to use atomic
compare-exchange on these pointers.

dyn_cast<> doesn't recognize atomic pointers as pointers,
so we need to call load(). This is unfortunate, but in other places
automatic type conversion works fine.

llvm-svn: 241416
This commit is contained in:
Rui Ueyama 2015-07-05 21:54:42 +00:00
parent cc9fad0bf7
commit c80c03da6c
4 changed files with 14 additions and 12 deletions

View File

@ -220,7 +220,7 @@ StringRef LinkerDriver::findDefaultEntry() {
};
for (auto E : Entries) {
Symbol *Sym = Symtab.find(E[0]);
if (Sym && !isa<Undefined>(Sym->Body))
if (Sym && !isa<Undefined>(Sym->Body.load()))
return E[1];
}
return "";
@ -591,7 +591,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
Symbol *Sym = Symtab.find(From);
if (!Sym)
continue;
if (auto *U = dyn_cast<Undefined>(Sym->Body))
if (auto *U = dyn_cast<Undefined>(Sym->Body.load()))
if (!U->WeakAlias)
U->WeakAlias = Symtab.addUndefined(To);
}

View File

@ -77,7 +77,7 @@ std::error_code SymbolTable::readArchives() {
// Add archive member files to ObjectQueue that should resolve
// existing undefined symbols.
for (Symbol *Sym : LazySyms)
if (auto EC = addMemberFile(cast<Lazy>(Sym->Body)))
if (auto EC = addMemberFile(cast<Lazy>(Sym->Body.load())))
return EC;
return std::error_code();
}
@ -126,7 +126,7 @@ bool SymbolTable::reportRemainingUndefines(bool Resolve) {
bool Ret = false;
for (auto &I : Symtab) {
Symbol *Sym = I.second;
auto *Undef = dyn_cast<Undefined>(Sym->Body);
auto *Undef = dyn_cast<Undefined>(Sym->Body.load());
if (!Undef)
continue;
StringRef Name = Undef->getName();
@ -140,10 +140,10 @@ bool SymbolTable::reportRemainingUndefines(bool Resolve) {
// This odd rule is for compatibility with MSVC linker.
if (Name.startswith("__imp_")) {
Symbol *Imp = find(Name.substr(strlen("__imp_")));
if (Imp && isa<Defined>(Imp->Body)) {
if (Imp && isa<Defined>(Imp->Body.load())) {
if (!Resolve)
continue;
auto *D = cast<Defined>(Imp->Body);
auto *D = cast<Defined>(Imp->Body.load());
auto *S = new (Alloc) DefinedLocalImport(Name, D);
LocalImportChunks.push_back(S->getChunk());
Sym->Body = S;
@ -320,11 +320,11 @@ std::error_code SymbolTable::addCombinedLTOObject() {
StringRef Name = Body->getName();
Symbol *Sym = insert(Body);
if (isa<DefinedBitcode>(Sym->Body)) {
if (isa<DefinedBitcode>(Sym->Body.load())) {
Sym->Body = Body;
continue;
}
if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
if (auto *L = dyn_cast<Lazy>(Sym->Body.load())) {
// We may see new references to runtime library symbols such as __chkstk
// here. These symbols must be wholly defined in non-bitcode files.
if (auto EC = addMemberFile(L))

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include <atomic>
#include <memory>
#include <vector>
@ -38,7 +39,7 @@ class SymbolBody;
// The resolver updates SymbolBody pointers as it resolves symbols.
struct Symbol {
explicit Symbol(SymbolBody *P) : Body(P) {}
SymbolBody *Body;
std::atomic<SymbolBody *> Body;
};
// The base class for real symbol classes.
@ -80,7 +81,7 @@ public:
// has chosen the object among other objects having the same name,
// you can access P->Backref->Body to get the resolver's result.
void setBackref(Symbol *P) { Backref = P; }
SymbolBody *repl() { return Backref ? Backref->Body : this; }
SymbolBody *repl() { return Backref ? Backref->Body.load() : this; }
// Decides which symbol should "win" in the symbol table, this or
// the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if

View File

@ -243,7 +243,8 @@ void Writer::createImportTables() {
Sec->addChunk(C);
}
if (!DelayIdata.empty()) {
Defined *Helper = cast<Defined>(Symtab->find("__delayLoadHelper2")->Body);
Symbol *Sym = Symtab->find("__delayLoadHelper2");
Defined *Helper = cast<Defined>(Sym->Body.load());
DelayIdata.create(Helper);
OutputSection *Sec = createSection(".didat");
for (Chunk *C : DelayIdata.getChunks())
@ -535,7 +536,7 @@ OutputSection *Writer::createSection(StringRef Name) {
// Dest is .reloc section. Add contents to that section.
void Writer::addBaserels(OutputSection *Dest) {
std::vector<uint32_t> V;
Defined *ImageBase = cast<Defined>(Symtab->find("__ImageBase")->Body);
Defined *ImageBase = cast<Defined>(Symtab->find("__ImageBase")->Body.load());
for (OutputSection *Sec : OutputSections) {
if (Sec == Dest)
continue;