[llvm] r285061 - Make the LTO comdat api more symbol table friendly.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 25 05:02:04 PDT 2016


Author: rafael
Date: Tue Oct 25 07:02:03 2016
New Revision: 285061

URL: http://llvm.org/viewvc/llvm-project?rev=285061&view=rev
Log:
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<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.

Modified:
    llvm/trunk/include/llvm/LTO/LTO.h
    llvm/trunk/lib/LTO/LTO.cpp
    llvm/trunk/tools/gold/gold-plugin.cpp

Modified: llvm/trunk/include/llvm/LTO/LTO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTO.h?rev=285061&r1=285060&r2=285061&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTO.h (original)
+++ llvm/trunk/include/llvm/LTO/LTO.h Tue Oct 25 07:02:03 2016
@@ -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.
@@ -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<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);
@@ -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<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 {
@@ -251,6 +249,9 @@ public:
   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

Modified: llvm/trunk/lib/LTO/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTO.cpp?rev=285061&r1=285060&r2=285061&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTO.cpp (original)
+++ llvm/trunk/lib/LTO/LTO.cpp Tue Oct 25 07:02:03 2016
@@ -218,9 +218,36 @@ Expected<std::unique_ptr<InputFile>> Inp
 
   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),
@@ -332,8 +359,8 @@ Error LTO::addRegularLTO(std::unique_ptr
 
   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);

Modified: llvm/trunk/tools/gold/gold-plugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=285061&r1=285060&r2=285061&view=diff
==============================================================================
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)
+++ llvm/trunk/tools/gold/gold-plugin.cpp Tue Oct 25 07:02:03 2016
@@ -526,9 +526,11 @@ static ld_plugin_status claim_file_hook(
 
     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;
   }




More information about the llvm-commits mailing list