Handle comdat in LTO.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 2 Mar 2016 15:43:50 +0000 (15:43 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 2 Mar 2016 15:43:50 +0000 (15:43 +0000)
llvm-svn: 262489

lld/ELF/InputFiles.cpp
lld/ELF/InputFiles.h
lld/ELF/SymbolTable.cpp
lld/test/ELF/lto/comdat.ll [new file with mode: 0644]

index 78abcf95fbee5eceed28115f5df12dfe6b86b655..8b8cf02a8de706441f2858a105acfed2c90f8aba 100644 (file)
@@ -13,6 +13,7 @@
 #include "Symbols.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -441,13 +442,27 @@ bool BitcodeFile::classof(const InputFile *F) {
   return F->kind() == BitcodeKind;
 }
 
-void BitcodeFile::parse() {
+void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) {
   LLVMContext Context;
   ErrorOr<std::unique_ptr<IRObjectFile>> ObjOrErr =
       IRObjectFile::create(MB, Context);
   fatal(ObjOrErr);
   IRObjectFile &Obj = **ObjOrErr;
+  const Module &M = Obj.getModule();
+
+  DenseSet<const Comdat *> KeptComdats;
+  for (const auto &P : M.getComdatSymbolTable()) {
+    StringRef N = Saver.save(P.first());
+    if (ComdatGroups.insert(N).second)
+      KeptComdats.insert(&P.second);
+  }
+
   for (const BasicSymbolRef &Sym : Obj.symbols()) {
+    if (const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl()))
+      if (const Comdat *C = GV->getComdat())
+        if (!KeptComdats.count(C))
+          continue;
+
     SmallString<64> Name;
     raw_svector_ostream OS(Name);
     Sym.printName(OS);
index 18debd420b59c04ba4da3a37c41fcf6aca2b3a87..48fe27d31f2d8579060e1f6f0aca9575a1c6ae3d 100644 (file)
@@ -183,7 +183,7 @@ class BitcodeFile : public InputFile {
 public:
   explicit BitcodeFile(MemoryBufferRef M);
   static bool classof(const InputFile *F);
-  void parse();
+  void parse(llvm::DenseSet<StringRef> &ComdatGroups);
   ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
 
 private:
index 095ad86764c62719432222a388af6b331c8e0969..6892968cf0404b682a4767b9af167ad77126f09d 100644 (file)
@@ -82,7 +82,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
   // LLVM bitcode file.
   if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
     BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
-    F->parse();
+    F->parse(ComdatGroups);
     for (SymbolBody *B : F->getSymbols())
       resolve(B);
     return;
@@ -151,8 +151,8 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
   if (BitcodeFiles.empty())
     return;
   ObjectFile<ELFT> *Obj = createCombinedLtoObject();
-  // FIXME: We probably have to ignore comdats here.
-  Obj->parse(ComdatGroups);
+  llvm::DenseSet<StringRef> DummyGroups;
+  Obj->parse(DummyGroups);
   for (SymbolBody *Body : Obj->getSymbols()) {
     Symbol *Sym = insert(Body);
     Sym->Body = Body;
diff --git a/lld/test/ELF/lto/comdat.ll b/lld/test/ELF/lto/comdat.ll
new file mode 100644 (file)
index 0000000..e1384d0
--- /dev/null
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK:      Name: foo
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+define void @foo() comdat {
+  ret void
+}
+