Fix target library name
[oota-llvm.git] / lib / Target / Mips / MipsAsmPrinter.cpp
index 4981b903bd28a5f06b9b10905d553150259ad35b..532c82df06fb8af19796845bddef6b2d2190dc29 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DwarfWriter.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -37,6 +38,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
 #include <cctype>
 
 using namespace llvm;
@@ -44,13 +46,12 @@ using namespace llvm;
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
 namespace {
-  struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
-
+  class VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
     const MipsSubtarget *Subtarget;
-
-    MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM, 
-                   const TargetAsmInfo *T): 
-                   AsmPrinter(O, TM, T) {
+  public:
+    MipsAsmPrinter(raw_ostream &O, MipsTargetMachine &TM, 
+                   const TargetAsmInfo *T, bool F, bool V)
+      : AsmPrinter(O, TM, T, F, V) {
       Subtarget = &TM.getSubtarget<MipsSubtarget>();
     }
 
@@ -58,22 +59,22 @@ namespace {
       return "Mips Assembly Printer";
     }
 
-    virtual std::string getSectionForFunction(const Function &F) const;
+    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 
+                         unsigned AsmVariant, const char *ExtraCode);
     void printOperand(const MachineInstr *MI, int opNum);
+    void printUnsignedImm(const MachineInstr *MI, int opNum);
     void printMemOperand(const MachineInstr *MI, int opNum, 
                          const char *Modifier = 0);
     void printFCCOperand(const MachineInstr *MI, int opNum, 
                          const char *Modifier = 0);
     void printModuleLevelGV(const GlobalVariable* GVar);
-    unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF);
+    void printSavedRegsBitmask(MachineFunction &MF);
     void printHex32(unsigned int Value);
 
     const char *emitCurrentABIString(void);
     void emitFunctionStart(MachineFunction &MF);
     void emitFunctionEnd(MachineFunction &MF);
     void emitFrameDirective(MachineFunction &MF);
-    void emitMaskDirective(MachineFunction &MF);
-    void emitFMaskDirective(MachineFunction &MF);
 
     bool printInstruction(const MachineInstr *MI);  // autogenerated.
     bool runOnMachineFunction(MachineFunction &F);
@@ -88,10 +89,10 @@ namespace {
 /// assembly code for a MachineFunction to the given output stream,
 /// using the given target machine description.  This should work
 /// regardless of whether the function is in SSA form.
-FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
-                                              MipsTargetMachine &tm
-{
-  return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo());
+FunctionPass *llvm::createMipsCodePrinterPass(raw_ostream &o,
+                                              MipsTargetMachine &tm,
+                                              bool fast, bool verbose) {
+  return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo(), fast, verbose);
 }
 
 //===----------------------------------------------------------------------===//
@@ -129,79 +130,54 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
 // Mask directives
 //===----------------------------------------------------------------------===//
 
-/// Mask directive for GPR
+// Create a bitmask with all callee saved registers for CPU or Floating Point 
+// registers. For CPU registers consider RA, GP and FP for saving if necessary.
 void MipsAsmPrinter::
-emitMaskDirective(MachineFunction &MF)
-{
-  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
-
-  int StackSize = MF.getFrameInfo()->getStackSize();
-  int Offset    = (!MipsFI->getTopSavedRegOffset()) ? 0 : 
-                  (-(StackSize-MipsFI->getTopSavedRegOffset()));
-
-  #ifndef NDEBUG
-  DOUT << "--> emitMaskDirective" << '\n';
-  DOUT << "StackSize :  " << StackSize << '\n';
-  DOUT << "getTopSavedReg : " << MipsFI->getTopSavedRegOffset() << '\n';
-  DOUT << "Offset : " << Offset << "\n\n";
-  #endif
-
-  unsigned int Bitmask = getSavedRegsBitmask(false, MF);
-  O << "\t.mask \t"; 
-  printHex32(Bitmask);
-  O << ',' << Offset << '\n';
-}
-
-/// TODO: Mask Directive for Floating Point
-void MipsAsmPrinter::
-emitFMaskDirective(MachineFunction &MF)
-{
-  unsigned int Bitmask = getSavedRegsBitmask(true, MF);
-
-  O << "\t.fmask\t";
-  printHex32(Bitmask);
-  O << ",0" << '\n';
-}
-
-// Create a bitmask with all callee saved registers for CPU
-// or Floating Point registers. For CPU registers consider RA,
-// GP and FP for saving if necessary.
-unsigned int MipsAsmPrinter::
-getSavedRegsBitmask(bool isFloat, MachineFunction &MF)
+printSavedRegsBitmask(MachineFunction &MF)
 {
   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
+  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
              
-  // Floating Point Registers, TODO
-  if (isFloat)
-    return 0;
-
-  // CPU Registers
-  unsigned int Bitmask = 0;
+  // CPU and FPU Saved Registers Bitmasks
+  unsigned int CPUBitmask = 0;
+  unsigned int FPUBitmask = 0;
 
+  // Set the CPU and FPU Bitmasks
   MachineFrameInfo *MFI = MF.getFrameInfo();
   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
-  for (unsigned i = 0, e = CSI.size(); i != e; ++i)
-    Bitmask |= (1 << MipsRegisterInfo::getRegisterNumbering(CSI[i].getReg()));
+  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+    unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(CSI[i].getReg());
+    if (CSI[i].getRegClass() == Mips::CPURegsRegisterClass)
+      CPUBitmask |= (1 << RegNum);
+    else
+      FPUBitmask |= (1 << RegNum);
+  }
 
+  // Return Address and Frame registers must also be set in CPUBitmask.
   if (RI.hasFP(MF)) 
-    Bitmask |= (1 << MipsRegisterInfo::
+    CPUBitmask |= (1 << MipsRegisterInfo::
                 getRegisterNumbering(RI.getFrameRegister(MF)));
   
   if (MF.getFrameInfo()->hasCalls()) 
-    Bitmask |= (1 << MipsRegisterInfo::
+    CPUBitmask |= (1 << MipsRegisterInfo::
                 getRegisterNumbering(RI.getRARegister()));
 
-  return Bitmask;
+  // Print CPUBitmask
+  O << "\t.mask \t"; printHex32(CPUBitmask); O << ','
+    << MipsFI->getCPUTopSavedRegOff() << '\n';
+
+  // Print FPUBitmask
+  O << "\t.fmask\t"; printHex32(FPUBitmask); O << ","
+    << MipsFI->getFPUTopSavedRegOff() << '\n';
 }
 
 // Print a 32 bit hex number with all numbers.
 void MipsAsmPrinter::
 printHex32(unsigned int Value) 
 {
-  O << "0x" << std::hex;
+  O << "0x";
   for (int i = 7; i >= 0; i--) 
-    O << std::hex << ( (Value & (0xF << (i*4))) >> (i*4) );
-  O << std::dec;
+    O << utohexstr( (Value & (0xF << (i*4))) >> (i*4) );
 }
 
 //===----------------------------------------------------------------------===//
@@ -242,18 +218,13 @@ emitCurrentABIString(void)
   return NULL;
 }  
 
-// Substitute old hook with new one temporary
-std::string MipsAsmPrinter::getSectionForFunction(const Function &F) const {
-  return TAI->SectionForGlobal(&F);
-}
-
 /// Emit the directives used by GAS on the start of functions
 void MipsAsmPrinter::
 emitFunctionStart(MachineFunction &MF)
 {
   // Print out the label for the function.
   const Function *F = MF.getFunction();
-  SwitchToTextSection(TAI->SectionForGlobal(F).c_str());
+  SwitchToSection(TAI->SectionForGlobal(F));
 
   // 2 bits aligned
   EmitAlignment(2, F);
@@ -261,14 +232,15 @@ emitFunctionStart(MachineFunction &MF)
   O << "\t.globl\t"  << CurrentFnName << '\n';
   O << "\t.ent\t"    << CurrentFnName << '\n';
 
+  printVisibility(CurrentFnName, F->getVisibility());
+
   if ((TAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
     O << "\t.type\t"   << CurrentFnName << ", @function\n";
 
   O << CurrentFnName << ":\n";
 
   emitFrameDirective(MF);
-  emitMaskDirective(MF);
-  emitFMaskDirective(MF);
+  printSavedRegsBitmask(MF);
 
   O << '\n';
 }
@@ -293,6 +265,8 @@ emitFunctionEnd(MachineFunction &MF)
 bool MipsAsmPrinter::
 runOnMachineFunction(MachineFunction &MF) 
 {
+  this->MF = &MF;
+
   SetupMachineFunction(MF);
 
   // Print out constants referenced by the function
@@ -303,9 +277,6 @@ runOnMachineFunction(MachineFunction &MF)
 
   O << "\n\n";
 
-  // What's my mangled name?
-  CurrentFnName = Mang->getValueName(MF.getFunction());
-
   // Emit the function start directives
   emitFunctionStart(MF);
 
@@ -337,6 +308,19 @@ runOnMachineFunction(MachineFunction &MF)
   return false;
 }
 
+// Print out an operand for an inline asm expression.
+bool MipsAsmPrinter::
+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]) 
+    return true; // Unknown modifier.
+
+  printOperand(MI, OpNo);
+  return false;
+}
+
 void MipsAsmPrinter::
 printOperand(const MachineInstr *MI, int opNum) 
 {
@@ -351,22 +335,24 @@ printOperand(const MachineInstr *MI, int opNum)
   // 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()) {
+  if (MI->getOpcode() == Mips::LUi && !MO.isReg() && !MO.isImm()) {
     if ((isPIC) && (isCodeLarge))
       O << "%call_hi(";
     else
       O << "%hi(";
     closeP = true;
-  } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() 
-             && !MO.isImmediate()) {
-    O << "%lo(";
+  } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isReg() && !MO.isImm()) {
+    const MachineOperand &firstMO = MI->getOperand(opNum-1);
+    if (firstMO.getReg() == Mips::GP)
+      O << "%gp_rel(";
+    else
+      O << "%lo(";
     closeP = true;
-  } else if ((isPIC) && (MI->getOpcode() == Mips::LW)
-             && (!MO.isRegister()) && (!MO.isImmediate())) {
+  } else if ((isPIC) && (MI->getOpcode() == Mips::LW) &&
+             (!MO.isReg()) && (!MO.isImm())) {
     const MachineOperand &firstMO = MI->getOperand(opNum-1);
     const MachineOperand &lastMO  = MI->getOperand(opNum+1);
-    if ((firstMO.isRegister()) && (lastMO.isRegister())) {
+    if ((firstMO.isReg()) && (lastMO.isReg())) {
       if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP) 
           && (!isCodeLarge))
         O << "%call16(";
@@ -389,11 +375,7 @@ printOperand(const MachineInstr *MI, int opNum)
       break;
 
     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.getImm();
-      else
-        O << (short int)MO.getImm();
+      O << (short int)MO.getImm();
       break;
 
     case MachineOperand::MO_MachineBasicBlock:
@@ -401,7 +383,10 @@ printOperand(const MachineInstr *MI, int opNum)
       return;
 
     case MachineOperand::MO_GlobalAddress:
-      O << Mang->getValueName(MO.getGlobal());
+      {
+        const GlobalValue *GV = MO.getGlobal();
+        O << Mang->getValueName(GV);
+      }
       break;
 
     case MachineOperand::MO_ExternalSymbol:
@@ -413,7 +398,6 @@ printOperand(const MachineInstr *MI, int opNum)
       << '_' << MO.getIndex();
       break;
 
-    // FIXME: Verify correct
     case MachineOperand::MO_ConstantPoolIndex:
       O << TAI->getPrivateGlobalPrefix() << "CPI"
         << getFunctionNumber() << "_" << MO.getIndex();
@@ -426,6 +410,16 @@ printOperand(const MachineInstr *MI, int opNum)
   if (closeP) O << ")";
 }
 
+void MipsAsmPrinter::
+printUnsignedImm(const MachineInstr *MI, int opNum) 
+{
+  const MachineOperand &MO = MI->getOperand(opNum);
+  if (MO.getType() == MachineOperand::MO_Immediate)
+    O << (unsigned short int)MO.getImm();
+  else 
+    printOperand(MI, opNum);
+}
+
 void MipsAsmPrinter::
 printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) 
 {
@@ -457,7 +451,7 @@ printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier)
 bool MipsAsmPrinter::
 doInitialization(Module &M) 
 {
-  Mang = new Mangler(M);
+  Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
 
   // Tell the assembler which ABI we are using
   O << "\t.section .mdebug." << emitCurrentABIString() << '\n';
@@ -485,19 +479,17 @@ printModuleLevelGV(const GlobalVariable* GVar) {
     return;
 
   O << "\n\n";
-  std::string SectionName = TAI->SectionForGlobal(GVar);
   std::string name = Mang->getValueName(GVar);
   Constant *C = GVar->getInitializer();
   const Type *CTy = C->getType();
-  unsigned Size = TD->getABITypeSize(CTy);
+  unsigned Size = TD->getTypePaddedSize(CTy);
+  const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
   bool printSizeAndType = true;
 
   // A data structure or array is aligned in memory to the largest
   // alignment boundary required by any data type inside it (this matches
   // the Preferred Type Alignment). For integral types, the alignment is
   // the type size.
-  //unsigned Align = TD->getPreferredAlignmentLog(I);
-  //unsigned Align = TD->getPrefTypeAlignment(C->getType());
   unsigned Align;
   if (CTy->getTypeID() == Type::IntegerTyID ||
       CTy->getTypeID() == Type::VoidTyID) {
@@ -506,34 +498,32 @@ printModuleLevelGV(const GlobalVariable* GVar) {
   } else
     Align = TD->getPreferredTypeAlignmentShift(CTy);
 
-  // FIXME: ELF supports visibility
+  printVisibility(name, GVar->getVisibility());
 
-  SwitchToDataSection(SectionName.c_str());
+  SwitchToSection(TAI->SectionForGlobal(GVar));
 
   if (C->isNullValue() && !GVar->hasSection()) {
     if (!GVar->isThreadLocal() &&
-        (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) {
+        (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
 
-      if (GVar->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 << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
-      }
+      if (GVar->hasLocalLinkage())
+        O << "\t.local\t" << name << '\n';
+
+      O << TAI->getCOMMDirective() << name << ',' << Size;
+      if (TAI->getCOMMDirectiveTakesAlignment())
+        O << ',' << (1 << Align);
+
       O << '\n';
       return;
     }
   }
   switch (GVar->getLinkage()) {
-   case GlobalValue::LinkOnceLinkage:
+   case GlobalValue::LinkOnceAnyLinkage:
+   case GlobalValue::LinkOnceODRLinkage:
    case GlobalValue::CommonLinkage:
-   case GlobalValue::WeakLinkage:
+   case GlobalValue::WeakAnyLinkage:
+   case GlobalValue::WeakODRLinkage:
     // FIXME: Verify correct for weak.
     // Nonnull linkonce -> weak
     O << "\t.weak " << name << '\n';
@@ -545,7 +535,10 @@ printModuleLevelGV(const GlobalVariable* GVar) {
     // If external or appending, declare as a global symbol
     O << TAI->getGlobalDirective() << name << '\n';
     // Fall Through
+   case GlobalValue::PrivateLinkage:
    case GlobalValue::InternalLinkage:
+    if (CVA && CVA->isCString())
+      printSizeAndType = false;
     break;
    case GlobalValue::GhostLinkage:
     cerr << "Should not have any unmaterialized functions!\n";
@@ -560,8 +553,7 @@ printModuleLevelGV(const GlobalVariable* GVar) {
     assert(0 && "Unknown linkage type!");
   }
 
-  if (Align)
-    O << "\t.align " << Align << '\n';
+  EmitAlignment(Align, GVar);
 
   if (TAI->hasDotTypeDotSizeDirective() && printSizeAndType) {
     O << "\t.type " << name << ",@object\n";