Skip to content

Commit

Permalink
Make the LTO comdat api more symbol table friendly.
Browse files Browse the repository at this point in the history
In an IR symbol table I would expect the comdats to be represented as:

- A table of strings, one for each comdat name.
- Each symbol has an optional index into that table.

The natural api for accessing that would be

InputFile:
ArrayRef<StringRef> getComdatTable() const;

Symbol:
int getComdatIndex() const;

This patch implements an API as close to that as possible.  The
implementation on top of the current IRObjectFile is a bit hackish,
but should map just fine over a symbol table and is very convenient to
use.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285061 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
espindola committed Oct 25, 2016
1 parent 797783e commit 050bf6c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 24 deletions.
41 changes: 21 additions & 20 deletions include/llvm/LTO/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ class InputFile {
// FIXME: Remove the LLVMContext once we have bitcode symbol tables.
LLVMContext Ctx;
std::unique_ptr<object::IRObjectFile> Obj;
std::vector<StringRef> Comdats;
DenseMap<const Comdat *, unsigned> ComdatMap;

public:
/// Create an InputFile.
Expand All @@ -124,6 +126,7 @@ class InputFile {
friend LTO;

object::basic_symbol_iterator I;
const InputFile *File;
const GlobalValue *GV;
uint32_t Flags;
SmallString<64> Name;
Expand Down Expand Up @@ -154,7 +157,10 @@ class InputFile {
}

public:
Symbol(object::basic_symbol_iterator I) : I(I) { skip(); }
Symbol(object::basic_symbol_iterator I, const InputFile *File)
: I(I), File(File) {
skip();
}

StringRef getName() const { return Name; }
StringRef getIRName() const {
Expand All @@ -176,22 +182,13 @@ class InputFile {
return GV && GV->isThreadLocal();
}

Expected<StringRef> getComdat() const {
if (!GV)
return "";
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);
}
if (const Comdat *C = GO->getComdat())
return C->getName();
return "";
}
// Returns the index of the comdat this symbol is in or -1 if the symbol
// is not in a comdat.
// FIXME: We have to return Expected<int> because aliases point to an
// arbitrary ConstantExpr and that might not actually be a constant. That
// means we might not be able to find what an alias is aliased to and
// so find its comdat.
Expected<int> getComdatIndex() const;

uint64_t getCommonSize() const {
assert(Flags & object::BasicSymbolRef::SF_Common);
Expand All @@ -212,7 +209,8 @@ class InputFile {
Symbol Sym;

public:
symbol_iterator(object::basic_symbol_iterator I) : Sym(I) {}
symbol_iterator(object::basic_symbol_iterator I, const InputFile *File)
: Sym(I, File) {}

symbol_iterator &operator++() {
++Sym.I;
Expand All @@ -236,8 +234,8 @@ class InputFile {

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

StringRef getDataLayoutStr() const {
Expand All @@ -251,6 +249,9 @@ class InputFile {
MemoryBufferRef getMemoryBufferRef() const {
return Obj->getMemoryBufferRef();
}

// Returns a table with all the comdats used by this file.
ArrayRef<StringRef> getComdatTable() const { return Comdats; }
};

/// This class wraps an output stream for a native object. Most clients should
Expand Down
31 changes: 29 additions & 2 deletions lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,36 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {

File->Ctx.setDiagnosticHandler(nullptr, nullptr);

for (const auto &C : File->Obj->getModule().getComdatSymbolTable()) {
auto P =
File->ComdatMap.insert(std::make_pair(&C.second, File->Comdats.size()));
assert(P.second);
File->Comdats.push_back(C.first());
}

return std::move(File);
}

Expected<int> InputFile::Symbol::getComdatIndex() const {
if (!GV)
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);
}
if (const Comdat *C = GO->getComdat()) {
auto I = File->ComdatMap.find(C);
assert(I != File->ComdatMap.end());
return I->second;
}
return -1;
}

LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
Config &Conf)
: ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
Expand Down Expand Up @@ -332,8 +359,8 @@ 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()),
InputFile::symbol_iterator(Obj->symbol_end()))) {
make_range(InputFile::symbol_iterator(Obj->symbol_begin(), nullptr),
InputFile::symbol_iterator(Obj->symbol_end(), nullptr))) {
assert(ResI != Res.end());
SymbolResolution Res = *ResI++;
addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
Expand Down
6 changes: 4 additions & 2 deletions tools/gold/gold-plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,11 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,

sym.size = 0;
sym.comdat_key = nullptr;
StringRef C = check(Sym.getComdat());
if (!C.empty())
int CI = check(Sym.getComdatIndex());
if (CI != -1) {
StringRef C = Obj->getComdatTable()[CI];
sym.comdat_key = strdup(C.str().c_str());
}

sym.resolution = LDPR_UNKNOWN;
}
Expand Down

0 comments on commit 050bf6c

Please sign in to comment.