xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZFrameLowering.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- SystemZFrameLowering.h - Frame lowering for SystemZ -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZFRAMELOWERING_H
100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZFRAMELOWERING_H
110b57cec5SDimitry Andric 
12e8d8bef9SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
13349cc55cSDimitry Andric #include "SystemZInstrBuilder.h"
14349cc55cSDimitry Andric #include "SystemZMachineFunctionInfo.h"
150b57cec5SDimitry Andric #include "llvm/ADT/IndexedMap.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
17e8d8bef9SDimitry Andric #include "llvm/Support/TypeSize.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace llvm {
200b57cec5SDimitry Andric class SystemZSubtarget;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric class SystemZFrameLowering : public TargetFrameLowering {
23349cc55cSDimitry Andric public:
24349cc55cSDimitry Andric   SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl,
25*0fca6ea1SDimitry Andric                        bool StackReal, unsigned PointerSize);
26349cc55cSDimitry Andric 
27349cc55cSDimitry Andric   static std::unique_ptr<SystemZFrameLowering>
28349cc55cSDimitry Andric   create(const SystemZSubtarget &STI);
29349cc55cSDimitry Andric 
30349cc55cSDimitry Andric   // Override TargetFrameLowering.
314824e7fdSDimitry Andric   bool allocateScavengingFrameIndexesNearIncomingSP(
324824e7fdSDimitry Andric     const MachineFunction &MF) const override {
334824e7fdSDimitry Andric     // SystemZ wants normal register scavenging slots, as close to the stack or
344824e7fdSDimitry Andric     // frame pointer as possible.
354824e7fdSDimitry Andric     // The default implementation assumes an x86-like layout, where the frame
364824e7fdSDimitry Andric     // pointer is at the opposite end of the frame from the stack pointer.
374824e7fdSDimitry Andric     // This meant that when frame pointer elimination was disabled,
384824e7fdSDimitry Andric     // the slots ended up being as close as possible to the incoming
394824e7fdSDimitry Andric     // stack pointer, which is the opposite of what we want on SystemZ.
404824e7fdSDimitry Andric     return false;
414824e7fdSDimitry Andric   }
424824e7fdSDimitry Andric 
43349cc55cSDimitry Andric   bool hasReservedCallFrame(const MachineFunction &MF) const override;
44*0fca6ea1SDimitry Andric 
45*0fca6ea1SDimitry Andric   // Return the offset of the backchain.
46*0fca6ea1SDimitry Andric   virtual unsigned getBackchainOffset(MachineFunction &MF) const = 0;
47*0fca6ea1SDimitry Andric 
48*0fca6ea1SDimitry Andric   // Return the offset of the return address.
49*0fca6ea1SDimitry Andric   virtual int getReturnAddressOffset(MachineFunction &MF) const = 0;
50*0fca6ea1SDimitry Andric 
51*0fca6ea1SDimitry Andric   // Get or create the frame index of where the old frame pointer is stored.
52*0fca6ea1SDimitry Andric   virtual int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const = 0;
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric   // Return the size of a pointer (in bytes).
55*0fca6ea1SDimitry Andric   unsigned getPointerSize() const { return PointerSize; }
56*0fca6ea1SDimitry Andric 
57*0fca6ea1SDimitry Andric private:
58*0fca6ea1SDimitry Andric   unsigned PointerSize;
59349cc55cSDimitry Andric };
60349cc55cSDimitry Andric 
61349cc55cSDimitry Andric class SystemZELFFrameLowering : public SystemZFrameLowering {
620b57cec5SDimitry Andric   IndexedMap<unsigned> RegSpillOffsets;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric public:
65*0fca6ea1SDimitry Andric   SystemZELFFrameLowering(unsigned PointerSize);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   // Override TargetFrameLowering.
68480093f4SDimitry Andric   bool
69480093f4SDimitry Andric   assignCalleeSavedSpillSlots(MachineFunction &MF,
70480093f4SDimitry Andric                               const TargetRegisterInfo *TRI,
71480093f4SDimitry Andric                               std::vector<CalleeSavedInfo> &CSI) const override;
720b57cec5SDimitry Andric   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
730b57cec5SDimitry Andric                             RegScavenger *RS) const override;
740b57cec5SDimitry Andric   bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
750b57cec5SDimitry Andric                                  MachineBasicBlock::iterator MBBI,
765ffd83dbSDimitry Andric                                  ArrayRef<CalleeSavedInfo> CSI,
770b57cec5SDimitry Andric                                  const TargetRegisterInfo *TRI) const override;
785ffd83dbSDimitry Andric   bool
795ffd83dbSDimitry Andric   restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
800b57cec5SDimitry Andric                               MachineBasicBlock::iterator MBBII,
815ffd83dbSDimitry Andric                               MutableArrayRef<CalleeSavedInfo> CSI,
825ffd83dbSDimitry Andric                               const TargetRegisterInfo *TRI) const override;
830b57cec5SDimitry Andric   void processFunctionBeforeFrameFinalized(MachineFunction &MF,
840b57cec5SDimitry Andric                                            RegScavenger *RS) const override;
850b57cec5SDimitry Andric   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
860b57cec5SDimitry Andric   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
875ffd83dbSDimitry Andric   void inlineStackProbe(MachineFunction &MF,
885ffd83dbSDimitry Andric                         MachineBasicBlock &PrologMBB) const override;
890b57cec5SDimitry Andric   bool hasFP(const MachineFunction &MF) const override;
90e8d8bef9SDimitry Andric   StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
915ffd83dbSDimitry Andric                                      Register &FrameReg) const override;
921fd87a68SDimitry Andric   void
931fd87a68SDimitry Andric   orderFrameObjects(const MachineFunction &MF,
941fd87a68SDimitry Andric                     SmallVectorImpl<int> &ObjectsToAllocate) const override;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   // Return the byte offset from the incoming stack pointer of Reg's
975ffd83dbSDimitry Andric   // ABI-defined save slot.  Return 0 if no slot is defined for Reg.  Adjust
985ffd83dbSDimitry Andric   // the offset in case MF has packed-stack.
995ffd83dbSDimitry Andric   unsigned getRegSpillOffset(MachineFunction &MF, Register Reg) const;
100480093f4SDimitry Andric 
1015ffd83dbSDimitry Andric   bool usePackedStack(MachineFunction &MF) const;
102e8d8bef9SDimitry Andric 
103e8d8bef9SDimitry Andric   // Return the offset of the backchain.
104*0fca6ea1SDimitry Andric   unsigned getBackchainOffset(MachineFunction &MF) const override {
105e8d8bef9SDimitry Andric     // The back chain is stored topmost with packed-stack.
106fe6060f1SDimitry Andric     return usePackedStack(MF) ? SystemZMC::ELFCallFrameSize - 8 : 0;
107e8d8bef9SDimitry Andric   }
108349cc55cSDimitry Andric 
109*0fca6ea1SDimitry Andric   // Return the offset of the return address.
110*0fca6ea1SDimitry Andric   int getReturnAddressOffset(MachineFunction &MF) const override {
111*0fca6ea1SDimitry Andric     return (usePackedStack(MF) ? -2 : 14) * getPointerSize();
112*0fca6ea1SDimitry Andric   }
113*0fca6ea1SDimitry Andric 
114349cc55cSDimitry Andric   // Get or create the frame index of where the old frame pointer is stored.
115*0fca6ea1SDimitry Andric   int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override;
116349cc55cSDimitry Andric };
117349cc55cSDimitry Andric 
118349cc55cSDimitry Andric class SystemZXPLINKFrameLowering : public SystemZFrameLowering {
119349cc55cSDimitry Andric   IndexedMap<unsigned> RegSpillOffsets;
120349cc55cSDimitry Andric 
121349cc55cSDimitry Andric public:
122*0fca6ea1SDimitry Andric   SystemZXPLINKFrameLowering(unsigned PointerSize);
123349cc55cSDimitry Andric 
124349cc55cSDimitry Andric   bool
125349cc55cSDimitry Andric   assignCalleeSavedSpillSlots(MachineFunction &MF,
126349cc55cSDimitry Andric                               const TargetRegisterInfo *TRI,
127349cc55cSDimitry Andric                               std::vector<CalleeSavedInfo> &CSI) const override;
128349cc55cSDimitry Andric 
129349cc55cSDimitry Andric   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
130349cc55cSDimitry Andric                             RegScavenger *RS) const override;
131349cc55cSDimitry Andric 
132349cc55cSDimitry Andric   bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
133349cc55cSDimitry Andric                                  MachineBasicBlock::iterator MBBI,
134349cc55cSDimitry Andric                                  ArrayRef<CalleeSavedInfo> CSI,
135349cc55cSDimitry Andric                                  const TargetRegisterInfo *TRI) const override;
136349cc55cSDimitry Andric 
1370eae32dcSDimitry Andric   bool
1380eae32dcSDimitry Andric   restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
1390eae32dcSDimitry Andric                               MachineBasicBlock::iterator MBBII,
1400eae32dcSDimitry Andric                               MutableArrayRef<CalleeSavedInfo> CSI,
1410eae32dcSDimitry Andric                               const TargetRegisterInfo *TRI) const override;
1420eae32dcSDimitry Andric 
143349cc55cSDimitry Andric   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
144349cc55cSDimitry Andric 
145349cc55cSDimitry Andric   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
146349cc55cSDimitry Andric 
14781ad6265SDimitry Andric   void inlineStackProbe(MachineFunction &MF,
14881ad6265SDimitry Andric                         MachineBasicBlock &PrologMBB) const override;
14981ad6265SDimitry Andric 
150349cc55cSDimitry Andric   bool hasFP(const MachineFunction &MF) const override;
1510eae32dcSDimitry Andric 
1520eae32dcSDimitry Andric   void processFunctionBeforeFrameFinalized(MachineFunction &MF,
1530eae32dcSDimitry Andric                                            RegScavenger *RS) const override;
154fcaf7f86SDimitry Andric 
155fcaf7f86SDimitry Andric   void determineFrameLayout(MachineFunction &MF) const;
156*0fca6ea1SDimitry Andric 
157*0fca6ea1SDimitry Andric   // Return the offset of the backchain.
158*0fca6ea1SDimitry Andric   unsigned getBackchainOffset(MachineFunction &MF) const override {
159*0fca6ea1SDimitry Andric     // The back chain is always the first element of the frame.
160*0fca6ea1SDimitry Andric     return 0;
161*0fca6ea1SDimitry Andric   }
162*0fca6ea1SDimitry Andric 
163*0fca6ea1SDimitry Andric   // Return the offset of the return address.
164*0fca6ea1SDimitry Andric   int getReturnAddressOffset(MachineFunction &MF) const override {
165*0fca6ea1SDimitry Andric     return 3 * getPointerSize();
166*0fca6ea1SDimitry Andric   }
167*0fca6ea1SDimitry Andric 
168*0fca6ea1SDimitry Andric   // Get or create the frame index of where the old frame pointer is stored.
169*0fca6ea1SDimitry Andric   int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override;
1700b57cec5SDimitry Andric };
1710b57cec5SDimitry Andric } // end namespace llvm
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric #endif
174