145 lines · cpp
1//===-- ARMInstrInfo.cpp - ARM Instruction Information --------------------===//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 the ARM implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "ARMInstrInfo.h"14#include "ARM.h"15#include "ARMConstantPoolValue.h"16#include "ARMMachineFunctionInfo.h"17#include "ARMTargetMachine.h"18#include "llvm/CodeGen/LiveVariables.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineJumpTableInfo.h"22#include "llvm/IR/Function.h"23#include "llvm/IR/GlobalVariable.h"24#include "llvm/IR/Module.h"25#include "llvm/MC/MCInst.h"26using namespace llvm;27 28ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)29 : ARMBaseInstrInfo(STI, RI) {}30 31/// Return the noop instruction to use for a noop.32MCInst ARMInstrInfo::getNop() const {33 MCInst NopInst;34 if (hasNOP()) {35 NopInst.setOpcode(ARM::HINT);36 NopInst.addOperand(MCOperand::createImm(0));37 NopInst.addOperand(MCOperand::createImm(ARMCC::AL));38 NopInst.addOperand(MCOperand::createReg(0));39 } else {40 NopInst.setOpcode(ARM::MOVr);41 NopInst.addOperand(MCOperand::createReg(ARM::R0));42 NopInst.addOperand(MCOperand::createReg(ARM::R0));43 NopInst.addOperand(MCOperand::createImm(ARMCC::AL));44 NopInst.addOperand(MCOperand::createReg(0));45 NopInst.addOperand(MCOperand::createReg(0));46 }47 return NopInst;48}49 50unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {51 switch (Opc) {52 default:53 break;54 case ARM::LDR_PRE_IMM:55 case ARM::LDR_PRE_REG:56 case ARM::LDR_POST_IMM:57 case ARM::LDR_POST_REG:58 return ARM::LDRi12;59 case ARM::LDRH_PRE:60 case ARM::LDRH_POST:61 return ARM::LDRH;62 case ARM::LDRB_PRE_IMM:63 case ARM::LDRB_PRE_REG:64 case ARM::LDRB_POST_IMM:65 case ARM::LDRB_POST_REG:66 return ARM::LDRBi12;67 case ARM::LDRSH_PRE:68 case ARM::LDRSH_POST:69 return ARM::LDRSH;70 case ARM::LDRSB_PRE:71 case ARM::LDRSB_POST:72 return ARM::LDRSB;73 case ARM::STR_PRE_IMM:74 case ARM::STR_PRE_REG:75 case ARM::STR_POST_IMM:76 case ARM::STR_POST_REG:77 return ARM::STRi12;78 case ARM::STRH_PRE:79 case ARM::STRH_POST:80 return ARM::STRH;81 case ARM::STRB_PRE_IMM:82 case ARM::STRB_PRE_REG:83 case ARM::STRB_POST_IMM:84 case ARM::STRB_POST_REG:85 return ARM::STRBi12;86 }87 88 return 0;89}90 91void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const {92 MachineFunction &MF = *MI->getParent()->getParent();93 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();94 const TargetMachine &TM = MF.getTarget();95 Module &M = *MF.getFunction().getParent();96 97 if (M.getStackProtectorGuard() == "tls") {98 expandLoadStackGuardBase(MI, ARM::MRC, ARM::LDRi12);99 return;100 }101 102 const GlobalValue *GV =103 cast<GlobalValue>((*MI->memoperands_begin())->getValue());104 105 bool ForceELFGOTPIC = Subtarget.isTargetELF() && !GV->isDSOLocal();106 if (!Subtarget.useMovt() || ForceELFGOTPIC) {107 // For ELF non-PIC, use GOT PIC code sequence as well because R_ARM_GOT_ABS108 // does not have assembler support.109 if (TM.isPositionIndependent() || ForceELFGOTPIC)110 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12);111 else112 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12);113 return;114 }115 116 if (!TM.isPositionIndependent()) {117 expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12);118 return;119 }120 121 if (!Subtarget.isGVIndirectSymbol(GV)) {122 expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12);123 return;124 }125 126 MachineBasicBlock &MBB = *MI->getParent();127 DebugLoc DL = MI->getDebugLoc();128 Register Reg = MI->getOperand(0).getReg();129 MachineInstrBuilder MIB;130 131 MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg)132 .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY);133 auto Flags = MachineMemOperand::MOLoad |134 MachineMemOperand::MODereferenceable |135 MachineMemOperand::MOInvariant;136 MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand(137 MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, Align(4));138 MIB.addMemOperand(MMO);139 BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg)140 .addReg(Reg, RegState::Kill)141 .addImm(0)142 .cloneMemRefs(*MI)143 .add(predOps(ARMCC::AL));144}145