Home | History | Annotate | Download | only in AArch64
      1 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an 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 AArch64 MachineInstrs to their corresponding
     11 // MCInst records.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "AArch64MCInstLower.h"
     16 #include "MCTargetDesc/AArch64MCExpr.h"
     17 #include "Utils/AArch64BaseInfo.h"
     18 #include "llvm/CodeGen/AsmPrinter.h"
     19 #include "llvm/CodeGen/MachineBasicBlock.h"
     20 #include "llvm/CodeGen/MachineInstr.h"
     21 #include "llvm/IR/Mangler.h"
     22 #include "llvm/MC/MCExpr.h"
     23 #include "llvm/MC/MCInst.h"
     24 #include "llvm/Support/CodeGen.h"
     25 #include "llvm/Target/TargetMachine.h"
     26 using namespace llvm;
     27 
     28 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, Mangler &mang,
     29                                        AsmPrinter &printer)
     30     : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
     31 
     32 MCSymbol *
     33 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
     34   return Printer.getSymbol(MO.getGlobal());
     35 }
     36 
     37 MCSymbol *
     38 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
     39   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
     40 }
     41 
     42 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
     43                                                        MCSymbol *Sym) const {
     44   // FIXME: We would like an efficient form for this, so we don't have to do a
     45   // lot of extra uniquing.
     46   MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
     47   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
     48     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
     49       RefKind = MCSymbolRefExpr::VK_GOTPAGE;
     50     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     51              AArch64II::MO_PAGEOFF)
     52       RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
     53     else
     54       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
     55   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
     56     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
     57       RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
     58     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     59              AArch64II::MO_PAGEOFF)
     60       RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
     61     else
     62       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
     63   } else {
     64     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
     65       RefKind = MCSymbolRefExpr::VK_PAGE;
     66     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     67              AArch64II::MO_PAGEOFF)
     68       RefKind = MCSymbolRefExpr::VK_PAGEOFF;
     69   }
     70   const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx);
     71   if (!MO.isJTI() && MO.getOffset())
     72     Expr = MCBinaryExpr::CreateAdd(
     73         Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
     74   return MCOperand::CreateExpr(Expr);
     75 }
     76 
     77 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
     78                                                     MCSymbol *Sym) const {
     79   uint32_t RefFlags = 0;
     80 
     81   if (MO.getTargetFlags() & AArch64II::MO_GOT)
     82     RefFlags |= AArch64MCExpr::VK_GOT;
     83   else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
     84     TLSModel::Model Model;
     85     if (MO.isGlobal()) {
     86       const GlobalValue *GV = MO.getGlobal();
     87       Model = Printer.TM.getTLSModel(GV);
     88     } else {
     89       assert(MO.isSymbol() &&
     90              StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
     91              "unexpected external TLS symbol");
     92       Model = TLSModel::GeneralDynamic;
     93     }
     94     switch (Model) {
     95     case TLSModel::InitialExec:
     96       RefFlags |= AArch64MCExpr::VK_GOTTPREL;
     97       break;
     98     case TLSModel::LocalExec:
     99       RefFlags |= AArch64MCExpr::VK_TPREL;
    100       break;
    101     case TLSModel::LocalDynamic:
    102       RefFlags |= AArch64MCExpr::VK_DTPREL;
    103       break;
    104     case TLSModel::GeneralDynamic:
    105       RefFlags |= AArch64MCExpr::VK_TLSDESC;
    106       break;
    107     }
    108   } else {
    109     // No modifier means this is a generic reference, classified as absolute for
    110     // the cases where it matters (:abs_g0: etc).
    111     RefFlags |= AArch64MCExpr::VK_ABS;
    112   }
    113 
    114   if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
    115     RefFlags |= AArch64MCExpr::VK_PAGE;
    116   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
    117            AArch64II::MO_PAGEOFF)
    118     RefFlags |= AArch64MCExpr::VK_PAGEOFF;
    119   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
    120     RefFlags |= AArch64MCExpr::VK_G3;
    121   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
    122     RefFlags |= AArch64MCExpr::VK_G2;
    123   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
    124     RefFlags |= AArch64MCExpr::VK_G1;
    125   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
    126     RefFlags |= AArch64MCExpr::VK_G0;
    127 
    128   if (MO.getTargetFlags() & AArch64II::MO_NC)
    129     RefFlags |= AArch64MCExpr::VK_NC;
    130 
    131   const MCExpr *Expr =
    132       MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx);
    133   if (!MO.isJTI() && MO.getOffset())
    134     Expr = MCBinaryExpr::CreateAdd(
    135         Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
    136 
    137   AArch64MCExpr::VariantKind RefKind;
    138   RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
    139   Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx);
    140 
    141   return MCOperand::CreateExpr(Expr);
    142 }
    143 
    144 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
    145                                                  MCSymbol *Sym) const {
    146   if (TargetTriple.isOSDarwin())
    147     return lowerSymbolOperandDarwin(MO, Sym);
    148 
    149   assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target");
    150   return lowerSymbolOperandELF(MO, Sym);
    151 }
    152 
    153 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
    154                                       MCOperand &MCOp) const {
    155   switch (MO.getType()) {
    156   default:
    157     llvm_unreachable("unknown operand type");
    158   case MachineOperand::MO_Register:
    159     // Ignore all implicit register operands.
    160     if (MO.isImplicit())
    161       return false;
    162     MCOp = MCOperand::CreateReg(MO.getReg());
    163     break;
    164   case MachineOperand::MO_RegisterMask:
    165     // Regmasks are like implicit defs.
    166     return false;
    167   case MachineOperand::MO_Immediate:
    168     MCOp = MCOperand::CreateImm(MO.getImm());
    169     break;
    170   case MachineOperand::MO_MachineBasicBlock:
    171     MCOp = MCOperand::CreateExpr(
    172         MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx));
    173     break;
    174   case MachineOperand::MO_GlobalAddress:
    175     MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
    176     break;
    177   case MachineOperand::MO_ExternalSymbol:
    178     MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
    179     break;
    180   case MachineOperand::MO_JumpTableIndex:
    181     MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
    182     break;
    183   case MachineOperand::MO_ConstantPoolIndex:
    184     MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
    185     break;
    186   case MachineOperand::MO_BlockAddress:
    187     MCOp = LowerSymbolOperand(
    188         MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
    189     break;
    190   }
    191   return true;
    192 }
    193 
    194 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
    195   OutMI.setOpcode(MI->getOpcode());
    196 
    197   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    198     MCOperand MCOp;
    199     if (lowerOperand(MI->getOperand(i), MCOp))
    200       OutMI.addOperand(MCOp);
    201   }
    202 }
    203