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-exception 6 // 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 "MCTargetDesc/ARMAddressingModes.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/CodeGen/LiveVariables.h" 21 #include "llvm/CodeGen/MachineFrameInfo.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineJumpTableInfo.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/GlobalVariable.h" 27 #include "llvm/MC/MCAsmInfo.h" 28 #include "llvm/MC/MCInst.h" 29 using namespace llvm; 30 31 ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) 32 : ARMBaseInstrInfo(STI), RI() {} 33 34 /// Return the noop instruction to use for a noop. 35 MCInst ARMInstrInfo::getNop() const { 36 MCInst NopInst; 37 if (hasNOP()) { 38 NopInst.setOpcode(ARM::HINT); 39 NopInst.addOperand(MCOperand::createImm(0)); 40 NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); 41 NopInst.addOperand(MCOperand::createReg(0)); 42 } else { 43 NopInst.setOpcode(ARM::MOVr); 44 NopInst.addOperand(MCOperand::createReg(ARM::R0)); 45 NopInst.addOperand(MCOperand::createReg(ARM::R0)); 46 NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); 47 NopInst.addOperand(MCOperand::createReg(0)); 48 NopInst.addOperand(MCOperand::createReg(0)); 49 } 50 return NopInst; 51 } 52 53 unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { 54 switch (Opc) { 55 default: 56 break; 57 case ARM::LDR_PRE_IMM: 58 case ARM::LDR_PRE_REG: 59 case ARM::LDR_POST_IMM: 60 case ARM::LDR_POST_REG: 61 return ARM::LDRi12; 62 case ARM::LDRH_PRE: 63 case ARM::LDRH_POST: 64 return ARM::LDRH; 65 case ARM::LDRB_PRE_IMM: 66 case ARM::LDRB_PRE_REG: 67 case ARM::LDRB_POST_IMM: 68 case ARM::LDRB_POST_REG: 69 return ARM::LDRBi12; 70 case ARM::LDRSH_PRE: 71 case ARM::LDRSH_POST: 72 return ARM::LDRSH; 73 case ARM::LDRSB_PRE: 74 case ARM::LDRSB_POST: 75 return ARM::LDRSB; 76 case ARM::STR_PRE_IMM: 77 case ARM::STR_PRE_REG: 78 case ARM::STR_POST_IMM: 79 case ARM::STR_POST_REG: 80 return ARM::STRi12; 81 case ARM::STRH_PRE: 82 case ARM::STRH_POST: 83 return ARM::STRH; 84 case ARM::STRB_PRE_IMM: 85 case ARM::STRB_PRE_REG: 86 case ARM::STRB_POST_IMM: 87 case ARM::STRB_POST_REG: 88 return ARM::STRBi12; 89 } 90 91 return 0; 92 } 93 94 void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const { 95 MachineFunction &MF = *MI->getParent()->getParent(); 96 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>(); 97 const TargetMachine &TM = MF.getTarget(); 98 Module &M = *MF.getFunction().getParent(); 99 100 if (M.getStackProtectorGuard() == "tls") { 101 expandLoadStackGuardBase(MI, ARM::MRC, ARM::LDRi12); 102 return; 103 } 104 105 const GlobalValue *GV = 106 cast<GlobalValue>((*MI->memoperands_begin())->getValue()); 107 108 if (!Subtarget.useMovt() || Subtarget.isGVInGOT(GV)) { 109 if (TM.isPositionIndependent()) 110 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12); 111 else 112 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