Home | History | Annotate | Download | only in MBlaze
      1 //===-- MBlazeAsmPrinter.cpp - MBlaze LLVM assembly writer ----------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains a printer that converts from our internal representation
     11 // of machine-dependent LLVM code to GAS-format MBlaze assembly language.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #define DEBUG_TYPE "mblaze-asm-printer"
     16 
     17 #include "MBlaze.h"
     18 #include "MBlazeSubtarget.h"
     19 #include "MBlazeInstrInfo.h"
     20 #include "MBlazeTargetMachine.h"
     21 #include "MBlazeMachineFunction.h"
     22 #include "MBlazeMCInstLower.h"
     23 #include "InstPrinter/MBlazeInstPrinter.h"
     24 #include "llvm/Constants.h"
     25 #include "llvm/DerivedTypes.h"
     26 #include "llvm/Module.h"
     27 #include "llvm/CodeGen/AsmPrinter.h"
     28 #include "llvm/CodeGen/MachineFunctionPass.h"
     29 #include "llvm/CodeGen/MachineConstantPool.h"
     30 #include "llvm/CodeGen/MachineFrameInfo.h"
     31 #include "llvm/CodeGen/MachineInstr.h"
     32 #include "llvm/MC/MCInst.h"
     33 #include "llvm/MC/MCStreamer.h"
     34 #include "llvm/MC/MCAsmInfo.h"
     35 #include "llvm/MC/MCSymbol.h"
     36 #include "llvm/Target/Mangler.h"
     37 #include "llvm/Target/TargetData.h"
     38 #include "llvm/Target/TargetLoweringObjectFile.h"
     39 #include "llvm/Target/TargetMachine.h"
     40 #include "llvm/Target/TargetOptions.h"
     41 #include "llvm/Support/ErrorHandling.h"
     42 #include "llvm/Support/TargetRegistry.h"
     43 #include "llvm/Support/raw_ostream.h"
     44 #include <cctype>
     45 
     46 using namespace llvm;
     47 
     48 namespace {
     49   class MBlazeAsmPrinter : public AsmPrinter {
     50     const MBlazeSubtarget *Subtarget;
     51   public:
     52     explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
     53       : AsmPrinter(TM, Streamer) {
     54       Subtarget = &TM.getSubtarget<MBlazeSubtarget>();
     55     }
     56 
     57     virtual const char *getPassName() const {
     58       return "MBlaze Assembly Printer";
     59     }
     60 
     61     void printSavedRegsBitmask();
     62     void emitFrameDirective();
     63     virtual void EmitFunctionBodyStart();
     64     virtual void EmitFunctionBodyEnd();
     65     virtual void EmitFunctionEntryLabel();
     66 
     67     virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
     68       const;
     69 
     70     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     71                          unsigned AsmVariant, const char *ExtraCode,
     72                          raw_ostream &O);
     73     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
     74     void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O);
     75     void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O);
     76     void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
     77                          const char *Modifier = 0);
     78 
     79     void EmitInstruction(const MachineInstr *MI);
     80   };
     81 } // end of anonymous namespace
     82 
     83 // #include "MBlazeGenAsmWriter.inc"
     84 
     85 //===----------------------------------------------------------------------===//
     86 //
     87 //  MBlaze Asm Directives
     88 //
     89 //  -- Frame directive "frame Stackpointer, Stacksize, RARegister"
     90 //  Describe the stack frame.
     91 //
     92 //  -- Mask directives "mask  bitmask, offset"
     93 //  Tells the assembler which registers are saved and where.
     94 //  bitmask - contain a little endian bitset indicating which registers are
     95 //            saved on function prologue (e.g. with a 0x80000000 mask, the
     96 //            assembler knows the register 31 (RA) is saved at prologue.
     97 //  offset  - the position before stack pointer subtraction indicating where
     98 //            the first saved register on prologue is located. (e.g. with a
     99 //
    100 //  Consider the following function prologue:
    101 //
    102 //    .frame  R19,48,R15
    103 //    .mask   0xc0000000,-8
    104 //       addiu R1, R1, -48
    105 //       sw R15, 40(R1)
    106 //       sw R19, 36(R1)
    107 //
    108 //    With a 0xc0000000 mask, the assembler knows the register 15 (R15) and
    109 //    19 (R19) are saved at prologue. As the save order on prologue is from
    110 //    left to right, R15 is saved first. A -8 offset means that after the
    111 //    stack pointer subtration, the first register in the mask (R15) will be
    112 //    saved at address 48-8=40.
    113 //
    114 //===----------------------------------------------------------------------===//
    115 
    116 // Print a 32 bit hex number with all numbers.
    117 static void printHex32(unsigned int Value, raw_ostream &O) {
    118   O << "0x";
    119   for (int i = 7; i >= 0; i--)
    120     O.write_hex((Value & (0xF << (i*4))) >> (i*4));
    121 }
    122 
    123 // Create a bitmask with all callee saved registers for CPU or Floating Point
    124 // registers. For CPU registers consider RA, GP and FP for saving if necessary.
    125 void MBlazeAsmPrinter::printSavedRegsBitmask() {
    126   const TargetFrameLowering *TFI = TM.getFrameLowering();
    127   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
    128 
    129   // CPU Saved Registers Bitmasks
    130   unsigned int CPUBitmask = 0;
    131 
    132   // Set the CPU Bitmasks
    133   const MachineFrameInfo *MFI = MF->getFrameInfo();
    134   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
    135   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    136     unsigned Reg = CSI[i].getReg();
    137     unsigned RegNum = getMBlazeRegisterNumbering(Reg);
    138     if (MBlaze::GPRRegClass.contains(Reg))
    139       CPUBitmask |= (1 << RegNum);
    140   }
    141 
    142   // Return Address and Frame registers must also be set in CPUBitmask.
    143   if (TFI->hasFP(*MF))
    144     CPUBitmask |= (1 <<  getMBlazeRegisterNumbering(RI.getFrameRegister(*MF)));
    145 
    146   if (MFI->adjustsStack())
    147     CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getRARegister()));
    148 
    149   // Print CPUBitmask
    150   OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask));
    151 }
    152 
    153 /// Frame Directive
    154 void MBlazeAsmPrinter::emitFrameDirective() {
    155   if (!OutStreamer.hasRawTextSupport())
    156     return;
    157 
    158   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
    159   unsigned stkReg = RI.getFrameRegister(*MF);
    160   unsigned retReg = RI.getRARegister();
    161   unsigned stkSze = MF->getFrameInfo()->getStackSize();
    162 
    163   OutStreamer.EmitRawText("\t.frame\t" +
    164                           Twine(MBlazeInstPrinter::getRegisterName(stkReg)) +
    165                           "," + Twine(stkSze) + "," +
    166                           Twine(MBlazeInstPrinter::getRegisterName(retReg)));
    167 }
    168 
    169 void MBlazeAsmPrinter::EmitFunctionEntryLabel() {
    170   if (OutStreamer.hasRawTextSupport())
    171     OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
    172   AsmPrinter::EmitFunctionEntryLabel();
    173 }
    174 
    175 void MBlazeAsmPrinter::EmitFunctionBodyStart() {
    176   if (!OutStreamer.hasRawTextSupport())
    177     return;
    178 
    179   emitFrameDirective();
    180   printSavedRegsBitmask();
    181 }
    182 
    183 void MBlazeAsmPrinter::EmitFunctionBodyEnd() {
    184   if (OutStreamer.hasRawTextSupport())
    185     OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
    186 }
    187 
    188 //===----------------------------------------------------------------------===//
    189 void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) {
    190   MBlazeMCInstLower MCInstLowering(OutContext, *this);
    191 
    192   MCInst TmpInst;
    193   MCInstLowering.Lower(MI, TmpInst);
    194   OutStreamer.EmitInstruction(TmpInst);
    195 }
    196 
    197 // Print out an operand for an inline asm expression.
    198 bool MBlazeAsmPrinter::
    199 PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
    200                 unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) {
    201   // Does this asm operand have a single letter operand modifier?
    202   if (ExtraCode && ExtraCode[0])
    203     if (ExtraCode[1] != 0) return true; // Unknown modifier.
    204 
    205     switch (ExtraCode[0]) {
    206     default:
    207       // See if this is a generic print operand
    208       return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
    209     }
    210 
    211   printOperand(MI, OpNo, O);
    212   return false;
    213 }
    214 
    215 void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
    216                                     raw_ostream &O) {
    217   const MachineOperand &MO = MI->getOperand(opNum);
    218 
    219   switch (MO.getType()) {
    220   case MachineOperand::MO_Register:
    221     O << MBlazeInstPrinter::getRegisterName(MO.getReg());
    222     break;
    223 
    224   case MachineOperand::MO_Immediate:
    225     O << (int32_t)MO.getImm();
    226     break;
    227 
    228   case MachineOperand::MO_FPImmediate: {
    229     const ConstantFP *fp = MO.getFPImm();
    230     printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O);
    231     O << ";\t# immediate = " << *fp;
    232     break;
    233   }
    234 
    235   case MachineOperand::MO_MachineBasicBlock:
    236     O << *MO.getMBB()->getSymbol();
    237     return;
    238 
    239   case MachineOperand::MO_GlobalAddress:
    240     O << *Mang->getSymbol(MO.getGlobal());
    241     break;
    242 
    243   case MachineOperand::MO_ExternalSymbol:
    244     O << *GetExternalSymbolSymbol(MO.getSymbolName());
    245     break;
    246 
    247   case MachineOperand::MO_JumpTableIndex:
    248     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
    249       << '_' << MO.getIndex();
    250     break;
    251 
    252   case MachineOperand::MO_ConstantPoolIndex:
    253     O << MAI->getPrivateGlobalPrefix() << "CPI"
    254       << getFunctionNumber() << "_" << MO.getIndex();
    255     if (MO.getOffset())
    256       O << "+" << MO.getOffset();
    257     break;
    258 
    259   default:
    260     llvm_unreachable("<unknown operand type>");
    261   }
    262 }
    263 
    264 void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum,
    265                                         raw_ostream &O) {
    266   const MachineOperand &MO = MI->getOperand(opNum);
    267   if (MO.isImm())
    268     O << (uint32_t)MO.getImm();
    269   else
    270     printOperand(MI, opNum, O);
    271 }
    272 
    273 void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum,
    274                                    raw_ostream &O) {
    275   const MachineOperand &MO = MI->getOperand(opNum);
    276   if (MO.isImm())
    277     O << "rfsl" << (unsigned int)MO.getImm();
    278   else
    279     printOperand(MI, opNum, O);
    280 }
    281 
    282 void MBlazeAsmPrinter::
    283 printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
    284                 const char *Modifier) {
    285   printOperand(MI, opNum, O);
    286   O << ", ";
    287   printOperand(MI, opNum+1, O);
    288 }
    289 
    290 /// isBlockOnlyReachableByFallthough - Return true if the basic block has
    291 /// exactly one predecessor and the control transfer mechanism between
    292 /// the predecessor and this block is a fall-through.
    293 bool MBlazeAsmPrinter::
    294 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
    295   // If this is a landing pad, it isn't a fall through.  If it has no preds,
    296   // then nothing falls through to it.
    297   if (MBB->isLandingPad() || MBB->pred_empty())
    298     return false;
    299 
    300   // If there isn't exactly one predecessor, it can't be a fall through.
    301   MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
    302   ++PI2;
    303   if (PI2 != MBB->pred_end())
    304     return false;
    305 
    306   // The predecessor has to be immediately before this block.
    307   const MachineBasicBlock *Pred = *PI;
    308 
    309   if (!Pred->isLayoutSuccessor(MBB))
    310     return false;
    311 
    312   // If the block is completely empty, then it definitely does fall through.
    313   if (Pred->empty())
    314     return true;
    315 
    316   // Check if the last terminator is an unconditional branch.
    317   MachineBasicBlock::const_iterator I = Pred->end();
    318   while (I != Pred->begin() && !(--I)->isTerminator())
    319     ; // Noop
    320   return I == Pred->end() || !I->isBarrier();
    321 }
    322 
    323 // Force static initialization.
    324 extern "C" void LLVMInitializeMBlazeAsmPrinter() {
    325   RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget);
    326 }
    327