Add dwarf register numbering to register data.
[oota-llvm.git] / lib / Target / PowerPC / PPCAsmPrinter.cpp
index 55f54c4bae5be713cee6b2356315eb1f60db2d5b..8b3ae47b4b2ba90df4b2149967e811277da14e63 100644 (file)
 #include "llvm/Support/Debug.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
+#include <iostream>
 #include <set>
 using namespace llvm;
 
@@ -82,7 +84,7 @@ namespace {
     void printMachineInstruction(const MachineInstr *MI);
     void printOp(const MachineOperand &MO);
 
-    void printOperand(const MachineInstr *MI, unsigned OpNo){
+    void printOperand(const MachineInstr *MI, unsigned OpNo) {
       const MachineOperand &MO = MI->getOperand(OpNo);
       if (MO.getType() == MachineOperand::MO_MachineRegister) {
         assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
@@ -93,7 +95,13 @@ namespace {
         printOp(MO);
       }
     }
-
+    
+    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                         unsigned AsmVariant, const char *ExtraCode);
+    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                               unsigned AsmVariant, const char *ExtraCode);
+    
+    
     void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
       unsigned char value = MI->getOperand(OpNo).getImmedValue();
       assert(value <= 31 && "Invalid u5imm argument!");
@@ -124,7 +132,7 @@ namespace {
     }
     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
       const MachineOperand &MO = MI->getOperand(OpNo);
-      if (!PPCGenerateStaticCode) {
+      if (TM.getRelocationModel() != Reloc::Static) {
         if (MO.getType() == MachineOperand::MO_GlobalAddress) {
           GlobalValue *GV = MO.getGlobal();
           if (((GV->isExternal() || GV->hasWeakLinkage() ||
@@ -159,7 +167,7 @@ namespace {
       } else {
         O << "ha16(";
         printOp(MI->getOperand(OpNo));
-        if (PICEnabled)
+        if (TM.getRelocationModel() == Reloc::PIC)
           O << "-\"L" << getFunctionNumber() << "$pb\")";
         else
           O << ')';
@@ -171,7 +179,7 @@ namespace {
       } else {
         O << "lo16(";
         printOp(MI->getOperand(OpNo));
-        if (PICEnabled)
+        if (TM.getRelocationModel() == Reloc::PIC)
           O << "-\"L" << getFunctionNumber() << "$pb\")";
         else
           O << ')';
@@ -182,13 +190,31 @@ namespace {
       unsigned RegNo = enumRegToMachineReg(CCReg);
       O << (0x80 >> RegNo);
     }
-    // The new addressing mode printers, currently empty
+    // The new addressing mode printers.
     void printMemRegImm(const MachineInstr *MI, unsigned OpNo) {
       printSymbolLo(MI, OpNo);
       O << '(';
-      printOperand(MI, OpNo+1);
+      if (MI->getOperand(OpNo+1).isRegister() && 
+          MI->getOperand(OpNo+1).getReg() == PPC::R0)
+        O << "0";
+      else
+        printOperand(MI, OpNo+1);
+      O << ')';
+    }
+    void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) {
+      if (MI->getOperand(OpNo).isImmediate())
+        printS16X4ImmOperand(MI, OpNo);
+      else 
+        printSymbolLo(MI, OpNo);
+      O << '(';
+      if (MI->getOperand(OpNo+1).isRegister() && 
+          MI->getOperand(OpNo+1).getReg() == PPC::R0)
+        O << "0";
+      else
+        printOperand(MI, OpNo+1);
       O << ')';
     }
+    
     void printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
       // When used as the base register, r0 reads constant zero rather than
       // the value contained in the register.  For this reason, the darwin
@@ -215,9 +241,17 @@ namespace {
     : DwarfWriter(o, ap)
     {
       needsSet = true;
-      DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
-      DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
-      DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
+      DwarfAbbrevSection = ".section __DWARFA,__debug_abbrev";
+      DwarfInfoSection = ".section __DWARFA,__debug_info";
+      DwarfLineSection = ".section __DWARFA,__debug_line";
+      DwarfFrameSection = ".section __DWARFA,__debug_frame";
+      DwarfPubNamesSection = ".section __DWARFA,__debug_pubnames";
+      DwarfPubTypesSection = ".section __DWARFA,__debug_pubtypes";
+      DwarfStrSection = ".section __DWARFA,__debug_str";
+      DwarfLocSection = ".section __DWARFA,__debug_loc";
+      DwarfARangesSection = ".section __DWARFA,__debug_aranges";
+      DwarfRangesSection = ".section __DWARFA,__debug_ranges";
+      DwarfMacInfoSection = ".section __DWARFA,__debug_macinfo";
       TextSection = ".text";
       DataSection = ".data";
     }
@@ -225,14 +259,12 @@ namespace {
 
   /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS
   /// X
-  ///
   struct DarwinAsmPrinter : public PPCAsmPrinter {
   
     DarwinDwarfWriter DW;
 
     DarwinAsmPrinter(std::ostream &O, TargetMachine &TM)
-      : PPCAsmPrinter(O, TM), DW(O, this)      
-      {
+      : PPCAsmPrinter(O, TM), DW(O, this) {
       CommentString = ";";
       GlobalPrefix = "_";
       PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
@@ -243,6 +275,7 @@ namespace {
       LCOMMDirective = "\t.lcomm\t";
       StaticCtorsSection = ".mod_init_func";
       StaticDtorsSection = ".mod_term_func";
+      InlineAsmStart = InlineAsmEnd = "";  // Don't use #APP/#NO_APP
     }
 
     virtual const char *getPassName() const {
@@ -292,7 +325,8 @@ namespace {
 /// code for a MachineFunction to the given output stream, in a format that the
 /// Darwin assembler can deal with.
 ///
-FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
+FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o,
+                                           PPCTargetMachine &tm) {
   return new DarwinAsmPrinter(o, tm);
 }
 
@@ -300,7 +334,7 @@ FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
 /// for a MachineFunction to the given output stream, in a format that the
 /// AIX 5L assembler can deal with.
 ///
-FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
+FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, PPCTargetMachine &tm) {
   return new AIXAsmPrinter(o, tm);
 }
 
@@ -347,7 +381,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
     return;
   case MachineOperand::MO_ExternalSymbol:
     // Computing the address of an external symbol, not calling it.
-    if (!PPCGenerateStaticCode) {
+    if (TM.getRelocationModel() != Reloc::Static) {
       std::string Name(GlobalPrefix); Name += MO.getSymbolName();
       GVStubs.insert(Name);
       O << "L" << Name << "$non_lazy_ptr";
@@ -362,7 +396,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
     int offset = MO.getOffset();
 
     // External or weakly linked global variables need non-lazily-resolved stubs
-    if (!PPCGenerateStaticCode) {
+    if (TM.getRelocationModel() != Reloc::Static) {
       if (((GV->isExternal() || GV->hasWeakLinkage() ||
             GV->hasLinkOnceLinkage()))) {
         GVStubs.insert(Name);
@@ -381,6 +415,41 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
   }
 }
 
+/// PrintAsmOperand - Print out an operand for an inline asm expression.
+///
+bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                    unsigned AsmVariant, 
+                                    const char *ExtraCode) {
+  // Does this asm operand have a single letter operand modifier?
+  if (ExtraCode && ExtraCode[0]) {
+    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    
+    switch (ExtraCode[0]) {
+    default: return true;  // Unknown modifier.
+    case 'L': // Write second word of DImode reference.  
+      // Verify that this operand has two consecutive registers.
+      if (!MI->getOperand(OpNo).isRegister() ||
+          OpNo+1 == MI->getNumOperands() ||
+          !MI->getOperand(OpNo+1).isRegister())
+        return true;
+      ++OpNo;   // Return the high-part.
+      break;
+    }
+  }
+  
+  printOperand(MI, OpNo);
+  return false;
+}
+
+bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                                          unsigned AsmVariant, 
+                                          const char *ExtraCode) {
+  if (ExtraCode && ExtraCode[0])
+    return true; // Unknown modifier.
+  printMemRegReg(MI, OpNo);
+  return false;
+}
+
 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
 /// the current output stream.
 ///
@@ -407,6 +476,15 @@ void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
       O << ", " << (unsigned int)SH << "\n";
       return;
     }
+  } else if (MI->getOpcode() == PPC::OR4 || MI->getOpcode() == PPC::OR8) {
+    if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
+      O << "mr ";
+      printOperand(MI, 0);
+      O << ", ";
+      printOperand(MI, 1);
+      O << "\n";
+      return;
+    }
   }
 
   if (printInstruction(MI))
@@ -422,14 +500,14 @@ void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
 /// method to print assembly for each instruction.
 ///
 bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
-  // FIXME - is this the earliest this can be set.
+  // FIXME - is this the earliest this can be set?
   DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
 
   SetupMachineFunction(MF);
   O << "\n\n";
   
   // Emit pre-function debug information.
-  DW.BeginFunction();
+  DW.BeginFunction(&MF);
 
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
@@ -440,11 +518,9 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   default: assert(0 && "Unknown linkage type!");
   case Function::InternalLinkage:  // Symbols default to internal.
     SwitchSection(".text", F);
-    EmitAlignment(4, F);
     break;
   case Function::ExternalLinkage:
     SwitchSection(".text", F);
-    EmitAlignment(4, F);
     O << "\t.globl\t" << CurrentFnName << "\n";
     break;
   case Function::WeakLinkage:
@@ -455,6 +531,7 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     O << "\t.weak_definition\t" << CurrentFnName << "\n";
     break;
   }
+  EmitAlignment(4, F);
   O << CurrentFnName << ":\n";
 
   // Print out code for the function.
@@ -493,7 +570,7 @@ bool DarwinAsmPrinter::doInitialization(Module &M) {
   Mang->setUseQuotes(true);
   
   // Emit initial debug information.
-  DW.BeginModule();
+  DW.BeginModule(&M);
   return false;
 }
 
@@ -506,24 +583,30 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
     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';
     std::string name = Mang->getValueName(I);
     Constant *C = I->getInitializer();
     unsigned Size = TD.getTypeSize(C->getType());
-    unsigned Align = TD.getTypeAlignmentShift(C->getType());
+    unsigned Align = getPreferredAlignmentLog(I);
 
     if (C->isNullValue() && /* FIXME: Verify correct */
         (I->hasInternalLinkage() || I->hasWeakLinkage() ||
-         I->hasLinkOnceLinkage())) {
-      SwitchSection(".data", I);
+         I->hasLinkOnceLinkage() ||
+         (I->hasExternalLinkage() && !I->hasSection()))) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
-      if (I->hasInternalLinkage())
+      if (I->hasExternalLinkage()) {
+        O << "\t.globl " << name << '\n';
+        O << "\t.zerofill __DATA, __common, " << name << ", "
+          << Size << ", " << Align;
+      } else if (I->hasInternalLinkage()) {
+        SwitchSection(".data", I);
         O << LCOMMDirective << name << "," << Size << "," << Align;
-      else
+      } else {
+        SwitchSection(".data", I);
         O << ".comm " << name << "," << Size;
+      }
       O << "\t\t; '" << I->getName() << "'\n";
     } else {
       switch (I->getLinkage()) {
@@ -551,11 +634,12 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
       EmitAlignment(Align, I);
       O << name << ":\t\t\t\t; '" << I->getName() << "'\n";
       EmitGlobalConstant(C);
+      O << '\n';
     }
   }
 
   // Output stubs for dynamically-linked functions
-  if (PICEnabled) {
+  if (TM.getRelocationModel() == Reloc::PIC) {
     for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
          i != e; ++i) {
       SwitchSection(".section __TEXT,__picsymbolstub1,symbol_stubs,"