Convert XO XS and XFX forms to use isPPC64
[oota-llvm.git] / lib / Target / PowerPC / PPCAsmPrinter.cpp
index b0503d2a2da38518148ac38f525e69abad081da8..4acaca7b51c6de7b01a0ea80760a06810111b2d9 100644 (file)
@@ -32,6 +32,8 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include <set>
@@ -40,11 +42,11 @@ using namespace llvm;
 namespace {
   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
 
-  struct PPC32AsmPrinter : public AsmPrinter {
+  struct PowerPCAsmPrinter : public AsmPrinter {
     std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
     std::set<std::string> Strings;
     
-    PPC32AsmPrinter(std::ostream &O, TargetMachine &TM)
+    PowerPCAsmPrinter(std::ostream &O, TargetMachine &TM)
       : AsmPrinter(O, TM), LabelNumber(0) {}
 
     /// Unique incrementer for label values for referencing Global values.
@@ -66,7 +68,7 @@ namespace {
     bool printInstruction(const MachineInstr *MI);
 
     void printMachineInstruction(const MachineInstr *MI);
-    void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
+    void printOp(const MachineOperand &MO, bool IsCallOp = false);
 
     void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
       const MachineOperand &MO = MI->getOperand(OpNo);
@@ -101,30 +103,30 @@ namespace {
       O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
     }
     void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
-                          MVT::ValueType VT) {
-      
+                            MVT::ValueType VT) {
       // Branches can take an immediate operand.  This is used by the branch
       // selection pass to print $+8, an eight byte displacement from the PC.
       if (MI->getOperand(OpNo).isImmediate()) {
-        O << "$+" << MI->getOperand(OpNo).getImmedValue() << '\n';
+        O << "$+" << MI->getOperand(OpNo).getImmedValue();
       } else {
-        printOp(MI->getOperand(OpNo));
+        printOp(MI->getOperand(OpNo), 
+                TM.getInstrInfo()->isCall(MI->getOpcode()));
       }
     }
     void printPICLabel(const MachineInstr *MI, unsigned OpNo,
-                         MVT::ValueType VT) {
+                       MVT::ValueType VT) {
       // FIXME: should probably be converted to cout.width and cout.fill
       O << "\"L0000" << LabelNumber << "$pb\"\n";
       O << "\"L0000" << LabelNumber << "$pb\":";
     }
     void printSymbolHi(const MachineInstr *MI, unsigned OpNo,
-                         MVT::ValueType VT) {
+                       MVT::ValueType VT) {
       O << "ha16(";
-      printOp(MI->getOperand(OpNo), true /* LoadAddrOp */);
+      printOp(MI->getOperand(OpNo));
       O << "-\"L0000" << LabelNumber << "$pb\")";
     }
     void printSymbolLo(const MachineInstr *MI, unsigned OpNo,
-                         MVT::ValueType VT) {
+                       MVT::ValueType VT) {
       // FIXME: Because LFS, LFD, and LWZ can be used either with a s16imm or
       // a lo16 of a global or constant pool operand, we must handle both here.
       // this isn't a great design, but it works for now.
@@ -132,22 +134,43 @@ namespace {
         O << (short)MI->getOperand(OpNo).getImmedValue();
       } else {
         O << "lo16(";
-        printOp(MI->getOperand(OpNo), true /* LoadAddrOp */);
+        printOp(MI->getOperand(OpNo));
         O << "-\"L0000" << LabelNumber << "$pb\")";
       }
     }
+    void printcrbit(const MachineInstr *MI, unsigned OpNo,
+                       MVT::ValueType VT) {
+      unsigned char value = MI->getOperand(OpNo).getImmedValue();
+      assert(value <= 3 && "Invalid crbit argument!");
+      unsigned RegNo, CCReg = MI->getOperand(OpNo-1).getReg();
+      switch (CCReg) {
+      case PPC::CR0:  RegNo = 0; break;
+      case PPC::CR1:  RegNo = 1; break;
+      case PPC::CR2:  RegNo = 2; break;
+      case PPC::CR3:  RegNo = 3; break;
+      case PPC::CR4:  RegNo = 4; break;
+      case PPC::CR5:  RegNo = 5; break;
+      case PPC::CR6:  RegNo = 6; break;
+      case PPC::CR7:  RegNo = 7; break;
+      default:
+        std::cerr << "Unhandled reg in enumRegToRealReg!\n";
+        abort();
+      }
+      O << 4 * RegNo + value;
+    }
   
     virtual void printConstantPool(MachineConstantPool *MCP) = 0;
     virtual bool runOnMachineFunction(MachineFunction &F) = 0;    
     virtual bool doFinalization(Module &M) = 0;
   };
   
-  //
-  //
-  struct DarwinAsmPrinter : public PPC32AsmPrinter {
+  /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS
+  /// X
+  ///
+  struct DarwinAsmPrinter : public PowerPCAsmPrinter {
 
     DarwinAsmPrinter(std::ostream &O, TargetMachine &TM)
-      : PPC32AsmPrinter(O, TM) {
+      : PowerPCAsmPrinter(O, TM) {
       CommentString = ";";
       GlobalPrefix = "_";
       ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
@@ -164,15 +187,15 @@ namespace {
     bool doFinalization(Module &M);
   };
   
-  //
-  //
-  struct AIXAsmPrinter : public PPC32AsmPrinter {
+  /// AIXAsmPrinter - PowerPC assembly printer, customized for AIX
+  ///
+  struct AIXAsmPrinter : public PowerPCAsmPrinter {
     /// Map for labels corresponding to global variables
     ///
     std::map<const GlobalVariable*,std::string> GVToLabelMap;
 
     AIXAsmPrinter(std::ostream &O, TargetMachine &TM)
-      : PPC32AsmPrinter(O, TM) {
+      : PowerPCAsmPrinter(O, TM) {
       CommentString = "#";
       GlobalPrefix = "_";
       ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
@@ -306,8 +329,7 @@ FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
 // Include the auto-generated portion of the assembly writer
 #include "PowerPCGenAsmWriter.inc"
 
-void PPC32AsmPrinter::printOp(const MachineOperand &MO,
-                              bool LoadAddrOp /* = false */) {
+void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
   const MRegisterInfo &RI = *TM.getRegisterInfo();
   int new_symbol;
   
@@ -347,7 +369,13 @@ void PPC32AsmPrinter::printOp(const MachineOperand &MO,
     return;
 
   case MachineOperand::MO_ExternalSymbol:
-    O << MO.getSymbolName();
+    if (IsCallOp) {
+      std::string Name(GlobalPrefix); Name += MO.getSymbolName();
+      FnStubs.insert(Name);
+      O << "L" << Name << "$stub";
+      return;
+    }
+    O << GlobalPrefix << MO.getSymbolName();
     return;
 
   case MachineOperand::MO_GlobalAddress: {
@@ -358,26 +386,22 @@ void PPC32AsmPrinter::printOp(const MachineOperand &MO,
     // wary however not to output $stub for external functions whose addresses
     // are taken.  Those should be emitted as $non_lazy_ptr below.
     Function *F = dyn_cast<Function>(GV);
-    if (F && F->isExternal() && !LoadAddrOp &&
-        getTM().CalledFunctions.count(F)) {
+    if (F && IsCallOp && F->isExternal()) {
       FnStubs.insert(Name);
       O << "L" << Name << "$stub";
       return;
     }
     
-    // External global variables need a non-lazily-resolved stub
-    if (GV->isExternal() && getTM().AddressTaken.count(GV)) {
-      GVStubs.insert(Name);
-      O << "L" << Name << "$non_lazy_ptr";
-      return;
-    }
-    
-    if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) {
-      LinkOnceStubs.insert(Name);
+    // External or weakly linked global variables need non-lazily-resolved stubs
+    if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())){
+      if (GV->hasLinkOnceLinkage())
+        LinkOnceStubs.insert(Name);
+      else
+        GVStubs.insert(Name);
       O << "L" << Name << "$non_lazy_ptr";
       return;
     }
-            
+
     O << Mang->getValueName(GV);
     return;
   }
@@ -391,8 +415,30 @@ void PPC32AsmPrinter::printOp(const MachineOperand &MO,
 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
 /// the current output stream.
 ///
-void PPC32AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
+void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
+  // Check for slwi/srwi mnemonics.
+  if (MI->getOpcode() == PPC::RLWINM) {
+    bool FoundMnemonic = false;
+    unsigned char SH = MI->getOperand(2).getImmedValue();
+    unsigned char MB = MI->getOperand(3).getImmedValue();
+    unsigned char ME = MI->getOperand(4).getImmedValue();
+    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
+      O << "slwi "; FoundMnemonic = true;
+    }
+    if (SH <= 31 && MB == (32-SH) && ME == 31) {
+      O << "srwi "; FoundMnemonic = true;
+      SH = 32-SH;
+    }
+    if (FoundMnemonic) {
+      printOperand(MI, 0, MVT::i64); 
+      O << ", "; 
+      printOperand(MI, 1, MVT::i64); 
+      O << ", " << (unsigned int)SH << "\n";
+      return;
+    }
+  }
+  
   if (printInstruction(MI))
     return; // Printer was automatically generated
   
@@ -461,25 +507,26 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
   std::string CurSection;
 
   // Print out module-level global variables here.
-  for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
     if (I->hasInitializer()) {   // External global require no code
-      O << "\n\n";
+      O << '\n';
       std::string name = Mang->getValueName(I);
       Constant *C = I->getInitializer();
       unsigned Size = TD.getTypeSize(C->getType());
       unsigned Align = TD.getTypeAlignmentShift(C->getType());
 
       if (C->isNullValue() && /* FIXME: Verify correct */
-          (I->hasInternalLinkage() || I->hasWeakLinkage())) {
+          (I->hasInternalLinkage() || I->hasWeakLinkage() || 
+           I->hasLinkOnceLinkage())) {
         SwitchSection(O, CurSection, ".data");
+        if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
         if (I->hasInternalLinkage())
-          O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
-            << "," << Align;
+          O << ".lcomm " << name << "," << Size << "," << Align;
         else 
-          O << ".comm " << name << "," << TD.getTypeSize(C->getType());
+          O << ".comm " << name << "," << Size;
         O << "\t\t; ";
         WriteAsOperand(O, I, true, true, &M);
-        O << "\n";
+        O << '\n';
       } else {
         switch (I->getLinkage()) {
         case GlobalValue::LinkOnceLinkage:
@@ -505,6 +552,9 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
         case GlobalValue::InternalLinkage:
           SwitchSection(O, CurSection, ".data");
           break;
+        case GlobalValue::GhostLinkage:
+          std::cerr << "Error: unmaterialized (GhostLinkage) function in asm!";
+          abort();
         }
 
         emitAlignment(Align);
@@ -644,7 +694,7 @@ bool AIXAsmPrinter::doInitialization(Module &M) {
     << "\t.csect .text[PR]\n";
 
   // Print out module-level global variables
-  for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
     if (!I->hasInitializer())
       continue;
  
@@ -662,8 +712,8 @@ bool AIXAsmPrinter::doInitialization(Module &M) {
   }
 
   // Output labels for globals
-  if (M.gbegin() != M.gend()) O << "\t.toc\n";
-  for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+  if (M.global_begin() != M.global_end()) O << "\t.toc\n";
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
     const GlobalVariable *GV = I;
     // Do not output labels for unused variables
     if (GV->isExternal() && GV->use_begin() == GV->use_end())
@@ -685,7 +735,7 @@ bool AIXAsmPrinter::doInitialization(Module &M) {
 bool AIXAsmPrinter::doFinalization(Module &M) {
   const TargetData &TD = TM.getTargetData();
   // Print out module-level global variables
-  for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
     if (I->hasInitializer() || I->hasExternalLinkage())
       continue;