mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-05 10:08:03 +00:00
LTO: Port the new LTO API to ModuleSymbolTable.
Differential Revision: https://reviews.llvm.org/D27077 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289574 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
068dd02393
commit
314f28e505
@ -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.
|
||||
@ -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;
|
||||
|
||||
@ -90,9 +93,9 @@ public:
|
||||
|
||||
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.
|
||||
@ -100,9 +103,9 @@ public:
|
||||
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;
|
||||
|
||||
@ -112,10 +115,9 @@ public:
|
||||
}
|
||||
|
||||
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;
|
||||
@ -126,14 +128,17 @@ public:
|
||||
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();
|
||||
}
|
||||
|
||||
@ -142,16 +147,16 @@ public:
|
||||
|
||||
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
|
||||
@ -164,16 +169,16 @@ public:
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
@ -181,8 +186,9 @@ public:
|
||||
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;
|
||||
@ -206,17 +212,13 @@ public:
|
||||
|
||||
/// 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; }
|
||||
@ -399,8 +401,7 @@ private:
|
||||
// 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);
|
||||
|
||||
|
@ -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);
|
||||
ErrorOr<MemoryBufferRef> BCOrErr =
|
||||
IRObjectFile::findBitcodeInMemBuffer(Object);
|
||||
if (!BCOrErr)
|
||||
return errorCodeToError(BCOrErr.getError());
|
||||
File->MBRef = *BCOrErr;
|
||||
|
||||
for (const auto &C : File->Obj->getModule().getComdatSymbolTable()) {
|
||||
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);
|
||||
@ -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());
|
||||
@ -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) {
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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:
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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)
|
||||
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user