minor cleanups
[oota-llvm.git] / lib / Target / Mips / MipsAsmPrinter.cpp
index ff02d431b8bdbfb6b2d8efa5ec25011d95092761..6c0c908ae7b06f0bdaaed06f014e2064c72262c0 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Bruno Cardoso Lopes and is distributed under the 
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -29,6 +29,7 @@
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/SetVector.h"
@@ -109,11 +110,11 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
 //
 //  Consider the following function prologue:
 //
-//    .frame   $fp,48,$ra
-//    .mask      0xc0000000,-8
-//       addiu $sp, $sp, -48
-//       sw $ra, 40($sp)
-//       sw $fp, 36($sp)
+//    .frame  $fp,48,$ra
+//    .mask   0xc0000000,-8
+//       addiu $sp, $sp, -48
+//       sw $ra, 40($sp)
+//       sw $fp, 36($sp)
 //
 //    With a 0xc0000000 mask, the assembler knows the register 31 (RA) and 
 //    30 (FP) are saved at prologue. As the save order on prologue is from 
@@ -161,16 +162,16 @@ emitFMaskDirective(MachineFunction &MF)
 void MipsAsmPrinter::
 emitFrameDirective(MachineFunction &MF)
 {
-  const MRegisterInfo &RI = *TM.getRegisterInfo();
+  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
 
   unsigned stackReg  = RI.getFrameRegister(MF);
   unsigned returnReg = RI.getRARegister();
   unsigned stackSize = MF.getFrameInfo()->getStackSize();
 
 
-  O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).Name) 
+  O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName)
                     << "," << stackSize << ","
-                    << "$" << LowercaseString(RI.get(returnReg).Name) 
+                    << "$" << LowercaseString(RI.get(returnReg).AsmName)
                     << "\n";
 }
 
@@ -194,7 +195,7 @@ emitSetDirective(SetDirectiveFlags Flag)
 unsigned int MipsAsmPrinter::
 getSavedRegsBitmask(bool isFloat, MachineFunction &MF)
 {
-  const MRegisterInfo &RI = *TM.getRegisterInfo();
+  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
              
   // Float Point Registers, TODO
   if (isFloat)
@@ -237,9 +238,8 @@ emitFunctionStart(MachineFunction &MF)
   const Function *F = MF.getFunction();
   SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
 
-  // On Mips GAS, if .align #n is present, #n means the number of bits 
-  // to be cleared. So, if we want 4 byte alignment, we must have .align 2
-  EmitAlignment(1, F);
+  // 2 bits aligned
+  EmitAlignment(2, F);
 
   O << "\t.globl\t"  << CurrentFnName << "\n";
   O << "\t.ent\t"    << CurrentFnName << "\n";
@@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF)
   emitMaskDirective(MF);
   emitFMaskDirective(MF);
 
-  if (MF.getTarget().getRelocationModel() == Reloc::Static) {
+  if (TM.getRelocationModel() == Reloc::Static) {
     emitSetDirective(NOREORDER);
     emitSetDirective(NOMACRO);
   }
@@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF)
 void MipsAsmPrinter::
 emitFunctionEnd(MachineFunction &MF) 
 {
-  if (MF.getTarget().getRelocationModel() == Reloc::Static) {
+  if (TM.getRelocationModel() == Reloc::Static) {
     emitSetDirective(MACRO);
     emitSetDirective(REORDER);
   }    
@@ -280,6 +280,9 @@ runOnMachineFunction(MachineFunction &MF)
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
 
+  // Print out jump tables referenced by the function
+  EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
+
   O << "\n\n";
 
   // What's my mangled name?
@@ -294,17 +297,19 @@ runOnMachineFunction(MachineFunction &MF)
 
     // 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();
          II != E; ++II) {
       // Print the assembly for the instruction.
-      O << "\t";
       printInstruction(II);
       ++EmittedInsts;
     }
+
+    // Each Basic Block is separated by a newline
+    O << '\n';
   }
 
   // Emit function end directives
@@ -318,25 +323,49 @@ void MipsAsmPrinter::
 printOperand(const MachineInstr *MI, int opNum) 
 {
   const MachineOperand &MO = MI->getOperand(opNum);
-  const MRegisterInfo  &RI = *TM.getRegisterInfo();
-  bool  closeP=false;
-
-  // %hi and %lo used on mips gas to break large constants
+  const TargetRegisterInfo  &RI = *TM.getRegisterInfo();
+  bool closeP = false;
+  bool isPIC = (TM.getRelocationModel() == Reloc::PIC_);
+  bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
+
+  // %hi and %lo used on mips gas to load global addresses on
+  // static code. %got is used to load global addresses when 
+  // using PIC_. %call16 is used to load direct call targets
+  // on PIC_ and small code size. %call_lo and %call_hi load 
+  // direct call targets on PIC_ and large code size.
   if (MI->getOpcode() == Mips::LUi && !MO.isRegister() 
       && !MO.isImmediate()) {
-    O << "%hi(";
+    if ((isPIC) && (isCodeLarge))
+      O << "%call_hi(";
+    else
+      O << "%hi(";
     closeP = true;
   } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() 
              && !MO.isImmediate()) {
     O << "%lo(";
     closeP = true;
+  } else if ((isPIC) && (MI->getOpcode() == Mips::LW)
+             && (!MO.isRegister()) && (!MO.isImmediate())) {
+    const MachineOperand &firstMO = MI->getOperand(opNum-1);
+    const MachineOperand &lastMO  = MI->getOperand(opNum+1);
+    if ((firstMO.isRegister()) && (lastMO.isRegister())) {
+      if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP) 
+          && (!isCodeLarge))
+        O << "%call16(";
+      else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP))
+        O << "%got(";
+      else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP) 
+               && (isCodeLarge))
+        O << "%call_lo(";
+      closeP = true;
+    }
   }
  
   switch (MO.getType()) 
   {
     case MachineOperand::MO_Register:
-      if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
-        O << "$" << LowercaseString (RI.get(MO.getReg()).Name);
+      if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+        O << "$" << LowercaseString (RI.get(MO.getReg()).AsmName);
       else
         O << "$" << MO.getReg();
       break;
@@ -344,13 +373,13 @@ printOperand(const MachineInstr *MI, int opNum)
     case MachineOperand::MO_Immediate:
       if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || 
           (MI->getOpcode() == Mips::LUi)   || (MI->getOpcode() == Mips::ANDi))
-        O << (unsigned short int)MO.getImmedValue();
+        O << (unsigned short int)MO.getImm();
       else
-        O << (short int)MO.getImmedValue();
+        O << (short int)MO.getImm();
       break;
 
     case MachineOperand::MO_MachineBasicBlock:
-      printBasicBlockLabel(MO.getMachineBasicBlock());
+      printBasicBlockLabel(MO.getMBB());
       return;
 
     case MachineOperand::MO_GlobalAddress:
@@ -361,9 +390,15 @@ printOperand(const MachineInstr *MI, int opNum)
       O << MO.getSymbolName();
       break;
 
+    case MachineOperand::MO_JumpTableIndex:
+      O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+      << '_' << MO.getIndex();
+      break;
+
+    // FIXME: Verify correct
     case MachineOperand::MO_ConstantPoolIndex:
       O << TAI->getPrivateGlobalPrefix() << "CPI"
-        << MO.getConstantPoolIndex() << '_' << CurrentFnName;
+        << getFunctionNumber() << "_" << MO.getIndex();
       break;
   
     default:
@@ -385,7 +420,9 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
     return;
   }
 
-  // Load/Store memory operands -- imm($reg)
+  // Load/Store memory operands -- imm($reg) 
+  // If PIC target the target is loaded as the 
+  // pattern lw $25,%call16($28)
   printOperand(MI, opNum);
   O << "(";
   printOperand(MI, opNum+1);
@@ -419,20 +456,31 @@ doFinalization(Module &M)
       O << "\n\n";
       std::string name = Mang->getValueName(I);
       Constant *C      = I->getInitializer();
-      unsigned Size    = TD->getTypeSize(C->getType());
-      unsigned Align   = TD->getPrefTypeAlignment(C->getType());
+      unsigned Size    = TD->getABITypeSize(C->getType());
+      unsigned Align   = TD->getPreferredAlignmentLog(I);
 
+      // Is this correct ?
       if (C->isNullValue() && (I->hasLinkOnceLinkage() || 
-        I->hasInternalLinkage() || I->hasWeakLinkage() 
-        /* FIXME: Verify correct */)) {
-
-        SwitchToDataSection(".data", I);
-        if (I->hasInternalLinkage())
-          O << "\t.local " << name << "\n";
-
-        O << "\t.comm " << name << "," 
-          << TD->getTypeSize(C->getType()) 
-          << "," << Align << "\n";
+          I->hasInternalLinkage() || I->hasWeakLinkage())) 
+      {
+        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 (I->hasInternalLinkage()) {
+          if (TAI->getLCOMMDirective())
+            O << TAI->getLCOMMDirective() << name << "," << Size;
+          else            
+            O << "\t.local\t" << name << "\n";
+        } else {
+          O << TAI->getCOMMDirective() << name << "," << Size;
+          // The .comm alignment in bytes.
+          if (TAI->getCOMMDirectiveTakesAlignment())
+            O << "," << (1 << Align);
+        }
 
       } else {
 
@@ -453,24 +501,37 @@ doFinalization(Module &M)
             // something.  For now, just emit them as external.
           case GlobalValue::ExternalLinkage:
             // If external or appending, declare as a global symbol
-            O << "\t.globl " << name << "\n";
+            O << TAI->getGlobalDirective() << name << "\n";
+            // Fall Through
           case GlobalValue::InternalLinkage:
-            if (C->isNullValue())
-              SwitchToDataSection(".bss", I);
-            else
-              SwitchToDataSection(".data", I);
+            // FIXME: special handling for ".ctors" & ".dtors" sections
+            if (I->hasSection() && (I->getSection() == ".ctors" ||
+                I->getSection() == ".dtors")) {
+              std::string SectionName = ".section " + I->getSection();
+              SectionName += ",\"aw\",%progbits";
+              SwitchToDataSection(SectionName.c_str());
+            } else {
+              if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
+                SwitchToDataSection(TAI->getBSSSection(), I);
+              else if (!I->isConstant())
+                SwitchToDataSection(TAI->getDataSection(), I);
+              else {
+                // Read-only data.
+                if (TAI->getReadOnlySection())
+                  SwitchToDataSection(TAI->getReadOnlySection(), I);
+                else
+                  SwitchToDataSection(TAI->getDataSection(), I);
+              }
+            }
             break;
           case GlobalValue::GhostLinkage:
-            cerr << "Should not have any" 
-                 << "unmaterialized functions!\n";
+            cerr << "Should not have any unmaterialized functions!\n";
             abort();
           case GlobalValue::DLLImportLinkage:
-            cerr << "DLLImport linkage is" 
-                 << "not supported by this target!\n";
+            cerr << "DLLImport linkage is not supported by this target!\n";
             abort();
           case GlobalValue::DLLExportLinkage:
-            cerr << "DLLExport linkage is" 
-                 << "not supported by this target!\n";
+            cerr << "DLLExport linkage is not supported by this target!\n";
             abort();
           default:
             assert(0 && "Unknown linkage type!");