]> granicus.if.org Git - llvm/commitdiff
LTO: Pass SF_Executable flag through to InputFile::Symbol
authorTobias Edler von Koch <tobias@codeaurora.org>
Thu, 13 Apr 2017 16:24:14 +0000 (16:24 +0000)
committerTobias Edler von Koch <tobias@codeaurora.org>
Thu, 13 Apr 2017 16:24:14 +0000 (16:24 +0000)
Summary:
The linker needs to be able to determine whether a symbol is text or data to
handle the case of a common being overridden by a strong definition in an
archive. If the archive contains a text member of the same name as the common,
that function is discarded. However, if the archive contains a data member of
the same name, that strong definition overrides the common. This is a behavior
of ld.bfd, which the Qualcomm linker also supports in LTO.

Here's a test case to illustrate:

####

cat > 1.c << \!
int blah;
!

cat > 2.c << \!
int blah() {
  return 0;
}
!

cat > 3.c << \!
int blah = 20;
!

clang -c 1.c
clang -c 2.c
clang -c 3.c

ar cr lib.a 2.o 3.o
ld 1.o lib.a -t

####

The correct output is:

1.o
(lib.a)3.o

Thanks to Shankar Easwaran and Hemant Kulkarni for the test case!

Reviewers: mehdi_amini, rafael, pcc, davide

Reviewed By: pcc

Subscribers: davide, llvm-commits, inglorion

Differential Revision: https://reviews.llvm.org/D31901

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300205 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/LTO/LTO.h
include/llvm/Object/IRSymtab.h
lib/Object/IRSymtab.cpp
test/LTO/Resolution/X86/symtab.ll
tools/llvm-lto2/llvm-lto2.cpp

index 693568f5b9a968b393ab02b8289019c5a4afc4fe..8c083947b849e8a09bf417e66e53cb1e12e70a6d 100644 (file)
@@ -126,6 +126,7 @@ public:
     using irsymtab::Symbol::getCommonSize;
     using irsymtab::Symbol::getCommonAlignment;
     using irsymtab::Symbol::getCOFFWeakExternalFallback;
+    using irsymtab::Symbol::isExecutable;
   };
 
   /// A range over the symbols in this InputFile.
index 7ce6fa50e6da32ab521f7fac039510b7d1989106..98ef3ffcc9774828bea5cbfecd8fdacd4415f82e 100644 (file)
@@ -92,6 +92,7 @@ struct Symbol {
     FB_global,
     FB_format_specific,
     FB_unnamed_addr,
+    FB_executable,
   };
 
   /// The index into the Uncommon table, or -1 if this symbol does not have an
@@ -166,6 +167,7 @@ struct Symbol {
   bool isGlobal() const { return (Flags >> S::FB_global) & 1; }
   bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; }
   bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; }
+  bool isExecutable() const { return (Flags >> S::FB_executable) & 1; }
 
   uint64_t getCommonSize() const {
     assert(isCommon());
index 1ef2c4bb730325cbd07b652bd9a52d8f26111fa2..f78b84b388a56af84bfce7b7bbe25f5bfecae976 100644 (file)
@@ -125,6 +125,8 @@ Error Builder::addSymbol(ModuleSymbolTable::Symbol Msym) {
     Sym.Flags |= 1 << storage::Symbol::FB_global;
   if (Flags & object::BasicSymbolRef::SF_FormatSpecific)
     Sym.Flags |= 1 << storage::Symbol::FB_format_specific;
+  if (Flags & object::BasicSymbolRef::SF_Executable)
+    Sym.Flags |= 1 << storage::Symbol::FB_executable;
 
   Sym.ComdatIndex = -1;
   auto *GV = Msym.dyn_cast<GlobalValue *>();
index 48eb198fb1cc1b6390ca610705b1a9c344fbba77..e2729ac918a063ec948138d4bb93d9723155ce58 100644 (file)
@@ -11,37 +11,42 @@ source_filename = "src.c"
 !0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}}
 !llvm.module.flags = !{ !0 }
 
-; CHECK: H------ _g1
+; CHECK: D------X _fun
+define i32 @fun() {
+  ret i32 0
+}
+
+; CHECK: H------- _g1
 @g1 = hidden global i32 0
 
-; CHECK: P------ _g2
+; CHECK: P------- _g2
 @g2 = protected global i32 0
 
-; CHECK: D------ _g3
+; CHECK: D------- _g3
 @g3 = global i32 0
 
-; CHECK: DU----- _g4
+; CHECK: DU------ _g4
 @g4 = external global i32
 
-; CHECK: D--W--- _g5
+; CHECK: D--W---- _g5
 @g5 = weak global i32 0
 
-; CHECK: D--W-O- _g6
+; CHECK: D--W-O-- _g6
 @g6 = linkonce_odr unnamed_addr global i32 0
 
-; CHECK: D-----T _g7
+; CHECK: D-----T- _g7
 @g7 = thread_local global i32 0
 
-; CHECK: D-C---- _g8
+; CHECK: D-C----- _g8
 ; CHECK-NEXT: size 4 align 8
 @g8 = common global i32 0, align 8
 
-; CHECK: D------ _g9
+; CHECK: D------- _g9
 ; CHECK-NEXT: comdat g9
 $g9 = comdat any
 @g9 = global i32 0, comdat
 
-; CHECK: D--WI-- _g10
+; CHECK: D--WI--- _g10
 ; CHECK-NEXT: comdat g9
 ; CHECK-NEXT: fallback _g9
 @g10 = weak alias i32, i32* @g9
index 52ba669279c699952f79c24599cb3e815ccd77fc..7a8d40553384b0f44dfcc97814f68811ecf0ee2e 100644 (file)
@@ -317,18 +317,19 @@ static int dumpSymtab(int argc, char **argv) {
       PrintBool('I', Sym.isIndirect());
       PrintBool('O', Sym.canBeOmittedFromSymbolTable());
       PrintBool('T', Sym.isTLS());
+      PrintBool('X', Sym.isExecutable());
       outs() << ' ' << Sym.getName() << '\n';
 
       if (Sym.isCommon())
-        outs() << "        size " << Sym.getCommonSize() << " align "
+        outs() << "         size " << Sym.getCommonSize() << " align "
                << Sym.getCommonAlignment() << '\n';
 
       int Comdat = Sym.getComdatIndex();
       if (Comdat != -1)
-        outs() << "        comdat " << ComdatTable[Comdat] << '\n';
+        outs() << "         comdat " << ComdatTable[Comdat] << '\n';
 
       if (Sym.isWeak() && Sym.isIndirect())
-        outs() << "        fallback " << Sym.getCOFFWeakExternalFallback() << '\n';
+        outs() << "         fallback " << Sym.getCOFFWeakExternalFallback() << '\n';
     }
 
     outs() << '\n';