| //==- AArch64FrameLowering.h - Define frame lowering for AArch64 -*- C++ -*--=// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This class implements the AArch64-specific parts of the TargetFrameLowering |
| // class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_AARCH64_FRAMEINFO_H |
| #define LLVM_AARCH64_FRAMEINFO_H |
| |
| #include "AArch64Subtarget.h" |
| #include "llvm/Target/TargetFrameLowering.h" |
| |
| namespace llvm { |
| class AArch64Subtarget; |
| |
| class AArch64FrameLowering : public TargetFrameLowering { |
| private: |
| // In order to unify the spilling and restoring of callee-saved registers into |
| // emitFrameMemOps, we need to be able to specify which instructions to use |
| // for the relevant memory operations on each register class. An array of the |
| // following struct is populated and passed in to achieve this. |
| struct LoadStoreMethod { |
| const TargetRegisterClass *RegClass; // E.g. GPR64RegClass |
| |
| // The preferred instruction. |
| unsigned PairOpcode; // E.g. LSPair64_STR |
| |
| // Sometimes only a single register can be handled at once. |
| unsigned SingleOpcode; // E.g. LS64_STR |
| }; |
| protected: |
| const AArch64Subtarget &STI; |
| |
| public: |
| explicit AArch64FrameLowering(const AArch64Subtarget &sti) |
| : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0, 16), |
| STI(sti) { |
| } |
| |
| /// emitProlog/emitEpilog - These methods insert prolog and epilog code into |
| /// the function. |
| virtual void emitPrologue(MachineFunction &MF) const; |
| virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; |
| |
| /// Decides how much stack adjustment to perform in each phase of the prologue |
| /// and epilogue. |
| void splitSPAdjustments(uint64_t Total, uint64_t &Initial, |
| uint64_t &Residual) const; |
| |
| int64_t resolveFrameIndexReference(MachineFunction &MF, int FrameIndex, |
| unsigned &FrameReg, int SPAdj, |
| bool IsCalleeSaveOp) const; |
| |
| virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, |
| RegScavenger *RS) const; |
| |
| virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| const std::vector<CalleeSavedInfo> &CSI, |
| const TargetRegisterInfo *TRI) const; |
| virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| const std::vector<CalleeSavedInfo> &CSI, |
| const TargetRegisterInfo *TRI) const; |
| |
| void eliminateCallFramePseudoInstr(MachineFunction &MF, |
| MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI) const; |
| |
| /// If the register is X30 (i.e. LR) and the return address is used in the |
| /// function then the callee-save store doesn't actually kill the register, |
| /// otherwise it does. |
| bool determinePrologueDeath(MachineBasicBlock &MBB, unsigned Reg) const; |
| |
| /// This function emits the loads or stores required during prologue and |
| /// epilogue as efficiently as possible. |
| /// |
| /// The operations involved in setting up and tearing down the frame are |
| /// similar enough to warrant a shared function, particularly as discrepancies |
| /// between the two would be disastrous. |
| void emitFrameMemOps(bool isStore, MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| const std::vector<CalleeSavedInfo> &CSI, |
| const TargetRegisterInfo *TRI, |
| LoadStoreMethod PossibleClasses[], |
| unsigned NumClasses) const; |
| |
| |
| virtual bool hasFP(const MachineFunction &MF) const; |
| |
| virtual bool useFPForAddressing(const MachineFunction &MF) const; |
| |
| /// On AA |
| virtual bool hasReservedCallFrame(const MachineFunction &MF) const; |
| |
| }; |
| |
| } // End llvm namespace |
| |
| #endif |