Build arbitrary vector with more than 2 distinct scalar elements with a
[oota-llvm.git] / lib / Target / X86 / X86AsmPrinter.cpp
index f3505fb912499f8a0837a01a98d0e5f1ec0c2a4c..990951ea7b8126fdb3dcffcd1cbe2319a428d226 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "X86AsmPrinter.h"
 #include "X86ATTAsmPrinter.h"
 #include "X86IntelAsmPrinter.h"
 #include "X86Subtarget.h"
-#include "X86.h"
 #include "llvm/Constants.h"
 #include "llvm/Module.h"
 #include "llvm/Type.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/Support/CommandLine.h"
 using namespace llvm;
-using namespace x86;
 
-Statistic<> llvm::x86::EmittedInsts("asm-printer",
-                                    "Number of machine instrs printed");
+Statistic<> llvm::EmittedInsts("asm-printer",
+                               "Number of machine instrs printed");
 
 enum AsmWriterFlavorTy { att, intel };
 cl::opt<AsmWriterFlavorTy>
@@ -45,6 +44,7 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) {
   const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
   
   forDarwin = false;
+  PrivateGlobalPrefix = ".L";
   
   switch (Subtarget->TargetType) {
   case X86Subtarget::isDarwin:
@@ -60,6 +60,7 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) {
     forDarwin = true;
     StaticCtorsSection = ".mod_init_func";
     StaticDtorsSection = ".mod_term_func";
+    InlineAsmStart = InlineAsmEnd = "";  // Don't use #APP/#NO_APP
     break;
   case X86Subtarget::isCygwin:
     GlobalPrefix = "_";
@@ -73,6 +74,11 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) {
   default: break;
   }
   
+  if (forDarwin) {
+    // Emit initial debug information.
+    DW.BeginModule(&M);
+  }
+
   return AsmPrinter::doInitialization(M);
 }
 
@@ -80,114 +86,119 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
   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) {
+  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
     
     // Check to see if this is a special global used by LLVM, if so, emit it.
-    if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I))
+    if (EmitSpecialLLVMGlobal(I))
       continue;
     
-    O << "\n\n";
     std::string name = Mang->getValueName(I);
     Constant *C = I->getInitializer();
     unsigned Size = TD.getTypeSize(C->getType());
-    unsigned Align = TD.getTypeAlignmentShift(C->getType());
-
-    switch (I->getLinkage()) {
-    default: assert(0 && "Unknown linkage type!");
-    case GlobalValue::LinkOnceLinkage:
-    case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
-      if (C->isNullValue()) {
-        O << COMMDirective << name << "," << Size;
-        if (COMMDirectiveTakesAlignment)
-          O << "," << (1 << Align);
-        O << "\t\t" << CommentString << " " << I->getName() << "\n";
-        continue;
-      }
-      
-      // Nonnull linkonce -> weak
-      O << "\t.weak " << name << "\n";
-      O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
-      SwitchSection("", I);
-      break;
-    case GlobalValue::InternalLinkage:
-      if (C->isNullValue()) {
-        if (LCOMMDirective) {
-          O << LCOMMDirective << name << "," << Size << "," << Align;
-          continue;
+    unsigned Align = getPreferredAlignmentLog(I);
+
+    if (C->isNullValue() && /* FIXME: Verify correct */
+        (I->hasInternalLinkage() || I->hasWeakLinkage() ||
+         I->hasLinkOnceLinkage() ||
+         (forDarwin && I->hasExternalLinkage() && !I->hasSection()))) {
+      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
+      if (I->hasExternalLinkage()) {
+          O << "\t.globl\t" << name << "\n";
+          O << "\t.zerofill __DATA__, __common, " << name << ", "
+            << Size << ", " << Align;
+      } else {
+        SwitchSection(".data", I);
+        if (LCOMMDirective != NULL) {
+          if (I->hasInternalLinkage()) {
+            O << LCOMMDirective << name << "," << Size;
+            if (forDarwin)
+              O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
+          } else
+            O << COMMDirective  << name << "," << Size;
         } else {
-          SwitchSection(".bss", I);
-          O << "\t.local " << name << "\n";
-          O << COMMDirective << name << "," << Size;
+          if (I->hasInternalLinkage())
+            O << "\t.local\t" << name << "\n";
+          O << COMMDirective  << name << "," << Size;
           if (COMMDirectiveTakesAlignment)
-            O << "," << (1 << Align);
-          O << "\t\t# ";
-          WriteAsOperand(O, I, true, true, &M);
-          O << "\n";
-          continue;
+            O << "," << (AlignmentIsInBytes ? (1 << Align) : Align);
         }
       }
-      SwitchSection(".data", I);
-      break;
-    case GlobalValue::AppendingLinkage:
-      // FIXME: appending linkage variables should go into a section of
-      // their name or something.  For now, just emit them as external.
-    case GlobalValue::ExternalLinkage:
-      SwitchSection(C->isNullValue() ? ".bss" : ".data", I);
-      // If external or appending, declare as a global symbol
-      O << "\t.globl " << name << "\n";
-      break;
-    }
+      O << "\t\t" << CommentString << " " << I->getName() << "\n";
+    } else {
+      switch (I->getLinkage()) {
+      case GlobalValue::LinkOnceLinkage:
+      case GlobalValue::WeakLinkage:
+        if (forDarwin) {
+          O << "\t.globl " << name << "\n"
+            << "\t.weak_definition " << name << "\n";
+          SwitchSection(".section __DATA,__datacoal_nt,coalesced", I);
+        } else {
+          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
+          O << "\t.weak " << name << "\n";
+        }
+        break;
+      case GlobalValue::AppendingLinkage:
+        // FIXME: appending linkage variables should go into a section of
+        // their name or something.  For now, just emit them as external.
+      case GlobalValue::ExternalLinkage:
+        // If external or appending, declare as a global symbol
+        O << "\t.globl " << name << "\n";
+        // FALL THROUGH
+      case GlobalValue::InternalLinkage:
+        SwitchSection(".data", I);
+        break;
+      default:
+        assert(0 && "Unknown linkage type!");
+      }
+
+      EmitAlignment(Align, I);
+      O << name << ":\t\t\t\t" << CommentString << " " << I->getName()
+        << "\n";
+      if (HasDotTypeDotSizeDirective)
+        O << "\t.size " << name << ", " << Size << "\n";
 
-    EmitAlignment(Align);
-    if (HasDotTypeDotSizeDirective) {
-      O << "\t.type " << name << ",@object\n";
-      O << "\t.size " << name << "," << Size << "\n";
+      EmitGlobalConstant(C);
+      O << '\n';
     }
-    O << name << ":\t\t\t" << CommentString << ' ' << I->getName() << '\n';
-    EmitGlobalConstant(C);
   }
   
   if (forDarwin) {
     SwitchSection("", 0);
-    // Output stubs for external global variables
-    if (GVStubs.begin() != GVStubs.end())
-      O << "\t.non_lazy_symbol_pointer\n";
-    for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
-         i != e; ++i) {
-      O << "L" << *i << "$non_lazy_ptr:\n";
-      O << "\t.indirect_symbol " << *i << "\n";
-      O << "\t.long\t0\n";
-    }
 
     // Output stubs for dynamically-linked functions
     unsigned j = 1;
     for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
          i != e; ++i, ++j) {
-      O << "\t.symbol_stub\n";
+      SwitchSection(".section __IMPORT,__jump_table,symbol_stubs,"
+                    "self_modifying_code+pure_instructions,5", 0);
       O << "L" << *i << "$stub:\n";
       O << "\t.indirect_symbol " << *i << "\n";
-      O << "\tjmp\t*L" << j << "$lz\n";
-      O << "L" << *i << "$stub_binder:\n";
-      O << "\tpushl\t$L" << j << "$lz\n";
-      O << "\tjmp\tdyld_stub_binding_helper\n";
-      O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n";
-      O << "L" << j << "$lz:\n";
-      O << "\t.indirect_symbol " << *i << "\n";
-      O << "\t.long\tL" << *i << "$stub_binder\n";
+      O << "\thlt ; hlt ; hlt ; hlt ; hlt\n";
     }
 
     O << "\n";
 
-    // Output stubs for link-once variables
-    if (LinkOnceStubs.begin() != LinkOnceStubs.end())
-      O << ".data\n.align 2\n";
-    for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
-         e = LinkOnceStubs.end(); i != e; ++i) {
-      O << "L" << *i << "$non_lazy_ptr:\n"
-        << "\t.long\t" << *i << '\n';
+    // Output stubs for external and common global variables.
+    if (GVStubs.begin() != GVStubs.end())
+      SwitchSection(".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0);
+    for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
+         i != e; ++i) {
+      O << "L" << *i << "$non_lazy_ptr:\n";
+      O << "\t.indirect_symbol " << *i << "\n";
+      O << "\t.long\t0\n";
     }
+
+    // Emit initial debug information.
+    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
+    // implementation of multiple entry points).  If this doesn't occur, the
+    // 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";
   }
 
   AsmPrinter::doFinalization(M);
@@ -198,7 +209,8 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
 /// for a MachineFunction to the given output stream, using the given target
 /// machine description.
 ///
-FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
+FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,
+                                             X86TargetMachine &tm){
   switch (AsmWriterFlavor) {
   default:
     assert(0 && "Unknown asm flavor!");