From 7912110ddc368f932d20bc82a951371bf9d48ae9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 25 Oct 2016 12:02:03 +0000 Subject: [PATCH] Make the LTO comdat api more symbol table friendly. 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 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. llvm-svn: 285061 --- llvm/include/llvm/LTO/LTO.h | 41 +++++++++++++++++++++-------------------- llvm/lib/LTO/LTO.cpp | 31 +++++++++++++++++++++++++++++-- llvm/tools/gold/gold-plugin.cpp | 6 ++++-- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 7ef6ee1..80e94e8 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -106,6 +106,8 @@ class InputFile { // FIXME: Remove the LLVMContext once we have bitcode symbol tables. LLVMContext Ctx; std::unique_ptr Obj; + std::vector Comdats; + DenseMap ComdatMap; public: /// Create an InputFile. @@ -124,6 +126,7 @@ public: friend LTO; object::basic_symbol_iterator I; + const InputFile *File; const GlobalValue *GV; uint32_t Flags; SmallString<64> Name; @@ -154,7 +157,10 @@ public: } 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 { @@ -176,22 +182,13 @@ public: return GV && GV->isThreadLocal(); } - Expected getComdat() const { - if (!GV) - return ""; - const GlobalObject *GO; - if (auto *GA = dyn_cast(GV)) { - GO = GA->getBaseObject(); - if (!GO) - return make_error("Unable to determine comdat of alias!", - inconvertibleErrorCode()); - } else { - GO = cast(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 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 getComdatIndex() const; uint64_t getCommonSize() const { assert(Flags & object::BasicSymbolRef::SF_Common); @@ -212,7 +209,8 @@ public: 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; @@ -236,8 +234,8 @@ public: /// A range over the symbols in this InputFile. iterator_range 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 { @@ -251,6 +249,9 @@ public: MemoryBufferRef getMemoryBufferRef() const { return Obj->getMemoryBufferRef(); } + + // Returns a table with all the comdats used by this file. + ArrayRef getComdatTable() const { return Comdats; } }; /// This class wraps an output stream for a native object. Most clients should diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index b4efb4a..d43b4d5 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -218,9 +218,36 @@ Expected> 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 InputFile::Symbol::getComdatIndex() const { + if (!GV) + return -1; + const GlobalObject *GO; + if (auto *GA = dyn_cast(GV)) { + GO = GA->getBaseObject(); + if (!GO) + return make_error("Unable to determine comdat of alias!", + inconvertibleErrorCode()); + } else { + GO = cast(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), @@ -332,8 +359,8 @@ Error LTO::addRegularLTO(std::unique_ptr 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); diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp index 1366c0f..7c5d481 100644 --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -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; } -- 2.7.4