[LTO] Create Undefined Bitcode symbol when we drop a comdat member.
authorDavide Italiano <davide@freebsd.org>
Fri, 22 Apr 2016 18:26:33 +0000 (18:26 +0000)
committerDavide Italiano <davide@freebsd.org>
Fri, 22 Apr 2016 18:26:33 +0000 (18:26 +0000)
Differential Revision:  http://reviews.llvm.org/D19389

llvm-svn: 267181

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

index bccbddf..98ca80d 100644 (file)
@@ -458,16 +458,19 @@ static uint8_t getGvVisibility(const GlobalValue *GV) {
 }
 
 SymbolBody *
-BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats,
+BitcodeFile::createBody(const DenseSet<const Comdat *> &KeptComdats,
                               const IRObjectFile &Obj,
-                              const BasicSymbolRef &Sym) {
-  const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl());
-  if (GV)
-    if (const Comdat *C = GV->getComdat())
-      if (!KeptComdats.count(C))
-        return nullptr;
+                              const BasicSymbolRef &Sym,
+                              const GlobalValue *GV) {
+  SmallString<64> Name;
+  raw_svector_ostream OS(Name);
+  Sym.printName(OS);
+  StringRef NameRef = Saver.save(StringRef(Name));
+  SymbolBody *Body;
 
   uint32_t Flags = Sym.getFlags();
+  bool IsWeak = Flags & BasicSymbolRef::SF_Weak;
+
   uint8_t Visibility;
   if (GV)
     Visibility = getGvVisibility(GV);
@@ -476,28 +479,37 @@ BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats,
     // protected visibility.
     Visibility = STV_DEFAULT;
 
-  SmallString<64> Name;
-  raw_svector_ostream OS(Name);
-  Sym.printName(OS);
-  StringRef NameRef = Saver.save(StringRef(Name));
+  if (GV)
+    if (const Comdat *C = GV->getComdat())
+      if (!KeptComdats.count(C)) {
+        Body = new (Alloc)
+          UndefinedBitcode(NameRef, IsWeak, Visibility);
+        return Body;
+      }
 
   const Module &M = Obj.getModule();
-  SymbolBody *Body;
-  bool IsWeak = Flags & BasicSymbolRef::SF_Weak;
-  if (Flags & BasicSymbolRef::SF_Undefined) {
-    Body = new (Alloc) UndefinedBitcode(NameRef, IsWeak, Visibility);
-  } else if (Flags & BasicSymbolRef::SF_Common) {
+  if (Flags & BasicSymbolRef::SF_Undefined)
+    return new (Alloc) UndefinedBitcode(NameRef, IsWeak, Visibility);
+  if (Flags & BasicSymbolRef::SF_Common) {
     // FIXME: Set SF_Common flag correctly for module asm symbols, and expose
     // size and alignment.
     assert(GV);
     const DataLayout &DL = M.getDataLayout();
     uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
-    Body = new (Alloc)
+    return new (Alloc)
         DefinedCommon(NameRef, Size, GV->getAlignment(),
                       IsWeak ? STB_WEAK : STB_GLOBAL, Visibility, /*Type*/ 0);
-  } else {
-    Body = new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility);
   }
+  return new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility);
+}
+
+SymbolBody *
+BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats,
+                              const IRObjectFile &Obj,
+                              const BasicSymbolRef &Sym) {
+  const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl());
+  SymbolBody *Body = createBody(KeptComdats, Obj, Sym, GV);
+
   // FIXME: Expose a thread-local flag for module asm symbols.
   if (GV) {
     if (GV->isThreadLocal())
index ca41d16..f6c9e9b 100644 (file)
@@ -226,6 +226,11 @@ private:
   createSymbolBody(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
                    const llvm::object::IRObjectFile &Obj,
                    const llvm::object::BasicSymbolRef &Sym);
+  SymbolBody *
+  createBody(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
+             const llvm::object::IRObjectFile &Obj,
+             const llvm::object::BasicSymbolRef &Sym,
+             const llvm::GlobalValue *GV);
 };
 
 // .so file.
diff --git a/lld/test/ELF/lto/Inputs/comdat.s b/lld/test/ELF/lto/Inputs/comdat.s
new file mode 100644 (file)
index 0000000..6f6e5ae
--- /dev/null
@@ -0,0 +1,5 @@
+    .section .text.f,"axG",@progbits,c,comdat
+    .globl foo
+
+foo:
+    retq
diff --git a/lld/test/ELF/lto/comdat2.ll b/lld/test/ELF/lto/comdat2.ll
new file mode 100644 (file)
index 0000000..1509585
--- /dev/null
@@ -0,0 +1,40 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.o -o %t2.so -shared
+; RUN: llvm-readobj -t %t2.so | FileCheck %s --check-prefix=OTHER
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$c = comdat any
+
+define protected void @foo() comdat($c) {
+  ret void
+}
+
+; CHECK: Symbol {
+; CHECK:   Name: foo
+; CHECK-NEXT:   Value: 0x1000
+; CHECK-NEXT:   Size: 1
+; CHECK-NEXT:   Binding: Global
+; CHECK-NEXT:   Type: Function
+; CHECK-NEXT:   Other [
+; CHECK-NEXT:     STV_PROTECTED
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   Section: .text
+; CHECK-NEXT: }
+
+; OTHER: Symbol {
+; OTHER:   Name: foo
+; OTHER-NEXT:   Value: 0x1000
+; OTHER-NEXT:   Size: 0
+; OTHER-NEXT:   Binding: Global
+; OTHER-NEXT:   Type: None
+; OTHER-NEXT:   Other [
+; OTHER-NEXT:     STV_PROTECTED
+; OTHER-NEXT:   ]
+; OTHER-NEXT:   Section: .text
+; OTHER-NEXT: }