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

Generated by: LCOV version 1.13