1 | //===-- M68kFrameLowering.cpp - M68k Frame Information ----------*- C++ -*-===// |
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 | /// \file |
10 | /// This file contains the M68k implementation of TargetFrameLowering class. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "M68kFrameLowering.h" |
15 | |
16 | #include "M68kInstrBuilder.h" |
17 | #include "M68kInstrInfo.h" |
18 | #include "M68kMachineFunction.h" |
19 | #include "M68kSubtarget.h" |
20 | |
21 | #include "llvm/ADT/SmallSet.h" |
22 | #include "llvm/CodeGen/MachineFrameInfo.h" |
23 | #include "llvm/CodeGen/MachineFunction.h" |
24 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
25 | #include "llvm/CodeGen/MachineModuleInfo.h" |
26 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
27 | #include "llvm/IR/DataLayout.h" |
28 | #include "llvm/IR/Function.h" |
29 | #include "llvm/Support/Alignment.h" |
30 | #include "llvm/Support/CommandLine.h" |
31 | #include "llvm/Target/TargetMachine.h" |
32 | #include "llvm/Target/TargetOptions.h" |
33 | |
34 | using namespace llvm; |
35 | |
36 | M68kFrameLowering::M68kFrameLowering(const M68kSubtarget &STI, Align Alignment) |
37 | : TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI), |
38 | TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) { |
39 | SlotSize = STI.getSlotSize(); |
40 | StackPtr = TRI->getStackRegister(); |
41 | } |
42 | |
43 | bool M68kFrameLowering::hasFP(const MachineFunction &MF) const { |
44 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
45 | const TargetRegisterInfo *TRI = STI.getRegisterInfo(); |
46 | |
47 | return MF.getTarget().Options.DisableFramePointerElim(MF) || |
48 | MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || |
49 | TRI->hasStackRealignment(MF); |
50 | } |
51 | |
52 | // FIXME Make sure no other factors prevent us from reserving call frame |
53 | bool M68kFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
54 | return !MF.getFrameInfo().hasVarSizedObjects() && |
55 | !MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences(); |
56 | } |
57 | |
58 | bool M68kFrameLowering::canSimplifyCallFramePseudos( |
59 | const MachineFunction &MF) const { |
60 | return hasReservedCallFrame(MF) || |
61 | (hasFP(MF) && !TRI->hasStackRealignment(MF)) || |
62 | TRI->hasBasePointer(MF); |
63 | } |
64 | |
65 | bool M68kFrameLowering::needsFrameIndexResolution( |
66 | const MachineFunction &MF) const { |
67 | return MF.getFrameInfo().hasStackObjects() || |
68 | MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences(); |
69 | } |
70 | |
71 | // NOTE: this only has a subset of the full frame index logic. In |
72 | // particular, the FI < 0 and AfterFPPop logic is handled in |
73 | // M68kRegisterInfo::eliminateFrameIndex, but not here. Possibly |
74 | // (probably?) it should be moved into here. |
75 | StackOffset |
76 | M68kFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, |
77 | Register &FrameReg) const { |
78 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
79 | |
80 | // We can't calculate offset from frame pointer if the stack is realigned, |
81 | // so enforce usage of stack/base pointer. The base pointer is used when we |
82 | // have dynamic allocas in addition to dynamic realignment. |
83 | if (TRI->hasBasePointer(MF)) |
84 | FrameReg = TRI->getBaseRegister(); |
85 | else if (TRI->hasStackRealignment(MF)) |
86 | FrameReg = TRI->getStackRegister(); |
87 | else |
88 | FrameReg = TRI->getFrameRegister(MF); |
89 | |
90 | // Offset will hold the offset from the stack pointer at function entry to the |
91 | // object. |
92 | // We need to factor in additional offsets applied during the prologue to the |
93 | // frame, base, and stack pointer depending on which is used. |
94 | int Offset = MFI.getObjectOffset(ObjectIdx: FI) - getOffsetOfLocalArea(); |
95 | const M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>(); |
96 | uint64_t StackSize = MFI.getStackSize(); |
97 | bool HasFP = hasFP(MF); |
98 | |
99 | // TODO: Support tail calls |
100 | if (TRI->hasBasePointer(MF)) { |
101 | assert(HasFP && "VLAs and dynamic stack realign, but no FP?!" ); |
102 | if (FI < 0) { |
103 | // Skip the saved FP. |
104 | return StackOffset::getFixed(Fixed: Offset + SlotSize); |
105 | } |
106 | |
107 | assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0); |
108 | return StackOffset::getFixed(Fixed: Offset + StackSize); |
109 | } |
110 | if (TRI->hasStackRealignment(MF)) { |
111 | if (FI < 0) { |
112 | // Skip the saved FP. |
113 | return StackOffset::getFixed(Fixed: Offset + SlotSize); |
114 | } |
115 | |
116 | assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0); |
117 | return StackOffset::getFixed(Fixed: Offset + StackSize); |
118 | } |
119 | |
120 | if (!HasFP) |
121 | return StackOffset::getFixed(Fixed: Offset + StackSize); |
122 | |
123 | // Skip the saved FP. |
124 | Offset += SlotSize; |
125 | |
126 | // Skip the RETADDR move area |
127 | int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta(); |
128 | if (TailCallReturnAddrDelta < 0) |
129 | Offset -= TailCallReturnAddrDelta; |
130 | |
131 | return StackOffset::getFixed(Fixed: Offset); |
132 | } |
133 | |
134 | /// Return a caller-saved register that isn't live |
135 | /// when it reaches the "return" instruction. We can then pop a stack object |
136 | /// to this register without worry about clobbering it. |
137 | static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB, |
138 | MachineBasicBlock::iterator &MBBI, |
139 | const M68kRegisterInfo *TRI) { |
140 | const MachineFunction *MF = MBB.getParent(); |
141 | if (MF->callsEHReturn()) |
142 | return 0; |
143 | |
144 | const TargetRegisterClass &AvailableRegs = *TRI->getRegsForTailCall(MF: *MF); |
145 | |
146 | if (MBBI == MBB.end()) |
147 | return 0; |
148 | |
149 | switch (MBBI->getOpcode()) { |
150 | default: |
151 | return 0; |
152 | case TargetOpcode::PATCHABLE_RET: |
153 | case M68k::RET: { |
154 | SmallSet<uint16_t, 8> Uses; |
155 | |
156 | for (unsigned i = 0, e = MBBI->getNumOperands(); i != e; ++i) { |
157 | MachineOperand &MO = MBBI->getOperand(i); |
158 | if (!MO.isReg() || MO.isDef()) |
159 | continue; |
160 | Register Reg = MO.getReg(); |
161 | if (!Reg) |
162 | continue; |
163 | for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) |
164 | Uses.insert(V: *AI); |
165 | } |
166 | |
167 | for (auto CS : AvailableRegs) |
168 | if (!Uses.count(V: CS)) |
169 | return CS; |
170 | } |
171 | } |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg) { |
177 | return llvm::any_of(Range: MBB.liveins(), |
178 | P: [Reg](MachineBasicBlock::RegisterMaskPair RegMask) { |
179 | return RegMask.PhysReg == Reg; |
180 | }); |
181 | } |
182 | |
183 | uint64_t |
184 | M68kFrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const { |
185 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
186 | uint64_t MaxAlign = MFI.getMaxAlign().value(); // Desired stack alignment. |
187 | unsigned StackAlign = getStackAlignment(); // ABI alignment |
188 | if (MF.getFunction().hasFnAttribute(Kind: "stackrealign" )) { |
189 | if (MFI.hasCalls()) |
190 | MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign; |
191 | else if (MaxAlign < SlotSize) |
192 | MaxAlign = SlotSize; |
193 | } |
194 | return MaxAlign; |
195 | } |
196 | |
197 | void M68kFrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB, |
198 | MachineBasicBlock::iterator MBBI, |
199 | const DebugLoc &DL, unsigned Reg, |
200 | uint64_t MaxAlign) const { |
201 | uint64_t Val = -MaxAlign; |
202 | unsigned AndOp = M68k::AND32di; |
203 | unsigned MovOp = M68k::MOV32rr; |
204 | |
205 | // This function is normally used with SP which is Address Register, but AND, |
206 | // or any other logical instructions in M68k do not support ARs so we need |
207 | // to use a temp Data Register to perform the op. |
208 | unsigned Tmp = M68k::D0; |
209 | |
210 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MovOp), DestReg: Tmp) |
211 | .addReg(RegNo: Reg) |
212 | .setMIFlag(MachineInstr::FrameSetup); |
213 | |
214 | MachineInstr *MI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AndOp), DestReg: Tmp) |
215 | .addReg(RegNo: Tmp) |
216 | .addImm(Val) |
217 | .setMIFlag(MachineInstr::FrameSetup); |
218 | |
219 | // The CCR implicit def is dead. |
220 | MI->getOperand(i: 3).setIsDead(); |
221 | |
222 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MovOp), DestReg: Reg) |
223 | .addReg(RegNo: Tmp) |
224 | .setMIFlag(MachineInstr::FrameSetup); |
225 | } |
226 | |
227 | MachineBasicBlock::iterator M68kFrameLowering::eliminateCallFramePseudoInstr( |
228 | MachineFunction &MF, MachineBasicBlock &MBB, |
229 | MachineBasicBlock::iterator I) const { |
230 | bool ReserveCallFrame = hasReservedCallFrame(MF); |
231 | unsigned Opcode = I->getOpcode(); |
232 | bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode(); |
233 | DebugLoc DL = I->getDebugLoc(); |
234 | uint64_t Amount = !ReserveCallFrame ? I->getOperand(i: 0).getImm() : 0; |
235 | uint64_t InternalAmt = (IsDestroy && Amount) ? I->getOperand(i: 1).getImm() : 0; |
236 | I = MBB.erase(I); |
237 | |
238 | if (!ReserveCallFrame) { |
239 | // If the stack pointer can be changed after prologue, turn the |
240 | // adjcallstackup instruction into a 'sub %SP, <amt>' and the |
241 | // adjcallstackdown instruction into 'add %SP, <amt>' |
242 | |
243 | // We need to keep the stack aligned properly. To do this, we round the |
244 | // amount of space needed for the outgoing arguments up to the next |
245 | // alignment boundary. |
246 | unsigned StackAlign = getStackAlignment(); |
247 | Amount = alignTo(Value: Amount, Align: StackAlign); |
248 | |
249 | MachineModuleInfo &MMI = MF.getMMI(); |
250 | const auto &Fn = MF.getFunction(); |
251 | bool DwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry(); |
252 | |
253 | // If we have any exception handlers in this function, and we adjust |
254 | // the SP before calls, we may need to indicate this to the unwinder |
255 | // using GNU_ARGS_SIZE. Note that this may be necessary even when |
256 | // Amount == 0, because the preceding function may have set a non-0 |
257 | // GNU_ARGS_SIZE. |
258 | // TODO: We don't need to reset this between subsequent functions, |
259 | // if it didn't change. |
260 | bool HasDwarfEHHandlers = !MF.getLandingPads().empty(); |
261 | |
262 | if (HasDwarfEHHandlers && !IsDestroy && |
263 | MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences()) { |
264 | BuildCFI(MBB, MBBI: I, DL, |
265 | CFIInst: MCCFIInstruction::createGnuArgsSize(L: nullptr, Size: Amount)); |
266 | } |
267 | |
268 | if (Amount == 0) |
269 | return I; |
270 | |
271 | // Factor out the amount that gets handled inside the sequence |
272 | // (Pushes of argument for frame setup, callee pops for frame destroy) |
273 | Amount -= InternalAmt; |
274 | |
275 | // TODO: This is needed only if we require precise CFA. |
276 | // If this is a callee-pop calling convention, emit a CFA adjust for |
277 | // the amount the callee popped. |
278 | if (IsDestroy && InternalAmt && DwarfCFI && !hasFP(MF)) |
279 | BuildCFI(MBB, MBBI: I, DL, |
280 | CFIInst: MCCFIInstruction::createAdjustCfaOffset(L: nullptr, Adjustment: -InternalAmt)); |
281 | |
282 | // Add Amount to SP to destroy a frame, or subtract to setup. |
283 | int64_t StackAdjustment = IsDestroy ? Amount : -Amount; |
284 | int64_t CfaAdjustment = -StackAdjustment; |
285 | |
286 | if (StackAdjustment) { |
287 | // Merge with any previous or following adjustment instruction. Note: the |
288 | // instructions merged with here do not have CFI, so their stack |
289 | // adjustments do not feed into CfaAdjustment. |
290 | StackAdjustment += mergeSPUpdates(MBB, MBBI&: I, doMergeWithPrevious: true); |
291 | StackAdjustment += mergeSPUpdates(MBB, MBBI&: I, doMergeWithPrevious: false); |
292 | |
293 | if (StackAdjustment) { |
294 | BuildStackAdjustment(MBB, MBBI: I, DL, Offset: StackAdjustment, InEpilogue: false); |
295 | } |
296 | } |
297 | |
298 | if (DwarfCFI && !hasFP(MF)) { |
299 | // If we don't have FP, but need to generate unwind information, |
300 | // we need to set the correct CFA offset after the stack adjustment. |
301 | // How much we adjust the CFA offset depends on whether we're emitting |
302 | // CFI only for EH purposes or for debugging. EH only requires the CFA |
303 | // offset to be correct at each call site, while for debugging we want |
304 | // it to be more precise. |
305 | |
306 | // TODO: When not using precise CFA, we also need to adjust for the |
307 | // InternalAmt here. |
308 | if (CfaAdjustment) { |
309 | BuildCFI( |
310 | MBB, MBBI: I, DL, |
311 | CFIInst: MCCFIInstruction::createAdjustCfaOffset(L: nullptr, Adjustment: CfaAdjustment)); |
312 | } |
313 | } |
314 | |
315 | return I; |
316 | } |
317 | |
318 | if (IsDestroy && InternalAmt) { |
319 | // If we are performing frame pointer elimination and if the callee pops |
320 | // something off the stack pointer, add it back. We do this until we have |
321 | // more advanced stack pointer tracking ability. |
322 | // We are not tracking the stack pointer adjustment by the callee, so make |
323 | // sure we restore the stack pointer immediately after the call, there may |
324 | // be spill code inserted between the CALL and ADJCALLSTACKUP instructions. |
325 | MachineBasicBlock::iterator CI = I; |
326 | MachineBasicBlock::iterator B = MBB.begin(); |
327 | while (CI != B && !std::prev(x: CI)->isCall()) |
328 | --CI; |
329 | BuildStackAdjustment(MBB, MBBI: CI, DL, Offset: -InternalAmt, /*InEpilogue=*/false); |
330 | } |
331 | |
332 | return I; |
333 | } |
334 | |
335 | /// Emit a series of instructions to increment / decrement the stack pointer by |
336 | /// a constant value. |
337 | void M68kFrameLowering::emitSPUpdate(MachineBasicBlock &MBB, |
338 | MachineBasicBlock::iterator &MBBI, |
339 | int64_t NumBytes, bool InEpilogue) const { |
340 | bool IsSub = NumBytes < 0; |
341 | uint64_t Offset = IsSub ? -NumBytes : NumBytes; |
342 | |
343 | uint64_t Chunk = (1LL << 31) - 1; |
344 | DebugLoc DL = MBB.findDebugLoc(MBBI); |
345 | |
346 | while (Offset) { |
347 | if (Offset > Chunk) { |
348 | // Rather than emit a long series of instructions for large offsets, |
349 | // load the offset into a register and do one sub/add |
350 | Register Reg; |
351 | |
352 | if (IsSub && !isRegLiveIn(MBB, M68k::D0)) |
353 | Reg = M68k::D0; |
354 | else |
355 | Reg = findDeadCallerSavedReg(MBB, MBBI, TRI); |
356 | |
357 | if (Reg) { |
358 | unsigned Opc = M68k::MOV32ri; |
359 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: Opc), DestReg: Reg).addImm(Val: Offset); |
360 | Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar; |
361 | MachineInstr *MI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: Opc), DestReg: StackPtr) |
362 | .addReg(RegNo: StackPtr) |
363 | .addReg(RegNo: Reg); |
364 | // ??? still no CCR |
365 | MI->getOperand(i: 3).setIsDead(); // The CCR implicit def is dead. |
366 | Offset = 0; |
367 | continue; |
368 | } |
369 | } |
370 | |
371 | uint64_t ThisVal = std::min(a: Offset, b: Chunk); |
372 | |
373 | MachineInstrBuilder MI = BuildStackAdjustment( |
374 | MBB, MBBI, DL, Offset: IsSub ? -ThisVal : ThisVal, InEpilogue); |
375 | if (IsSub) |
376 | MI.setMIFlag(MachineInstr::FrameSetup); |
377 | else |
378 | MI.setMIFlag(MachineInstr::FrameDestroy); |
379 | |
380 | Offset -= ThisVal; |
381 | } |
382 | } |
383 | |
384 | int M68kFrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, |
385 | MachineBasicBlock::iterator &MBBI, |
386 | bool MergeWithPrevious) const { |
387 | if ((MergeWithPrevious && MBBI == MBB.begin()) || |
388 | (!MergeWithPrevious && MBBI == MBB.end())) |
389 | return 0; |
390 | |
391 | MachineBasicBlock::iterator PI = MergeWithPrevious ? std::prev(x: MBBI) : MBBI; |
392 | MachineBasicBlock::iterator NI = |
393 | MergeWithPrevious ? nullptr : std::next(x: MBBI); |
394 | unsigned Opc = PI->getOpcode(); |
395 | int Offset = 0; |
396 | |
397 | if (!MergeWithPrevious && NI != MBB.end() && |
398 | NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) { |
399 | // Don't merge with the next instruction if it has CFI. |
400 | return Offset; |
401 | } |
402 | |
403 | if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) { |
404 | assert(PI->getOperand(1).getReg() == StackPtr); |
405 | Offset += PI->getOperand(i: 2).getImm(); |
406 | MBB.erase(I: PI); |
407 | if (!MergeWithPrevious) |
408 | MBBI = NI; |
409 | } else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) { |
410 | assert(PI->getOperand(1).getReg() == StackPtr); |
411 | Offset -= PI->getOperand(i: 2).getImm(); |
412 | MBB.erase(I: PI); |
413 | if (!MergeWithPrevious) |
414 | MBBI = NI; |
415 | } |
416 | |
417 | return Offset; |
418 | } |
419 | |
420 | MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment( |
421 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
422 | const DebugLoc &DL, int64_t Offset, bool InEpilogue) const { |
423 | assert(Offset != 0 && "zero offset stack adjustment requested" ); |
424 | |
425 | // TODO can `lea` be used to adjust stack? |
426 | |
427 | bool IsSub = Offset < 0; |
428 | uint64_t AbsOffset = IsSub ? -Offset : Offset; |
429 | unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai; |
430 | |
431 | MachineInstrBuilder MI = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: Opc), DestReg: StackPtr) |
432 | .addReg(RegNo: StackPtr) |
433 | .addImm(Val: AbsOffset); |
434 | // FIXME Update CCR as well. For now we just |
435 | // conservatively say CCR implicit def is dead |
436 | MI->getOperand(i: 3).setIsDead(); |
437 | return MI; |
438 | } |
439 | |
440 | void M68kFrameLowering::BuildCFI(MachineBasicBlock &MBB, |
441 | MachineBasicBlock::iterator MBBI, |
442 | const DebugLoc &DL, |
443 | const MCCFIInstruction &CFIInst) const { |
444 | MachineFunction &MF = *MBB.getParent(); |
445 | unsigned CFIIndex = MF.addFrameInst(Inst: CFIInst); |
446 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::CFI_INSTRUCTION)) |
447 | .addCFIIndex(CFIIndex); |
448 | } |
449 | |
450 | void M68kFrameLowering::emitPrologueCalleeSavedFrameMoves( |
451 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
452 | const DebugLoc &DL) const { |
453 | MachineFunction &MF = *MBB.getParent(); |
454 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
455 | MachineModuleInfo &MMI = MF.getMMI(); |
456 | const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); |
457 | |
458 | // Add callee saved registers to move list. |
459 | const auto &CSI = MFI.getCalleeSavedInfo(); |
460 | if (CSI.empty()) |
461 | return; |
462 | |
463 | // Calculate offsets. |
464 | for (const auto &I : CSI) { |
465 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: I.getFrameIdx()); |
466 | Register Reg = I.getReg(); |
467 | |
468 | unsigned DwarfReg = MRI->getDwarfRegNum(RegNum: Reg, isEH: true); |
469 | BuildCFI(MBB, MBBI, DL, |
470 | CFIInst: MCCFIInstruction::createOffset(L: nullptr, Register: DwarfReg, Offset)); |
471 | } |
472 | } |
473 | |
474 | void M68kFrameLowering::emitPrologue(MachineFunction &MF, |
475 | MachineBasicBlock &MBB) const { |
476 | assert(&STI == &MF.getSubtarget<M68kSubtarget>() && |
477 | "MF used frame lowering for wrong subtarget" ); |
478 | |
479 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
480 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
481 | const auto &Fn = MF.getFunction(); |
482 | MachineModuleInfo &MMI = MF.getMMI(); |
483 | M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>(); |
484 | uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment. |
485 | uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate. |
486 | bool HasFP = hasFP(MF); |
487 | bool NeedsDwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry(); |
488 | Register FramePtr = TRI->getFrameRegister(MF); |
489 | const unsigned MachineFramePtr = FramePtr; |
490 | unsigned BasePtr = TRI->getBaseRegister(); |
491 | |
492 | // Debug location must be unknown since the first debug location is used |
493 | // to determine the end of the prologue. |
494 | DebugLoc DL; |
495 | |
496 | // Add RETADDR move area to callee saved frame size. |
497 | int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta(); |
498 | |
499 | if (TailCallReturnAddrDelta < 0) { |
500 | MMFI->setCalleeSavedFrameSize(MMFI->getCalleeSavedFrameSize() - |
501 | TailCallReturnAddrDelta); |
502 | } |
503 | |
504 | // Insert stack pointer adjustment for later moving of return addr. Only |
505 | // applies to tail call optimized functions where the callee argument stack |
506 | // size is bigger than the callers. |
507 | if (TailCallReturnAddrDelta < 0) { |
508 | BuildStackAdjustment(MBB, MBBI, DL, Offset: TailCallReturnAddrDelta, |
509 | /*InEpilogue=*/false) |
510 | .setMIFlag(MachineInstr::FrameSetup); |
511 | } |
512 | |
513 | // Mapping for machine moves: |
514 | // |
515 | // DST: VirtualFP AND |
516 | // SRC: VirtualFP => DW_CFA_def_cfa_offset |
517 | // ELSE => DW_CFA_def_cfa |
518 | // |
519 | // SRC: VirtualFP AND |
520 | // DST: Register => DW_CFA_def_cfa_register |
521 | // |
522 | // ELSE |
523 | // OFFSET < 0 => DW_CFA_offset_extended_sf |
524 | // REG < 64 => DW_CFA_offset + Reg |
525 | // ELSE => DW_CFA_offset_extended |
526 | |
527 | uint64_t NumBytes = 0; |
528 | int stackGrowth = -SlotSize; |
529 | |
530 | if (HasFP) { |
531 | // Calculate required stack adjustment. |
532 | uint64_t FrameSize = StackSize - SlotSize; |
533 | // If required, include space for extra hidden slot for stashing base |
534 | // pointer. |
535 | if (MMFI->getRestoreBasePointer()) |
536 | FrameSize += SlotSize; |
537 | |
538 | NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize(); |
539 | |
540 | // Callee-saved registers are pushed on stack before the stack is realigned. |
541 | if (TRI->hasStackRealignment(MF)) |
542 | NumBytes = alignTo(Value: NumBytes, Align: MaxAlign); |
543 | |
544 | // Get the offset of the stack slot for the FP register, which is |
545 | // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. |
546 | // Update the frame offset adjustment. |
547 | MFI.setOffsetAdjustment(-NumBytes); |
548 | |
549 | BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16)) |
550 | .addReg(M68k::WA6, RegState::Kill) |
551 | .addImm(-NumBytes) |
552 | .setMIFlag(MachineInstr::FrameSetup); |
553 | |
554 | if (NeedsDwarfCFI) { |
555 | // Mark the place where FP was saved. |
556 | // Define the current CFA rule to use the provided offset. |
557 | assert(StackSize); |
558 | BuildCFI(MBB, MBBI, DL, |
559 | CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: 2 * stackGrowth)); |
560 | |
561 | // Change the rule for the FramePtr to be an "offset" rule. |
562 | int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); |
563 | assert(DwarfFramePtr > 0); |
564 | BuildCFI(MBB, MBBI, DL, |
565 | CFIInst: MCCFIInstruction::createOffset(L: nullptr, Register: DwarfFramePtr, |
566 | Offset: 2 * stackGrowth)); |
567 | } |
568 | |
569 | if (NeedsDwarfCFI) { |
570 | // Mark effective beginning of when frame pointer becomes valid. |
571 | // Define the current CFA to use the FP register. |
572 | unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); |
573 | BuildCFI(MBB, MBBI, DL, |
574 | CFIInst: MCCFIInstruction::createDefCfaRegister(L: nullptr, Register: DwarfFramePtr)); |
575 | } |
576 | |
577 | // Mark the FramePtr as live-in in every block. Don't do this again for |
578 | // funclet prologues. |
579 | for (MachineBasicBlock &EveryMBB : MF) |
580 | EveryMBB.addLiveIn(PhysReg: MachineFramePtr); |
581 | } else { |
582 | NumBytes = StackSize - MMFI->getCalleeSavedFrameSize(); |
583 | } |
584 | |
585 | // Skip the callee-saved push instructions. |
586 | bool PushedRegs = false; |
587 | int StackOffset = 2 * stackGrowth; |
588 | |
589 | while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) && |
590 | MBBI->getOpcode() == M68k::PUSH32r) { |
591 | PushedRegs = true; |
592 | ++MBBI; |
593 | |
594 | if (!HasFP && NeedsDwarfCFI) { |
595 | // Mark callee-saved push instruction. |
596 | // Define the current CFA rule to use the provided offset. |
597 | assert(StackSize); |
598 | BuildCFI(MBB, MBBI, DL, |
599 | CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: StackOffset)); |
600 | StackOffset += stackGrowth; |
601 | } |
602 | } |
603 | |
604 | // Realign stack after we pushed callee-saved registers (so that we'll be |
605 | // able to calculate their offsets from the frame pointer). |
606 | if (TRI->hasStackRealignment(MF)) { |
607 | assert(HasFP && "There should be a frame pointer if stack is realigned." ); |
608 | BuildStackAlignAND(MBB, MBBI, DL, Reg: StackPtr, MaxAlign); |
609 | } |
610 | |
611 | // If there is an SUB32ri of SP immediately before this instruction, merge |
612 | // the two. This can be the case when tail call elimination is enabled and |
613 | // the callee has more arguments then the caller. |
614 | NumBytes -= mergeSPUpdates(MBB, MBBI, MergeWithPrevious: true); |
615 | |
616 | // Adjust stack pointer: ESP -= numbytes. |
617 | if (!HasFP) |
618 | emitSPUpdate(MBB, MBBI, NumBytes: -(int64_t)NumBytes, /*InEpilogue=*/false); |
619 | |
620 | unsigned SPOrEstablisher = StackPtr; |
621 | |
622 | // If we need a base pointer, set it up here. It's whatever the value |
623 | // of the stack pointer is at this point. Any variable size objects |
624 | // will be allocated after this, so we can still use the base pointer |
625 | // to reference locals. |
626 | if (TRI->hasBasePointer(MF)) { |
627 | // Update the base pointer with the current stack pointer. |
628 | BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr) |
629 | .addReg(SPOrEstablisher) |
630 | .setMIFlag(MachineInstr::FrameSetup); |
631 | if (MMFI->getRestoreBasePointer()) { |
632 | // Stash value of base pointer. Saving SP instead of FP shortens |
633 | // dependence chain. Used by SjLj EH. |
634 | unsigned Opm = M68k::MOV32ja; |
635 | M68k::addRegIndirectWithDisp(MIB: BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: Opm)), |
636 | Reg: FramePtr, IsKill: true, |
637 | Offset: MMFI->getRestoreBasePointerOffset()) |
638 | .addReg(RegNo: SPOrEstablisher) |
639 | .setMIFlag(MachineInstr::FrameSetup); |
640 | } |
641 | } |
642 | |
643 | if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) { |
644 | // Mark end of stack pointer adjustment. |
645 | if (!HasFP && NumBytes) { |
646 | // Define the current CFA rule to use the provided offset. |
647 | assert(StackSize); |
648 | BuildCFI( |
649 | MBB, MBBI, DL, |
650 | CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: -StackSize + stackGrowth)); |
651 | } |
652 | |
653 | // Emit DWARF info specifying the offsets of the callee-saved registers. |
654 | if (PushedRegs) |
655 | emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL); |
656 | } |
657 | |
658 | // TODO Interrupt handlers |
659 | // M68k Interrupt handling function cannot assume anything about the |
660 | // direction flag (DF in CCR register). Clear this flag by creating "cld" |
661 | // instruction in each prologue of interrupt handler function. The "cld" |
662 | // instruction should only in these cases: |
663 | // 1. The interrupt handling function uses any of the "rep" instructions. |
664 | // 2. Interrupt handling function calls another function. |
665 | } |
666 | |
667 | static bool isTailCallOpcode(unsigned Opc) { |
668 | return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq; |
669 | } |
670 | |
671 | void M68kFrameLowering::emitEpilogue(MachineFunction &MF, |
672 | MachineBasicBlock &MBB) const { |
673 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
674 | M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>(); |
675 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
676 | std::optional<unsigned> RetOpcode; |
677 | if (MBBI != MBB.end()) |
678 | RetOpcode = MBBI->getOpcode(); |
679 | DebugLoc DL; |
680 | if (MBBI != MBB.end()) |
681 | DL = MBBI->getDebugLoc(); |
682 | Register FramePtr = TRI->getFrameRegister(MF); |
683 | unsigned MachineFramePtr = FramePtr; |
684 | |
685 | // Get the number of bytes to allocate from the FrameInfo. |
686 | uint64_t StackSize = MFI.getStackSize(); |
687 | uint64_t MaxAlign = calculateMaxStackAlign(MF); |
688 | unsigned CSSize = MMFI->getCalleeSavedFrameSize(); |
689 | uint64_t NumBytes = 0; |
690 | |
691 | if (hasFP(MF)) { |
692 | // Calculate required stack adjustment. |
693 | uint64_t FrameSize = StackSize - SlotSize; |
694 | NumBytes = FrameSize - CSSize; |
695 | |
696 | // Callee-saved registers were pushed on stack before the stack was |
697 | // realigned. |
698 | if (TRI->hasStackRealignment(MF)) |
699 | NumBytes = alignTo(Value: FrameSize, Align: MaxAlign); |
700 | |
701 | } else { |
702 | NumBytes = StackSize - CSSize; |
703 | } |
704 | |
705 | // Skip the callee-saved pop instructions. |
706 | while (MBBI != MBB.begin()) { |
707 | MachineBasicBlock::iterator PI = std::prev(x: MBBI); |
708 | unsigned Opc = PI->getOpcode(); |
709 | |
710 | if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) && |
711 | Opc != M68k::DBG_VALUE && !PI->isTerminator()) |
712 | break; |
713 | |
714 | --MBBI; |
715 | } |
716 | MachineBasicBlock::iterator FirstCSPop = MBBI; |
717 | |
718 | if (MBBI != MBB.end()) |
719 | DL = MBBI->getDebugLoc(); |
720 | |
721 | // If there is an ADD32ri or SUB32ri of SP immediately before this |
722 | // instruction, merge the two instructions. |
723 | if (NumBytes || MFI.hasVarSizedObjects()) |
724 | NumBytes += mergeSPUpdates(MBB, MBBI, MergeWithPrevious: true); |
725 | |
726 | // If dynamic alloca is used, then reset SP to point to the last callee-saved |
727 | // slot before popping them off! Same applies for the case, when stack was |
728 | // realigned. Don't do this if this was a funclet epilogue, since the funclets |
729 | // will not do realignment or dynamic stack allocation. |
730 | if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) { |
731 | if (TRI->hasStackRealignment(MF)) |
732 | MBBI = FirstCSPop; |
733 | uint64_t LEAAmount = -CSSize; |
734 | |
735 | // 'move %FramePtr, SP' will not be recognized as an epilogue sequence. |
736 | // However, we may use this sequence if we have a frame pointer because the |
737 | // effects of the prologue can safely be undone. |
738 | if (LEAAmount != 0) { |
739 | unsigned Opc = M68k::LEA32p; |
740 | M68k::addRegIndirectWithDisp( |
741 | MIB: BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: Opc), DestReg: StackPtr), Reg: FramePtr, IsKill: false, |
742 | Offset: LEAAmount); |
743 | --MBBI; |
744 | } else { |
745 | BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK)) |
746 | .addReg(MachineFramePtr, RegState::Kill) |
747 | .setMIFlag(MachineInstr::FrameDestroy); |
748 | --MBBI; |
749 | } |
750 | } else if (hasFP(MF)) { |
751 | BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK)) |
752 | .addReg(MachineFramePtr, RegState::Kill) |
753 | .setMIFlag(MachineInstr::FrameDestroy); |
754 | } else if (NumBytes) { |
755 | // Adjust stack pointer back: SP += numbytes. |
756 | emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true); |
757 | --MBBI; |
758 | } |
759 | |
760 | if (!RetOpcode || !isTailCallOpcode(Opc: *RetOpcode)) { |
761 | // Add the return addr area delta back since we are not tail calling. |
762 | int Offset = -1 * MMFI->getTCReturnAddrDelta(); |
763 | assert(Offset >= 0 && "TCDelta should never be positive" ); |
764 | if (Offset) { |
765 | MBBI = MBB.getFirstTerminator(); |
766 | |
767 | // Check for possible merge with preceding ADD instruction. |
768 | Offset += mergeSPUpdates(MBB, MBBI, MergeWithPrevious: true); |
769 | emitSPUpdate(MBB, MBBI, NumBytes: Offset, /*InEpilogue=*/true); |
770 | } |
771 | } |
772 | } |
773 | |
774 | void M68kFrameLowering::determineCalleeSaves(MachineFunction &MF, |
775 | BitVector &SavedRegs, |
776 | RegScavenger *RS) const { |
777 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
778 | |
779 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
780 | |
781 | M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>(); |
782 | int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta(); |
783 | |
784 | if (TailCallReturnAddrDelta < 0) { |
785 | // create RETURNADDR area |
786 | // arg |
787 | // arg |
788 | // RETADDR |
789 | // { ... |
790 | // RETADDR area |
791 | // ... |
792 | // } |
793 | // [FP] |
794 | MFI.CreateFixedObject(Size: -TailCallReturnAddrDelta, |
795 | SPOffset: TailCallReturnAddrDelta - SlotSize, IsImmutable: true); |
796 | } |
797 | |
798 | // Spill the BasePtr if it's used. |
799 | if (TRI->hasBasePointer(MF)) { |
800 | SavedRegs.set(TRI->getBaseRegister()); |
801 | } |
802 | } |
803 | |
804 | bool M68kFrameLowering::assignCalleeSavedSpillSlots( |
805 | MachineFunction &MF, const TargetRegisterInfo *TRI, |
806 | std::vector<CalleeSavedInfo> &CSI) const { |
807 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
808 | M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>(); |
809 | |
810 | int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta(); |
811 | |
812 | if (hasFP(MF)) { |
813 | // emitPrologue always spills frame register the first thing. |
814 | SpillSlotOffset -= SlotSize; |
815 | MFI.CreateFixedSpillStackObject(Size: SlotSize, SPOffset: SpillSlotOffset); |
816 | |
817 | // Since emitPrologue and emitEpilogue will handle spilling and restoring of |
818 | // the frame register, we can delete it from CSI list and not have to worry |
819 | // about avoiding it later. |
820 | Register FPReg = TRI->getFrameRegister(MF); |
821 | for (unsigned i = 0, e = CSI.size(); i < e; ++i) { |
822 | if (TRI->regsOverlap(RegA: CSI[i].getReg(), RegB: FPReg)) { |
823 | CSI.erase(position: CSI.begin() + i); |
824 | break; |
825 | } |
826 | } |
827 | } |
828 | |
829 | // The rest is fine |
830 | return false; |
831 | } |
832 | |
833 | bool M68kFrameLowering::spillCalleeSavedRegisters( |
834 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
835 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
836 | auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI); |
837 | auto DL = MBB.findDebugLoc(MBBI: MI); |
838 | |
839 | int FI = 0; |
840 | unsigned Mask = 0; |
841 | for (const auto &Info : CSI) { |
842 | FI = std::max(a: FI, b: Info.getFrameIdx()); |
843 | Register Reg = Info.getReg(); |
844 | unsigned Shift = MRI.getSpillRegisterOrder(Reg); |
845 | Mask |= 1 << Shift; |
846 | } |
847 | |
848 | auto I = |
849 | M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI) |
850 | .addImm(Mask) |
851 | .setMIFlag(MachineInstr::FrameSetup); |
852 | |
853 | // Append implicit registers and mem locations |
854 | const MachineFunction &MF = *MBB.getParent(); |
855 | const MachineRegisterInfo &RI = MF.getRegInfo(); |
856 | for (const auto &Info : CSI) { |
857 | Register Reg = Info.getReg(); |
858 | bool IsLiveIn = RI.isLiveIn(Reg); |
859 | if (!IsLiveIn) |
860 | MBB.addLiveIn(PhysReg: Reg); |
861 | I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill); |
862 | M68k::addMemOperand(MIB: I, FI: Info.getFrameIdx(), Offset: 0); |
863 | } |
864 | |
865 | return true; |
866 | } |
867 | |
868 | bool M68kFrameLowering::restoreCalleeSavedRegisters( |
869 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
870 | MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
871 | auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI); |
872 | auto DL = MBB.findDebugLoc(MBBI: MI); |
873 | |
874 | int FI = 0; |
875 | unsigned Mask = 0; |
876 | for (const auto &Info : CSI) { |
877 | FI = std::max(a: FI, b: Info.getFrameIdx()); |
878 | Register Reg = Info.getReg(); |
879 | unsigned Shift = MRI.getSpillRegisterOrder(Reg); |
880 | Mask |= 1 << Shift; |
881 | } |
882 | |
883 | auto I = M68k::addFrameReference( |
884 | BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI) |
885 | .setMIFlag(MachineInstr::FrameDestroy); |
886 | |
887 | // Append implicit registers and mem locations |
888 | for (const auto &Info : CSI) { |
889 | I.addReg(Info.getReg(), RegState::ImplicitDefine); |
890 | M68k::addMemOperand(MIB: I, FI: Info.getFrameIdx(), Offset: 0); |
891 | } |
892 | |
893 | return true; |
894 | } |
895 | |