Home | History | Annotate | Download | only in Mips
      1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===//
      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 code to lower Mips MachineInstrs to their corresponding
     11 // MCInst records.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "MipsMCInstLower.h"
     16 #include "MCTargetDesc/MipsBaseInfo.h"
     17 #include "MCTargetDesc/MipsMCExpr.h"
     18 #include "MipsAsmPrinter.h"
     19 #include "llvm/CodeGen/MachineBasicBlock.h"
     20 #include "llvm/CodeGen/MachineInstr.h"
     21 #include "llvm/CodeGen/MachineOperand.h"
     22 #include "llvm/MC/MCExpr.h"
     23 #include "llvm/MC/MCInst.h"
     24 #include "llvm/Support/ErrorHandling.h"
     25 #include <cassert>
     26 
     27 using namespace llvm;
     28 
     29 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
     30   : AsmPrinter(asmprinter) {}
     31 
     32 void MipsMCInstLower::Initialize(MCContext *C) {
     33   Ctx = C;
     34 }
     35 
     36 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
     37                                               MachineOperandType MOTy,
     38                                               unsigned Offset) const {
     39   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
     40   MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
     41   bool IsGpOff = false;
     42   const MCSymbol *Symbol;
     43 
     44   switch(MO.getTargetFlags()) {
     45   default:
     46     llvm_unreachable("Invalid target flag!");
     47   case MipsII::MO_NO_FLAG:
     48     break;
     49   case MipsII::MO_GPREL:
     50     TargetKind = MipsMCExpr::MEK_GPREL;
     51     break;
     52   case MipsII::MO_GOT_CALL:
     53     TargetKind = MipsMCExpr::MEK_GOT_CALL;
     54     break;
     55   case MipsII::MO_GOT:
     56     TargetKind = MipsMCExpr::MEK_GOT;
     57     break;
     58   case MipsII::MO_ABS_HI:
     59     TargetKind = MipsMCExpr::MEK_HI;
     60     break;
     61   case MipsII::MO_ABS_LO:
     62     TargetKind = MipsMCExpr::MEK_LO;
     63     break;
     64   case MipsII::MO_TLSGD:
     65     TargetKind = MipsMCExpr::MEK_TLSGD;
     66     break;
     67   case MipsII::MO_TLSLDM:
     68     TargetKind = MipsMCExpr::MEK_TLSLDM;
     69     break;
     70   case MipsII::MO_DTPREL_HI:
     71     TargetKind = MipsMCExpr::MEK_DTPREL_HI;
     72     break;
     73   case MipsII::MO_DTPREL_LO:
     74     TargetKind = MipsMCExpr::MEK_DTPREL_LO;
     75     break;
     76   case MipsII::MO_GOTTPREL:
     77     TargetKind = MipsMCExpr::MEK_GOTTPREL;
     78     break;
     79   case MipsII::MO_TPREL_HI:
     80     TargetKind = MipsMCExpr::MEK_TPREL_HI;
     81     break;
     82   case MipsII::MO_TPREL_LO:
     83     TargetKind = MipsMCExpr::MEK_TPREL_LO;
     84     break;
     85   case MipsII::MO_GPOFF_HI:
     86     TargetKind = MipsMCExpr::MEK_HI;
     87     IsGpOff = true;
     88     break;
     89   case MipsII::MO_GPOFF_LO:
     90     TargetKind = MipsMCExpr::MEK_LO;
     91     IsGpOff = true;
     92     break;
     93   case MipsII::MO_GOT_DISP:
     94     TargetKind = MipsMCExpr::MEK_GOT_DISP;
     95     break;
     96   case MipsII::MO_GOT_HI16:
     97     TargetKind = MipsMCExpr::MEK_GOT_HI16;
     98     break;
     99   case MipsII::MO_GOT_LO16:
    100     TargetKind = MipsMCExpr::MEK_GOT_LO16;
    101     break;
    102   case MipsII::MO_GOT_PAGE:
    103     TargetKind = MipsMCExpr::MEK_GOT_PAGE;
    104     break;
    105   case MipsII::MO_GOT_OFST:
    106     TargetKind = MipsMCExpr::MEK_GOT_OFST;
    107     break;
    108   case MipsII::MO_HIGHER:
    109     TargetKind = MipsMCExpr::MEK_HIGHER;
    110     break;
    111   case MipsII::MO_HIGHEST:
    112     TargetKind = MipsMCExpr::MEK_HIGHEST;
    113     break;
    114   case MipsII::MO_CALL_HI16:
    115     TargetKind = MipsMCExpr::MEK_CALL_HI16;
    116     break;
    117   case MipsII::MO_CALL_LO16:
    118     TargetKind = MipsMCExpr::MEK_CALL_LO16;
    119     break;
    120   }
    121 
    122   switch (MOTy) {
    123   case MachineOperand::MO_MachineBasicBlock:
    124     Symbol = MO.getMBB()->getSymbol();
    125     break;
    126 
    127   case MachineOperand::MO_GlobalAddress:
    128     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
    129     Offset += MO.getOffset();
    130     break;
    131 
    132   case MachineOperand::MO_BlockAddress:
    133     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
    134     Offset += MO.getOffset();
    135     break;
    136 
    137   case MachineOperand::MO_ExternalSymbol:
    138     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
    139     Offset += MO.getOffset();
    140     break;
    141 
    142   case MachineOperand::MO_MCSymbol:
    143     Symbol = MO.getMCSymbol();
    144     Offset += MO.getOffset();
    145     break;
    146 
    147   case MachineOperand::MO_JumpTableIndex:
    148     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
    149     break;
    150 
    151   case MachineOperand::MO_ConstantPoolIndex:
    152     Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
    153     Offset += MO.getOffset();
    154     break;
    155 
    156   default:
    157     llvm_unreachable("<unknown operand type>");
    158   }
    159 
    160   const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
    161 
    162   if (Offset) {
    163     // Assume offset is never negative.
    164     assert(Offset > 0);
    165 
    166     Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
    167                                    *Ctx);
    168   }
    169 
    170   if (IsGpOff)
    171     Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
    172   else if (TargetKind != MipsMCExpr::MEK_None)
    173     Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
    174 
    175   return MCOperand::createExpr(Expr);
    176 }
    177 
    178 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
    179                                         unsigned offset) const {
    180   MachineOperandType MOTy = MO.getType();
    181 
    182   switch (MOTy) {
    183   default: llvm_unreachable("unknown operand type");
    184   case MachineOperand::MO_Register:
    185     // Ignore all implicit register operands.
    186     if (MO.isImplicit()) break;
    187     return MCOperand::createReg(MO.getReg());
    188   case MachineOperand::MO_Immediate:
    189     return MCOperand::createImm(MO.getImm() + offset);
    190   case MachineOperand::MO_MachineBasicBlock:
    191   case MachineOperand::MO_GlobalAddress:
    192   case MachineOperand::MO_ExternalSymbol:
    193   case MachineOperand::MO_MCSymbol:
    194   case MachineOperand::MO_JumpTableIndex:
    195   case MachineOperand::MO_ConstantPoolIndex:
    196   case MachineOperand::MO_BlockAddress:
    197     return LowerSymbolOperand(MO, MOTy, offset);
    198   case MachineOperand::MO_RegisterMask:
    199     break;
    200  }
    201 
    202   return MCOperand();
    203 }
    204 
    205 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
    206                                      MachineBasicBlock *BB2,
    207                                      MipsMCExpr::MipsExprKind Kind) const {
    208   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
    209   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
    210   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
    211 
    212   return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
    213 }
    214 
    215 void MipsMCInstLower::
    216 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
    217   OutMI.setOpcode(Mips::LUi);
    218 
    219   // Lower register operand.
    220   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
    221 
    222   MipsMCExpr::MipsExprKind Kind;
    223   unsigned TargetFlags = MI->getOperand(1).getTargetFlags();
    224   switch (TargetFlags) {
    225   case MipsII::MO_HIGHEST:
    226     Kind = MipsMCExpr::MEK_HIGHEST;
    227     break;
    228   case MipsII::MO_HIGHER:
    229     Kind = MipsMCExpr::MEK_HIGHER;
    230     break;
    231   case MipsII::MO_ABS_HI:
    232     Kind = MipsMCExpr::MEK_HI;
    233     break;
    234   case MipsII::MO_ABS_LO:
    235     Kind = MipsMCExpr::MEK_LO;
    236     break;
    237   default:
    238     report_fatal_error("Unexpected flags for lowerLongBranchLUi");
    239   }
    240 
    241   if (MI->getNumOperands() == 2) {
    242     const MCExpr *Expr =
    243         MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx);
    244     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
    245     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
    246   } else if (MI->getNumOperands() == 3) {
    247     // Create %hi($tgt-$baltgt).
    248     OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
    249                                MI->getOperand(2).getMBB(), Kind));
    250   }
    251 }
    252 
    253 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI,
    254                                            MCInst &OutMI, int Opcode) const {
    255   OutMI.setOpcode(Opcode);
    256 
    257   MipsMCExpr::MipsExprKind Kind;
    258   unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
    259   switch (TargetFlags) {
    260   case MipsII::MO_HIGHEST:
    261     Kind = MipsMCExpr::MEK_HIGHEST;
    262     break;
    263   case MipsII::MO_HIGHER:
    264     Kind = MipsMCExpr::MEK_HIGHER;
    265     break;
    266   case MipsII::MO_ABS_HI:
    267     Kind = MipsMCExpr::MEK_HI;
    268     break;
    269   case MipsII::MO_ABS_LO:
    270     Kind = MipsMCExpr::MEK_LO;
    271     break;
    272   default:
    273     report_fatal_error("Unexpected flags for lowerLongBranchADDiu");
    274   }
    275 
    276   // Lower two register operands.
    277   for (unsigned I = 0, E = 2; I != E; ++I) {
    278     const MachineOperand &MO = MI->getOperand(I);
    279     OutMI.addOperand(LowerOperand(MO));
    280   }
    281 
    282   if (MI->getNumOperands() == 3) {
    283     // Lower register operand.
    284     const MCExpr *Expr =
    285         MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx);
    286     const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx);
    287     OutMI.addOperand(MCOperand::createExpr(MipsExpr));
    288   } else if (MI->getNumOperands() == 4) {
    289     // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
    290     OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
    291                                MI->getOperand(3).getMBB(), Kind));
    292   }
    293 }
    294 
    295 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
    296                                       MCInst &OutMI) const {
    297   switch (MI->getOpcode()) {
    298   default:
    299     return false;
    300   case Mips::LONG_BRANCH_LUi:
    301     lowerLongBranchLUi(MI, OutMI);
    302     return true;
    303   case Mips::LONG_BRANCH_ADDiu:
    304     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu);
    305     return true;
    306   case Mips::LONG_BRANCH_DADDiu:
    307     lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu);
    308     return true;
    309   }
    310 }
    311 
    312 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
    313   if (lowerLongBranch(MI, OutMI))
    314     return;
    315 
    316   OutMI.setOpcode(MI->getOpcode());
    317 
    318   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    319     const MachineOperand &MO = MI->getOperand(i);
    320     MCOperand MCOp = LowerOperand(MO);
    321 
    322     if (MCOp.isValid())
    323       OutMI.addOperand(MCOp);
    324   }
    325 }
    326