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