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