GV with null value initializer shouldn't go to BSS if it's meant for a mergeable...
[oota-llvm.git] / lib / Target / PowerPC / AsmPrinter / PPCAsmPrinter.cpp
index 3043b0098b4112c83fec081c092ca74daafb59a9..6c5d8b9d476756f94709c488fdf348d5baef839a 100644 (file)
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
-#include <set>
+#include "llvm/ADT/StringSet.h"
 using namespace llvm;
 
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
 namespace {
   struct VISIBILITY_HIDDEN PPCAsmPrinter : public AsmPrinter {
-    std::set<std::string> FnStubs, GVStubs;
+    StringSet<> FnStubs, GVStubs, HiddenGVStubs;
     const PPCSubtarget &Subtarget;
 
     PPCAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
@@ -292,13 +292,12 @@ namespace {
 
   /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
   struct VISIBILITY_HIDDEN PPCLinuxAsmPrinter : public PPCAsmPrinter {
-
-    DwarfWriter DW;
+    DwarfWriter *DW;
     MachineModuleInfo *MMI;
 
     PPCLinuxAsmPrinter(raw_ostream &O, PPCTargetMachine &TM,
                     const TargetAsmInfo *T)
-      : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) {
+      : PPCAsmPrinter(O, TM, T), DW(0), MMI(0) {
     }
 
     virtual const char *getPassName() const {
@@ -312,6 +311,7 @@ namespace {
     void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesAll();
       AU.addRequired<MachineModuleInfo>();
+      AU.addRequired<DwarfWriter>();
       PPCAsmPrinter::getAnalysisUsage(AU);
     }
 
@@ -322,12 +322,12 @@ namespace {
   /// OS X
   struct VISIBILITY_HIDDEN PPCDarwinAsmPrinter : public PPCAsmPrinter {
 
-    DwarfWriter DW;
+    DwarfWriter *DW;
     MachineModuleInfo *MMI;
-
+    raw_ostream &OS;
     PPCDarwinAsmPrinter(raw_ostream &O, PPCTargetMachine &TM,
                         const TargetAsmInfo *T)
-      : PPCAsmPrinter(O, TM, T), DW(O, this, T), MMI(0) {
+      : PPCAsmPrinter(O, TM, T), DW(0), MMI(0), OS(O) {
     }
 
     virtual const char *getPassName() const {
@@ -341,6 +341,7 @@ namespace {
     void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesAll();
       AU.addRequired<MachineModuleInfo>();
+      AU.addRequired<DwarfWriter>();
       PPCAsmPrinter::getAnalysisUsage(AU);
     }
 
@@ -387,10 +388,18 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
 
     // External or weakly linked global variables need non-lazily-resolved stubs
     if (TM.getRelocationModel() != Reloc::Static) {
-      if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
-            GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
-        GVStubs.insert(Name);
-        printSuffixedName(Name, "$non_lazy_ptr");
+      if (GV->isDeclaration() || GV->mayBeOverridden()) {
+        if (GV->hasHiddenVisibility()) {
+          if (!GV->isDeclaration() && !GV->hasCommonLinkage())
+            O << Name;
+          else {
+            HiddenGVStubs.insert(Name);
+            printSuffixedName(Name, "$non_lazy_ptr");
+          }
+        } else {
+          GVStubs.insert(Name);
+          printSuffixedName(Name, "$non_lazy_ptr");
+        }
         if (GV->hasExternalWeakLinkage())
           ExtWeakSymbols.insert(GV);
         return;
@@ -398,10 +407,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
     }
     O << Name;
 
-    if (MO.getOffset() > 0)
-      O << "+" << MO.getOffset();
-    else if (MO.getOffset() < 0)
-      O << MO.getOffset();
+    printOffset(MO.getOffset());
 
     if (GV->hasExternalWeakLinkage())
       ExtWeakSymbols.insert(GV);
@@ -419,7 +425,10 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
 void PPCAsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) {
   std::string Name = getGlobalLinkName(GV);
   if (TM.getRelocationModel() != Reloc::Static) {
-    GVStubs.insert(Name);
+    if (GV->hasHiddenVisibility())
+      HiddenGVStubs.insert(Name);
+    else
+      GVStubs.insert(Name);
     printSuffixedName(Name, "$non_lazy_ptr");
     return;
   }
@@ -575,6 +584,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
   switch (F->getLinkage()) {
   default: assert(0 && "Unknown linkage type!");
+  case Function::PrivateLinkage:
   case Function::InternalLinkage:  // Symbols default to internal.
     break;
   case Function::ExternalLinkage:
@@ -594,7 +604,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   O << CurrentFnName << ":\n";
 
   // Emit pre-function debug information.
-  DW.BeginFunction(&MF);
+  DW->BeginFunction(&MF);
 
   // Print out code for the function.
   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@@ -616,8 +626,10 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   // Print out jump tables referenced by the function.
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
 
+  SwitchToSection(TAI->SectionForGlobal(F));
+
   // Emit post-function debug information.
-  DW.EndFunction(&MF);
+  DW->EndFunction(&MF);
 
   O.flush();
 
@@ -629,12 +641,11 @@ bool PPCLinuxAsmPrinter::doInitialization(Module &M) {
   bool Result = AsmPrinter::doInitialization(M);
 
   // Emit initial debug information.
-  DW.BeginModule(&M);
-
-  // AsmPrinter::doInitialization should have done this analysis.
-  MMI = getAnalysisToUpdate<MachineModuleInfo>();
+  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
   assert(MMI);
-  DW.SetModuleInfo(MMI);
+  DW = getAnalysisIfAvailable<DwarfWriter>();
+  assert(DW && "DwarfWriter is not available");
+  DW->BeginModule(&M, MMI, O, this, TAI);
 
   // GNU as handles section names wrapped in quotes
   Mang->setUseQuotes(true);
@@ -669,14 +680,14 @@ void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
 
   Constant *C = GVar->getInitializer();
   const Type *Type = C->getType();
-  unsigned Size = TD->getABITypeSize(Type);
+  unsigned Size = TD->getTypePaddedSize(Type);
   unsigned Align = TD->getPreferredAlignmentLog(GVar);
 
   SwitchToSection(TAI->SectionForGlobal(GVar));
 
   if (C->isNullValue() && /* FIXME: Verify correct */
       !GVar->hasSection() &&
-      (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() ||
+      (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
        GVar->mayBeOverridden())) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
 
@@ -685,7 +696,7 @@ void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
         O << "\t.type " << name << ", @object\n";
         O << name << ":\n";
         O << "\t.zero " << Size << '\n';
-      } else if (GVar->hasInternalLinkage()) {
+      } else if (GVar->hasLocalLinkage()) {
         O << TAI->getLCOMMDirective() << name << ',' << Size;
       } else {
         O << ".comm " << name << ',' << Size;
@@ -713,6 +724,7 @@ void PPCLinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
       << "\t.type " << name << ", @object\n";
     // FALL THROUGH
    case GlobalValue::InternalLinkage:
+   case GlobalValue::PrivateLinkage:
     break;
    default:
     cerr << "Unknown linkage type!";
@@ -743,7 +755,7 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
   // TODO
 
   // Emit initial debug information.
-  DW.EndModule();
+  DW->EndModule();
 
   return AsmPrinter::doFinalization(M);
 }
@@ -764,6 +776,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
   switch (F->getLinkage()) {
   default: assert(0 && "Unknown linkage type!");
+  case Function::PrivateLinkage:
   case Function::InternalLinkage:  // Symbols default to internal.
     break;
   case Function::ExternalLinkage:
@@ -782,7 +795,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   O << CurrentFnName << ":\n";
 
   // Emit pre-function debug information.
-  DW.BeginFunction(&MF);
+  DW->BeginFunction(&MF);
 
   // If the function is empty, then we need to emit *something*. Otherwise, the
   // function's label might be associated with something that it wasn't meant to
@@ -811,7 +824,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
 
   // Emit post-function debug information.
-  DW.EndFunction(&MF);
+  DW->EndFunction(&MF);
 
   // We didn't modify anything.
   return false;
@@ -844,13 +857,13 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) {
   bool Result = AsmPrinter::doInitialization(M);
 
   // Emit initial debug information.
-  DW.BeginModule(&M);
-
   // We need this for Personality functions.
   // AsmPrinter::doInitialization should have done this analysis.
-  MMI = getAnalysisToUpdate<MachineModuleInfo>();
+  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
   assert(MMI);
-  DW.SetModuleInfo(MMI);
+  DW = getAnalysisIfAvailable<DwarfWriter>();
+  assert(DW && "DwarfWriter is not available");
+  DW->BeginModule(&M, MMI, O, this, TAI);
 
   // Darwin wants symbols to be quoted if they have complex names.
   Mang->setUseQuotes(true);
@@ -894,22 +907,23 @@ void PPCDarwinAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
 
   Constant *C = GVar->getInitializer();
   const Type *Type = C->getType();
-  unsigned Size = TD->getABITypeSize(Type);
+  unsigned Size = TD->getTypePaddedSize(Type);
   unsigned Align = TD->getPreferredAlignmentLog(GVar);
 
   SwitchToSection(TAI->SectionForGlobal(GVar));
 
   if (C->isNullValue() && /* FIXME: Verify correct */
       !GVar->hasSection() &&
-      (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() ||
-       GVar->mayBeOverridden())) {
+      (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
+       GVar->mayBeOverridden()) &&
+      TAI->SectionKindForGlobal(GVar) != SectionKind::RODataMergeStr) {
     if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
 
     if (GVar->hasExternalLinkage()) {
       O << "\t.globl " << name << '\n';
       O << "\t.zerofill __DATA, __common, " << name << ", "
         << Size << ", " << Align;
-    } else if (GVar->hasInternalLinkage()) {
+    } else if (GVar->hasLocalLinkage()) {
       O << TAI->getLCOMMDirective() << name << ',' << Size << ',' << Align;
     } else if (!GVar->hasCommonLinkage()) {
       O << "\t.globl " << name << '\n'
@@ -947,6 +961,7 @@ void PPCDarwinAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
     O << "\t.globl " << name << '\n';
     // FALL THROUGH
    case GlobalValue::InternalLinkage:
+   case GlobalValue::PrivateLinkage:
     break;
    default:
     cerr << "Unknown linkage type!";
@@ -980,51 +995,70 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
 
   // Output stubs for dynamically-linked functions
   if (TM.getRelocationModel() == Reloc::PIC_) {
-    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
+    for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
          i != e; ++i) {
       SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs,"
                           "pure_instructions,32");
       EmitAlignment(4);
-      std::string p = *i;
-      std::string L0p = (p[0]=='\"') ? "\"L0$" + p.substr(1) : "L0$" + p ;
+      const char *p = i->getKeyData();
+      bool hasQuote = p[0]=='\"';
       printSuffixedName(p, "$stub");
       O << ":\n";
-      O << "\t.indirect_symbol " << *i << '\n';
+      O << "\t.indirect_symbol " << p << '\n';
       O << "\tmflr r0\n";
-      O << "\tbcl 20,31," << L0p << '\n';
-      O << L0p << ":\n";
+      O << "\tbcl 20,31,";
+      if (hasQuote)
+        O << "\"L0$" << &p[1];
+      else
+        O << "L0$" << p;
+      O << '\n';
+      if (hasQuote)
+        O << "\"L0$" << &p[1];
+      else
+        O << "L0$" << p;
+      O << ":\n";
       O << "\tmflr r11\n";
       O << "\taddis r11,r11,ha16(";
       printSuffixedName(p, "$lazy_ptr");
-      O << "-" << L0p << ")\n";
+      O << "-";
+      if (hasQuote)
+        O << "\"L0$" << &p[1];
+      else
+        O << "L0$" << p;
+      O << ")\n";
       O << "\tmtlr r0\n";
       if (isPPC64)
         O << "\tldu r12,lo16(";
       else
         O << "\tlwzu r12,lo16(";
       printSuffixedName(p, "$lazy_ptr");
-      O << "-" << L0p << ")(r11)\n";
+      O << "-";
+      if (hasQuote)
+        O << "\"L0$" << &p[1];
+      else
+        O << "L0$" << p;
+      O << ")(r11)\n";
       O << "\tmtctr r12\n";
       O << "\tbctr\n";
       SwitchToDataSection(".lazy_symbol_pointer");
       printSuffixedName(p, "$lazy_ptr");
       O << ":\n";
-      O << "\t.indirect_symbol " << *i << '\n';
+      O << "\t.indirect_symbol " << p << '\n';
       if (isPPC64)
         O << "\t.quad dyld_stub_binding_helper\n";
       else
         O << "\t.long dyld_stub_binding_helper\n";
     }
   } else {
-    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
+    for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
          i != e; ++i) {
       SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs,"
                           "pure_instructions,16");
       EmitAlignment(4);
-      std::string p = *i;
+      const char *p = i->getKeyData();
       printSuffixedName(p, "$stub");
       O << ":\n";
-      O << "\t.indirect_symbol " << *i << '\n';
+      O << "\t.indirect_symbol " << p << '\n';
       O << "\tlis r11,ha16(";
       printSuffixedName(p, "$lazy_ptr");
       O << ")\n";
@@ -1039,7 +1073,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
       SwitchToDataSection(".lazy_symbol_pointer");
       printSuffixedName(p, "$lazy_ptr");
       O << ":\n";
-      O << "\t.indirect_symbol " << *i << '\n';
+      O << "\t.indirect_symbol " << p << '\n';
       if (isPPC64)
         O << "\t.quad dyld_stub_binding_helper\n";
       else
@@ -1062,12 +1096,12 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
   // Output stubs for external and common global variables.
   if (!GVStubs.empty()) {
     SwitchToDataSection(".non_lazy_symbol_pointer");
-    for (std::set<std::string>::iterator I = GVStubs.begin(),
-         E = GVStubs.end(); I != E; ++I) {
-      std::string p = *I;
+    for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end();
+         i != e; ++i) {
+      std::string p = i->getKeyData();
       printSuffixedName(p, "$non_lazy_ptr");
       O << ":\n";
-      O << "\t.indirect_symbol " << *I << '\n';
+      O << "\t.indirect_symbol " << p << '\n';
       if (isPPC64)
         O << "\t.quad\t0\n";
       else
@@ -1075,8 +1109,25 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
     }
   }
 
+  if (!HiddenGVStubs.empty()) {
+    SwitchToSection(TAI->getDataSection());
+    for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end();
+         i != e; ++i) {
+      std::string p = i->getKeyData();
+      EmitAlignment(isPPC64 ? 3 : 2);
+      printSuffixedName(p, "$non_lazy_ptr");
+      O << ":\n";
+      if (isPPC64)
+        O << "\t.quad\t";
+      else
+        O << "\t.long\t";
+      O << p << '\n';
+    }
+  }
+
+
   // Emit initial debug information.
-  DW.EndModule();
+  DW->EndModule();
 
   // Funny Darwin hack: This flag tells the linker that no global symbols
   // contain code that falls through to other global symbols (e.g. the obvious