109467b48Spatrick //===- TargetFrameLoweringImpl.cpp - Implement target frame interface ------==//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // Implements the layout of a stack frame on the target machine.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/ADT/BitVector.h"
1409467b48Spatrick #include "llvm/CodeGen/MachineFrameInfo.h"
1509467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
1609467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
17*d415bd75Srobert #include "llvm/CodeGen/TargetFrameLowering.h"
1809467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
1909467b48Spatrick #include "llvm/IR/Attributes.h"
2009467b48Spatrick #include "llvm/IR/CallingConv.h"
2109467b48Spatrick #include "llvm/IR/Function.h"
22097a140dSpatrick #include "llvm/IR/InstrTypes.h"
23*d415bd75Srobert #include "llvm/MC/MCAsmInfo.h"
2409467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
2509467b48Spatrick #include "llvm/Support/Compiler.h"
2609467b48Spatrick #include "llvm/Target/TargetMachine.h"
2709467b48Spatrick #include "llvm/Target/TargetOptions.h"
2809467b48Spatrick 
2909467b48Spatrick using namespace llvm;
3009467b48Spatrick 
3109467b48Spatrick TargetFrameLowering::~TargetFrameLowering() = default;
3209467b48Spatrick 
enableCalleeSaveSkip(const MachineFunction & MF) const3309467b48Spatrick bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {
3409467b48Spatrick   assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
3509467b48Spatrick          MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
3609467b48Spatrick          !MF.getFunction().hasFnAttribute(Attribute::UWTable));
3709467b48Spatrick   return false;
3809467b48Spatrick }
3909467b48Spatrick 
enableCFIFixup(MachineFunction & MF) const40*d415bd75Srobert bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const {
41*d415bd75Srobert   return MF.needsFrameMoves() &&
42*d415bd75Srobert          !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
43*d415bd75Srobert }
44*d415bd75Srobert 
4509467b48Spatrick /// Returns the displacement from the frame register to the stack
4609467b48Spatrick /// frame of the specified index, along with the frame register used
4709467b48Spatrick /// (in output arg FrameReg). This is the default implementation which
4809467b48Spatrick /// is overridden for some targets.
4973471bf0Spatrick StackOffset
getFrameIndexReference(const MachineFunction & MF,int FI,Register & FrameReg) const5073471bf0Spatrick TargetFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
51097a140dSpatrick                                             Register &FrameReg) const {
5209467b48Spatrick   const MachineFrameInfo &MFI = MF.getFrameInfo();
5309467b48Spatrick   const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
5409467b48Spatrick 
5509467b48Spatrick   // By default, assume all frame indices are referenced via whatever
5609467b48Spatrick   // getFrameRegister() says. The target can override this if it's doing
5709467b48Spatrick   // something different.
5809467b48Spatrick   FrameReg = RI->getFrameRegister(MF);
5909467b48Spatrick 
6073471bf0Spatrick   return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() -
6173471bf0Spatrick                                getOffsetOfLocalArea() +
6273471bf0Spatrick                                MFI.getOffsetAdjustment());
6309467b48Spatrick }
6409467b48Spatrick 
needsFrameIndexResolution(const MachineFunction & MF) const6509467b48Spatrick bool TargetFrameLowering::needsFrameIndexResolution(
6609467b48Spatrick     const MachineFunction &MF) const {
6709467b48Spatrick   return MF.getFrameInfo().hasStackObjects();
6809467b48Spatrick }
6909467b48Spatrick 
getCalleeSaves(const MachineFunction & MF,BitVector & CalleeSaves) const7009467b48Spatrick void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF,
7109467b48Spatrick                                          BitVector &CalleeSaves) const {
7209467b48Spatrick   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
7309467b48Spatrick   CalleeSaves.resize(TRI.getNumRegs());
7409467b48Spatrick 
7509467b48Spatrick   const MachineFrameInfo &MFI = MF.getFrameInfo();
7609467b48Spatrick   if (!MFI.isCalleeSavedInfoValid())
7709467b48Spatrick     return;
7809467b48Spatrick 
7909467b48Spatrick   for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
8009467b48Spatrick     CalleeSaves.set(Info.getReg());
8109467b48Spatrick }
8209467b48Spatrick 
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const8309467b48Spatrick void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
8409467b48Spatrick                                                BitVector &SavedRegs,
8509467b48Spatrick                                                RegScavenger *RS) const {
8609467b48Spatrick   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
8709467b48Spatrick 
8809467b48Spatrick   // Resize before the early returns. Some backends expect that
8909467b48Spatrick   // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no
9009467b48Spatrick   // saved registers.
9109467b48Spatrick   SavedRegs.resize(TRI.getNumRegs());
9209467b48Spatrick 
9309467b48Spatrick   // When interprocedural register allocation is enabled caller saved registers
9409467b48Spatrick   // are preferred over callee saved registers.
9509467b48Spatrick   if (MF.getTarget().Options.EnableIPRA &&
9609467b48Spatrick       isSafeForNoCSROpt(MF.getFunction()) &&
9709467b48Spatrick       isProfitableForNoCSROpt(MF.getFunction()))
9809467b48Spatrick     return;
9909467b48Spatrick 
10009467b48Spatrick   // Get the callee saved register list...
10109467b48Spatrick   const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
10209467b48Spatrick 
10309467b48Spatrick   // Early exit if there are no callee saved registers.
10409467b48Spatrick   if (!CSRegs || CSRegs[0] == 0)
10509467b48Spatrick     return;
10609467b48Spatrick 
10709467b48Spatrick   // In Naked functions we aren't going to save any registers.
10809467b48Spatrick   if (MF.getFunction().hasFnAttribute(Attribute::Naked))
10909467b48Spatrick     return;
11009467b48Spatrick 
11109467b48Spatrick   // Noreturn+nounwind functions never restore CSR, so no saves are needed.
11209467b48Spatrick   // Purely noreturn functions may still return through throws, so those must
11309467b48Spatrick   // save CSR for caller exception handlers.
11409467b48Spatrick   //
11509467b48Spatrick   // If the function uses longjmp to break out of its current path of
11609467b48Spatrick   // execution we do not need the CSR spills either: setjmp stores all CSRs
11709467b48Spatrick   // it was called with into the jmp_buf, which longjmp then restores.
11809467b48Spatrick   if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
11909467b48Spatrick         MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
12009467b48Spatrick         !MF.getFunction().hasFnAttribute(Attribute::UWTable) &&
12109467b48Spatrick         enableCalleeSaveSkip(MF))
12209467b48Spatrick     return;
12309467b48Spatrick 
12409467b48Spatrick   // Functions which call __builtin_unwind_init get all their registers saved.
12509467b48Spatrick   bool CallsUnwindInit = MF.callsUnwindInit();
12609467b48Spatrick   const MachineRegisterInfo &MRI = MF.getRegInfo();
12709467b48Spatrick   for (unsigned i = 0; CSRegs[i]; ++i) {
12809467b48Spatrick     unsigned Reg = CSRegs[i];
12909467b48Spatrick     if (CallsUnwindInit || MRI.isPhysRegModified(Reg))
13009467b48Spatrick       SavedRegs.set(Reg);
13109467b48Spatrick   }
13209467b48Spatrick }
13309467b48Spatrick 
getStackAlignmentSkew(const MachineFunction & MF) const13409467b48Spatrick unsigned TargetFrameLowering::getStackAlignmentSkew(
13509467b48Spatrick     const MachineFunction &MF) const {
13609467b48Spatrick   // When HHVM function is called, the stack is skewed as the return address
13709467b48Spatrick   // is removed from the stack before we enter the function.
13809467b48Spatrick   if (LLVM_UNLIKELY(MF.getFunction().getCallingConv() == CallingConv::HHVM))
13909467b48Spatrick     return MF.getTarget().getAllocaPointerSize();
14009467b48Spatrick 
14109467b48Spatrick   return 0;
14209467b48Spatrick }
14309467b48Spatrick 
allocateScavengingFrameIndexesNearIncomingSP(const MachineFunction & MF) const144*d415bd75Srobert bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP(
145*d415bd75Srobert   const MachineFunction &MF) const {
146*d415bd75Srobert   if (!hasFP(MF))
147*d415bd75Srobert     return false;
148*d415bd75Srobert 
149*d415bd75Srobert   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
150*d415bd75Srobert   return RegInfo->useFPForScavengingIndex(MF) &&
151*d415bd75Srobert          !RegInfo->hasStackRealignment(MF);
152*d415bd75Srobert }
153*d415bd75Srobert 
isSafeForNoCSROpt(const Function & F)15409467b48Spatrick bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) {
15509467b48Spatrick   if (!F.hasLocalLinkage() || F.hasAddressTaken() ||
15609467b48Spatrick       !F.hasFnAttribute(Attribute::NoRecurse))
15709467b48Spatrick     return false;
15809467b48Spatrick   // Function should not be optimized as tail call.
15909467b48Spatrick   for (const User *U : F.users())
160097a140dSpatrick     if (auto *CB = dyn_cast<CallBase>(U))
161097a140dSpatrick       if (CB->isTailCall())
16209467b48Spatrick         return false;
16309467b48Spatrick   return true;
16409467b48Spatrick }
16509467b48Spatrick 
getInitialCFAOffset(const MachineFunction & MF) const16609467b48Spatrick int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {
16709467b48Spatrick   llvm_unreachable("getInitialCFAOffset() not implemented!");
16809467b48Spatrick }
16909467b48Spatrick 
170097a140dSpatrick Register
getInitialCFARegister(const MachineFunction & MF) const171097a140dSpatrick TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {
17209467b48Spatrick   llvm_unreachable("getInitialCFARegister() not implemented!");
17309467b48Spatrick }
174097a140dSpatrick 
175097a140dSpatrick TargetFrameLowering::DwarfFrameBase
getDwarfFrameBase(const MachineFunction & MF) const176097a140dSpatrick TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
177097a140dSpatrick   const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
178097a140dSpatrick   return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}};
179097a140dSpatrick }
180