LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMMCInstLower.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 64 85 75.3 %
Date: 2018-10-20 13:21:21 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- ARMMCInstLower.cpp - Convert ARM 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 ARM MachineInstrs to their corresponding
      11             : // MCInst records.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "ARM.h"
      16             : #include "ARMAsmPrinter.h"
      17             : #include "ARMBaseInstrInfo.h"
      18             : #include "ARMMachineFunctionInfo.h"
      19             : #include "ARMSubtarget.h"
      20             : #include "MCTargetDesc/ARMAddressingModes.h"
      21             : #include "MCTargetDesc/ARMBaseInfo.h"
      22             : #include "MCTargetDesc/ARMMCExpr.h"
      23             : #include "llvm/ADT/APFloat.h"
      24             : #include "llvm/CodeGen/MachineBasicBlock.h"
      25             : #include "llvm/CodeGen/MachineInstr.h"
      26             : #include "llvm/CodeGen/MachineOperand.h"
      27             : #include "llvm/IR/Constants.h"
      28             : #include "llvm/MC/MCContext.h"
      29             : #include "llvm/MC/MCExpr.h"
      30             : #include "llvm/MC/MCInst.h"
      31             : #include "llvm/MC/MCInstBuilder.h"
      32             : #include "llvm/MC/MCStreamer.h"
      33             : #include "llvm/Support/ErrorHandling.h"
      34             : #include <cassert>
      35             : #include <cstdint>
      36             : 
      37             : using namespace llvm;
      38             : 
      39       12776 : MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
      40             :                                       const MCSymbol *Symbol) {
      41             :   MCSymbolRefExpr::VariantKind SymbolVariant = MCSymbolRefExpr::VK_None;
      42       12776 :   if (MO.getTargetFlags() & ARMII::MO_SBREL)
      43             :     SymbolVariant = MCSymbolRefExpr::VK_ARM_SBREL;
      44             : 
      45             :   const MCExpr *Expr =
      46       12776 :       MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
      47       12776 :   switch (MO.getTargetFlags() & ARMII::MO_OPTION_MASK) {
      48           0 :   default:
      49           0 :     llvm_unreachable("Unknown target flag on symbol operand");
      50             :   case ARMII::MO_NO_FLAG:
      51             :     break;
      52         990 :   case ARMII::MO_LO16:
      53             :     Expr =
      54         990 :         MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
      55         990 :     Expr = ARMMCExpr::createLower16(Expr, OutContext);
      56             :     break;
      57         990 :   case ARMII::MO_HI16:
      58             :     Expr =
      59         990 :         MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
      60         990 :     Expr = ARMMCExpr::createUpper16(Expr, OutContext);
      61             :     break;
      62             :   }
      63             : 
      64       12776 :   if (!MO.isJTI() && MO.getOffset())
      65           0 :     Expr = MCBinaryExpr::createAdd(Expr,
      66           0 :                                    MCConstantExpr::create(MO.getOffset(),
      67             :                                                           OutContext),
      68             :                                    OutContext);
      69       12776 :   return MCOperand::createExpr(Expr);
      70             : 
      71             : }
      72             : 
      73      711052 : bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
      74             :                                  MCOperand &MCOp) {
      75      711052 :   switch (MO.getType()) {
      76           0 :   default: llvm_unreachable("unknown operand type");
      77             :   case MachineOperand::MO_Register:
      78             :     // Ignore all non-CPSR implicit register operands.
      79      492920 :     if (MO.isImplicit() && MO.getReg() != ARM::CPSR)
      80             :       return false;
      81             :     assert(!MO.getSubReg() && "Subregs should be eliminated!");
      82      421439 :     MCOp = MCOperand::createReg(MO.getReg());
      83      421439 :     break;
      84      195101 :   case MachineOperand::MO_Immediate:
      85      195101 :     MCOp = MCOperand::createImm(MO.getImm());
      86      195101 :     break;
      87        2779 :   case MachineOperand::MO_MachineBasicBlock:
      88        2779 :     MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(
      89        2779 :         MO.getMBB()->getSymbol(), OutContext));
      90        2779 :     break;
      91             :   case MachineOperand::MO_GlobalAddress:
      92             :     MCOp = GetSymbolRef(MO,
      93        6534 :                         GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
      94        6534 :     break;
      95        3389 :   case MachineOperand::MO_ExternalSymbol:
      96             :     MCOp = GetSymbolRef(MO,
      97        6778 :                         GetExternalSymbolSymbol(MO.getSymbolName()));
      98        3389 :     break;
      99           0 :   case MachineOperand::MO_JumpTableIndex:
     100           0 :     MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
     101           0 :     break;
     102        2853 :   case MachineOperand::MO_ConstantPoolIndex:
     103        2853 :     if (Subtarget->genExecuteOnly())
     104           0 :       llvm_unreachable("execute-only should not generate constant pools");
     105        2853 :     MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
     106        2853 :     break;
     107           0 :   case MachineOperand::MO_BlockAddress:
     108           0 :     MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
     109           0 :     break;
     110           0 :   case MachineOperand::MO_FPImmediate: {
     111           0 :     APFloat Val = MO.getFPImm()->getValueAPF();
     112             :     bool ignored;
     113           0 :     Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &ignored);
     114           0 :     MCOp = MCOperand::createFPImm(Val.convertToDouble());
     115             :     break;
     116             :   }
     117             :   case MachineOperand::MO_RegisterMask:
     118             :     // Ignore call clobbers.
     119             :     return false;
     120             :   }
     121             :   return true;
     122             : }
     123             : 
     124      128359 : void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
     125             :                                         ARMAsmPrinter &AP) {
     126      128359 :   OutMI.setOpcode(MI->getOpcode());
     127             : 
     128             :   // In the MC layer, we keep modified immediates in their encoded form
     129             :   bool EncodeImms = false;
     130      128359 :   switch (MI->getOpcode()) {
     131             :   default: break;
     132       10072 :   case ARM::MOVi:
     133             :   case ARM::MVNi:
     134             :   case ARM::CMPri:
     135             :   case ARM::CMNri:
     136             :   case ARM::TSTri:
     137             :   case ARM::TEQri:
     138             :   case ARM::MSRi:
     139             :   case ARM::ADCri:
     140             :   case ARM::ADDri:
     141             :   case ARM::ADDSri:
     142             :   case ARM::SBCri:
     143             :   case ARM::SUBri:
     144             :   case ARM::SUBSri:
     145             :   case ARM::ANDri:
     146             :   case ARM::ORRri:
     147             :   case ARM::EORri:
     148             :   case ARM::BICri:
     149             :   case ARM::RSBri:
     150             :   case ARM::RSBSri:
     151             :   case ARM::RSCri:
     152             :     EncodeImms = true;
     153       10072 :     break;
     154             :   }
     155             : 
     156      806827 :   for (const MachineOperand &MO : MI->operands()) {
     157             :     MCOperand MCOp;
     158      678468 :     if (AP.lowerOperand(MO, MCOp)) {
     159      602995 :       if (MCOp.isImm() && EncodeImms) {
     160       20144 :         int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
     161       20144 :         if (Enc != -1)
     162       20144 :           MCOp.setImm(Enc);
     163             :       }
     164             :       OutMI.addOperand(MCOp);
     165             :     }
     166             :   }
     167      128359 : }
     168             : 
     169          16 : void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
     170             : {
     171          16 :   if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
     172          16 :     ->isThumbFunction())
     173             :   {
     174           0 :     MI.emitError("An attempt to perform XRay instrumentation for a"
     175             :       " Thumb function (not supported). Detected when emitting a sled.");
     176           0 :     return;
     177             :   }
     178             :   static const int8_t NoopsInSledCount = 6;
     179             :   // We want to emit the following pattern:
     180             :   //
     181             :   // .Lxray_sled_N:
     182             :   //   ALIGN
     183             :   //   B #20
     184             :   //   ; 6 NOP instructions (24 bytes)
     185             :   // .tmpN
     186             :   //
     187             :   // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
     188             :   // over the full 28 bytes (7 instructions) with the following pattern:
     189             :   //
     190             :   //   PUSH{ r0, lr }
     191             :   //   MOVW r0, #<lower 16 bits of function ID>
     192             :   //   MOVT r0, #<higher 16 bits of function ID>
     193             :   //   MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
     194             :   //   MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
     195             :   //   BLX ip
     196             :   //   POP{ r0, lr }
     197             :   //
     198          16 :   OutStreamer->EmitCodeAlignment(4);
     199          32 :   auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
     200          16 :   OutStreamer->EmitLabel(CurSled);
     201          16 :   auto Target = OutContext.createTempSymbol();
     202             : 
     203             :   // Emit "B #20" instruction, which jumps over the next 24 bytes (because
     204             :   // register pc is 8 bytes ahead of the jump instruction by the moment CPU
     205             :   // is executing it).
     206             :   // By analogy to ARMAsmPrinter::emitPseudoExpansionLowering() |case ARM::B|.
     207             :   // It is not clear why |addReg(0)| is needed (the last operand).
     208          48 :   EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
     209             :     .addImm(ARMCC::AL).addReg(0));
     210             : 
     211             :   MCInst Noop;
     212          16 :   Subtarget->getInstrInfo()->getNoop(Noop);
     213         112 :   for (int8_t I = 0; I < NoopsInSledCount; I++)
     214          96 :     OutStreamer->EmitInstruction(Noop, getSubtargetInfo());
     215             : 
     216          16 :   OutStreamer->EmitLabel(Target);
     217          16 :   recordSled(CurSled, MI, Kind);
     218             : }
     219             : 
     220           8 : void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
     221             : {
     222           8 :   EmitSled(MI, SledKind::FUNCTION_ENTER);
     223           8 : }
     224             : 
     225           8 : void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
     226             : {
     227           8 :   EmitSled(MI, SledKind::FUNCTION_EXIT);
     228           8 : }
     229             : 
     230           0 : void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
     231             : {
     232           0 :   EmitSled(MI, SledKind::TAIL_CALL);
     233           0 : }

Generated by: LCOV version 1.13