LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64MCInstLower.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 107 118 90.7 %
Date: 2017-09-14 15:23:50 Functions: 8 9 88.9 %
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/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         988 : AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
      32        1976 :     : Ctx(ctx), Printer(printer) {}
      33             : 
      34             : MCSymbol *
      35           0 : AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
      36        6071 :   return Printer.getSymbol(MO.getGlobal());
      37             : }
      38             : 
      39             : MCSymbol *
      40         484 : AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
      41         968 :   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
      42             : }
      43             : 
      44        1363 : 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        1363 :   MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
      49        1363 :   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
      50         360 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      51             :       RefKind = MCSymbolRefExpr::VK_GOTPAGE;
      52         180 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      53             :              AArch64II::MO_PAGEOFF)
      54             :       RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
      55             :     else
      56           0 :       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
      57        1003 :   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
      58          44 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      59             :       RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
      60          22 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      61             :              AArch64II::MO_PAGEOFF)
      62             :       RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
      63             :     else
      64           0 :       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
      65             :   } else {
      66         959 :     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
      67             :       RefKind = MCSymbolRefExpr::VK_PAGE;
      68         724 :     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
      69             :              AArch64II::MO_PAGEOFF)
      70         374 :       RefKind = MCSymbolRefExpr::VK_PAGEOFF;
      71             :   }
      72        1363 :   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
      73        2724 :   if (!MO.isJTI() && MO.getOffset())
      74           0 :     Expr = MCBinaryExpr::createAdd(
      75           0 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
      76        1363 :   return MCOperand::createExpr(Expr);
      77             : }
      78             : 
      79        5549 : MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
      80             :                                                     MCSymbol *Sym) const {
      81        5549 :   uint32_t RefFlags = 0;
      82             : 
      83        5549 :   if (MO.getTargetFlags() & AArch64II::MO_GOT)
      84             :     RefFlags |= AArch64MCExpr::VK_GOT;
      85        5433 :   else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
      86             :     TLSModel::Model Model;
      87         110 :     if (MO.isGlobal()) {
      88          92 :       const GlobalValue *GV = MO.getGlobal();
      89          92 :       Model = Printer.TM.getTLSModel(GV);
      90          92 :       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          68 :     switch (Model) {
     103           8 :     case TLSModel::InitialExec:
     104           8 :       RefFlags |= AArch64MCExpr::VK_GOTTPREL;
     105           8 :       break;
     106          14 :     case TLSModel::LocalExec:
     107          14 :       RefFlags |= AArch64MCExpr::VK_TPREL;
     108          14 :       break;
     109          16 :     case TLSModel::LocalDynamic:
     110          16 :       RefFlags |= AArch64MCExpr::VK_DTPREL;
     111          16 :       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        5549 :   if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
     123        1852 :     RefFlags |= AArch64MCExpr::VK_PAGE;
     124        3697 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
     125             :            AArch64II::MO_PAGEOFF)
     126        2258 :     RefFlags |= AArch64MCExpr::VK_PAGEOFF;
     127        1439 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
     128          31 :     RefFlags |= AArch64MCExpr::VK_G3;
     129        1408 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
     130          31 :     RefFlags |= AArch64MCExpr::VK_G2;
     131        1377 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
     132          31 :     RefFlags |= AArch64MCExpr::VK_G1;
     133        1346 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
     134          31 :     RefFlags |= AArch64MCExpr::VK_G0;
     135        1315 :   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
     136          15 :     RefFlags |= AArch64MCExpr::VK_HI12;
     137             : 
     138        5549 :   if (MO.getTargetFlags() & AArch64II::MO_NC)
     139        2327 :     RefFlags |= AArch64MCExpr::VK_NC;
     140             : 
     141             :   const MCExpr *Expr =
     142        5549 :       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
     143       11048 :   if (!MO.isJTI() && MO.getOffset())
     144           0 :     Expr = MCBinaryExpr::createAdd(
     145           0 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
     146             : 
     147             :   AArch64MCExpr::VariantKind RefKind;
     148        5549 :   RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
     149        5549 :   Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
     150             : 
     151        5549 :   return MCOperand::createExpr(Expr);
     152             : }
     153             : 
     154          10 : MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
     155             :                                                      MCSymbol *Sym) const {
     156          10 :   MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
     157          10 :   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
     158          20 :   if (!MO.isJTI() && MO.getOffset())
     159           0 :     Expr = MCBinaryExpr::createAdd(
     160           0 :         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
     161          10 :   return MCOperand::createExpr(Expr);
     162             : }
     163             : 
     164        6922 : MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
     165             :                                                  MCSymbol *Sym) const {
     166       12481 :   if (Printer.TM.getTargetTriple().isOSDarwin())
     167        1363 :     return lowerSymbolOperandDarwin(MO, Sym);
     168        5559 :   if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
     169          10 :     return lowerSymbolOperandCOFF(MO, Sym);
     170             : 
     171             :   assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
     172        5549 :   return lowerSymbolOperandELF(MO, Sym);
     173             : }
     174             : 
     175      193268 : bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
     176             :                                       MCOperand &MCOp) const {
     177      193268 :   switch (MO.getType()) {
     178           0 :   default:
     179           0 :     llvm_unreachable("unknown operand type");
     180      147763 :   case MachineOperand::MO_Register:
     181             :     // Ignore all implicit register operands.
     182      147763 :     if (MO.isImplicit())
     183             :       return false;
     184      245960 :     MCOp = MCOperand::createReg(MO.getReg());
     185      122980 :     break;
     186             :   case MachineOperand::MO_RegisterMask:
     187             :     // Regmasks are like implicit defs.
     188             :     return false;
     189       35778 :   case MachineOperand::MO_Immediate:
     190       71556 :     MCOp = MCOperand::createImm(MO.getImm());
     191       35778 :     break;
     192        1284 :   case MachineOperand::MO_MachineBasicBlock:
     193        1284 :     MCOp = MCOperand::createExpr(
     194        2568 :         MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
     195        1284 :     break;
     196        6071 :   case MachineOperand::MO_GlobalAddress:
     197        6071 :     MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
     198        6071 :     break;
     199         484 :   case MachineOperand::MO_ExternalSymbol:
     200         484 :     MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
     201         484 :     break;
     202          31 :   case MachineOperand::MO_MCSymbol:
     203          31 :     MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
     204          31 :     break;
     205          52 :   case MachineOperand::MO_JumpTableIndex:
     206          52 :     MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
     207          52 :     break;
     208         268 :   case MachineOperand::MO_ConstantPoolIndex:
     209         268 :     MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
     210         268 :     break;
     211          16 :   case MachineOperand::MO_BlockAddress:
     212          16 :     MCOp = LowerSymbolOperand(
     213          16 :         MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
     214          16 :     break;
     215             :   }
     216             :   return true;
     217             : }
     218             : 
     219       60857 : void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
     220      182571 :   OutMI.setOpcode(MI->getOpcode());
     221             : 
     222      253887 :   for (const MachineOperand &MO : MI->operands()) {
     223      193030 :     MCOperand MCOp;
     224      193030 :     if (lowerOperand(MO, MCOp))
     225             :       OutMI.addOperand(MCOp);
     226             :   }
     227       60857 : }

Generated by: LCOV version 1.13