/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/XCore/XCoreFrameLowering.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===// |
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 XCore frame information that doesn't fit anywhere else |
10 | | // cleanly... |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "XCoreFrameLowering.h" |
15 | | #include "XCore.h" |
16 | | #include "XCoreInstrInfo.h" |
17 | | #include "XCoreMachineFunctionInfo.h" |
18 | | #include "XCoreSubtarget.h" |
19 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
20 | | #include "llvm/CodeGen/MachineFunction.h" |
21 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
22 | | #include "llvm/CodeGen/MachineModuleInfo.h" |
23 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
24 | | #include "llvm/CodeGen/RegisterScavenging.h" |
25 | | #include "llvm/CodeGen/TargetLowering.h" |
26 | | #include "llvm/IR/DataLayout.h" |
27 | | #include "llvm/IR/Function.h" |
28 | | #include "llvm/Support/ErrorHandling.h" |
29 | | #include "llvm/Target/TargetOptions.h" |
30 | | #include <algorithm> // std::sort |
31 | | |
32 | | using namespace llvm; |
33 | | |
34 | | static const unsigned FramePtr = XCore::R10; |
35 | | static const int MaxImmU16 = (1<<16) - 1; |
36 | | |
37 | | // helper functions. FIXME: Eliminate. |
38 | 262 | static inline bool isImmU6(unsigned val) { |
39 | 262 | return val < (1 << 6); |
40 | 262 | } |
41 | | |
42 | 0 | static inline bool isImmU16(unsigned val) { |
43 | 0 | return val < (1 << 16); |
44 | 0 | } |
45 | | |
46 | | // Helper structure with compare function for handling stack slots. |
47 | | namespace { |
48 | | struct StackSlotInfo { |
49 | | int FI; |
50 | | int Offset; |
51 | | unsigned Reg; |
52 | 84 | StackSlotInfo(int f, int o, int r) : FI(f), Offset(o), Reg(r){}; |
53 | | }; |
54 | | } // end anonymous namespace |
55 | | |
56 | 20 | static bool CompareSSIOffset(const StackSlotInfo& a, const StackSlotInfo& b) { |
57 | 20 | return a.Offset < b.Offset; |
58 | 20 | } |
59 | | |
60 | | static void EmitDefCfaRegister(MachineBasicBlock &MBB, |
61 | | MachineBasicBlock::iterator MBBI, |
62 | | const DebugLoc &dl, const TargetInstrInfo &TII, |
63 | 9 | MachineFunction &MF, unsigned DRegNum) { |
64 | 9 | unsigned CFIIndex = MF.addFrameInst( |
65 | 9 | MCCFIInstruction::createDefCfaRegister(nullptr, DRegNum)); |
66 | 9 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) |
67 | 9 | .addCFIIndex(CFIIndex); |
68 | 9 | } |
69 | | |
70 | | static void EmitDefCfaOffset(MachineBasicBlock &MBB, |
71 | | MachineBasicBlock::iterator MBBI, |
72 | | const DebugLoc &dl, const TargetInstrInfo &TII, |
73 | 58 | int Offset) { |
74 | 58 | MachineFunction &MF = *MBB.getParent(); |
75 | 58 | unsigned CFIIndex = |
76 | 58 | MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, -Offset)); |
77 | 58 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) |
78 | 58 | .addCFIIndex(CFIIndex); |
79 | 58 | } |
80 | | |
81 | | static void EmitCfiOffset(MachineBasicBlock &MBB, |
82 | | MachineBasicBlock::iterator MBBI, const DebugLoc &dl, |
83 | | const TargetInstrInfo &TII, unsigned DRegNum, |
84 | 132 | int Offset) { |
85 | 132 | MachineFunction &MF = *MBB.getParent(); |
86 | 132 | unsigned CFIIndex = MF.addFrameInst( |
87 | 132 | MCCFIInstruction::createOffset(nullptr, DRegNum, Offset)); |
88 | 132 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) |
89 | 132 | .addCFIIndex(CFIIndex); |
90 | 132 | } |
91 | | |
92 | | /// The SP register is moved in steps of 'MaxImmU16' towards the bottom of the |
93 | | /// frame. During these steps, it may be necessary to spill registers. |
94 | | /// IfNeededExtSP emits the necessary EXTSP instructions to move the SP only |
95 | | /// as far as to make 'OffsetFromBottom' reachable using an STWSP_lru6. |
96 | | /// \param OffsetFromTop the spill offset from the top of the frame. |
97 | | /// \param [in,out] Adjusted the current SP offset from the top of the frame. |
98 | | static void IfNeededExtSP(MachineBasicBlock &MBB, |
99 | | MachineBasicBlock::iterator MBBI, const DebugLoc &dl, |
100 | | const TargetInstrInfo &TII, int OffsetFromTop, |
101 | 303 | int &Adjusted, int FrameSize, bool emitFrameMoves) { |
102 | 321 | while (OffsetFromTop > Adjusted) { |
103 | 18 | assert(Adjusted < FrameSize && "OffsetFromTop is beyond FrameSize"); |
104 | 18 | int remaining = FrameSize - Adjusted; |
105 | 18 | int OpImm = (remaining > MaxImmU16) ? MaxImmU164 : remaining14 ; |
106 | 18 | int Opcode = isImmU6(OpImm) ? XCore::EXTSP_u69 : XCore::EXTSP_lu69 ; |
107 | 18 | BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(OpImm); |
108 | 18 | Adjusted += OpImm; |
109 | 18 | if (emitFrameMoves) |
110 | 11 | EmitDefCfaOffset(MBB, MBBI, dl, TII, Adjusted*4); |
111 | 18 | } |
112 | 303 | } |
113 | | |
114 | | /// The SP register is moved in steps of 'MaxImmU16' towards the top of the |
115 | | /// frame. During these steps, it may be necessary to re-load registers. |
116 | | /// IfNeededLDAWSP emits the necessary LDAWSP instructions to move the SP only |
117 | | /// as far as to make 'OffsetFromTop' reachable using an LDAWSP_lru6. |
118 | | /// \param OffsetFromTop the spill offset from the top of the frame. |
119 | | /// \param [in,out] RemainingAdj the current SP offset from the top of the |
120 | | /// frame. |
121 | | static void IfNeededLDAWSP(MachineBasicBlock &MBB, |
122 | | MachineBasicBlock::iterator MBBI, const DebugLoc &dl, |
123 | | const TargetInstrInfo &TII, int OffsetFromTop, |
124 | 113 | int &RemainingAdj) { |
125 | 122 | while (OffsetFromTop < RemainingAdj - MaxImmU16) { |
126 | 9 | assert(RemainingAdj && "OffsetFromTop is beyond FrameSize"); |
127 | 9 | int OpImm = (RemainingAdj > MaxImmU16) ? MaxImmU16 : RemainingAdj0 ; |
128 | 9 | int Opcode = isImmU6(OpImm) ? XCore::LDAWSP_ru60 : XCore::LDAWSP_lru6; |
129 | 9 | BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(OpImm); |
130 | 9 | RemainingAdj -= OpImm; |
131 | 9 | } |
132 | 113 | } |
133 | | |
134 | | /// Creates an ordered list of registers that are spilled |
135 | | /// during the emitPrologue/emitEpilogue. |
136 | | /// Registers are ordered according to their frame offset. |
137 | | /// As offsets are negative, the largest offsets will be first. |
138 | | static void GetSpillList(SmallVectorImpl<StackSlotInfo> &SpillList, |
139 | | MachineFrameInfo &MFI, XCoreFunctionInfo *XFI, |
140 | 589 | bool fetchLR, bool fetchFP) { |
141 | 589 | if (fetchLR) { |
142 | 7 | int Offset = MFI.getObjectOffset(XFI->getLRSpillSlot()); |
143 | 7 | SpillList.push_back(StackSlotInfo(XFI->getLRSpillSlot(), |
144 | 7 | Offset, |
145 | 7 | XCore::LR)); |
146 | 7 | } |
147 | 589 | if (fetchFP) { |
148 | 37 | int Offset = MFI.getObjectOffset(XFI->getFPSpillSlot()); |
149 | 37 | SpillList.push_back(StackSlotInfo(XFI->getFPSpillSlot(), |
150 | 37 | Offset, |
151 | 37 | FramePtr)); |
152 | 37 | } |
153 | 589 | llvm::sort(SpillList, CompareSSIOffset); |
154 | 589 | } |
155 | | |
156 | | /// Creates an ordered list of EH info register 'spills'. |
157 | | /// These slots are only used by the unwinder and calls to llvm.eh.return(). |
158 | | /// Registers are ordered according to their frame offset. |
159 | | /// As offsets are negative, the largest offsets will be first. |
160 | | static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList, |
161 | | MachineFrameInfo &MFI, XCoreFunctionInfo *XFI, |
162 | | const Constant *PersonalityFn, |
163 | 20 | const TargetLowering *TL) { |
164 | 20 | assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots"); |
165 | 20 | const int *EHSlot = XFI->getEHSpillSlot(); |
166 | 20 | SpillList.push_back( |
167 | 20 | StackSlotInfo(EHSlot[0], MFI.getObjectOffset(EHSlot[0]), |
168 | 20 | TL->getExceptionPointerRegister(PersonalityFn))); |
169 | 20 | SpillList.push_back( |
170 | 20 | StackSlotInfo(EHSlot[0], MFI.getObjectOffset(EHSlot[1]), |
171 | 20 | TL->getExceptionSelectorRegister(PersonalityFn))); |
172 | 20 | llvm::sort(SpillList, CompareSSIOffset); |
173 | 20 | } |
174 | | |
175 | | static MachineMemOperand *getFrameIndexMMO(MachineBasicBlock &MBB, |
176 | | int FrameIndex, |
177 | 60 | MachineMemOperand::Flags flags) { |
178 | 60 | MachineFunction *MF = MBB.getParent(); |
179 | 60 | const MachineFrameInfo &MFI = MF->getFrameInfo(); |
180 | 60 | MachineMemOperand *MMO = MF->getMachineMemOperand( |
181 | 60 | MachinePointerInfo::getFixedStack(*MF, FrameIndex), flags, |
182 | 60 | MFI.getObjectSize(FrameIndex), MFI.getObjectAlignment(FrameIndex)); |
183 | 60 | return MMO; |
184 | 60 | } |
185 | | |
186 | | |
187 | | /// Restore clobbered registers with their spill slot value. |
188 | | /// The SP will be adjusted at the same time, thus the SpillList must be ordered |
189 | | /// with the largest (negative) offsets first. |
190 | | static void RestoreSpillList(MachineBasicBlock &MBB, |
191 | | MachineBasicBlock::iterator MBBI, |
192 | | const DebugLoc &dl, const TargetInstrInfo &TII, |
193 | | int &RemainingAdj, |
194 | 318 | SmallVectorImpl<StackSlotInfo> &SpillList) { |
195 | 354 | for (unsigned i = 0, e = SpillList.size(); i != e; ++i36 ) { |
196 | 36 | assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); |
197 | 36 | assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); |
198 | 36 | int OffsetFromTop = - SpillList[i].Offset/4; |
199 | 36 | IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj); |
200 | 36 | int Offset = RemainingAdj - OffsetFromTop; |
201 | 36 | int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru60 ; |
202 | 36 | BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpillList[i].Reg) |
203 | 36 | .addImm(Offset) |
204 | 36 | .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, |
205 | 36 | MachineMemOperand::MOLoad)); |
206 | 36 | } |
207 | 318 | } |
208 | | |
209 | | //===----------------------------------------------------------------------===// |
210 | | // XCoreFrameLowering: |
211 | | //===----------------------------------------------------------------------===// |
212 | | |
213 | | XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti) |
214 | 81 | : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) { |
215 | 81 | // Do nothing |
216 | 81 | } |
217 | | |
218 | 5.01k | bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const { |
219 | 5.01k | return MF.getTarget().Options.DisableFramePointerElim(MF) || |
220 | 5.01k | MF.getFrameInfo().hasVarSizedObjects()4.56k ; |
221 | 5.01k | } |
222 | | |
223 | | void XCoreFrameLowering::emitPrologue(MachineFunction &MF, |
224 | 280 | MachineBasicBlock &MBB) const { |
225 | 280 | assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); |
226 | 280 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
227 | 280 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
228 | 280 | MachineModuleInfo *MMI = &MF.getMMI(); |
229 | 280 | const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo(); |
230 | 280 | const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo(); |
231 | 280 | XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); |
232 | 280 | // Debug location must be unknown since the first debug location is used |
233 | 280 | // to determine the end of the prologue. |
234 | 280 | DebugLoc dl; |
235 | 280 | |
236 | 280 | if (MFI.getMaxAlignment() > getStackAlignment()) |
237 | 1 | report_fatal_error("emitPrologue unsupported alignment: " |
238 | 1 | + Twine(MFI.getMaxAlignment())); |
239 | 279 | |
240 | 279 | const AttributeList &PAL = MF.getFunction().getAttributes(); |
241 | 279 | if (PAL.hasAttrSomewhere(Attribute::Nest)) |
242 | 1 | BuildMI(MBB, MBBI, dl, TII.get(XCore::LDWSP_ru6), XCore::R11).addImm(0); |
243 | 279 | // FIX: Needs addMemOperand() but can't use getFixedStack() or getStack(). |
244 | 279 | |
245 | 279 | // Work out frame sizes. |
246 | 279 | // We will adjust the SP in stages towards the final FrameSize. |
247 | 279 | assert(MFI.getStackSize()%4 == 0 && "Misaligned frame size"); |
248 | 279 | const int FrameSize = MFI.getStackSize() / 4; |
249 | 279 | int Adjusted = 0; |
250 | 279 | |
251 | 279 | bool saveLR = XFI->hasLRSpillSlot(); |
252 | 279 | bool UseENTSP = saveLR && FrameSize82 |
253 | 279 | && (MFI.getObjectOffset(XFI->getLRSpillSlot()) == 0)80 ; |
254 | 279 | if (UseENTSP) |
255 | 78 | saveLR = false; |
256 | 279 | bool FP = hasFP(MF); |
257 | 279 | bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); |
258 | 279 | |
259 | 279 | if (UseENTSP) { |
260 | 78 | // Allocate space on the stack at the same time as saving LR. |
261 | 78 | Adjusted = (FrameSize > MaxImmU16) ? MaxImmU165 : FrameSize73 ; |
262 | 78 | int Opcode = isImmU6(Adjusted) ? XCore::ENTSP_u662 : XCore::ENTSP_lu616 ; |
263 | 78 | MBB.addLiveIn(XCore::LR); |
264 | 78 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)); |
265 | 78 | MIB.addImm(Adjusted); |
266 | 78 | MIB->addRegisterKilled(XCore::LR, MF.getSubtarget().getRegisterInfo(), |
267 | 78 | true); |
268 | 78 | if (emitFrameMoves) { |
269 | 47 | EmitDefCfaOffset(MBB, MBBI, dl, TII, Adjusted*4); |
270 | 47 | unsigned DRegNum = MRI->getDwarfRegNum(XCore::LR, true); |
271 | 47 | EmitCfiOffset(MBB, MBBI, dl, TII, DRegNum, 0); |
272 | 47 | } |
273 | 78 | } |
274 | 279 | |
275 | 279 | // If necessary, save LR and FP to the stack, as we EXTSP. |
276 | 279 | SmallVector<StackSlotInfo,2> SpillList; |
277 | 279 | GetSpillList(SpillList, MFI, XFI, saveLR, FP); |
278 | 279 | // We want the nearest (negative) offsets first, so reverse list. |
279 | 279 | std::reverse(SpillList.begin(), SpillList.end()); |
280 | 303 | for (unsigned i = 0, e = SpillList.size(); i != e; ++i24 ) { |
281 | 24 | assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); |
282 | 24 | assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); |
283 | 24 | int OffsetFromTop = - SpillList[i].Offset/4; |
284 | 24 | IfNeededExtSP(MBB, MBBI, dl, TII, OffsetFromTop, Adjusted, FrameSize, |
285 | 24 | emitFrameMoves); |
286 | 24 | int Offset = Adjusted - OffsetFromTop; |
287 | 24 | int Opcode = isImmU6(Offset) ? XCore::STWSP_ru6 : XCore::STWSP_lru60 ; |
288 | 24 | MBB.addLiveIn(SpillList[i].Reg); |
289 | 24 | BuildMI(MBB, MBBI, dl, TII.get(Opcode)) |
290 | 24 | .addReg(SpillList[i].Reg, RegState::Kill) |
291 | 24 | .addImm(Offset) |
292 | 24 | .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, |
293 | 24 | MachineMemOperand::MOStore)); |
294 | 24 | if (emitFrameMoves) { |
295 | 9 | unsigned DRegNum = MRI->getDwarfRegNum(SpillList[i].Reg, true); |
296 | 9 | EmitCfiOffset(MBB, MBBI, dl, TII, DRegNum, SpillList[i].Offset); |
297 | 9 | } |
298 | 24 | } |
299 | 279 | |
300 | 279 | // Complete any remaining Stack adjustment. |
301 | 279 | IfNeededExtSP(MBB, MBBI, dl, TII, FrameSize, Adjusted, FrameSize, |
302 | 279 | emitFrameMoves); |
303 | 279 | assert(Adjusted==FrameSize && "IfNeededExtSP has not completed adjustment"); |
304 | 279 | |
305 | 279 | if (FP) { |
306 | 20 | // Set the FP from the SP. |
307 | 20 | BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0); |
308 | 20 | if (emitFrameMoves) |
309 | 9 | EmitDefCfaRegister(MBB, MBBI, dl, TII, MF, |
310 | 9 | MRI->getDwarfRegNum(FramePtr, true)); |
311 | 20 | } |
312 | 279 | |
313 | 279 | if (emitFrameMoves) { |
314 | 162 | // Frame moves for callee saved. |
315 | 162 | for (const auto &SpillLabel : XFI->getSpillLabels()) { |
316 | 52 | MachineBasicBlock::iterator Pos = SpillLabel.first; |
317 | 52 | ++Pos; |
318 | 52 | const CalleeSavedInfo &CSI = SpillLabel.second; |
319 | 52 | int Offset = MFI.getObjectOffset(CSI.getFrameIdx()); |
320 | 52 | unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true); |
321 | 52 | EmitCfiOffset(MBB, Pos, dl, TII, DRegNum, Offset); |
322 | 52 | } |
323 | 162 | if (XFI->hasEHSpillSlot()) { |
324 | 12 | // The unwinder requires stack slot & CFI offsets for the exception info. |
325 | 12 | // We do not save/spill these registers. |
326 | 12 | const Function *Fn = &MF.getFunction(); |
327 | 12 | const Constant *PersonalityFn = |
328 | 12 | Fn->hasPersonalityFn() ? Fn->getPersonalityFn()0 : nullptr; |
329 | 12 | SmallVector<StackSlotInfo, 2> SpillList; |
330 | 12 | GetEHSpillList(SpillList, MFI, XFI, PersonalityFn, |
331 | 12 | MF.getSubtarget().getTargetLowering()); |
332 | 12 | assert(SpillList.size()==2 && "Unexpected SpillList size"); |
333 | 12 | EmitCfiOffset(MBB, MBBI, dl, TII, |
334 | 12 | MRI->getDwarfRegNum(SpillList[0].Reg, true), |
335 | 12 | SpillList[0].Offset); |
336 | 12 | EmitCfiOffset(MBB, MBBI, dl, TII, |
337 | 12 | MRI->getDwarfRegNum(SpillList[1].Reg, true), |
338 | 12 | SpillList[1].Offset); |
339 | 12 | } |
340 | 162 | } |
341 | 279 | } |
342 | | |
343 | | void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, |
344 | 318 | MachineBasicBlock &MBB) const { |
345 | 318 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
346 | 318 | MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); |
347 | 318 | const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo(); |
348 | 318 | XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); |
349 | 318 | DebugLoc dl = MBBI->getDebugLoc(); |
350 | 318 | unsigned RetOpcode = MBBI->getOpcode(); |
351 | 318 | |
352 | 318 | // Work out frame sizes. |
353 | 318 | // We will adjust the SP in stages towards the final FrameSize. |
354 | 318 | int RemainingAdj = MFI.getStackSize(); |
355 | 318 | assert(RemainingAdj%4 == 0 && "Misaligned frame size"); |
356 | 318 | RemainingAdj /= 4; |
357 | 318 | |
358 | 318 | if (RetOpcode == XCore::EH_RETURN) { |
359 | 8 | // 'Restore' the exception info the unwinder has placed into the stack |
360 | 8 | // slots. |
361 | 8 | const Function *Fn = &MF.getFunction(); |
362 | 8 | const Constant *PersonalityFn = |
363 | 8 | Fn->hasPersonalityFn() ? Fn->getPersonalityFn()0 : nullptr; |
364 | 8 | SmallVector<StackSlotInfo, 2> SpillList; |
365 | 8 | GetEHSpillList(SpillList, MFI, XFI, PersonalityFn, |
366 | 8 | MF.getSubtarget().getTargetLowering()); |
367 | 8 | RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); |
368 | 8 | |
369 | 8 | // Return to the landing pad. |
370 | 8 | unsigned EhStackReg = MBBI->getOperand(0).getReg(); |
371 | 8 | unsigned EhHandlerReg = MBBI->getOperand(1).getReg(); |
372 | 8 | BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg); |
373 | 8 | BuildMI(MBB, MBBI, dl, TII.get(XCore::BAU_1r)).addReg(EhHandlerReg); |
374 | 8 | MBB.erase(MBBI); // Erase the previous return instruction. |
375 | 8 | return; |
376 | 8 | } |
377 | 310 | |
378 | 310 | bool restoreLR = XFI->hasLRSpillSlot(); |
379 | 310 | bool UseRETSP = restoreLR && RemainingAdj72 |
380 | 310 | && (MFI.getObjectOffset(XFI->getLRSpillSlot()) == 0)70 ; |
381 | 310 | if (UseRETSP) |
382 | 69 | restoreLR = false; |
383 | 310 | bool FP = hasFP(MF); |
384 | 310 | |
385 | 310 | if (FP) // Restore the stack pointer. |
386 | 17 | BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr); |
387 | 310 | |
388 | 310 | // If necessary, restore LR and FP from the stack, as we EXTSP. |
389 | 310 | SmallVector<StackSlotInfo,2> SpillList; |
390 | 310 | GetSpillList(SpillList, MFI, XFI, restoreLR, FP); |
391 | 310 | RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); |
392 | 310 | |
393 | 310 | if (RemainingAdj) { |
394 | 77 | // Complete all but one of the remaining Stack adjustments. |
395 | 77 | IfNeededLDAWSP(MBB, MBBI, dl, TII, 0, RemainingAdj); |
396 | 77 | if (UseRETSP) { |
397 | 69 | // Fold prologue into return instruction |
398 | 69 | assert(RetOpcode == XCore::RETSP_u6 |
399 | 69 | || RetOpcode == XCore::RETSP_lu6); |
400 | 69 | int Opcode = isImmU6(RemainingAdj) ? XCore::RETSP_u653 : XCore::RETSP_lu616 ; |
401 | 69 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)) |
402 | 69 | .addImm(RemainingAdj); |
403 | 120 | for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i51 ) |
404 | 51 | MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands |
405 | 69 | MBB.erase(MBBI); // Erase the previous return instruction. |
406 | 69 | } else { |
407 | 8 | int Opcode = isImmU6(RemainingAdj) ? XCore::LDAWSP_ru6 : |
408 | 8 | XCore::LDAWSP_lru60 ; |
409 | 8 | BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(RemainingAdj); |
410 | 8 | // Don't erase the return instruction. |
411 | 8 | } |
412 | 77 | } // else Don't erase the return instruction. |
413 | 310 | } |
414 | | |
415 | | bool XCoreFrameLowering:: |
416 | | spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
417 | | MachineBasicBlock::iterator MI, |
418 | | const std::vector<CalleeSavedInfo> &CSI, |
419 | 21 | const TargetRegisterInfo *TRI) const { |
420 | 21 | if (CSI.empty()) |
421 | 0 | return true; |
422 | 21 | |
423 | 21 | MachineFunction *MF = MBB.getParent(); |
424 | 21 | const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); |
425 | 21 | XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); |
426 | 21 | bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); |
427 | 21 | |
428 | 21 | DebugLoc DL; |
429 | 21 | if (MI != MBB.end() && !MI->isDebugInstr()) |
430 | 21 | DL = MI->getDebugLoc(); |
431 | 21 | |
432 | 21 | for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); |
433 | 94 | it != CSI.end(); ++it73 ) { |
434 | 73 | unsigned Reg = it->getReg(); |
435 | 73 | assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) && |
436 | 73 | "LR & FP are always handled in emitPrologue"); |
437 | 73 | |
438 | 73 | // Add the callee-saved register as live-in. It's killed at the spill. |
439 | 73 | MBB.addLiveIn(Reg); |
440 | 73 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
441 | 73 | TII.storeRegToStackSlot(MBB, MI, Reg, true, it->getFrameIdx(), RC, TRI); |
442 | 73 | if (emitFrameMoves) { |
443 | 52 | auto Store = MI; |
444 | 52 | --Store; |
445 | 52 | XFI->getSpillLabels().push_back(std::make_pair(Store, *it)); |
446 | 52 | } |
447 | 73 | } |
448 | 21 | return true; |
449 | 21 | } |
450 | | |
451 | | bool XCoreFrameLowering:: |
452 | | restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
453 | | MachineBasicBlock::iterator MI, |
454 | | std::vector<CalleeSavedInfo> &CSI, |
455 | 24 | const TargetRegisterInfo *TRI) const{ |
456 | 24 | MachineFunction *MF = MBB.getParent(); |
457 | 24 | const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); |
458 | 24 | bool AtStart = MI == MBB.begin(); |
459 | 24 | MachineBasicBlock::iterator BeforeI = MI; |
460 | 24 | if (!AtStart) |
461 | 20 | --BeforeI; |
462 | 24 | for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); |
463 | 113 | it != CSI.end(); ++it89 ) { |
464 | 89 | unsigned Reg = it->getReg(); |
465 | 89 | assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) && |
466 | 89 | "LR & FP are always handled in emitEpilogue"); |
467 | 89 | |
468 | 89 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
469 | 89 | TII.loadRegFromStackSlot(MBB, MI, Reg, it->getFrameIdx(), RC, TRI); |
470 | 89 | assert(MI != MBB.begin() && |
471 | 89 | "loadRegFromStackSlot didn't insert any code!"); |
472 | 89 | // Insert in reverse order. loadRegFromStackSlot can insert multiple |
473 | 89 | // instructions. |
474 | 89 | if (AtStart) |
475 | 19 | MI = MBB.begin(); |
476 | 70 | else { |
477 | 70 | MI = BeforeI; |
478 | 70 | ++MI; |
479 | 70 | } |
480 | 89 | } |
481 | 24 | return true; |
482 | 24 | } |
483 | | |
484 | | // This function eliminates ADJCALLSTACKDOWN, |
485 | | // ADJCALLSTACKUP pseudo instructions |
486 | | MachineBasicBlock::iterator XCoreFrameLowering::eliminateCallFramePseudoInstr( |
487 | | MachineFunction &MF, MachineBasicBlock &MBB, |
488 | 144 | MachineBasicBlock::iterator I) const { |
489 | 144 | const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo(); |
490 | 144 | if (!hasReservedCallFrame(MF)) { |
491 | 24 | // Turn the adjcallstackdown instruction into 'extsp <amt>' and the |
492 | 24 | // adjcallstackup instruction into 'ldaw sp, sp[<amt>]' |
493 | 24 | MachineInstr &Old = *I; |
494 | 24 | uint64_t Amount = Old.getOperand(0).getImm(); |
495 | 24 | if (Amount != 0) { |
496 | 20 | // We need to keep the stack aligned properly. To do this, we round the |
497 | 20 | // amount of space needed for the outgoing arguments up to the next |
498 | 20 | // alignment boundary. |
499 | 20 | unsigned Align = getStackAlignment(); |
500 | 20 | Amount = (Amount+Align-1)/Align*Align; |
501 | 20 | |
502 | 20 | assert(Amount%4 == 0); |
503 | 20 | Amount /= 4; |
504 | 20 | |
505 | 20 | bool isU6 = isImmU6(Amount); |
506 | 20 | if (!isU6 && !isImmU16(Amount)0 ) { |
507 | 0 | // FIX could emit multiple instructions in this case. |
508 | | #ifndef NDEBUG |
509 | | errs() << "eliminateCallFramePseudoInstr size too big: " |
510 | | << Amount << "\n"; |
511 | | #endif |
512 | 0 | llvm_unreachable(nullptr); |
513 | 0 | } |
514 | 20 | |
515 | 20 | MachineInstr *New; |
516 | 20 | if (Old.getOpcode() == XCore::ADJCALLSTACKDOWN) { |
517 | 10 | int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu60 ; |
518 | 10 | New = BuildMI(MF, Old.getDebugLoc(), TII.get(Opcode)).addImm(Amount); |
519 | 10 | } else { |
520 | 10 | assert(Old.getOpcode() == XCore::ADJCALLSTACKUP); |
521 | 10 | int Opcode = isU6 ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru60 ; |
522 | 10 | New = BuildMI(MF, Old.getDebugLoc(), TII.get(Opcode), XCore::SP) |
523 | 10 | .addImm(Amount); |
524 | 10 | } |
525 | 20 | |
526 | 20 | // Replace the pseudo instruction with a new instruction... |
527 | 20 | MBB.insert(I, New); |
528 | 20 | } |
529 | 24 | } |
530 | 144 | |
531 | 144 | return MBB.erase(I); |
532 | 144 | } |
533 | | |
534 | | void XCoreFrameLowering::determineCalleeSaves(MachineFunction &MF, |
535 | | BitVector &SavedRegs, |
536 | 282 | RegScavenger *RS) const { |
537 | 282 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
538 | 282 | |
539 | 282 | XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); |
540 | 282 | |
541 | 282 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
542 | 282 | bool LRUsed = MRI.isPhysRegModified(XCore::LR); |
543 | 282 | |
544 | 282 | if (!LRUsed && !MF.getFunction().isVarArg()222 && |
545 | 282 | MF.getFrameInfo().estimateStackSize(MF)220 ) |
546 | 16 | // If we need to extend the stack it is more efficient to use entsp / retsp. |
547 | 16 | // We force the LR to be saved so these instructions are used. |
548 | 16 | LRUsed = true; |
549 | 282 | |
550 | 282 | if (MF.callsUnwindInit() || MF.callsEHReturn()276 ) { |
551 | 12 | // The unwinder expects to find spill slots for the exception info regs R0 |
552 | 12 | // & R1. These are used during llvm.eh.return() to 'restore' the exception |
553 | 12 | // info. N.B. we do not spill or restore R0, R1 during normal operation. |
554 | 12 | XFI->createEHSpillSlot(MF); |
555 | 12 | // As we will have a stack, we force the LR to be saved. |
556 | 12 | LRUsed = true; |
557 | 12 | } |
558 | 282 | |
559 | 282 | if (LRUsed) { |
560 | 82 | // We will handle the LR in the prologue/epilogue |
561 | 82 | // and allocate space on the stack ourselves. |
562 | 82 | SavedRegs.reset(XCore::LR); |
563 | 82 | XFI->createLRSpillSlot(MF); |
564 | 82 | } |
565 | 282 | |
566 | 282 | if (hasFP(MF)) |
567 | 20 | // A callee save register is used to hold the FP. |
568 | 20 | // This needs saving / restoring in the epilogue / prologue. |
569 | 20 | XFI->createFPSpillSlot(MF); |
570 | 282 | } |
571 | | |
572 | | void XCoreFrameLowering:: |
573 | | processFunctionBeforeFrameFinalized(MachineFunction &MF, |
574 | 280 | RegScavenger *RS) const { |
575 | 280 | assert(RS && "requiresRegisterScavenging failed"); |
576 | 280 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
577 | 280 | const TargetRegisterClass &RC = XCore::GRRegsRegClass; |
578 | 280 | const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); |
579 | 280 | XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); |
580 | 280 | // Reserve slots close to SP or frame pointer for Scavenging spills. |
581 | 280 | // When using SP for small frames, we don't need any scratch registers. |
582 | 280 | // When using SP for large frames, we may need 2 scratch registers. |
583 | 280 | // When using FP, for large or small frames, we may need 1 scratch register. |
584 | 280 | unsigned Size = TRI.getSpillSize(RC); |
585 | 280 | unsigned Align = TRI.getSpillAlignment(RC); |
586 | 280 | if (XFI->isLargeFrame(MF) || hasFP(MF)273 ) |
587 | 24 | RS->addScavengingFrameIndex(MFI.CreateStackObject(Size, Align, false)); |
588 | 280 | if (XFI->isLargeFrame(MF) && !hasFP(MF)7 ) |
589 | 4 | RS->addScavengingFrameIndex(MFI.CreateStackObject(Size, Align, false)); |
590 | 280 | } |