Support printing base+offset pairs where the offset is a register.
[oota-llvm.git] / lib / Target / SparcV8 / SparcV8AsmPrinter.cpp
index 9adb0e7b2217f6d9cc194817568568b623c29b4d..09d61b7b2d9951b5c6b2a86fa4fe5b38c2049c03 100644 (file)
@@ -26,6 +26,7 @@
 #include "Support/Statistic.h"
 #include "Support/StringExtras.h"
 #include "Support/CommandLine.h"
+#include <cctype>
 using namespace llvm;
 
 namespace {
@@ -67,6 +68,8 @@ namespace {
     void emitConstantValueOnly(const Constant *CV);
     void emitGlobalConstant(const Constant *CV);
     void printConstantPool(MachineConstantPool *MCP);
+    void printOperand(const MachineInstr *MI, int opNum);
+    void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
     void printMachineInstruction(const MachineInstr *MI);
     bool runOnMachineFunction(MachineFunction &F);    
     bool doInitialization(Module &M);
@@ -246,7 +249,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
     // FP Constants are printed as integer constants to avoid losing
     // precision...
     double Val = CFP->getValue();
-    switch (CFP->getType()->getPrimitiveID()) {
+    switch (CFP->getType()->getTypeID()) {
     default: assert(0 && "Unknown floating point type!");
     case Type::FloatTyID: {
       union FU {                            // Abide by C TBAA rules
@@ -254,7 +257,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
         unsigned UVal;
       } U;
       U.FVal = Val;
-      O << ".long\t" << U.UVal << "\t# float " << Val << "\n";
+      O << ".long\t" << U.UVal << "\t! float " << Val << "\n";
       return;
     }
     case Type::DoubleTyID: {
@@ -263,7 +266,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
         uint64_t UVal;
       } U;
       U.FVal = Val;
-      O << ".quad\t" << U.UVal << "\t# double " << Val << "\n";
+      O << ".quad\t" << U.UVal << "\t! double " << Val << "\n";
       return;
     }
     }
@@ -271,7 +274,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
 
   const Type *type = CV->getType();
   O << "\t";
-  switch (type->getPrimitiveID()) {
+  switch (type->getTypeID()) {
   case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
     O << ".byte";
     break;
@@ -310,7 +313,7 @@ void V8Printer::printConstantPool(MachineConstantPool *MCP) {
     O << "\t.section .rodata\n";
     O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
       << "\n";
-    O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t#"
+    O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!"
       << *CP[i] << "\n";
     emitGlobalConstant(CP[i]);
   }
@@ -335,7 +338,7 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) {
   O << "\t.text\n";
   O << "\t.align 16\n";
   O << "\t.globl\t" << CurrentFnName << "\n";
-  O << "\t.type\t" << CurrentFnName << ", @function\n";
+  O << "\t.type\t" << CurrentFnName << ", #function\n";
   O << CurrentFnName << ":\n";
 
   // Number each basic block so that we can consistently refer to them
@@ -350,8 +353,9 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) {
   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
        I != E; ++I) {
     // Print a label for the basic block.
-    O << ".LBB" << NumberForBB[I->getBasicBlock()] << ":\t# "
-      << I->getBasicBlock()->getName() << "\n";
+    O << ".LBB" << Mang->getValueName(MF.getFunction ())
+      << "_" << I->getNumber () << ":\t! "
+      << I->getBasicBlock ()->getName () << "\n";
     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II) {
       // Print the assembly for the instruction.
@@ -364,14 +368,168 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) {
   return false;
 }
 
+
+std::string LowercaseString (const std::string &S) {
+  std::string result (S);
+  for (unsigned i = 0; i < S.length(); ++i) 
+    if (isupper (result[i]))
+      result[i] = tolower(result[i]);
+  return result;
+}
+
+void V8Printer::printOperand(const MachineInstr *MI, int opNum) {
+  const MachineOperand &MO = MI->getOperand (opNum);
+  const MRegisterInfo &RI = *TM.getRegisterInfo();
+  bool CloseParen = false;
+  if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
+    O << "%hi(";
+    CloseParen = true;
+  } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) {
+    O << "%lo(";
+    CloseParen = true;
+  }
+  switch (MO.getType()) {
+  case MachineOperand::MO_VirtualRegister:
+    if (Value *V = MO.getVRegValueOrNull()) {
+      O << "<" << V->getName() << ">";
+      break;
+    }
+    // FALLTHROUGH
+  case MachineOperand::MO_MachineRegister:
+    if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
+      O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
+    else
+      O << "%reg" << MO.getReg();
+    break;
+
+  case MachineOperand::MO_SignExtendedImmed:
+  case MachineOperand::MO_UnextendedImmed:
+    O << (int)MO.getImmedValue();
+    break;
+  case MachineOperand::MO_MachineBasicBlock: {
+    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
+    O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
+      << "_" << MBBOp->getNumber () << "\t! "
+      << MBBOp->getBasicBlock ()->getName ();
+    return;
+  }
+  case MachineOperand::MO_PCRelativeDisp:
+    std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs";
+    abort ();
+    return;
+  case MachineOperand::MO_GlobalAddress:
+    O << Mang->getValueName(MO.getGlobal());
+    break;
+  case MachineOperand::MO_ExternalSymbol:
+    O << MO.getSymbolName();
+    break;
+  default:
+    O << "<unknown operand type>"; break;    
+  }
+  if (CloseParen) O << ")";
+}
+
+static bool isLoadInstruction (const MachineInstr *MI) {
+  switch (MI->getOpcode ()) {
+  case V8::LDSBmr:
+  case V8::LDSHmr:
+  case V8::LDUBmr:
+  case V8::LDUHmr:
+  case V8::LDmr:
+  case V8::LDDmr:
+    return true;
+  default:
+    return false;
+  }
+}
+
+static bool isStoreInstruction (const MachineInstr *MI) {
+  switch (MI->getOpcode ()) {
+  case V8::STBrm:
+  case V8::STHrm:
+  case V8::STrm:
+  case V8::STDrm:
+    return true;
+  default:
+    return false;
+  }
+}
+
+/// printBaseOffsetPair - Print two consecutive operands of MI, starting at #i,
+/// which form a base + offset pair (which may have brackets around it, if
+/// brackets is true, or may be in the form base - constant, if offset is a
+/// negative constant).
+///
+void V8Printer::printBaseOffsetPair (const MachineInstr *MI, int i,
+                                     bool brackets) {
+  if (brackets) O << "[";
+  printOperand (MI, i);
+  if (MI->getOperand (i + 1).isImmediate()) {
+    int Val = (int) MI->getOperand (i + 1).getImmedValue ();
+    if (Val != 0) {
+      O << ((Val >= 0) ? " + " : " - ");
+      O << ((Val >= 0) ? Val : -Val);
+    }
+  } else {
+    O << " + ";
+    printOperand (MI, i + 1);
+  }
+  if (brackets) O << "]";
+}
+
 /// printMachineInstruction -- Print out a single SparcV8 LLVM instruction
 /// MI in GAS syntax to the current output stream.
 ///
 void V8Printer::printMachineInstruction(const MachineInstr *MI) {
   unsigned Opcode = MI->getOpcode();
-  const TargetInstrInfo &TII = TM.getInstrInfo();
+  const TargetInstrInfo &TII = *TM.getInstrInfo();
   const TargetInstrDescriptor &Desc = TII.get(Opcode);
-  O << Desc.Name << "\n";  // not yet done
+  O << Desc.Name << " ";
+  
+  // Printing memory instructions is a special case.
+  // for loads:  %dest = op %base, offset --> op [%base + offset], %dest
+  // for stores: op %base, offset, %src   --> op %src, [%base + offset]
+  if (isLoadInstruction (MI)) {
+    printBaseOffsetPair (MI, 1);
+    O << ", ";
+    printOperand (MI, 0);
+    O << "\n";
+    return;
+  } else if (isStoreInstruction (MI)) {
+    printOperand (MI, 2);
+    O << ", ";
+    printBaseOffsetPair (MI, 0);
+    O << "\n";
+    return;
+  } else if (Opcode == V8::JMPLrr) {
+    printBaseOffsetPair (MI, 1, false);
+    O << ", ";
+    printOperand (MI, 0);
+    O << "\n";
+    return;
+  }
+
+  // print non-immediate, non-register-def operands
+  // then print immediate operands
+  // then print register-def operands.
+  std::vector<int> print_order;
+  for (unsigned i = 0; i < MI->getNumOperands (); ++i)
+    if (!(MI->getOperand (i).isImmediate ()
+          || (MI->getOperand (i).isRegister ()
+              && MI->getOperand (i).isDef ())))
+      print_order.push_back (i);
+  for (unsigned i = 0; i < MI->getNumOperands (); ++i)
+    if (MI->getOperand (i).isImmediate ())
+      print_order.push_back (i);
+  for (unsigned i = 0; i < MI->getNumOperands (); ++i)
+    if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ())
+      print_order.push_back (i);
+  for (unsigned i = 0, e = print_order.size (); i != e; ++i) { 
+    printOperand (MI, print_order[i]);
+    if (i != (print_order.size () - 1))
+      O << ", ";
+  }
+  O << "\n";
 }
 
 bool V8Printer::doInitialization(Module &M) {
@@ -413,7 +571,7 @@ bool V8Printer::doFinalization(Module &M) {
         
         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
           << "," << (unsigned)TD.getTypeAlignment(C->getType());
-        O << "\t\t# ";
+        O << "\t\t! ";
         WriteAsOperand(O, I, true, true, &M);
         O << "\n";
       } else {
@@ -442,9 +600,9 @@ bool V8Printer::doFinalization(Module &M) {
         }
 
         O << "\t.align " << Align << "\n";
-        O << "\t.type " << name << ",@object\n";
+        O << "\t.type " << name << ",#object\n";
         O << "\t.size " << name << "," << Size << "\n";
-        O << name << ":\t\t\t\t# ";
+        O << name << ":\t\t\t\t! ";
         WriteAsOperand(O, I, true, true, &M);
         O << " = ";
         WriteAsOperand(O, C, false, false, &M);