LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64MCInstLower.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 115 121 95.0 %
Date: 2018-06-17 00:07:59 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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        1102 : AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
      34        2204 :     : Ctx(ctx), Printer(printer) {}
      35             : 
      36             : MCSymbol *
      37        8100 : AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
      38        8100 :   const GlobalValue *GV = MO.getGlobal();
      39             :   unsigned TargetFlags = MO.getTargetFlags();
      40        8100 :   const Triple &TheTriple = Printer.TM.getTargetTriple();
      41        8100 :   if (!TheTriple.isOSBinFormatCOFF())
      42        8041 :     return Printer.getSymbol(GV);
      43             : 
      44             :   assert(TheTriple.isOSWindows() &&
      45             :          "Windows is the only supported COFF target");
      46             : 
      47          59 :   bool IsIndirect = (TargetFlags & AArch64II::MO_DLLIMPORT);
      48          59 :   if (!IsIndirect)
      49          41 :     return Printer.getSymbol(GV);
      50             : 
      51             :   SmallString<128> Name;
      52             :   Name = "__imp_";
      53          36 :   Printer.TM.getNameWithPrefix(Name, GV,
      54          18 :                                Printer.getObjFileLowering().getMangler());
      55             : 
      56          36 :   return Ctx.getOrCreateSymbol(Name);
      57             : }
      58             : 
      59             : MCSymbol *
      60         566 : AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
      61        1132 :   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
      62             : }
      63             : 
      64        1351 : 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        1351 :   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
      70         364 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      71             :       RefKind = MCSymbolRefExpr::VK_GOTPAGE;
      72         182 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      73             :              AArch64II::MO_PAGEOFF)
      74             :       RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
      75             :     else
      76           0 :       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
      77         987 :   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
      78          50 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      79             :       RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
      80          25 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      81             :              AArch64II::MO_PAGEOFF)
      82             :       RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
      83             :     else
      84           0 :       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
      85             :   } else {
      86         937 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      87             :       RefKind = MCSymbolRefExpr::VK_PAGE;
      88         721 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      89             :              AArch64II::MO_PAGEOFF)
      90             :       RefKind = MCSymbolRefExpr::VK_PAGEOFF;
      91             :   }
      92        1351 :   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
      93        2700 :   if (!MO.isJTI() && MO.getOffset())
      94          10 :     Expr = MCBinaryExpr::createAdd(
      95          10 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
      96        1351 :   return MCOperand::createExpr(Expr);
      97             : }
      98             : 
      99        7594 : MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
     100             :                                                     MCSymbol *Sym) const {
     101             :   uint32_t RefFlags = 0;
     102             : 
     103        7594 :   if (MO.getTargetFlags() & AArch64II::MO_GOT)
     104             :     RefFlags |= AArch64MCExpr::VK_GOT;
     105        7460 :   else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
     106             :     TLSModel::Model Model;
     107         104 :     if (MO.isGlobal()) {
     108          86 :       const GlobalValue *GV = MO.getGlobal();
     109          86 :       Model = Printer.TM.getTLSModel(GV);
     110          86 :       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          62 :     switch (Model) {
     123           8 :     case TLSModel::InitialExec:
     124             :       RefFlags |= AArch64MCExpr::VK_GOTTPREL;
     125           8 :       break;
     126           8 :     case TLSModel::LocalExec:
     127             :       RefFlags |= AArch64MCExpr::VK_TPREL;
     128           8 :       break;
     129          16 :     case TLSModel::LocalDynamic:
     130             :       RefFlags |= AArch64MCExpr::VK_DTPREL;
     131          16 :       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        7594 :   if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
     143        2817 :     RefFlags |= AArch64MCExpr::VK_PAGE;
     144        4777 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     145             :            AArch64II::MO_PAGEOFF)
     146        3220 :     RefFlags |= AArch64MCExpr::VK_PAGEOFF;
     147        1557 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
     148          31 :     RefFlags |= AArch64MCExpr::VK_G3;
     149        1526 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
     150          31 :     RefFlags |= AArch64MCExpr::VK_G2;
     151        1495 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
     152          31 :     RefFlags |= AArch64MCExpr::VK_G1;
     153        1464 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
     154          31 :     RefFlags |= AArch64MCExpr::VK_G0;
     155        1433 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
     156          12 :     RefFlags |= AArch64MCExpr::VK_HI12;
     157             : 
     158        7594 :   if (MO.getTargetFlags() & AArch64II::MO_NC)
     159        3289 :     RefFlags |= AArch64MCExpr::VK_NC;
     160             : 
     161             :   const MCExpr *Expr =
     162        7594 :       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
     163       15134 :   if (!MO.isJTI() && MO.getOffset())
     164          44 :     Expr = MCBinaryExpr::createAdd(
     165          44 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
     166             : 
     167             :   AArch64MCExpr::VariantKind RefKind;
     168             :   RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
     169        7594 :   Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
     170             : 
     171        7594 :   return MCOperand::createExpr(Expr);
     172             : }
     173             : 
     174          78 : MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
     175             :                                                      MCSymbol *Sym) const {
     176             :   AArch64MCExpr::VariantKind RefKind = AArch64MCExpr::VK_NONE;
     177          78 :   if (MO.getTargetFlags() & AArch64II::MO_TLS) {
     178          10 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
     179             :       RefKind = AArch64MCExpr::VK_SECREL_LO12;
     180           5 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     181             :              AArch64II::MO_HI12)
     182             :       RefKind = AArch64MCExpr::VK_SECREL_HI12;
     183             :   }
     184             :   const MCExpr *Expr =
     185          78 :       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
     186         156 :   if (!MO.isJTI() && MO.getOffset())
     187           0 :     Expr = MCBinaryExpr::createAdd(
     188           0 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
     189          78 :   Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
     190          78 :   return MCOperand::createExpr(Expr);
     191             : }
     192             : 
     193        9023 : MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
     194             :                                                  MCSymbol *Sym) const {
     195        9023 :   if (Printer.TM.getTargetTriple().isOSDarwin())
     196        1351 :     return lowerSymbolOperandDarwin(MO, Sym);
     197        7672 :   if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
     198          78 :     return lowerSymbolOperandCOFF(MO, Sym);
     199             : 
     200             :   assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
     201        7594 :   return lowerSymbolOperandELF(MO, Sym);
     202             : }
     203             : 
     204      223792 : bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
     205             :                                       MCOperand &MCOp) const {
     206      223792 :   switch (MO.getType()) {
     207           0 :   default:
     208           0 :     llvm_unreachable("unknown operand type");
     209             :   case MachineOperand::MO_Register:
     210             :     // Ignore all implicit register operands.
     211      171570 :     if (MO.isImplicit())
     212             :       return false;
     213      287274 :     MCOp = MCOperand::createReg(MO.getReg());
     214      143637 :     break;
     215             :   case MachineOperand::MO_RegisterMask:
     216             :     // Regmasks are like implicit defs.
     217             :     return false;
     218       40254 :   case MachineOperand::MO_Immediate:
     219       80508 :     MCOp = MCOperand::createImm(MO.getImm());
     220       40254 :     break;
     221        1315 :   case MachineOperand::MO_MachineBasicBlock:
     222        1315 :     MCOp = MCOperand::createExpr(
     223        1315 :         MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
     224        1315 :     break;
     225        8100 :   case MachineOperand::MO_GlobalAddress:
     226        8100 :     MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
     227        8100 :     break;
     228         566 :   case MachineOperand::MO_ExternalSymbol:
     229         566 :     MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
     230         566 :     break;
     231          31 :   case MachineOperand::MO_MCSymbol:
     232          31 :     MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
     233          31 :     break;
     234          56 :   case MachineOperand::MO_JumpTableIndex:
     235          56 :     MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
     236          56 :     break;
     237         254 :   case MachineOperand::MO_ConstantPoolIndex:
     238         254 :     MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
     239         254 :     break;
     240          16 :   case MachineOperand::MO_BlockAddress:
     241          16 :     MCOp = LowerSymbolOperand(
     242          16 :         MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
     243          16 :     break;
     244             :   }
     245             :   return true;
     246             : }
     247             : 
     248       71122 : void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
     249       71122 :   OutMI.setOpcode(MI->getOpcode());
     250             : 
     251      518172 :   for (const MachineOperand &MO : MI->operands()) {
     252             :     MCOperand MCOp;
     253      223525 :     if (lowerOperand(MO, MCOp))
     254             :       OutMI.addOperand(MCOp);
     255             :   }
     256       71122 : }

Generated by: LCOV version 1.13