* Fix one more bug in PIC codegen: extra load is needed for *all*
[oota-llvm.git] / lib / Target / X86 / X86AsmPrinter.cpp
index f27f44053bbc4b2ef99d7616f420854c0d1c41cf..bea3914fe649be3752c28655937186af58546e7d 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "X86AsmPrinter.h"
 #include "X86ATTAsmPrinter.h"
+#include "X86COFF.h"
 #include "X86IntelAsmPrinter.h"
 #include "X86MachineFunctionInfo.h"
 #include "X86Subtarget.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/Target/TargetAsmInfo.h"
-
+#include "llvm/Target/TargetOptions.h"
 using namespace llvm;
 
-Statistic<> llvm::EmittedInsts("asm-printer",
-                               "Number of machine instrs printed");
-
 static X86FunctionInfo calculateFunctionInfo(const Function *F,
                                              const TargetData *TD) {
   X86FunctionInfo Info;
@@ -109,14 +107,9 @@ void X86SharedAsmPrinter::decorateName(std::string &Name,
 
 /// doInitialization
 bool X86SharedAsmPrinter::doInitialization(Module &M) {
-  if (Subtarget->isTargetDarwin()) {
-    const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
-    if (!Subtarget->is64Bit())
-      X86PICStyle = PICStyle::Stub;
-
-    // Emit initial debug information.
-    DW.BeginModule(&M);
-  } else if (Subtarget->isTargetELF()) {
+  if (Subtarget->isTargetELF() ||
+      Subtarget->isTargetCygMing() ||
+      Subtarget->isTargetDarwin()) {
     // Emit initial debug information.
     DW.BeginModule(&M);
   }
@@ -129,11 +122,12 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
   // from how MASM does things.  When making changes here don't forget to look
   // at X86IntelAsmPrinter::doFinalization().
   const TargetData *TD = TM.getTargetData();
-
+  
   // Print out module-level global variables here.
   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
        I != E; ++I) {
-    if (!I->hasInitializer()) continue;   // External global require no code
+    if (!I->hasInitializer())
+      continue;   // External global require no code
     
     // Check to see if this is a special global used by LLVM, if so, emit it.
     if (EmitSpecialLLVMGlobal(I))
@@ -156,7 +150,10 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
           O << "\t.zerofill __DATA__, __common, " << name << ", "
             << Size << ", " << Align;
       } else {
-        SwitchToDataSection(TAI->getDataSection(), I);
+        if (!NoZerosInBSS && TAI->getBSSSection())
+          SwitchToDataSection(TAI->getBSSSection(), I);
+        else
+          SwitchToDataSection(TAI->getDataSection(), I);
         if (TAI->getLCOMMDirective() != NULL) {
           if (I->hasInternalLinkage()) {
             O << TAI->getLCOMMDirective() << name << "," << Size;
@@ -165,7 +162,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
           } else
             O << TAI->getCOMMDirective()  << name << "," << Size;
         } else {
-          if (!Subtarget->isTargetCygwin()) {
+          if (!Subtarget->isTargetCygMing()) {
             if (I->hasInternalLinkage())
               O << "\t.local\t" << name << "\n";
           }
@@ -183,7 +180,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
           O << "\t.globl " << name << "\n"
             << "\t.weak_definition " << name << "\n";
           SwitchToDataSection(".section __DATA,__const_coal,coalesced", I);
-        } else if (Subtarget->isTargetCygwin()) {
+        } else if (Subtarget->isTargetCygMing()) {
           std::string SectionName(".section\t.data$linkonce." +
                                   name +
                                   ",\"aw\"");
@@ -222,16 +219,19 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
              I->getSection() == ".dtors")) {
           std::string SectionName = ".section " + I->getSection();
           
-          if (Subtarget->isTargetCygwin()) {
+          if (Subtarget->isTargetCygMing()) {
             SectionName += ",\"aw\"";
           } else {
             assert(!Subtarget->isTargetDarwin());
             SectionName += ",\"aw\",@progbits";
           }
 
-          SwitchToDataSection(SectionName.c_str(), I);
+          SwitchToDataSection(SectionName.c_str());
         } else {
-          SwitchToDataSection(TAI->getDataSection(), I);
+          if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
+            SwitchToDataSection(TAI->getBSSSection(), I);
+          else
+            SwitchToDataSection(TAI->getDataSection(), I);
         }
         
         break;
@@ -245,15 +245,26 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
         << "\n";
       if (TAI->hasDotTypeDotSizeDirective())
         O << "\t.size " << name << ", " << Size << "\n";
+      // If the initializer is a extern weak symbol, remember to emit the weak
+      // reference!
+      if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+        if (GV->hasExternalWeakLinkage())
+          ExtWeakSymbols.insert(GV);
 
       EmitGlobalConstant(C);
       O << '\n';
     }
+    if (I->hasHiddenVisibility())
+      if (const char *Directive = TAI->getHiddenDirective())
+        O << Directive << name << "\n";
+    
+    if (Subtarget->isTargetELF())
+      O << "\t.type " << name << ",@object\n";
   }
   
   // Output linker support code for dllexported globals
   if (DLLExportedGVs.begin() != DLLExportedGVs.end()) {
-    SwitchToDataSection(".section .drectve", 0);    
+    SwitchToDataSection(".section .drectve");
   }
 
   for (std::set<std::string>::iterator i = DLLExportedGVs.begin(),
@@ -263,7 +274,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
   }    
 
   if (DLLExportedFns.begin() != DLLExportedFns.end()) {
-    SwitchToDataSection(".section .drectve", 0);    
+    SwitchToDataSection(".section .drectve");
   }
 
   for (std::set<std::string>::iterator i = DLLExportedFns.begin(),
@@ -271,9 +282,9 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
          i != e; ++i) {
     O << "\t.ascii \" -export:" << *i << "\"\n";
   }    
+
   if (Subtarget->isTargetDarwin()) {
-    SwitchToDataSection("", 0);
+    SwitchToDataSection("");
 
     // Output stubs for dynamically-linked functions
     unsigned j = 1;
@@ -291,7 +302,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
     // Output stubs for external and common global variables.
     if (GVStubs.begin() != GVStubs.end())
       SwitchToDataSection(
-                    ".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0);
+                    ".section __IMPORT,__pointers,non_lazy_symbol_pointers");
     for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
          i != e; ++i) {
       O << "L" << *i << "$non_lazy_ptr:\n";
@@ -308,6 +319,18 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
     // linker can safely perform dead code stripping.  Since LLVM never
     // generates code that does this, it is always safe to set.
     O << "\t.subsections_via_symbols\n";
+  } else if (Subtarget->isTargetCygMing()) {
+    // Emit type information for external functions
+    for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
+         i != e; ++i) {
+      O << "\t.def\t " << *i
+        << ";\t.scl\t" << COFF::C_EXT
+        << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
+        << ";\t.endef\n";
+    }
+    
+    // Emit final debug information.
+    DW.EndModule();    
   } else if (Subtarget->isTargetELF()) {
     // Emit final debug information.
     DW.EndModule();