diff --git a/lib/Target/VE/VEFrameLowering.cpp b/lib/Target/VE/VEFrameLowering.cpp index ec18bee7432..8be298b46f0 100644 --- a/lib/Target/VE/VEFrameLowering.cpp +++ b/lib/Target/VE/VEFrameLowering.cpp @@ -8,6 +8,105 @@ // // 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" diff --git a/lib/Target/VE/VESubtarget.cpp b/lib/Target/VE/VESubtarget.cpp index e15969cd609..a484e7c2c7a 100644 --- a/lib/Target/VE/VESubtarget.cpp +++ b/lib/Target/VE/VESubtarget.cpp @@ -48,50 +48,8 @@ VESubtarget::VESubtarget(const Triple &TT, const std::string &CPU, FrameLowering(*this) {} uint64_t VESubtarget::getAdjustedFrameSize(uint64_t FrameSize) const { - - // VE stack frame: - // - // +----------------------------------------+ - // | Locals and temporaries | - // +----------------------------------------+ - // | Parameter area for callee | - // 176(fp) | | - // +----------------------------------------+ - // | Register save area (RSA) for callee | - // | | - // 16(fp) | 20 * 8 bytes | - // +----------------------------------------+ - // 8(fp) | Return address | - // +----------------------------------------+ - // 0(fp) | Frame pointer of caller | - // --------+----------------------------------------+-------- - // | Locals and temporaries for callee | - // +----------------------------------------+ - // | Parameter area for callee of callee | - // +----------------------------------------+ - // 16(sp) | RSA for callee of callee | - // +----------------------------------------+ - // 8(sp) | Return address | - // +----------------------------------------+ - // 0(sp) | Frame pointer of callee | - // +----------------------------------------+ - - // RSA frame: - // +----------------------------------------------+ - // 168(fp) | %s33 | - // +----------------------------------------------+ - // | %s19...%s32 | - // +----------------------------------------------+ - // 48(fp) | %s18 | - // +----------------------------------------------+ - // 40(fp) | Linkage area register (%s17) | - // +----------------------------------------------+ - // 32(fp) | Procedure linkage table register (%plt=%s16) | - // +----------------------------------------------+ - // 24(fp) | Global offset table register (%got=%s15) | - // +----------------------------------------------+ - // 16(fp) | Thread pointer register (%tp=%s14) | - // +----------------------------------------------+ + // Calculate adjusted frame size by adding the size of RSA frame, + // return address, and frame poitner as described in VEFrameLowering.cpp. FrameSize += 176; // For RSA, RA, and FP. FrameSize = alignTo(FrameSize, 16); // Requires 16 bytes alignment.