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