Introduce new headers whose inclusion forces linking and
[oota-llvm.git] / lib / Target / ARM / AsmPrinter / ARMAsmPrinter.cpp
index 62bf87b46b2e28cab58ab9ec1a3b1dfa127cca4d..662dc4351422ecedbf97a9676144bb7ed9bcbd93 100644 (file)
@@ -14,6 +14,7 @@
 
 #define DEBUG_TYPE "asm-printer"
 #include "ARM.h"
+#include "ARMBuildAttrs.h"
 #include "ARMTargetMachine.h"
 #include "ARMAddressingModes.h"
 #include "ARMConstantPoolValue.h"
@@ -29,9 +30,9 @@
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
-#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/Support/MathExtras.h"
@@ -42,14 +43,8 @@ using namespace llvm;
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
 namespace {
-  struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
-    ARMAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
-      : AsmPrinter(O, TM, T), DW(O, this, T), MMI(NULL), AFI(NULL), MCP(NULL),
-        InCPMode(false) {
-      Subtarget = &TM.getSubtarget<ARMSubtarget>();
-    }
-
-    DwarfWriter DW;
+  class VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
+    DwarfWriter *DW;
     MachineModuleInfo *MMI;
 
     /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
@@ -73,19 +68,27 @@ namespace {
 
     /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
     /// non-lazy-pointers for indirect access.
-    std::set<std::string> GVNonLazyPtrs;
+    StringSet<> GVNonLazyPtrs;
+
+    /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden
+    /// visibility that require non-lazy-pointers for indirect access.
+    StringSet<> HiddenGVNonLazyPtrs;
 
     /// FnStubs - Keeps the set of external function GlobalAddresses that the
     /// asm printer should generate stubs for.
-    std::set<std::string> FnStubs;
-
-    /// PCRelGVs - Keeps the set of GlobalValues used in pc relative
-    /// constantpool.
-    SmallPtrSet<const GlobalValue*, 8> PCRelGVs;
+    StringSet<> FnStubs;
 
     /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
     bool InCPMode;
-    
+  public:
+    explicit ARMAsmPrinter(raw_ostream &O, TargetMachine &TM,
+                           const TargetAsmInfo *T, CodeGenOpt::Level OL,
+                           bool V)
+      : AsmPrinter(O, TM, T, OL, V), DW(0), MMI(NULL), AFI(NULL), MCP(NULL),
+        InCPMode(false) {
+      Subtarget = &TM.getSubtarget<ARMSubtarget>();
+    }
+
     virtual const char *getPassName() const {
       return "ARM Assembly Printer";
     }
@@ -122,6 +125,9 @@ namespace {
 
     virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                  unsigned AsmVariant, const char *ExtraCode);
+    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                                       unsigned AsmVariant,
+                                       const char *ExtraCode);
 
     void printModuleLevelGV(const GlobalVariable* GVar);
     bool printInstruction(const MachineInstr *MI);  // autogenerated.
@@ -141,7 +147,10 @@ namespace {
       if (!GV)
         Name += ACPV->getSymbol();
       if (ACPV->isNonLazyPointer()) {
-        GVNonLazyPtrs.insert(Name);
+        if (GV->hasHiddenVisibility())
+          HiddenGVNonLazyPtrs.insert(Name);
+        else
+          GVNonLazyPtrs.insert(Name);
         printSuffixedName(Name, "$non_lazy_ptr");
       } else if (ACPV->isStub()) {
         FnStubs.insert(Name);
@@ -169,6 +178,7 @@ namespace {
       AsmPrinter::getAnalysisUsage(AU);
       AU.setPreservesAll();
       AU.addRequired<MachineModuleInfo>();
+      AU.addRequired<DwarfWriter>();
     }
   };
 } // end of anonymous namespace
@@ -179,6 +189,8 @@ namespace {
 /// method to print assembly for each instruction.
 ///
 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  this->MF = &MF;
+
   AFI = MF.getInfo<ARMFunctionInfo>();
   MCP = MF.getConstantPool();
 
@@ -193,6 +205,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   const Function *F = MF.getFunction();
   switch (F->getLinkage()) {
   default: assert(0 && "Unknown linkage type!");
+  case Function::PrivateLinkage:
   case Function::InternalLinkage:
     SwitchToTextSection("\t.text", F);
     break;
@@ -200,8 +213,10 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     SwitchToTextSection("\t.text", F);
     O << "\t.globl\t" << CurrentFnName << "\n";
     break;
-  case Function::WeakLinkage:
-  case Function::LinkOnceLinkage:
+  case Function::WeakAnyLinkage:
+  case Function::WeakODRLinkage:
+  case Function::LinkOnceAnyLinkage:
+  case Function::LinkOnceODRLinkage:
     if (Subtarget->isTargetDarwin()) {
       SwitchToTextSection(
                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
@@ -228,8 +243,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
   O << CurrentFnName << ":\n";
   // Emit pre-function debug information.
-  // FIXME: Dwarf support.
-  //DW.BeginFunction(&MF);
+  DW->BeginFunction(&MF);
 
   if (Subtarget->isTargetDarwin()) {
     // If the function is empty, then we need to emit *something*. Otherwise,
@@ -246,7 +260,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
        I != E; ++I) {
     // Print a label for the basic block.
     if (I != MF.begin()) {
-      printBasicBlockLabel(I, true, true);
+      printBasicBlockLabel(I, true, true, VerboseAsm);
       O << '\n';
     }
     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
@@ -260,8 +274,9 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
 
   // Emit post-function debug information.
-  // FIXME: Dwarf support.
-  //DW.EndFunction();
+  DW->EndFunction(&MF);
+
+  O.flush();
 
   return false;
 }
@@ -280,7 +295,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
     if (!Modifier || strcmp(Modifier, "no_hash") != 0)
       O << "#";
 
-    O << (int)MO.getImm();
+    O << MO.getImm();
     break;
   }
   case MachineOperand::MO_MachineBasicBlock:
@@ -298,12 +313,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
       FnStubs.insert(Name);
     } else
       O << Name;
-    
-    if (MO.getOffset() > 0)
-      O << '+' << MO.getOffset();
-    else if (MO.getOffset() < 0)
-      O << MO.getOffset();
-    
+
+    printOffset(MO.getOffset());
+
     if (isCallOp && Subtarget->isTargetELF() &&
         TM.getRelocationModel() == Reloc::PIC_)
       O << "(PLT)";
@@ -339,17 +351,20 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
   }
 }
 
-static void printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI) {
+static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
+                       const TargetAsmInfo *TAI) {
   assert(V < (1 << 12) && "Not a valid so_imm value!");
   unsigned Imm = ARM_AM::getSOImmValImm(V);
   unsigned Rot = ARM_AM::getSOImmValRot(V);
-  
+
   // Print low-level immediate formation info, per
   // A5.1.3: "Data-processing operands - Immediate".
   if (Rot) {
     O << "#" << Imm << ", " << Rot;
     // Pretty printed version.
-    O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
+    if (VerboseAsm)
+      O << ' ' << TAI->getCommentString()
+        << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
   } else {
     O << "#" << Imm;
   }
@@ -360,17 +375,17 @@ static void printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI) {
 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
   const MachineOperand &MO = MI->getOperand(OpNum);
   assert(MO.isImm() && "Not a valid so_imm value!");
-  printSOImm(O, MO.getImm(), TAI);
+  printSOImm(O, MO.getImm(), VerboseAsm, TAI);
 }
 
-/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
-/// followed by a or to materialize.
+/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
+/// followed by an 'orr' to materialize.
 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
   const MachineOperand &MO = MI->getOperand(OpNum);
   assert(MO.isImm() && "Not a valid so_imm value!");
   unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
   unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
-  printSOImm(O, ARM_AM::getSOImmVal(V1), TAI);
+  printSOImm(O, ARM_AM::getSOImmVal(V1), VerboseAsm, TAI);
   O << "\n\torr";
   printPredicateOperand(MI, 2);
   O << " ";
@@ -378,7 +393,7 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
   O << ", ";
   printOperand(MI, 0); 
   O << ", ";
-  printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
+  printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
 }
 
 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
@@ -670,12 +685,6 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
     
     if (MCPE.isMachineConstantPoolEntry()) {
       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
-      ARMConstantPoolValue *ACPV =
-        static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
-      if (ACPV->getPCAdjustment() != 0) {
-        const GlobalValue *GV = ACPV->getGV();
-        PCRelGVs.insert(GV);
-      }
     } else {
       EmitGlobalConstant(MCPE.Val.ConstVal);
       // remember to emit the weak reference
@@ -735,7 +744,10 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     
     switch (ExtraCode[0]) {
     default: return true;  // Unknown modifier.
+    case 'a': // Don't print "#" before a global var name or constant.
     case 'c': // Don't print "$" before a global var name or constant.
+      printOperand(MI, OpNo, "no_hash");
+      return false;
     case 'P': // Print a VFP double precision register.
       printOperand(MI, OpNo);
       return false;
@@ -761,6 +773,15 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   return false;
 }
 
+bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+                                          unsigned OpNo, unsigned AsmVariant,
+                                          const char *ExtraCode) {
+  if (ExtraCode && ExtraCode[0])
+    return true; // Unknown modifier.
+  printAddrMode2Operand(MI, OpNo);
+  return false;
+}
+
 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
 
@@ -775,23 +796,6 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   default: {
     if (InCPMode && AFI->isThumbFunction())
       InCPMode = false;
-    switch (Opc) {
-    case ARM::PICADD:
-    case ARM::PICLD:
-    case ARM::PICLDZH:
-    case ARM::PICLDZB:
-    case ARM::PICLDH:
-    case ARM::PICLDB:
-    case ARM::PICLDSH:
-    case ARM::PICLDSB:
-    case ARM::PICSTR:
-    case ARM::PICSTRH:
-    case ARM::PICSTRB:
-    case ARM::tPICADD:
-      break;
-    default:
-      break;
-    }
   }}
 
   // Call the autogenerated instruction printer routines.
@@ -799,27 +803,53 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
 }
 
 bool ARMAsmPrinter::doInitialization(Module &M) {
-  // Emit initial debug information.
-  // FIXME: Dwarf support.
-  //DW.BeginModule(&M);
-  
+
   bool Result = AsmPrinter::doInitialization(M);
 
-  // AsmPrinter::doInitialization should have done this analysis.
-  MMI = getAnalysisToUpdate<MachineModuleInfo>();
+  // Emit initial debug information.
+  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
   assert(MMI);
-  // FIXME: Dwarf support.
-  //DW.SetModuleInfo(MMI);
+  DW = getAnalysisIfAvailable<DwarfWriter>();
+  assert(DW && "Dwarf Writer is not available");
+  DW->BeginModule(&M, MMI, O, this, TAI);
 
   // Darwin wants symbols to be quoted if they have complex names.
   if (Subtarget->isTargetDarwin())
     Mang->setUseQuotes(true);
 
+  // Emit ARM Build Attributes
+  if (Subtarget->isTargetELF()) {
+    // CPU Type
+    std::string CPUString = Subtarget->getCPUString();
+    if (CPUString != "generic")
+      O << "\t.cpu " << CPUString << '\n';
+
+    // FIXME: Emit FPU type
+    if (Subtarget->hasVFP2())
+      O << "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch << ", 2\n";
+
+    // Signal various FP modes.
+    if (!UnsafeFPMath)
+      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal << ", 1\n"
+        << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions << ", 1\n";
+
+    if (FiniteOnlyFPMath())
+      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 1\n";
+    else
+      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 3\n";
+
+    // 8-bytes alignment stuff.
+    O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n"
+      << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n";
+
+    // FIXME: Should we signal R9 usage?
+  }
+
   return Result;
 }
 
 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \n or \0.
+/// Don't print things like \\n or \\0.
 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
        Name != E; ++Name)
@@ -849,20 +879,22 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
   std::string name = Mang->getValueName(GVar);
   Constant *C = GVar->getInitializer();
   const Type *Type = C->getType();
-  unsigned Size = TD->getABITypeSize(Type);
+  unsigned Size = TD->getTypeAllocSize(Type);
   unsigned Align = TD->getPreferredAlignmentLog(GVar);
+  bool isDarwin = Subtarget->isTargetDarwin();
 
   printVisibility(name, GVar->getVisibility());
 
   if (Subtarget->isTargetELF())
     O << "\t.type " << name << ",%object\n";
 
-  SwitchToSection(TAI->SectionForGlobal(GVar));
-
-  if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal()) {
+  if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() &&
+      !(isDarwin &&
+        TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) {
     // FIXME: This seems to be pretty darwin-specific
 
     if (GVar->hasExternalLinkage()) {
+      SwitchToSection(TAI->SectionForGlobal(GVar));
       if (const char *Directive = TAI->getZeroFillDirective()) {
         O << "\t.globl\t" << name << "\n";
         O << Directive << "__DATA, __common, " << name << ", "
@@ -871,34 +903,63 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
       }
     }
 
-    if (GVar->hasInternalLinkage() || GVar->mayBeOverridden()) {
+    if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
 
-      if (TAI->getLCOMMDirective() != NULL) {
-        if (PCRelGVs.count(GVar) || GVar->hasInternalLinkage()) {
+      if (isDarwin) {
+        if (GVar->hasLocalLinkage()) {
+          O << TAI->getLCOMMDirective()  << name << "," << Size
+            << ',' << Align;
+        } else if (GVar->hasCommonLinkage()) {
+          O << TAI->getCOMMDirective()  << name << "," << Size
+            << ',' << Align;
+        } else {
+          SwitchToSection(TAI->SectionForGlobal(GVar));
+          O << "\t.globl " << name << '\n'
+            << TAI->getWeakDefDirective() << name << '\n';
+          EmitAlignment(Align, GVar);
+          O << name << ":";
+          if (VerboseAsm) {
+            O << "\t\t\t\t" << TAI->getCommentString() << ' ';
+            PrintUnmangledNameSafely(GVar, O);
+          }
+          O << '\n';
+          EmitGlobalConstant(C);
+          return;
+        }
+      } else if (TAI->getLCOMMDirective() != NULL) {
+        if (GVar->hasLocalLinkage()) {
           O << TAI->getLCOMMDirective() << name << "," << Size;
-          if (Subtarget->isTargetDarwin())
-            O << "," << Align;
-        } else
+        } else {
           O << TAI->getCOMMDirective()  << name << "," << Size;
+          if (TAI->getCOMMDirectiveTakesAlignment())
+            O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+        }
       } else {
-        if (GVar->hasInternalLinkage())
+        SwitchToSection(TAI->SectionForGlobal(GVar));
+        if (GVar->hasLocalLinkage())
           O << "\t.local\t" << name << "\n";
         O << TAI->getCOMMDirective()  << name << "," << Size;
         if (TAI->getCOMMDirectiveTakesAlignment())
           O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
       }
-      O << "\t\t" << TAI->getCommentString() << " ";
-      PrintUnmangledNameSafely(GVar, O);
+      if (VerboseAsm) {
+        O << "\t\t" << TAI->getCommentString() << " ";
+        PrintUnmangledNameSafely(GVar, O);
+      }
       O << "\n";
       return;
     }
   }
 
+  SwitchToSection(TAI->SectionForGlobal(GVar));
   switch (GVar->getLinkage()) {
-   case GlobalValue::LinkOnceLinkage:
-   case GlobalValue::WeakLinkage:
-    if (Subtarget->isTargetDarwin()) {
+   case GlobalValue::CommonLinkage:
+   case GlobalValue::LinkOnceAnyLinkage:
+   case GlobalValue::LinkOnceODRLinkage:
+   case GlobalValue::WeakAnyLinkage:
+   case GlobalValue::WeakODRLinkage:
+    if (isDarwin) {
       O << "\t.globl " << name << "\n"
         << "\t.weak_definition " << name << "\n";
     } else {
@@ -911,6 +972,7 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
    case GlobalValue::ExternalLinkage:
     O << "\t.globl " << name << "\n";
     // FALL THROUGH
+   case GlobalValue::PrivateLinkage:
    case GlobalValue::InternalLinkage:
     break;
    default:
@@ -919,8 +981,11 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
   }
 
   EmitAlignment(Align, GVar);
-  O << name << ":\t\t\t\t" << TAI->getCommentString() << " ";
-  PrintUnmangledNameSafely(GVar, O);
+  O << name << ":";
+  if (VerboseAsm) {
+    O << "\t\t\t\t" << TAI->getCommentString() << " ";
+    PrintUnmangledNameSafely(GVar, O);
+  }
   O << "\n";
   if (TAI->hasDotTypeDotSizeDirective())
     O << "\t.size " << name << ", " << Size << "\n";
@@ -945,9 +1010,8 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
     SwitchToDataSection("");
 
     // 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) {
+    for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
+         i != e; ++i) {
       if (TM.getRelocationModel() == Reloc::PIC_)
         SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
                             "none,16", 0);
@@ -958,10 +1022,10 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
       EmitAlignment(2);
       O << "\t.code\t32\n";
 
-      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 << "\tldr ip, ";
       printSuffixedName(p, "$slp");
       O << "\n";
@@ -984,26 +1048,39 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
       SwitchToDataSection(".lazy_symbol_pointer", 0);
       printSuffixedName(p, "$lazy_ptr");
       O << ":\n";
-      O << "\t.indirect_symbol " << *i << "\n";
+      O << "\t.indirect_symbol " << p << "\n";
       O << "\t.long\tdyld_stub_binding_helper\n";
     }
     O << "\n";
 
     // Output non-lazy-pointers for external and common global variables.
-    if (!GVNonLazyPtrs.empty())
-      SwitchToDataSection(".non_lazy_symbol_pointer", 0);
-    for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(),
-           e = GVNonLazyPtrs.end(); i != e; ++i) {
-      std::string p = *i;
-      printSuffixedName(p, "$non_lazy_ptr");
-      O << ":\n";
-      O << "\t.indirect_symbol " << *i << "\n";
-      O << "\t.long\t0\n";
+    if (!GVNonLazyPtrs.empty()) {
+      SwitchToDataSection("\t.non_lazy_symbol_pointer", 0);
+      for (StringSet<>::iterator i =  GVNonLazyPtrs.begin(),
+             e = GVNonLazyPtrs.end(); i != e; ++i) {
+        const char *p = i->getKeyData();
+        printSuffixedName(p, "$non_lazy_ptr");
+        O << ":\n";
+        O << "\t.indirect_symbol " << p << "\n";
+        O << "\t.long\t0\n";
+      }
     }
 
+    if (!HiddenGVNonLazyPtrs.empty()) {
+      SwitchToSection(TAI->getDataSection());
+      for (StringSet<>::iterator i = HiddenGVNonLazyPtrs.begin(),
+             e = HiddenGVNonLazyPtrs.end(); i != e; ++i) {
+        const char *p = i->getKeyData();
+        EmitAlignment(2);
+        printSuffixedName(p, "$non_lazy_ptr");
+        O << ":\n";
+        O << "\t.long " << p << "\n";
+      }
+    }
+
+
     // Emit initial debug information.
-    // FIXME: Dwarf support.
-    //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
@@ -1013,8 +1090,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
     O << "\t.subsections_via_symbols\n";
   } else {
     // Emit final debug information for ELF.
-    // FIXME: Dwarf support.
-    //DW.EndModule();
+    DW->EndModule();
   }
 
   return AsmPrinter::doFinalization(M);
@@ -1026,8 +1102,10 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
 /// regardless of whether the function is in SSA form.
 ///
 FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
-                                             ARMTargetMachine &tm) {
-  return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
+                                             ARMTargetMachine &tm,
+                                             CodeGenOpt::Level OptLevel,
+                                             bool verbose) {
+  return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
 }
 
 namespace {
@@ -1037,3 +1115,9 @@ namespace {
     }
   } Registrator;
 }
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+  void InitializeARMAsmPrinter() { }
+}