]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- ARMInstrInfo.cpp - ARM Instruction Information --------------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file contains the ARM implementation of the TargetInstrInfo class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "ARMInstrInfo.h" | |
15 | #include "ARM.h" | |
16 | #include "ARMConstantPoolValue.h" | |
17 | #include "ARMMachineFunctionInfo.h" | |
18 | #include "ARMTargetMachine.h" | |
19 | #include "MCTargetDesc/ARMAddressingModes.h" | |
20 | #include "llvm/ADT/STLExtras.h" | |
21 | #include "llvm/CodeGen/LiveVariables.h" | |
22 | #include "llvm/CodeGen/MachineFrameInfo.h" | |
23 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
24 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | |
1a4d82fc | 25 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
970d7e83 LB |
26 | #include "llvm/IR/Function.h" |
27 | #include "llvm/IR/GlobalVariable.h" | |
223e47cc LB |
28 | #include "llvm/MC/MCAsmInfo.h" |
29 | #include "llvm/MC/MCInst.h" | |
30 | using namespace llvm; | |
31 | ||
32 | ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) | |
1a4d82fc | 33 | : ARMBaseInstrInfo(STI), RI(STI) { |
223e47cc LB |
34 | } |
35 | ||
36 | /// getNoopForMachoTarget - Return the noop instruction to use for a noop. | |
37 | void ARMInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { | |
38 | if (hasNOP()) { | |
39 | NopInst.setOpcode(ARM::HINT); | |
40 | NopInst.addOperand(MCOperand::CreateImm(0)); | |
41 | NopInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); | |
42 | NopInst.addOperand(MCOperand::CreateReg(0)); | |
43 | } else { | |
44 | NopInst.setOpcode(ARM::MOVr); | |
45 | NopInst.addOperand(MCOperand::CreateReg(ARM::R0)); | |
46 | NopInst.addOperand(MCOperand::CreateReg(ARM::R0)); | |
47 | NopInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); | |
48 | NopInst.addOperand(MCOperand::CreateReg(0)); | |
49 | NopInst.addOperand(MCOperand::CreateReg(0)); | |
50 | } | |
51 | } | |
52 | ||
53 | unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { | |
54 | switch (Opc) { | |
55 | default: break; | |
56 | case ARM::LDR_PRE_IMM: | |
57 | case ARM::LDR_PRE_REG: | |
58 | case ARM::LDR_POST_IMM: | |
59 | case ARM::LDR_POST_REG: | |
60 | return ARM::LDRi12; | |
61 | case ARM::LDRH_PRE: | |
62 | case ARM::LDRH_POST: | |
63 | return ARM::LDRH; | |
64 | case ARM::LDRB_PRE_IMM: | |
65 | case ARM::LDRB_PRE_REG: | |
66 | case ARM::LDRB_POST_IMM: | |
67 | case ARM::LDRB_POST_REG: | |
68 | return ARM::LDRBi12; | |
69 | case ARM::LDRSH_PRE: | |
70 | case ARM::LDRSH_POST: | |
71 | return ARM::LDRSH; | |
72 | case ARM::LDRSB_PRE: | |
73 | case ARM::LDRSB_POST: | |
74 | return ARM::LDRSB; | |
75 | case ARM::STR_PRE_IMM: | |
76 | case ARM::STR_PRE_REG: | |
77 | case ARM::STR_POST_IMM: | |
78 | case ARM::STR_POST_REG: | |
79 | return ARM::STRi12; | |
80 | case ARM::STRH_PRE: | |
81 | case ARM::STRH_POST: | |
82 | return ARM::STRH; | |
83 | case ARM::STRB_PRE_IMM: | |
84 | case ARM::STRB_PRE_REG: | |
85 | case ARM::STRB_POST_IMM: | |
86 | case ARM::STRB_POST_REG: | |
87 | return ARM::STRBi12; | |
88 | } | |
89 | ||
90 | return 0; | |
91 | } | |
92 | ||
1a4d82fc JJ |
93 | void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI, |
94 | Reloc::Model RM) const { | |
85aaf69f SL |
95 | MachineFunction &MF = *MI->getParent()->getParent(); |
96 | const ARMSubtarget &Subtarget = MF.getTarget().getSubtarget<ARMSubtarget>(); | |
97 | ||
98 | if (!Subtarget.useMovt(MF)) { | |
99 | if (RM == Reloc::PIC_) | |
100 | expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12, RM); | |
101 | else | |
102 | expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12, RM); | |
103 | return; | |
104 | } | |
105 | ||
106 | if (RM != Reloc::PIC_) { | |
107 | expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12, RM); | |
108 | return; | |
109 | } | |
110 | ||
111 | const GlobalValue *GV = | |
112 | cast<GlobalValue>((*MI->memoperands_begin())->getValue()); | |
113 | ||
114 | if (!Subtarget.GVIsIndirectSymbol(GV, RM)) { | |
115 | expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12, RM); | |
116 | return; | |
117 | } | |
118 | ||
119 | MachineBasicBlock &MBB = *MI->getParent(); | |
120 | DebugLoc DL = MI->getDebugLoc(); | |
121 | unsigned Reg = MI->getOperand(0).getReg(); | |
122 | MachineInstrBuilder MIB; | |
123 | ||
124 | MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg) | |
125 | .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); | |
126 | unsigned Flag = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant; | |
127 | MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( | |
128 | MachinePointerInfo::getGOT(), Flag, 4, 4); | |
129 | MIB.addMemOperand(MMO); | |
130 | MIB = BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg); | |
131 | MIB.addReg(Reg, RegState::Kill).addImm(0); | |
132 | MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); | |
133 | AddDefaultPred(MIB); | |
1a4d82fc JJ |
134 | } |
135 | ||
223e47cc LB |
136 | namespace { |
137 | /// ARMCGBR - Create Global Base Reg pass. This initializes the PIC | |
138 | /// global base register for ARM ELF. | |
139 | struct ARMCGBR : public MachineFunctionPass { | |
140 | static char ID; | |
141 | ARMCGBR() : MachineFunctionPass(ID) {} | |
142 | ||
1a4d82fc | 143 | bool runOnMachineFunction(MachineFunction &MF) override { |
223e47cc LB |
144 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); |
145 | if (AFI->getGlobalBaseReg() == 0) | |
146 | return false; | |
147 | ||
148 | const ARMTargetMachine *TM = | |
149 | static_cast<const ARMTargetMachine *>(&MF.getTarget()); | |
150 | if (TM->getRelocationModel() != Reloc::PIC_) | |
151 | return false; | |
152 | ||
1a4d82fc JJ |
153 | LLVMContext *Context = &MF.getFunction()->getContext(); |
154 | unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); | |
155 | unsigned PCAdj = TM->getSubtarget<ARMSubtarget>().isThumb() ? 4 : 8; | |
156 | ARMConstantPoolValue *CPV = ARMConstantPoolSymbol::Create( | |
157 | *Context, "_GLOBAL_OFFSET_TABLE_", ARMPCLabelIndex, PCAdj); | |
158 | ||
159 | unsigned Align = | |
160 | TM->getSubtargetImpl()->getDataLayout()->getPrefTypeAlignment( | |
161 | Type::getInt32PtrTy(*Context)); | |
223e47cc LB |
162 | unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align); |
163 | ||
164 | MachineBasicBlock &FirstMBB = MF.front(); | |
165 | MachineBasicBlock::iterator MBBI = FirstMBB.begin(); | |
166 | DebugLoc DL = FirstMBB.findDebugLoc(MBBI); | |
1a4d82fc JJ |
167 | unsigned TempReg = |
168 | MF.getRegInfo().createVirtualRegister(&ARM::rGPRRegClass); | |
223e47cc LB |
169 | unsigned Opc = TM->getSubtarget<ARMSubtarget>().isThumb2() ? |
170 | ARM::t2LDRpci : ARM::LDRcp; | |
1a4d82fc | 171 | const TargetInstrInfo &TII = *TM->getSubtargetImpl()->getInstrInfo(); |
223e47cc | 172 | MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL, |
1a4d82fc | 173 | TII.get(Opc), TempReg) |
223e47cc LB |
174 | .addConstantPoolIndex(Idx); |
175 | if (Opc == ARM::LDRcp) | |
176 | MIB.addImm(0); | |
177 | AddDefaultPred(MIB); | |
178 | ||
1a4d82fc JJ |
179 | // Fix the GOT address by adding pc. |
180 | unsigned GlobalBaseReg = AFI->getGlobalBaseReg(); | |
181 | Opc = TM->getSubtarget<ARMSubtarget>().isThumb2() ? ARM::tPICADD | |
182 | : ARM::PICADD; | |
183 | MIB = BuildMI(FirstMBB, MBBI, DL, TII.get(Opc), GlobalBaseReg) | |
184 | .addReg(TempReg) | |
185 | .addImm(ARMPCLabelIndex); | |
186 | if (Opc == ARM::PICADD) | |
187 | AddDefaultPred(MIB); | |
188 | ||
189 | ||
223e47cc LB |
190 | return true; |
191 | } | |
192 | ||
1a4d82fc | 193 | const char *getPassName() const override { |
223e47cc LB |
194 | return "ARM PIC Global Base Reg Initialization"; |
195 | } | |
196 | ||
1a4d82fc | 197 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
223e47cc LB |
198 | AU.setPreservesCFG(); |
199 | MachineFunctionPass::getAnalysisUsage(AU); | |
200 | } | |
201 | }; | |
202 | } | |
203 | ||
204 | char ARMCGBR::ID = 0; | |
205 | FunctionPass* | |
206 | llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); } |