| 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(Op: MCOperand::createImm(Val: 0)); |
| 36 | NopInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL)); |
| 37 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 0)); |
| 38 | } else { |
| 39 | NopInst.setOpcode(ARM::MOVr); |
| 40 | NopInst.addOperand(Op: MCOperand::createReg(Reg: ARM::R0)); |
| 41 | NopInst.addOperand(Op: MCOperand::createReg(Reg: ARM::R0)); |
| 42 | NopInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL)); |
| 43 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 0)); |
| 44 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 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, LoadImmOpc: ARM::MRC, LoadOpc: ARM::LDRi12); |
| 98 | return; |
| 99 | } |
| 100 | |
| 101 | const GlobalValue *GV = |
| 102 | cast<GlobalValue>(Val: (*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, LoadImmOpc: ARM::LDRLIT_ga_pcrel, LoadOpc: ARM::LDRi12); |
| 110 | else |
| 111 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::LDRLIT_ga_abs, LoadOpc: ARM::LDRi12); |
| 112 | return; |
| 113 | } |
| 114 | |
| 115 | if (!TM.isPositionIndependent()) { |
| 116 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::MOVi32imm, LoadOpc: ARM::LDRi12); |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | if (!Subtarget.isGVIndirectSymbol(GV)) { |
| 121 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::MOV_ga_pcrel, LoadOpc: ARM::LDRi12); |
| 122 | return; |
| 123 | } |
| 124 | |
| 125 | MachineBasicBlock &MBB = *MI->getParent(); |
| 126 | DebugLoc DL = MI->getDebugLoc(); |
| 127 | Register Reg = MI->getOperand(i: 0).getReg(); |
| 128 | MachineInstrBuilder MIB; |
| 129 | |
| 130 | MIB = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: ARM::MOV_ga_pcrel_ldr), DestReg: Reg) |
| 131 | .addGlobalAddress(GV, Offset: 0, TargetFlags: ARMII::MO_NONLAZY); |
| 132 | auto Flags = MachineMemOperand::MOLoad | |
| 133 | MachineMemOperand::MODereferenceable | |
| 134 | MachineMemOperand::MOInvariant; |
| 135 | MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( |
| 136 | PtrInfo: MachinePointerInfo::getGOT(MF&: *MBB.getParent()), F: Flags, Size: 4, BaseAlignment: Align(4)); |
| 137 | MIB.addMemOperand(MMO); |
| 138 | BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: ARM::LDRi12), DestReg: Reg) |
| 139 | .addReg(RegNo: Reg, flags: RegState::Kill) |
| 140 | .addImm(Val: 0) |
| 141 | .cloneMemRefs(OtherMI: *MI) |
| 142 | .add(MOs: predOps(Pred: ARMCC::AL)); |
| 143 | } |
| 144 | |