//===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the VE implementation of TargetFrameLowering class. // // On VE, stack frames are structured as follows: // // The stack grows downward. // // All of the individual frame areas on the frame below are optional, i.e. it's // possible to create a function so that the particular area isn't present // in the frame. // // At function entry, the "frame" looks as follows: // // | | Higher address // |----------------------------------------------| // | Parameter area for this function | // |----------------------------------------------| // | Register save area (RSA) for this function | // |----------------------------------------------| // | Return address for this function | // |----------------------------------------------| // | Frame pointer for this function | // |----------------------------------------------| <- sp // | | Lower address // // VE doesn't use on demand stack allocation, so user code generated by LLVM // needs to call VEOS to allocate stack frame. VE's ABI want to reduce the // number of VEOS calls, so ABI requires to allocate not only RSA (in general // CSR, callee saved register) area but also call frame at the prologue of // caller function. // // After the prologue has run, the frame has the following general structure. // Note that technically the last frame area (VLAs) doesn't get created until // in the main function body, after the prologue is run. However, it's depicted // here for completeness. // // | | Higher address // |----------------------------------------------| // | Parameter area for this function | // |----------------------------------------------| // | Register save area (RSA) for this function | // |----------------------------------------------| // | Return address for this function | // |----------------------------------------------| // | Frame pointer for this function | // |----------------------------------------------| <- fp(=old sp) // |.empty.space.to.make.part.below.aligned.in....| // |.case.it.needs.more.than.the.standard.16-byte.| (size of this area is // |.alignment....................................| unknown at compile time) // |----------------------------------------------| // | Local variables of fixed size including spill| // | slots | // |----------------------------------------------| <- bp(not defined by ABI, // |.variable-sized.local.variables.(VLAs)........| LLVM chooses SX17) // |..............................................| (size of this area is // |..............................................| unknown at compile time) // |----------------------------------------------| <- stack top (returned by // | Parameter area for callee | alloca) // |----------------------------------------------| // | Register save area (RSA) for callee | // |----------------------------------------------| // | Return address for callee | // |----------------------------------------------| // | Frame pointer for callee | // |----------------------------------------------| <- sp // | | Lower address // // To access the data in a frame, at-compile time, a constant offset must be // computable from one of the pointers (fp, bp, sp) to access it. The size // of the areas with a dotted background cannot be computed at compile-time // if they are present, making it required to have all three of fp, bp and // sp to be set up to be able to access all contents in the frame areas, // assuming all of the frame areas are non-empty. // // For most functions, some of the frame areas are empty. For those functions, // it may not be necessary to set up fp or bp: // * A base pointer is definitely needed when there are both VLAs and local // variables with more-than-default alignment requirements. // * A frame pointer is definitely needed when there are local variables with // more-than-default alignment requirements. // // In addition, VE ABI defines RSA frame, return address, and frame pointer // as follows: // // |----------------------------------------------| <- sp+176 // | %s18...%s33 | // |----------------------------------------------| <- sp+48 // | Linkage area register (%s17) | // |----------------------------------------------| <- sp+40 // | Procedure linkage table register (%plt=%s16) | // |----------------------------------------------| <- sp+32 // | Global offset table register (%got=%s15) | // |----------------------------------------------| <- sp+24 // | Thread pointer register (%tp=%s14) | // |----------------------------------------------| <- sp+16 // | Return address | // |----------------------------------------------| <- sp+8 // | Frame pointer | // |----------------------------------------------| <- sp+0 // // NOTE: This description is based on VE ABI and description in // AArch64FrameLowering.cpp. Thanks a lot. //===----------------------------------------------------------------------===// #include "VEFrameLowering.h" #include "VEInstrInfo.h" #include "VEMachineFunctionInfo.h" #include "VESubtarget.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/MathExtras.h" usingnamespacellvm; VEFrameLowering::VEFrameLowering(const VESubtarget &ST) : … { … } void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, uint64_t NumBytes, bool RequireFPUpdate) const { … } void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, uint64_t NumBytes, bool RequireFPUpdate) const { … } void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int64_t NumBytes, MaybeAlign MaybeAlign) const { … } void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { … } void VEFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { … } MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { … } void VEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { … } // hasFP - Return true if the specified function should have a dedicated frame // pointer register. This is true if the function has variable sized allocas // or if frame pointer elimination is disabled. bool VEFrameLowering::hasFP(const MachineFunction &MF) const { … } bool VEFrameLowering::hasBP(const MachineFunction &MF) const { … } bool VEFrameLowering::hasGOT(const MachineFunction &MF) const { … } StackOffset VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const { … } bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { … } void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { … }