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