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/IR/Module.h" |
28 | #include "llvm/MC/MCAsmInfo.h" |
29 | #include "llvm/MC/MCInst.h" |
30 | using namespace llvm; |
31 | |
32 | ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) : ARMBaseInstrInfo(STI) {} |
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(Op: MCOperand::createImm(Val: 0)); |
40 | NopInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL)); |
41 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 0)); |
42 | } else { |
43 | NopInst.setOpcode(ARM::MOVr); |
44 | NopInst.addOperand(Op: MCOperand::createReg(Reg: ARM::R0)); |
45 | NopInst.addOperand(Op: MCOperand::createReg(Reg: ARM::R0)); |
46 | NopInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL)); |
47 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 0)); |
48 | NopInst.addOperand(Op: MCOperand::createReg(Reg: 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, LoadImmOpc: ARM::MRC, LoadOpc: ARM::LDRi12); |
102 | return; |
103 | } |
104 | |
105 | const GlobalValue *GV = |
106 | cast<GlobalValue>(Val: (*MI->memoperands_begin())->getValue()); |
107 | |
108 | bool ForceELFGOTPIC = Subtarget.isTargetELF() && !GV->isDSOLocal(); |
109 | if (!Subtarget.useMovt() || ForceELFGOTPIC) { |
110 | // For ELF non-PIC, use GOT PIC code sequence as well because R_ARM_GOT_ABS |
111 | // does not have assembler support. |
112 | if (TM.isPositionIndependent() || ForceELFGOTPIC) |
113 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::LDRLIT_ga_pcrel, LoadOpc: ARM::LDRi12); |
114 | else |
115 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::LDRLIT_ga_abs, LoadOpc: ARM::LDRi12); |
116 | return; |
117 | } |
118 | |
119 | if (!TM.isPositionIndependent()) { |
120 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::MOVi32imm, LoadOpc: ARM::LDRi12); |
121 | return; |
122 | } |
123 | |
124 | if (!Subtarget.isGVIndirectSymbol(GV)) { |
125 | expandLoadStackGuardBase(MI, LoadImmOpc: ARM::MOV_ga_pcrel, LoadOpc: ARM::LDRi12); |
126 | return; |
127 | } |
128 | |
129 | MachineBasicBlock &MBB = *MI->getParent(); |
130 | DebugLoc DL = MI->getDebugLoc(); |
131 | Register Reg = MI->getOperand(i: 0).getReg(); |
132 | MachineInstrBuilder MIB; |
133 | |
134 | MIB = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: ARM::MOV_ga_pcrel_ldr), DestReg: Reg) |
135 | .addGlobalAddress(GV, Offset: 0, TargetFlags: ARMII::MO_NONLAZY); |
136 | auto Flags = MachineMemOperand::MOLoad | |
137 | MachineMemOperand::MODereferenceable | |
138 | MachineMemOperand::MOInvariant; |
139 | MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( |
140 | PtrInfo: MachinePointerInfo::getGOT(MF&: *MBB.getParent()), F: Flags, Size: 4, BaseAlignment: Align(4)); |
141 | MIB.addMemOperand(MMO); |
142 | BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: ARM::LDRi12), DestReg: Reg) |
143 | .addReg(RegNo: Reg, flags: RegState::Kill) |
144 | .addImm(Val: 0) |
145 | .cloneMemRefs(OtherMI: *MI) |
146 | .add(MOs: predOps(Pred: ARMCC::AL)); |
147 | } |
148 | |