brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · c040904 Raw
246 lines · cpp
1//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains code to lower ARM MachineInstrs to their corresponding10// MCInst records.11//12//===----------------------------------------------------------------------===//13 14#include "ARM.h"15#include "ARMAsmPrinter.h"16#include "ARMBaseInstrInfo.h"17#include "ARMMachineFunctionInfo.h"18#include "ARMSubtarget.h"19#include "MCTargetDesc/ARMAddressingModes.h"20#include "MCTargetDesc/ARMBaseInfo.h"21#include "MCTargetDesc/ARMMCAsmInfo.h"22#include "llvm/ADT/APFloat.h"23#include "llvm/CodeGen/MachineBasicBlock.h"24#include "llvm/CodeGen/MachineInstr.h"25#include "llvm/CodeGen/MachineOperand.h"26#include "llvm/IR/Constants.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCExpr.h"29#include "llvm/MC/MCInst.h"30#include "llvm/MC/MCInstBuilder.h"31#include "llvm/MC/MCStreamer.h"32#include "llvm/Support/ErrorHandling.h"33#include <cassert>34#include <cstdint>35 36using namespace llvm;37 38MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,39                                      const MCSymbol *Symbol) {40  auto Specifier = ARM::S_None;41  if (MO.getTargetFlags() & ARMII::MO_SBREL)42    Specifier = ARM::S_SBREL;43 44  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);45  switch (MO.getTargetFlags() & ARMII::MO_OPTION_MASK) {46  default:47    llvm_unreachable("Unknown target flag on symbol operand");48  case ARMII::MO_NO_FLAG:49    break;50  case ARMII::MO_LO16:51    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);52    Expr = ARM::createLower16(Expr, OutContext);53    break;54  case ARMII::MO_HI16:55    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);56    Expr = ARM::createUpper16(Expr, OutContext);57    break;58  case ARMII::MO_LO_0_7:59    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);60    Expr = ARM::createLower0_7(Expr, OutContext);61    break;62  case ARMII::MO_LO_8_15:63    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);64    Expr = ARM::createLower8_15(Expr, OutContext);65    break;66  case ARMII::MO_HI_0_7:67    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);68    Expr = ARM::createUpper0_7(Expr, OutContext);69    break;70  case ARMII::MO_HI_8_15:71    Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);72    Expr = ARM::createUpper8_15(Expr, OutContext);73    break;74  }75 76  if (!MO.isJTI() && MO.getOffset())77    Expr = MCBinaryExpr::createAdd(Expr,78                                   MCConstantExpr::create(MO.getOffset(),79                                                          OutContext),80                                   OutContext);81  return MCOperand::createExpr(Expr);82 83}84 85bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,86                                 MCOperand &MCOp) {87  switch (MO.getType()) {88  default: llvm_unreachable("unknown operand type");89  case MachineOperand::MO_Register:90    // Ignore all implicit register operands.91    if (MO.isImplicit())92      return false;93    assert(!MO.getSubReg() && "Subregs should be eliminated!");94    MCOp = MCOperand::createReg(MO.getReg());95    break;96  case MachineOperand::MO_Immediate:97    MCOp = MCOperand::createImm(MO.getImm());98    break;99  case MachineOperand::MO_MachineBasicBlock:100    MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(101        MO.getMBB()->getSymbol(), OutContext));102    break;103  case MachineOperand::MO_GlobalAddress:104    MCOp = GetSymbolRef(MO,105                        GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));106    break;107  case MachineOperand::MO_ExternalSymbol:108    MCOp = GetSymbolRef(MO,109                        GetExternalSymbolSymbol(MO.getSymbolName()));110    break;111  case MachineOperand::MO_JumpTableIndex:112    MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));113    break;114  case MachineOperand::MO_ConstantPoolIndex:115    assert(!MF->getSubtarget<ARMSubtarget>().genExecuteOnly() &&116           "execute-only should not generate constant pools");117    MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));118    break;119  case MachineOperand::MO_BlockAddress:120    MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));121    break;122  case MachineOperand::MO_FPImmediate: {123    APFloat Val = MO.getFPImm()->getValueAPF();124    bool ignored;125    Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &ignored);126    MCOp = MCOperand::createDFPImm(bit_cast<uint64_t>(Val.convertToDouble()));127    break;128  }129  case MachineOperand::MO_RegisterMask:130    // Ignore call clobbers.131    return false;132  }133  return true;134}135 136void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,137                                        ARMAsmPrinter &AP) {138  OutMI.setOpcode(MI->getOpcode());139 140  // In the MC layer, we keep modified immediates in their encoded form141  bool EncodeImms = false;142  switch (MI->getOpcode()) {143  default: break;144  case ARM::MOVi:145  case ARM::MVNi:146  case ARM::CMPri:147  case ARM::CMNri:148  case ARM::TSTri:149  case ARM::TEQri:150  case ARM::MSRi:151  case ARM::ADCri:152  case ARM::ADDri:153  case ARM::ADDSri:154  case ARM::SBCri:155  case ARM::SUBri:156  case ARM::SUBSri:157  case ARM::ANDri:158  case ARM::ORRri:159  case ARM::EORri:160  case ARM::BICri:161  case ARM::RSBri:162  case ARM::RSBSri:163  case ARM::RSCri:164    EncodeImms = true;165    break;166  }167 168  for (const MachineOperand &MO : MI->operands()) {169    MCOperand MCOp;170    if (AP.lowerOperand(MO, MCOp)) {171      if (MCOp.isImm() && EncodeImms) {172        int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());173        if (Enc != -1)174          MCOp.setImm(Enc);175      }176      OutMI.addOperand(MCOp);177    }178  }179}180 181void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)182{183  const MachineFunction *MF = MI.getParent()->getParent();184  if (MF->getInfo<ARMFunctionInfo>()->isThumbFunction()) {185    const Function &Fn = MF->getFunction();186    Fn.getContext().diagnose(DiagnosticInfoUnsupported(187        Fn,188        "An attempt to perform XRay instrumentation for a Thumb function (not "189        "supported). Detected when emitting a sled.",190        MI.getDebugLoc()));191    return;192  }193  static const int8_t NoopsInSledCount = 6;194  // We want to emit the following pattern:195  //196  // .Lxray_sled_N:197  //   ALIGN198  //   B #20199  //   ; 6 NOP instructions (24 bytes)200  // .tmpN201  //202  // We need the 24 bytes (6 instructions) because at runtime, we'd be patching203  // over the full 28 bytes (7 instructions) with the following pattern:204  //205  //   PUSH{ r0, lr }206  //   MOVW r0, #<lower 16 bits of function ID>207  //   MOVT r0, #<higher 16 bits of function ID>208  //   MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>209  //   MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>210  //   BLX ip211  //   POP{ r0, lr }212  //213  OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());214  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);215  OutStreamer->emitLabel(CurSled);216  auto Target = OutContext.createTempSymbol();217 218  // Emit "B #20" instruction, which jumps over the next 24 bytes (because219  // register pc is 8 bytes ahead of the jump instruction by the moment CPU220  // is executing it).221  // By analogy to ARMAsmPrinter::lowerPseudoInstExpansion() |case ARM::B|.222  // It is not clear why |addReg(0)| is needed (the last operand).223  EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)224    .addImm(ARMCC::AL).addReg(0));225 226  emitNops(NoopsInSledCount);227 228  OutStreamer->emitLabel(Target);229  recordSled(CurSled, MI, Kind, 2);230}231 232void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)233{234  EmitSled(MI, SledKind::FUNCTION_ENTER);235}236 237void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)238{239  EmitSled(MI, SledKind::FUNCTION_EXIT);240}241 242void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)243{244  EmitSled(MI, SledKind::TAIL_CALL);245}246