//
// 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"
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.