Skip to content

Commit

Permalink
LTO: Port the new LTO API to ModuleSymbolTable.
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D27077

llvm-svn: 289574
  • Loading branch information
pcc committed Dec 13, 2016
1 parent 77c5eaa commit ad90369
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 80 deletions.
73 changes: 37 additions & 36 deletions llvm/include/llvm/LTO/LTO.h
Expand Up @@ -71,7 +71,7 @@ class LTO;
struct SymbolResolution;
class ThinBackendProc;

/// An input file. This is a wrapper for IRObjectFile that exposes only the
/// An input file. This is a wrapper for ModuleSymbolTable that exposes only the
/// information that an LTO client should need in order to do symbol resolution.
class InputFile {
// FIXME: Remove LTO class friendship once we have bitcode symbol tables.
Expand All @@ -80,7 +80,10 @@ class InputFile {

// FIXME: Remove the LLVMContext once we have bitcode symbol tables.
LLVMContext Ctx;
std::unique_ptr<object::IRObjectFile> Obj;
ModuleSymbolTable SymTab;
std::unique_ptr<Module> Mod;
MemoryBufferRef MBRef;

std::vector<StringRef> Comdats;
DenseMap<const Comdat *, unsigned> ComdatMap;

Expand All @@ -90,19 +93,19 @@ class InputFile {

class symbol_iterator;

/// This is a wrapper for object::basic_symbol_iterator that exposes only the
/// information that an LTO client should need in order to do symbol
/// resolution.
/// This is a wrapper for ArrayRef<ModuleSymbolTable::Symbol>::iterator that
/// exposes only the information that an LTO client should need in order to do
/// symbol resolution.
///
/// This object is ephemeral; it is only valid as long as an iterator obtained
/// from symbols() refers to it.
class Symbol {
friend symbol_iterator;
friend LTO;

object::basic_symbol_iterator I;
ArrayRef<ModuleSymbolTable::Symbol>::iterator I;
const ModuleSymbolTable &SymTab;
const InputFile *File;
const GlobalValue *GV;
uint32_t Flags;
SmallString<64> Name;

Expand All @@ -112,10 +115,9 @@ class InputFile {
}

void skip() {
const object::SymbolicFile *Obj = I->getObject();
auto E = Obj->symbol_end();
ArrayRef<ModuleSymbolTable::Symbol>::iterator E = SymTab.symbols().end();
while (I != E) {
Flags = I->getFlags();
Flags = SymTab.getSymbolFlags(*I);
if (!shouldSkip())
break;
++I;
Expand All @@ -126,14 +128,17 @@ class InputFile {
Name.clear();
{
raw_svector_ostream OS(Name);
I->printName(OS);
SymTab.printSymbolName(OS, *I);
}
GV = cast<object::IRObjectFile>(Obj)->getSymbolGV(I->getRawDataRefImpl());
}

bool isGV() const { return I->is<GlobalValue *>(); }
GlobalValue *getGV() const { return I->get<GlobalValue *>(); }

public:
Symbol(object::basic_symbol_iterator I, const InputFile *File)
: I(I), File(File) {
Symbol(ArrayRef<ModuleSymbolTable::Symbol>::iterator I,
const ModuleSymbolTable &SymTab, const InputFile *File)
: I(I), SymTab(SymTab), File(File) {
skip();
}

Expand All @@ -142,16 +147,16 @@ class InputFile {

uint32_t getFlags() const { return Flags; }
GlobalValue::VisibilityTypes getVisibility() const {
if (GV)
return GV->getVisibility();
if (isGV())
return getGV()->getVisibility();
return GlobalValue::DefaultVisibility;
}
bool canBeOmittedFromSymbolTable() const {
return GV && llvm::canBeOmittedFromSymbolTable(GV);
return isGV() && llvm::canBeOmittedFromSymbolTable(getGV());
}
bool isTLS() const {
// FIXME: Expose a thread-local flag for module asm symbols.
return GV && GV->isThreadLocal();
return isGV() && getGV()->isThreadLocal();
}

// Returns the index of the comdat this symbol is in or -1 if the symbol
Expand All @@ -164,25 +169,26 @@ class InputFile {

uint64_t getCommonSize() const {
assert(Flags & object::BasicSymbolRef::SF_Common);
if (!GV)
if (!isGV())
return 0;
return GV->getParent()->getDataLayout().getTypeAllocSize(
GV->getType()->getElementType());
return getGV()->getParent()->getDataLayout().getTypeAllocSize(
getGV()->getType()->getElementType());
}
unsigned getCommonAlignment() const {
assert(Flags & object::BasicSymbolRef::SF_Common);
if (!GV)
if (!isGV())
return 0;
return GV->getAlignment();
return getGV()->getAlignment();
}
};

class symbol_iterator {
Symbol Sym;

public:
symbol_iterator(object::basic_symbol_iterator I, const InputFile *File)
: Sym(I, File) {}
symbol_iterator(ArrayRef<ModuleSymbolTable::Symbol>::iterator I,
const ModuleSymbolTable &SymTab, const InputFile *File)
: Sym(I, SymTab, File) {}

symbol_iterator &operator++() {
++Sym.I;
Expand All @@ -206,17 +212,13 @@ class InputFile {

/// A range over the symbols in this InputFile.
iterator_range<symbol_iterator> symbols() {
return llvm::make_range(symbol_iterator(Obj->symbol_begin(), this),
symbol_iterator(Obj->symbol_end(), this));
return llvm::make_range(
symbol_iterator(SymTab.symbols().begin(), SymTab, this),
symbol_iterator(SymTab.symbols().end(), SymTab, this));
}

StringRef getSourceFileName() const {
return Obj->getModule().getSourceFileName();
}

MemoryBufferRef getMemoryBufferRef() const {
return Obj->getMemoryBufferRef();
}
StringRef getSourceFileName() const { return Mod->getSourceFileName(); }
MemoryBufferRef getMemoryBufferRef() const { return MBRef; }

// Returns a table with all the comdats used by this file.
ArrayRef<StringRef> getComdatTable() const { return Comdats; }
Expand Down Expand Up @@ -399,8 +401,7 @@ class LTO {
// Global mapping from mangled symbol names to resolutions.
StringMap<GlobalResolution> GlobalResolutions;

void addSymbolToGlobalRes(object::IRObjectFile *Obj,
SmallPtrSet<GlobalValue *, 8> &Used,
void addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
const InputFile::Symbol &Sym, SymbolResolution Res,
unsigned Partition);

Expand Down
92 changes: 48 additions & 44 deletions llvm/lib/LTO/LTO.cpp
Expand Up @@ -217,13 +217,22 @@ void llvm::thinLTOInternalizeAndPromoteInIndex(
Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
std::unique_ptr<InputFile> File(new InputFile);

Expected<std::unique_ptr<object::IRObjectFile>> IRObj =
IRObjectFile::create(Object, File->Ctx);
if (!IRObj)
return IRObj.takeError();
File->Obj = std::move(*IRObj);

for (const auto &C : File->Obj->getModule().getComdatSymbolTable()) {
ErrorOr<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(Object);
if (!BCOrErr)
return errorCodeToError(BCOrErr.getError());
File->MBRef = *BCOrErr;

Expected<std::unique_ptr<Module>> MOrErr =
getLazyBitcodeModule(*BCOrErr, File->Ctx,
/*ShouldLazyLoadMetadata*/ true);
if (!MOrErr)
return MOrErr.takeError();

File->Mod = std::move(*MOrErr);
File->SymTab.addModule(File->Mod.get());

for (const auto &C : File->Mod->getComdatSymbolTable()) {
auto P =
File->ComdatMap.insert(std::make_pair(&C.second, File->Comdats.size()));
assert(P.second);
Expand All @@ -235,17 +244,12 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
}

Expected<int> InputFile::Symbol::getComdatIndex() const {
if (!GV)
if (!isGV())
return -1;
const GlobalObject *GO;
if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
GO = GA->getBaseObject();
if (!GO)
return make_error<StringError>("Unable to determine comdat of alias!",
inconvertibleErrorCode());
} else {
GO = cast<GlobalObject>(GV);
}
const GlobalObject *GO = getGV()->getBaseObject();
if (!GO)
return make_error<StringError>("Unable to determine comdat of alias!",
inconvertibleErrorCode());
if (const Comdat *C = GO->getComdat()) {
auto I = File->ComdatMap.find(C);
assert(I != File->ComdatMap.end());
Expand All @@ -272,11 +276,10 @@ LTO::LTO(Config Conf, ThinBackend Backend,
ThinLTO(std::move(Backend)) {}

// Add the given symbol to the GlobalResolutions map, and resolve its partition.
void LTO::addSymbolToGlobalRes(IRObjectFile *Obj,
SmallPtrSet<GlobalValue *, 8> &Used,
void LTO::addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
const InputFile::Symbol &Sym,
SymbolResolution Res, unsigned Partition) {
GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
GlobalValue *GV = Sym.isGV() ? Sym.getGV() : nullptr;

auto &GlobalRes = GlobalResolutions[Sym.getName()];
if (GV) {
Expand Down Expand Up @@ -321,14 +324,13 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);

// FIXME: move to backend
Module &M = Input->Obj->getModule();
Module &M = *Input->Mod;
if (!Conf.OverrideTriple.empty())
M.setTargetTriple(Conf.OverrideTriple);
else if (M.getTargetTriple().empty())
M.setTargetTriple(Conf.DefaultTriple);

MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
Expected<bool> HasThinLTOSummary = hasGlobalValueSummary(MBRef);
Expected<bool> HasThinLTOSummary = hasGlobalValueSummary(Input->MBRef);
if (!HasThinLTOSummary)
return HasThinLTOSummary.takeError();

Expand All @@ -346,17 +348,20 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
}
Expected<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
IRObjectFile::create(Input->Obj->getMemoryBufferRef(), RegularLTO.Ctx);
if (!ObjOrErr)
return ObjOrErr.takeError();
std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
Expected<std::unique_ptr<Module>> MOrErr =
getLazyBitcodeModule(Input->MBRef, RegularLTO.Ctx,
/*ShouldLazyLoadMetadata*/ true);
if (!MOrErr)
return MOrErr.takeError();

Module &M = Obj->getModule();
Module &M = **MOrErr;
if (Error Err = M.materializeMetadata())
return Err;
UpgradeDebugInfo(M);

ModuleSymbolTable SymTab;
SymTab.addModule(&M);

SmallPtrSet<GlobalValue *, 8> Used;
collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);

Expand All @@ -368,16 +373,18 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,

auto ResI = Res.begin();
for (const InputFile::Symbol &Sym :
make_range(InputFile::symbol_iterator(Obj->symbol_begin(), nullptr),
InputFile::symbol_iterator(Obj->symbol_end(), nullptr))) {
make_range(InputFile::symbol_iterator(SymTab.symbols().begin(), SymTab,
nullptr),
InputFile::symbol_iterator(SymTab.symbols().end(), SymTab,
nullptr))) {
assert(ResI != Res.end());
SymbolResolution Res = *ResI++;
addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
addSymbolToGlobalRes(Used, Sym, Res, 0);

GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)
continue;
if (Res.Prevailing && GV) {
if (Res.Prevailing && Sym.isGV()) {
GlobalValue *GV = Sym.getGV();
Keep.push_back(GV);
switch (GV->getLinkage()) {
default:
Expand All @@ -396,8 +403,7 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
if (Sym.getFlags() & object::BasicSymbolRef::SF_Common) {
// FIXME: We should figure out what to do about commons defined by asm.
// For now they aren't reported correctly by ModuleSymbolTable.
assert(GV);
auto &CommonRes = RegularLTO.Commons[GV->getName()];
auto &CommonRes = RegularLTO.Commons[Sym.getGV()->getName()];
CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
CommonRes.Prevailing |= Res.Prevailing;
Expand All @@ -407,7 +413,7 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
}
assert(ResI == Res.end());

return RegularLTO.Mover->move(Obj->takeModule(), Keep,
return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
[](GlobalValue &, IRMover::ValueAdder) {},
/* LinkModuleInlineAsm */ true,
/* IsPerformingImport */ false);
Expand All @@ -416,11 +422,11 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
// Add a ThinLTO object to the link.
Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
ArrayRef<SymbolResolution> Res) {
Module &M = Input->Obj->getModule();
Module &M = *Input->Mod;
SmallPtrSet<GlobalValue *, 8> Used;
collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);

MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
MemoryBufferRef MBRef = Input->MBRef;
Expected<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
SummaryObjOrErr = object::ModuleSummaryIndexObjectFile::create(MBRef);
if (!SummaryObjOrErr)
Expand All @@ -432,12 +438,10 @@ Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
for (const InputFile::Symbol &Sym : Input->symbols()) {
assert(ResI != Res.end());
SymbolResolution Res = *ResI++;
addSymbolToGlobalRes(Input->Obj.get(), Used, Sym, Res,
ThinLTO.ModuleMap.size() + 1);
addSymbolToGlobalRes(Used, Sym, Res, ThinLTO.ModuleMap.size() + 1);

GlobalValue *GV = Input->Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
if (Res.Prevailing && GV)
ThinLTO.PrevailingModuleForGUID[GV->getGUID()] =
if (Res.Prevailing && Sym.isGV())
ThinLTO.PrevailingModuleForGUID[Sym.getGV()->getGUID()] =
MBRef.getBufferIdentifier();
}
assert(ResI == Res.end());
Expand Down

0 comments on commit ad90369

Please sign in to comment.