xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/Thumb1FrameLowering.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- Thumb1FrameLowering.h - Thumb1-specific frame info stuff ---*- C++ -*-=//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_THUMB1FRAMELOWERING_H
10*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_THUMB1FRAMELOWERING_H
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "ARMFrameLowering.h"
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric namespace llvm {
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric class ARMSubtarget;
17*0b57cec5SDimitry Andric class MachineFunction;
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric class Thumb1FrameLowering : public ARMFrameLowering {
20*0b57cec5SDimitry Andric public:
21*0b57cec5SDimitry Andric   explicit Thumb1FrameLowering(const ARMSubtarget &sti);
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric   /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
24*0b57cec5SDimitry Andric   /// the function.
25*0b57cec5SDimitry Andric   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
26*0b57cec5SDimitry Andric   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
27*0b57cec5SDimitry Andric 
28*0b57cec5SDimitry Andric   bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
29*0b57cec5SDimitry Andric                                  MachineBasicBlock::iterator MI,
30*0b57cec5SDimitry Andric                                  const std::vector<CalleeSavedInfo> &CSI,
31*0b57cec5SDimitry Andric                                  const TargetRegisterInfo *TRI) const override;
32*0b57cec5SDimitry Andric   bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
33*0b57cec5SDimitry Andric                                   MachineBasicBlock::iterator MI,
34*0b57cec5SDimitry Andric                                   std::vector<CalleeSavedInfo> &CSI,
35*0b57cec5SDimitry Andric                                   const TargetRegisterInfo *TRI) const override;
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric   bool hasReservedCallFrame(const MachineFunction &MF) const override;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   MachineBasicBlock::iterator
40*0b57cec5SDimitry Andric   eliminateCallFramePseudoInstr(MachineFunction &MF,
41*0b57cec5SDimitry Andric                                 MachineBasicBlock &MBB,
42*0b57cec5SDimitry Andric                                 MachineBasicBlock::iterator MI) const override;
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric   /// Check whether or not the given \p MBB can be used as a epilogue
45*0b57cec5SDimitry Andric   /// for the target.
46*0b57cec5SDimitry Andric   /// The epilogue will be inserted before the first terminator of that block.
47*0b57cec5SDimitry Andric   /// This method is used by the shrink-wrapping pass to decide if
48*0b57cec5SDimitry Andric   /// \p MBB will be correctly handled by the target.
49*0b57cec5SDimitry Andric   bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric   /// Disable shrink wrap as tBfar/BL will be used to adjust for long jumps.
52*0b57cec5SDimitry Andric   bool enableShrinkWrapping(const MachineFunction &MF) const override {
53*0b57cec5SDimitry Andric     return false;
54*0b57cec5SDimitry Andric   }
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric private:
57*0b57cec5SDimitry Andric   /// Check if the frame lowering of \p MF needs a special fixup
58*0b57cec5SDimitry Andric   /// code sequence for the epilogue.
59*0b57cec5SDimitry Andric   /// Unlike T2 and ARM mode, the T1 pop instruction cannot restore
60*0b57cec5SDimitry Andric   /// to LR, and we can't pop the value directly to the PC when
61*0b57cec5SDimitry Andric   /// we need to update the SP after popping the value. So instead
62*0b57cec5SDimitry Andric   /// we have to emit:
63*0b57cec5SDimitry Andric   ///   POP {r3}
64*0b57cec5SDimitry Andric   ///   ADD sp, #offset
65*0b57cec5SDimitry Andric   ///   BX r3
66*0b57cec5SDimitry Andric   /// If this would clobber a return value, then generate this sequence instead:
67*0b57cec5SDimitry Andric   ///   MOV ip, r3
68*0b57cec5SDimitry Andric   ///   POP {r3}
69*0b57cec5SDimitry Andric   ///   ADD sp, #offset
70*0b57cec5SDimitry Andric   ///   MOV lr, r3
71*0b57cec5SDimitry Andric   ///   MOV r3, ip
72*0b57cec5SDimitry Andric   ///   BX lr
73*0b57cec5SDimitry Andric   bool needPopSpecialFixUp(const MachineFunction &MF) const;
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   /// Emit the special fixup code sequence for the epilogue.
76*0b57cec5SDimitry Andric   /// \see needPopSpecialFixUp for more details.
77*0b57cec5SDimitry Andric   /// \p DoIt, tells this method whether or not to actually insert
78*0b57cec5SDimitry Andric   /// the code sequence in \p MBB. I.e., when \p DoIt is false,
79*0b57cec5SDimitry Andric   /// \p MBB is left untouched.
80*0b57cec5SDimitry Andric   /// \returns For \p DoIt == true: True when the emission succeeded
81*0b57cec5SDimitry Andric   /// false otherwise. For \p DoIt == false: True when the emission
82*0b57cec5SDimitry Andric   /// would have been possible, false otherwise.
83*0b57cec5SDimitry Andric   bool emitPopSpecialFixUp(MachineBasicBlock &MBB, bool DoIt) const;
84*0b57cec5SDimitry Andric };
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric } // end namespace llvm
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_THUMB1FRAMELOWERING_H
89