Handle quoted names when constructing $stub's,
[oota-llvm.git] / lib / Target / ARM / ARMAsmPrinter.cpp
index a6ceb85cb3c9a5b020ca520956e9be180a8ceafc..e850ef1983b0fa004fe5604ef7a0a09aa45f3003 100644 (file)
@@ -2,8 +2,7 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the "Instituto Nokia de Tecnologia" and
-// is distributed under the University of Illinois Open Source
+// This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 #include "llvm/Module.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineDebugInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/Support/MathExtras.h"
 #include <cctype>
-#include <iostream>
-#include <set>
 using namespace llvm;
 
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
@@ -83,6 +81,7 @@ namespace {
     void printOperand(const MachineInstr *MI, int opNum,
                       const char *Modifier = 0);
     void printSOImmOperand(const MachineInstr *MI, int opNum);
+    void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
     void printSORegOperand(const MachineInstr *MI, int opNum);
     void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
     void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
@@ -97,11 +96,12 @@ namespace {
     void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
     void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
                                       unsigned Scale);
-    void printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int OpNo);
+    void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
+    void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
+    void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
     void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
-    void printCCOperand(const MachineInstr *MI, int opNum);
+    void printPredicateOperand(const MachineInstr *MI, int opNum);
+    void printSBitModifierOperand(const MachineInstr *MI, int opNum);
     void printPCLabel(const MachineInstr *MI, int opNum);
     void printRegisterList(const MachineInstr *MI, int opNum);
     void printCPInstOperand(const MachineInstr *MI, int opNum,
@@ -121,22 +121,39 @@ namespace {
       printDataDirective(MCPV->getType());
 
       ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV;
-      std::string Name = Mang->getValueName(ACPV->getGV());
+      GlobalValue *GV = ACPV->getGV();
+      std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
+      if (!GV)
+        Name += ACPV->getSymbol();
       if (ACPV->isNonLazyPointer()) {
         GVNonLazyPtrs.insert(Name);
-        O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
+        printSuffixedName(Name, "$non_lazy_ptr");
+      } else if (ACPV->isStub()) {
+        FnStubs.insert(Name);
+        printSuffixedName(Name, "$stub");
       } else
         O << Name;
-      if (ACPV->getPCAdjustment() != 0)
+      if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
+      if (ACPV->getPCAdjustment() != 0) {
         O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
           << utostr(ACPV->getLabelId())
-          << "+" << (unsigned)ACPV->getPCAdjustment() << ")";
+          << "+" << (unsigned)ACPV->getPCAdjustment();
+         if (ACPV->mustAddCurrentAddress())
+           O << "-.";
+         O << ")";
+      }
       O << "\n";
+
+      // If the constant pool value is a extern weak symbol, remember to emit
+      // the weak reference.
+      if (GV && GV->hasExternalWeakLinkage())
+        ExtWeakSymbols.insert(GV);
     }
     
     void getAnalysisUsage(AnalysisUsage &AU) const {
+      AsmPrinter::getAnalysisUsage(AU);
       AU.setPreservesAll();
-      AU.addRequired<MachineDebugInfo>();
+      AU.addRequired<MachineModuleInfo>();
     }
   };
 } // end of anonymous namespace
@@ -159,9 +176,7 @@ FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   AFI = MF.getInfo<ARMFunctionInfo>();
 
-  if (Subtarget->isDarwin()) {
-    DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
-  }
+  DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>());
 
   SetupMachineFunction(MF);
   O << "\n";
@@ -183,7 +198,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     break;
   case Function::WeakLinkage:
   case Function::LinkOnceLinkage:
-    if (Subtarget->isDarwin()) {
+    if (Subtarget->isTargetDarwin()) {
       SwitchToTextSection(
                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
       O << "\t.globl\t" << CurrentFnName << "\n";
@@ -194,18 +209,38 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     break;
   }
 
+  const char *VisibilityDirective = NULL;
+  if (F->hasHiddenVisibility())
+    VisibilityDirective = TAI->getHiddenDirective();
+  else if (F->hasProtectedVisibility())
+    VisibilityDirective = TAI->getProtectedDirective();
+
+  if (VisibilityDirective)
+    O << VisibilityDirective << CurrentFnName << "\n";
+
   if (AFI->isThumbFunction()) {
-    EmitAlignment(1, F);
+    EmitAlignment(1, F, AFI->getAlign());
     O << "\t.code\t16\n";
-    O << "\t.thumb_func\t" << CurrentFnName << "\n";
+    O << "\t.thumb_func";
+    if (Subtarget->isTargetDarwin())
+      O << "\t" << CurrentFnName;
+    O << "\n";
     InCPMode = false;
   } else
     EmitAlignment(2, F);
 
   O << CurrentFnName << ":\n";
-  if (Subtarget->isDarwin()) {
-    // Emit pre-function debug information.
-    DW.BeginFunction(&MF);
+  // Emit pre-function debug information.
+  DW.BeginFunction(&MF);
+
+  if (Subtarget->isTargetDarwin()) {
+    // 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 be associated with. We emit a noop in this situation.
+    MachineFunction::iterator I = MF.begin();
+
+    if (++I == MF.end() && MF.front().empty())
+      O << "\tnop\n";
   }
 
   // Print out code for the function.
@@ -213,7 +248,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
        I != E; ++I) {
     // Print a label for the basic block.
     if (I != MF.begin()) {
-      printBasicBlockLabel(I, true);
+      printBasicBlockLabel(I, true, true);
       O << '\n';
     }
     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
@@ -226,10 +261,8 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   if (TAI->hasDotTypeDotSizeDirective())
     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
 
-  if (Subtarget->isDarwin()) {
-    // Emit post-function debug information.
-    DW.EndFunction();
-  }
+  // Emit post-function debug information.
+  DW.EndFunction();
 
   return false;
 }
@@ -239,8 +272,8 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
   const MachineOperand &MO = MI->getOperand(opNum);
   switch (MO.getType()) {
   case MachineOperand::MO_Register:
-    if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
-      O << TM.getRegisterInfo()->get(MO.getReg()).Name;
+    if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+      O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
     else
       assert(0 && "not implemented");
     break;
@@ -248,25 +281,33 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
     if (!Modifier || strcmp(Modifier, "no_hash") != 0)
       O << "#";
 
-    O << (int)MO.getImmedValue();
+    O << (int)MO.getImm();
     break;
   }
   case MachineOperand::MO_MachineBasicBlock:
-    printBasicBlockLabel(MO.getMachineBasicBlock());
+    printBasicBlockLabel(MO.getMBB());
     return;
   case MachineOperand::MO_GlobalAddress: {
     bool isCallOp = Modifier && !strcmp(Modifier, "call");
     GlobalValue *GV = MO.getGlobal();
     std::string Name = Mang->getValueName(GV);
-    bool isExt = (GV->isExternal() || GV->hasWeakLinkage() ||
+    bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
                   GV->hasLinkOnceLinkage());
-    if (isExt && isCallOp && Subtarget->isDarwin() &&
+    if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
         TM.getRelocationModel() != Reloc::Static) {
-      O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+      printSuffixedName(Name, "$stub");
       FnStubs.insert(Name);
     } else
       O << Name;
-
+    
+    if (MO.getOffset() > 0)
+      O << '+' << MO.getOffset();
+    else if (MO.getOffset() < 0)
+      O << MO.getOffset();
+    
+    if (isCallOp && Subtarget->isTargetELF() &&
+        TM.getRelocationModel() == Reloc::PIC_)
+      O << "(PLT)";
     if (GV->hasExternalWeakLinkage())
       ExtWeakSymbols.insert(GV);
     break;
@@ -275,35 +316,34 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
     bool isCallOp = Modifier && !strcmp(Modifier, "call");
     std::string Name(TAI->getGlobalPrefix());
     Name += MO.getSymbolName();
-    if (isCallOp && Subtarget->isDarwin() &&
+    if (isCallOp && Subtarget->isTargetDarwin() &&
         TM.getRelocationModel() != Reloc::Static) {
-      O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+      printSuffixedName(Name, "$stub");
       FnStubs.insert(Name);
     } else
       O << Name;
+    if (isCallOp && Subtarget->isTargetELF() &&
+        TM.getRelocationModel() == Reloc::PIC_)
+      O << "(PLT)";
     break;
   }
   case MachineOperand::MO_ConstantPoolIndex:
     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
-      << '_' << MO.getConstantPoolIndex();
+      << '_' << MO.getIndex();
     break;
   case MachineOperand::MO_JumpTableIndex:
     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
-      << '_' << MO.getJumpTableIndex();
+      << '_' << MO.getIndex();
     break;
   default:
     O << "<unknown operand type>"; abort (); break;
   }
 }
 
-/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
-/// immediate in bits 0-7.
-void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
-  const MachineOperand &MO = MI->getOperand(OpNum);
-  assert(MO.isImmediate() && (MO.getImmedValue() < (1 << 12)) &&
-         "Not a valid so_imm value!");
-  unsigned Imm = ARM_AM::getSOImmValImm(MO.getImmedValue());
-  unsigned Rot = ARM_AM::getSOImmValRot(MO.getImmedValue());
+static void printSOImm(std::ostream &O, int64_t V, 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".
@@ -316,6 +356,32 @@ void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
   }
 }
 
+/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
+/// immediate in bits 0-7.
+void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
+  const MachineOperand &MO = MI->getOperand(OpNum);
+  assert(MO.isImmediate() && "Not a valid so_imm value!");
+  printSOImm(O, MO.getImm(), TAI);
+}
+
+/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
+/// followed by a or to materialize.
+void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
+  const MachineOperand &MO = MI->getOperand(OpNum);
+  assert(MO.isImmediate() && "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);
+  O << "\n\torr";
+  printPredicateOperand(MI, 2);
+  O << " ";
+  printOperand(MI, 0); 
+  O << ", ";
+  printOperand(MI, 0); 
+  O << ", ";
+  printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
+}
+
 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
 //    REG 0   0    - e.g. R5
@@ -326,17 +392,17 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
   const MachineOperand &MO2 = MI->getOperand(Op+1);
   const MachineOperand &MO3 = MI->getOperand(Op+2);
 
-  assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
-  O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+  O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
 
   // Print the shift opc.
   O << ", "
-    << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue()))
+    << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
     << " ";
 
   if (MO2.getReg()) {
-    assert(MRegisterInfo::isPhysicalRegister(MO2.getReg()));
-    O << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+    assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
+    O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
   } else {
     O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
@@ -353,7 +419,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
     return;
   }
 
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
 
   if (!MO2.getReg()) {
     if (ARM_AM::getAM2Offset(MO3.getImm()))  // Don't print +0.
@@ -366,11 +432,11 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
 
   O << ", "
     << (char)ARM_AM::getAM2Op(MO3.getImm())
-    << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+    << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
   
   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
     O << ", "
-      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue()))
+      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
       << " #" << ShImm;
   O << "]";
 }
@@ -380,19 +446,20 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
   const MachineOperand &MO2 = MI->getOperand(Op+1);
 
   if (!MO1.getReg()) {
-    if (ARM_AM::getAM2Offset(MO2.getImm()))  // Don't print +0.
-      O << "#"
-        << (char)ARM_AM::getAM2Op(MO2.getImm())
-        << ARM_AM::getAM2Offset(MO2.getImm());
+    unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
+    assert(ImmOffs && "Malformed indexed load / store!");
+    O << "#"
+      << (char)ARM_AM::getAM2Op(MO2.getImm())
+      << ImmOffs;
     return;
   }
 
   O << (char)ARM_AM::getAM2Op(MO2.getImm())
-    << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+    << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
   
   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
     O << ", "
-      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue()))
+      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
       << " #" << ShImm;
 }
 
@@ -401,13 +468,13 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
   const MachineOperand &MO2 = MI->getOperand(Op+1);
   const MachineOperand &MO3 = MI->getOperand(Op+2);
   
-  assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
 
   if (MO2.getReg()) {
     O << ", "
       << (char)ARM_AM::getAM3Op(MO3.getImm())
-      << TM.getRegisterInfo()->get(MO2.getReg()).Name
+      << TM.getRegisterInfo()->get(MO2.getReg()).AsmName
       << "]";
     return;
   }
@@ -425,13 +492,14 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
 
   if (MO1.getReg()) {
     O << (char)ARM_AM::getAM3Op(MO2.getImm())
-      << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+      << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
     return;
   }
 
   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
+  assert(ImmOffs && "Malformed indexed load / store!");
   O << "#"
-  << (char)ARM_AM::getAM3Op(MO2.getImm())
+    << (char)ARM_AM::getAM3Op(MO2.getImm())
     << ImmOffs;
 }
   
@@ -464,7 +532,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
     return;
   }
   
-  assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
+  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
 
   if (Modifier && strcmp(Modifier, "submode") == 0) {
     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
@@ -477,13 +545,13 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
     return;
   } else if (Modifier && strcmp(Modifier, "base") == 0) {
     // Used for FSTM{D|S} and LSTM{D|S} operations.
-    O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+    O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
     if (ARM_AM::getAM5WBFlag(MO2.getImm()))
       O << "!";
     return;
   }
   
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
   
   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
     O << ", #"
@@ -501,16 +569,16 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
   }
 
   const MachineOperand &MO1 = MI->getOperand(Op);
-  assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
-  O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]";
+  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+  O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
 }
 
 void
 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
   const MachineOperand &MO1 = MI->getOperand(Op);
   const MachineOperand &MO2 = MI->getOperand(Op+1);
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
-  O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).Name << "]";
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+  O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]";
 }
 
 void
@@ -518,14 +586,17 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
                                             unsigned Scale) {
   const MachineOperand &MO1 = MI->getOperand(Op);
   const MachineOperand &MO2 = MI->getOperand(Op+1);
+  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
   if (!MO1.isRegister()) {   // FIXME: This is for CP entries, but isn't right.
     printOperand(MI, Op);
     return;
   }
 
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
-  if (unsigned ImmOffs = MO2.getImm()) {
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+  if (MO3.getReg())
+    O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName;
+  else if (unsigned ImmOffs = MO2.getImm()) {
     O << ", #" << ImmOffs;
     if (Scale > 1)
       O << " * " << Scale;
@@ -534,34 +605,43 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
 }
 
 void
-ARMAsmPrinter::printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
   printThumbAddrModeRI5Operand(MI, Op, 1);
 }
 void
-ARMAsmPrinter::printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
   printThumbAddrModeRI5Operand(MI, Op, 2);
 }
 void
-ARMAsmPrinter::printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
   printThumbAddrModeRI5Operand(MI, Op, 4);
 }
 
 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
   const MachineOperand &MO1 = MI->getOperand(Op);
   const MachineOperand &MO2 = MI->getOperand(Op+1);
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
   if (unsigned ImmOffs = MO2.getImm())
     O << ", #" << ImmOffs << " * 4";
   O << "]";
 }
 
-void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
-  int CC = (int)MI->getOperand(opNum).getImmedValue();
-  O << ARMCondCodeToString((ARMCC::CondCodes)CC);
+void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
+  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
+  if (CC != ARMCC::AL)
+    O << ARMCondCodeToString(CC);
+}
+
+void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
+  unsigned Reg = MI->getOperand(opNum).getReg();
+  if (Reg) {
+    assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
+    O << 's';
+  }
 }
 
 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
-  int Id = (int)MI->getOperand(opNum).getImmedValue();
+  int Id = (int)MI->getOperand(opNum).getImm();
   O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
 }
 
@@ -585,24 +665,29 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
       << '_' << ID << ":\n";
   } else {
     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
-    unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex();
+    unsigned CPI = MI->getOperand(OpNo).getIndex();
 
     const MachineConstantPoolEntry &MCPE =  // Chasing pointers is fun?
       MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
     
     if (MCPE.isMachineConstantPoolEntry())
       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
-    else
+    else {
       EmitGlobalConstant(MCPE.Val.ConstVal);
+      // remember to emit the weak reference
+      if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
+        if (GV->hasExternalWeakLinkage())
+          ExtWeakSymbols.insert(GV);
+    }
   }
 }
 
 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
   const MachineOperand &MO1 = MI->getOperand(OpNo);
   const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
-  unsigned JTI = MO1.getJumpTableIndex();
+  unsigned JTI = MO1.getIndex();
   O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
-    << '_' << JTI << '_' << MO2.getImmedValue() << ":\n";
+    << '_' << JTI << '_' << MO2.getImm() << ":\n";
 
   const char *JTEntryDirective = TAI->getJumpTableDirective();
   if (!JTEntryDirective)
@@ -617,22 +702,23 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
     MachineBasicBlock *MBB = JTBBs[i];
     if (UseSet && JTSets.insert(MBB).second)
-      printSetLabel(JTI, MO2.getImmedValue(), MBB);
+      printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
 
     O << JTEntryDirective << ' ';
     if (UseSet)
       O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
-        << '_' << JTI << '_' << MO2.getImmedValue()
+        << '_' << JTI << '_' << MO2.getImm()
         << "_set_" << MBB->getNumber();
     else if (TM.getRelocationModel() == Reloc::PIC_) {
-      printBasicBlockLabel(MBB, false, false);
+      printBasicBlockLabel(MBB, false, false, false);
       // If the arch uses custom Jump Table directives, don't calc relative to JT
       if (!TAI->getJumpTableDirective()) 
         O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
-          << getFunctionNumber() << '_' << JTI << '_' << MO2.getImmedValue();
+          << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
     } else
-      printBasicBlockLabel(MBB, false, false);
-    O << '\n';
+      printBasicBlockLabel(MBB, false, false, false);
+    if (i != e-1)
+      O << '\n';
   }
 }
 
@@ -645,6 +731,10 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     
     switch (ExtraCode[0]) {
     default: return true;  // Unknown modifier.
+    case 'c': // Don't print "$" before a global var name or constant.
+    case 'P': // Print a VFP double precision register.
+      printOperand(MI, OpNo);
+      return false;
     case 'Q':
       if (TM.getTargetData()->isLittleEndian())
         break;
@@ -670,30 +760,60 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
 
-  if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) {
+  int Opc = MI->getOpcode();
+  switch (Opc) {
+  case ARM::CONSTPOOL_ENTRY:
     if (!InCPMode && AFI->isThumbFunction()) {
       EmitAlignment(2);
       InCPMode = true;
     }
-  } else {
-    if (InCPMode && AFI->isThumbFunction()) {
-      EmitAlignment(1);
+    break;
+  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;
     }
-    O << "\t";
-  }
+  }}
 
   // Call the autogenerated instruction printer routines.
   printInstruction(MI);
 }
 
 bool ARMAsmPrinter::doInitialization(Module &M) {
-  if (Subtarget->isDarwin()) {
-    // Emit initial debug information.
-    DW.BeginModule(&M);
-  }
+  // Emit initial debug information.
+  DW.BeginModule(&M);
   
-  return AsmPrinter::doInitialization(M);
+  bool Result = AsmPrinter::doInitialization(M);
+
+  // Darwin wants symbols to be quoted if they have complex names.
+  if (Subtarget->isTargetDarwin())
+    Mang->setUseQuotes(true);
+
+  return Result;
+}
+
+/// PrintUnmangledNameSafely - Print out the printable characters in the name.
+/// Don't print things like \n or \0.
+static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) {
+  for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
+       Name != E; ++Name)
+    if (isprint(*Name))
+      OS << *Name;
 }
 
 bool ARMAsmPrinter::doFinalization(Module &M) {
@@ -704,30 +824,56 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
     if (!I->hasInitializer())   // External global require no code
       continue;
 
-    if (EmitSpecialLLVMGlobal(I))
+    if (EmitSpecialLLVMGlobal(I)) {
+      if (Subtarget->isTargetDarwin() &&
+          TM.getRelocationModel() == Reloc::Static) {
+        if (I->getName() == "llvm.global_ctors")
+          O << ".reference .constructors_used\n";
+        else if (I->getName() == "llvm.global_dtors")
+          O << ".reference .destructors_used\n";
+      }
       continue;
+    }
 
     std::string name = Mang->getValueName(I);
     Constant *C = I->getInitializer();
-    unsigned Size = TD->getTypeSize(C->getType());
+    const Type *Type = C->getType();
+    unsigned Size = TD->getABITypeSize(Type);
     unsigned Align = TD->getPreferredAlignmentLog(I);
 
-    if (C->isNullValue() &&
-        !I->hasSection() &&
-        (I->hasInternalLinkage() || I->hasWeakLinkage() ||
-         I->hasLinkOnceLinkage() ||
-         (Subtarget->isDarwin() &&  I->hasExternalLinkage()))) {
-      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
+    const char *VisibilityDirective = NULL;
+    if (I->hasHiddenVisibility())
+      VisibilityDirective = TAI->getHiddenDirective();
+    else if (I->hasProtectedVisibility())
+      VisibilityDirective = TAI->getProtectedDirective();
+
+    if (VisibilityDirective)
+      O << VisibilityDirective << name << "\n";
+
+    if (Subtarget->isTargetELF())
+      O << "\t.type " << name << ",%object\n";
+    
+    if (C->isNullValue() && !I->hasSection() && !I->isThreadLocal()) {
       if (I->hasExternalLinkage()) {
+        if (const char *Directive = TAI->getZeroFillDirective()) {
           O << "\t.globl\t" << name << "\n";
-          O << "\t.zerofill __DATA__, __common, " << name << ", "
-            << Size << ", " << Align;
-      } else {
-        SwitchToDataSection(TAI->getDataSection(), I);
+          O << Directive << "__DATA, __common, " << name << ", "
+            << Size << ", " << Align << "\n";
+          continue;
+        }
+      }
+
+      if (I->hasInternalLinkage() || I->hasWeakLinkage() ||
+          I->hasLinkOnceLinkage()) {
+        if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
+        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;
-            if (Subtarget->isDarwin())
+            if (Subtarget->isTargetDarwin())
               O << "," << Align;
           } else
             O << TAI->getCOMMDirective()  << name << "," << Size;
@@ -738,59 +884,99 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
           if (TAI->getCOMMDirectiveTakesAlignment())
             O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
         }
+        O << "\t\t" << TAI->getCommentString() << " ";
+        PrintUnmangledNameSafely(I, O);
+        O << "\n";
+        continue;
       }
-      O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n";
-      continue;
-    } else {
-      switch (I->getLinkage()) {
-      default:
-        assert(0 && "Unknown linkage type!");
-        break;
-      case GlobalValue::LinkOnceLinkage:
-      case GlobalValue::WeakLinkage:
-        if (Subtarget->isDarwin()) {
-          O << "\t.globl " << name << "\n"
-            << "\t.weak_definition " << name << "\n";
-          SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I);
-        } else {
-          O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"
-            << "\t.weak " << name << "\n";
-        }
-        break;
-      case GlobalValue::ExternalLinkage:
-        O << "\t.globl " << name << "\n";
-        // FALL THROUGH
-      case GlobalValue::InternalLinkage:
-        if (I->isConstant()) {
-          const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
-          if (TAI->getCStringSection() && CVA && CVA->isCString()) {
-            SwitchToDataSection(TAI->getCStringSection(), I);
-            break;
-          }
-        }
+    }
 
-        if (I->hasSection() &&
-            (I->getSection() == ".ctors" ||
-             I->getSection() == ".dtors")) {
-          assert(!Subtarget->isDarwin());
-          std::string SectionName = ".section " + I->getSection();
-          SectionName += ",\"aw\",@progbits";
-          SwitchToDataSection(SectionName.c_str());
-        } else {
-          SwitchToDataSection(TAI->getDataSection(), I);
+    switch (I->getLinkage()) {
+    case GlobalValue::LinkOnceLinkage:
+    case GlobalValue::WeakLinkage:
+      if (Subtarget->isTargetDarwin()) {
+        O << "\t.globl " << name << "\n"
+          << "\t.weak_definition " << name << "\n";
+        SwitchToDataSection("\t.section __DATA,__datacoal_nt,coalesced", I);
+      } else {
+        std::string SectionName("\t.section\t.llvm.linkonce.d." +
+                                name +
+                                ",\"aw\",%progbits");
+        SwitchToDataSection(SectionName.c_str(), I);
+        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:
+      O << "\t.globl " << name << "\n";
+      // FALL THROUGH
+    case GlobalValue::InternalLinkage: {
+      if (I->isConstant()) {
+        const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+        if (TAI->getCStringSection() && CVA && CVA->isCString()) {
+          SwitchToDataSection(TAI->getCStringSection(), I);
+          break;
+        }
+      }
+      // FIXME: special handling for ".ctors" & ".dtors" sections
+      if (I->hasSection() &&
+          (I->getSection() == ".ctors" ||
+           I->getSection() == ".dtors")) {
+        assert(!Subtarget->isTargetDarwin());
+        std::string SectionName = ".section " + I->getSection();
+        SectionName += ",\"aw\",%progbits";
+        SwitchToDataSection(SectionName.c_str());
+      } else if (I->hasSection() && Subtarget->isTargetDarwin()) {
+        // Honor all section names on Darwin; ObjC uses this
+        std::string SectionName = ".section " + I->getSection();
+        SwitchToDataSection(SectionName.c_str());
+      } else {
+        if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
+          SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() :
+                              TAI->getBSSSection(), I);
+        else if (!I->isConstant())
+          SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() :
+                              TAI->getDataSection(), I);
+        else if (I->isThreadLocal())
+          SwitchToDataSection(TAI->getTLSDataSection());
+        else {
+          // Read-only data.
+          bool HasReloc = C->ContainsRelocations();
+          if (HasReloc &&
+              Subtarget->isTargetDarwin() &&
+              TM.getRelocationModel() != Reloc::Static)
+            SwitchToDataSection("\t.const_data\n");
+          else if (!HasReloc && Size == 4 &&
+                   TAI->getFourByteConstantSection())
+            SwitchToDataSection(TAI->getFourByteConstantSection(), I);
+          else if (!HasReloc && Size == 8 &&
+                   TAI->getEightByteConstantSection())
+            SwitchToDataSection(TAI->getEightByteConstantSection(), I);
+          else if (!HasReloc && Size == 16 &&
+                   TAI->getSixteenByteConstantSection())
+            SwitchToDataSection(TAI->getSixteenByteConstantSection(), I);
+          else if (TAI->getReadOnlySection())
+            SwitchToDataSection(TAI->getReadOnlySection(), I);
+          else
+            SwitchToDataSection(TAI->getDataSection(), I);
         }
-
-        break;
       }
+
+      break;
+    }
+    default:
+      assert(0 && "Unknown linkage type!");
+      break;
     }
 
     EmitAlignment(Align, I);
-    if (TAI->hasDotTypeDotSizeDirective()) {
-      O << "\t.type " << name << ", %object\n";
+    O << name << ":\t\t\t\t" << TAI->getCommentString() << " ";
+    PrintUnmangledNameSafely(I, O);
+    O << "\n";
+    if (TAI->hasDotTypeDotSizeDirective())
       O << "\t.size " << name << ", " << Size << "\n";
-    }
-    O << name << ":\n";
-    
     // If the initializer is a extern weak symbol, remember to emit the weak
     // reference!
     if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
@@ -801,7 +987,9 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
     O << '\n';
   }
 
-  if (Subtarget->isDarwin()) {
+  if (Subtarget->isTargetDarwin()) {
+    SwitchToDataSection("");
+
     // Output stubs for dynamically-linked functions
     unsigned j = 1;
     for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
@@ -816,32 +1004,45 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
       EmitAlignment(2);
       O << "\t.code\t32\n";
 
-      O << "L" << *i << "$stub:\n";
+      std::string p = *i;
+      printSuffixedName(p, "$stub");
+      O << ":\n";
       O << "\t.indirect_symbol " << *i << "\n";
-      O << "\tldr ip, L" << *i << "$slp\n";
+      O << "\tldr ip, ";
+      printSuffixedName(p, "$slp");
+      O << "\n";
       if (TM.getRelocationModel() == Reloc::PIC_) {
-        O << "L" << *i << "$scv:\n";
+        printSuffixedName(p, "$scv");
+        O << ":\n";
         O << "\tadd ip, pc, ip\n";
       }
       O << "\tldr pc, [ip, #0]\n";
-      O << "L" << *i << "$slp:\n";
-      if (TM.getRelocationModel() == Reloc::PIC_)
-        O << "\t.long\tL" << *i << "$lazy_ptr-(L" << *i << "$scv+8)\n";
-      else
-        O << "\t.long\tL" << *i << "$lazy_ptr\n";
+      printSuffixedName(p, "$slp");
+      O << ":\n";
+      O << "\t.long\t";
+      printSuffixedName(p, "$lazy_ptr");
+      if (TM.getRelocationModel() == Reloc::PIC_) {
+        O << "-(";
+        printSuffixedName(p, "$scv");
+        O << "+8)\n";
+      } else
+        O << "\n";
       SwitchToDataSection(".lazy_symbol_pointer", 0);
-      O << "L" << *i << "$lazy_ptr:\n";
+      printSuffixedName(p, "$lazy_ptr");
+      O << ":\n";
       O << "\t.indirect_symbol " << *i << "\n";
       O << "\t.long\tdyld_stub_binding_helper\n";
     }
     O << "\n";
 
     // Output non-lazy-pointers for external and common global variables.
-    if (GVNonLazyPtrs.begin() != GVNonLazyPtrs.end())
+    if (!GVNonLazyPtrs.empty())
       SwitchToDataSection(".non_lazy_symbol_pointer", 0);
     for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(),
            e = GVNonLazyPtrs.end(); i != e; ++i) {
-      O << "L" << *i << "$non_lazy_ptr:\n";
+      std::string p = *i;
+      printSuffixedName(p, "$non_lazy_ptr");
+      O << ":\n";
       O << "\t.indirect_symbol " << *i << "\n";
       O << "\t.long\t0\n";
     }
@@ -855,8 +1056,10 @@ bool ARMAsmPrinter::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 {
+    // Emit final debug information for ELF.
+    DW.EndModule();
   }
 
-  AsmPrinter::doFinalization(M);
-  return false; // success
+  return AsmPrinter::doFinalization(M);
 }