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