Initial Mips support, here we go! =)
- Modifications from the last patch included
  (issues pointed by Evan Cheng are now fixed).
- Added more MipsI instructions.
- Added more patterns to match branch instructions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37461 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
new file mode 100644
index 0000000..fdf60d9
--- /dev/null
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -0,0 +1,294 @@
+//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===//
+//
+//                     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 contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to GAS-format MIPS assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-asm-printer"
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsTargetMachine.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MathExtras.h"
+#include <cctype>
+
+using namespace llvm;
+
+STATISTIC(EmittedInsts, "Number of machine instrs printed");
+
+namespace {
+  struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
+    MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM, 
+                   const TargetAsmInfo *T): 
+                   AsmPrinter(O, TM, T) {}
+
+    virtual const char *getPassName() const {
+      return "Mips Assembly Printer";
+    }
+
+    void printOperand(const MachineInstr *MI, int opNum);
+    void printMemOperand(const MachineInstr *MI, int opNum, 
+                         const char *Modifier = 0);
+
+    bool printInstruction(const MachineInstr *MI);  // autogenerated.
+    bool runOnMachineFunction(MachineFunction &F);
+    bool doInitialization(Module &M);
+    bool doFinalization(Module &M);
+  };
+} // end of anonymous namespace
+
+#include "MipsGenAsmWriter.inc"
+
+/// createMipsCodePrinterPass - Returns a pass that prints the MIPS
+/// 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());
+}
+
+/// runOnMachineFunction - This uses the printMachineInstruction()
+/// method to print assembly for each instruction.
+bool MipsAsmPrinter::
+runOnMachineFunction(MachineFunction &MF) 
+{
+  SetupMachineFunction(MF);
+
+  // Print out constants referenced by the function
+  EmitConstantPool(MF.getConstantPool());
+
+  O << "\n\n";
+
+  // What's my mangled name?
+  CurrentFnName = Mang->getValueName(MF.getFunction());
+
+  // Print out the label for the function.
+  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 to align. So, if we want 4 byte alignment, we must 
+  // have .align 2
+  // TODO:
+  //  add gas ".mask" and ".fmask"
+  EmitAlignment(1, F);
+  O << "\t.globl\t" << CurrentFnName << "\n";
+  O << "\t.ent\t" << CurrentFnName << "\n";
+  O << "\t.type\t"  << CurrentFnName << ", @function\n";
+  O << CurrentFnName << ":\n";
+
+  // Print out code for the function.
+  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+       I != E; ++I) {
+
+    // Print a label for the basic block.
+    if (I != MF.begin()) {
+      printBasicBlockLabel(I, 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;
+    }
+  }
+
+  // close function with asm directive
+  O << "\t.end\t" << CurrentFnName << "\n";
+
+  // We didn't modify anything.
+  return false;
+}
+
+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
+  if (MI->getOpcode() == Mips::LUi && !MO.isRegister() 
+      && !MO.isImmediate()) {
+    O << "%hi(";
+    closeP = true;
+  } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() 
+             && !MO.isImmediate()) {
+    O << "%lo(";
+    closeP = true;
+  }
+ 
+  switch (MO.getType()) 
+  {
+    case MachineOperand::MO_Register:
+      if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
+        O << "$" << LowercaseString (RI.get(MO.getReg()).Name);
+      else
+        O << "$" << MO.getReg();
+      break;
+
+    case MachineOperand::MO_Immediate:
+      if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || 
+          (MI->getOpcode() == Mips::LUi) || (MI->getOpcode() == Mips::ANDi))
+        O << (unsigned int)MO.getImmedValue();
+      else
+        O << (int)MO.getImmedValue();
+      break;
+
+    case MachineOperand::MO_MachineBasicBlock:
+      printBasicBlockLabel(MO.getMachineBasicBlock());
+      return;
+
+    case MachineOperand::MO_GlobalAddress:
+      O << Mang->getValueName(MO.getGlobal());
+      break;
+
+    case MachineOperand::MO_ExternalSymbol:
+      O << MO.getSymbolName();
+      break;
+
+    case MachineOperand::MO_ConstantPoolIndex:
+      O << TAI->getPrivateGlobalPrefix() << "CPI"
+        << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
+      break;
+  
+    default:
+      O << "<unknown operand type>"; abort (); break;
+  }
+
+  if (closeP) O << ")";
+}
+
+void MipsAsmPrinter::
+printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) 
+{
+  // lw/sw $reg, MemOperand
+  // will turn into :
+  // lw/sw $reg, imm($reg)
+  printOperand(MI, opNum);
+  O << "(";
+  printOperand(MI, opNum+1);
+  O << ")";
+}
+
+bool MipsAsmPrinter::
+doInitialization(Module &M) 
+{
+  Mang = new Mangler(M);
+  return false; // success
+}
+
+bool MipsAsmPrinter::
+doFinalization(Module &M) 
+{
+  const TargetData *TD = TM.getTargetData();
+
+  // Print out module-level global variables here.
+  for (Module::const_global_iterator I = M.global_begin(),
+         E = M.global_end(); I != E; ++I)
+
+    // External global require no code
+    if (I->hasInitializer()) {
+
+      // Check to see if this is a special global 
+      // used by LLVM, if so, emit it.
+      if (EmitSpecialLLVMGlobal(I))
+        continue;
+      
+      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());
+
+      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";
+
+      } else {
+
+        switch (I->getLinkage()) 
+        {
+          case GlobalValue::LinkOnceLinkage:
+          case GlobalValue::WeakLinkage:   
+            // FIXME: Verify correct for weak.
+            // Nonnull linkonce -> weak
+            O << "\t.weak " << name << "\n";
+            SwitchToDataSection("", I);
+            O << "\t.section\t\".llvm.linkonce.d." << name
+                          << "\",\"aw\",@progbits\n";
+            break;
+          case GlobalValue::AppendingLinkage:
+            // FIXME: appending linkage variables 
+            // should go into a section of  their name or 
+            // 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";
+          case GlobalValue::InternalLinkage:
+            if (C->isNullValue())
+              SwitchToDataSection(".bss", I);
+            else
+              SwitchToDataSection(".data", I);
+            break;
+          case GlobalValue::GhostLinkage:
+            cerr << "Should not have any" 
+                 << "unmaterialized functions!\n";
+            abort();
+          case GlobalValue::DLLImportLinkage:
+            cerr << "DLLImport linkage is" 
+                 << "not supported by this target!\n";
+            abort();
+          case GlobalValue::DLLExportLinkage:
+            cerr << "DLLExport linkage is" 
+                 << "not supported by this target!\n";
+            abort();
+          default:
+            assert(0 && "Unknown linkage type!");          
+        }
+        O << "\t.align " << Align << "\n";
+        O << "\t.type " << name << ",@object\n";
+        O << "\t.size " << name << "," << Size << "\n";
+        O << name << ":\n";
+        EmitGlobalConstant(C);
+    }
+  }
+
+  AsmPrinter::doFinalization(M);
+  return false; // success
+}