mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
Compute correct frame sizes for SPARC v9 64-bit frames.
The save area is twice as big and there is no struct return slot. The stack pointer is always 16-byte aligned (after adding the bias). Also eliminate the stack adjustment instructions around calls when the function has a reserved stack frame. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179083 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8faf7df144
commit
6ed9284c2b
@ -37,18 +37,27 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
int NumBytes = (int) MFI->getStackSize();
|
||||
|
||||
// Emit the correct save instruction based on the number of bytes in
|
||||
// the frame. Minimum stack frame size according to V8 ABI is:
|
||||
// 16 words for register window spill
|
||||
// 1 word for address of returned aggregate-value
|
||||
// + 6 words for passing parameters on the stack
|
||||
// ----------
|
||||
// 23 words * 4 bytes per word = 92 bytes
|
||||
NumBytes += 92;
|
||||
if (SubTarget.is64Bit()) {
|
||||
// All 64-bit stack frames must be 16-byte aligned, and must reserve space
|
||||
// for spilling the 16 window registers at %sp+BIAS..%sp+BIAS+128.
|
||||
NumBytes += 128;
|
||||
// Frames with calls must also reserve space for 6 outgoing arguments
|
||||
// whether they are used or not. LowerCall_64 takes care of that.
|
||||
assert(NumBytes % 16 == 0 && "Stack size not 16-byte aligned");
|
||||
} else {
|
||||
// Emit the correct save instruction based on the number of bytes in
|
||||
// the frame. Minimum stack frame size according to V8 ABI is:
|
||||
// 16 words for register window spill
|
||||
// 1 word for address of returned aggregate-value
|
||||
// + 6 words for passing parameters on the stack
|
||||
// ----------
|
||||
// 23 words * 4 bytes per word = 92 bytes
|
||||
NumBytes += 92;
|
||||
|
||||
// Round up to next doubleword boundary -- a double-word boundary
|
||||
// is required by the ABI.
|
||||
NumBytes = (NumBytes + 7) & ~7;
|
||||
// Round up to next doubleword boundary -- a double-word boundary
|
||||
// is required by the ABI.
|
||||
NumBytes = RoundUpToAlignment(NumBytes, 8);
|
||||
}
|
||||
NumBytes = -NumBytes;
|
||||
|
||||
if (NumBytes >= -4096) {
|
||||
@ -70,15 +79,18 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
void SparcFrameLowering::
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
MachineInstr &MI = *I;
|
||||
DebugLoc dl = MI.getDebugLoc();
|
||||
int Size = MI.getOperand(0).getImm();
|
||||
if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
|
||||
Size = -Size;
|
||||
const SparcInstrInfo &TII =
|
||||
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
if (Size)
|
||||
BuildMI(MBB, I, dl, TII.get(SP::ADDri), SP::O6).addReg(SP::O6).addImm(Size);
|
||||
if (!hasReservedCallFrame(MF)) {
|
||||
MachineInstr &MI = *I;
|
||||
DebugLoc DL = MI.getDebugLoc();
|
||||
int Size = MI.getOperand(0).getImm();
|
||||
if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
|
||||
Size = -Size;
|
||||
const SparcInstrInfo &TII =
|
||||
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
if (Size)
|
||||
BuildMI(MBB, I, DL, TII.get(SP::ADDri), SP::O6).addReg(SP::O6)
|
||||
.addImm(Size);
|
||||
}
|
||||
MBB.erase(I);
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,12 @@ namespace llvm {
|
||||
class SparcSubtarget;
|
||||
|
||||
class SparcFrameLowering : public TargetFrameLowering {
|
||||
const SparcSubtarget &SubTarget;
|
||||
public:
|
||||
explicit SparcFrameLowering(const SparcSubtarget &/*sti*/)
|
||||
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, 0) {
|
||||
}
|
||||
explicit SparcFrameLowering(const SparcSubtarget &ST)
|
||||
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
|
||||
ST.is64Bit() ? 16 : 8, 0, ST.is64Bit() ? 16 : 8),
|
||||
SubTarget(ST) {}
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
|
@ -912,8 +912,9 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
|
||||
|
||||
// Get the size of the outgoing arguments stack space requirement.
|
||||
// The stack offset computed by CC_Sparc64 includes all arguments.
|
||||
// We always allocate space for 6 arguments in the prolog.
|
||||
unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()) - 6*8u;
|
||||
// Called functions expect 6 argument words to exist in the stack frame, used
|
||||
// or not.
|
||||
unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset());
|
||||
|
||||
// Keep stack frames 16-byte aligned.
|
||||
ArgsSize = RoundUpToAlignment(ArgsSize, 16);
|
||||
|
@ -1,6 +1,9 @@
|
||||
; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler | FileCheck %s
|
||||
|
||||
; CHECK: intarg
|
||||
; The save/restore frame is not strictly necessary here, but we would need to
|
||||
; refer to %o registers instead.
|
||||
; CHECK: save %sp, -128, %sp
|
||||
; CHECK: stb %i0, [%i4]
|
||||
; CHECK: stb %i1, [%i4]
|
||||
; CHECK: sth %i2, [%i4]
|
||||
@ -11,6 +14,7 @@
|
||||
; CHECK: st [[R]], [%i4]
|
||||
; CHECK: ldx [%fp+2231], [[R:%[gilo][0-7]]]
|
||||
; CHECK: stx [[R]], [%i4]
|
||||
; CHECK: restore
|
||||
define void @intarg(i8 %a0, ; %i0
|
||||
i8 %a1, ; %i1
|
||||
i16 %a2, ; %i2
|
||||
@ -34,18 +38,23 @@ define void @intarg(i8 %a0, ; %i0
|
||||
}
|
||||
|
||||
; CHECK: call_intarg
|
||||
; 16 saved + 8 args.
|
||||
; CHECK: save %sp, -192, %sp
|
||||
; Sign-extend and store the full 64 bits.
|
||||
; CHECK: sra %i0, 0, [[R:%[gilo][0-7]]]
|
||||
; CHECK: stx [[R]], [%sp+2223]
|
||||
; Use %o0-%o5 for outgoing arguments
|
||||
; CHECK: or %g0, 5, %o5
|
||||
; CHECK: call intarg
|
||||
; CHECK-NOT: add %sp
|
||||
; CHECK: restore
|
||||
define void @call_intarg(i32 %i0, i8* %i1) {
|
||||
call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: floatarg
|
||||
; CHECK: save %sp, -128, %sp
|
||||
; CHECK: fstod %f1,
|
||||
; CHECK: faddd %f2,
|
||||
; CHECK: faddd %f4,
|
||||
@ -81,12 +90,15 @@ define double @floatarg(float %a0, ; %f1
|
||||
}
|
||||
|
||||
; CHECK: call_floatarg
|
||||
; CHECK: save %sp, -272, %sp
|
||||
; Store 4 bytes, right-aligned in slot.
|
||||
; CHECK: st %f1, [%sp+2307]
|
||||
; Store 8 bytes in full slot.
|
||||
; CHECK: std %f2, [%sp+2311]
|
||||
; CHECK: fmovd %f2, %f4
|
||||
; CHECK: call floatarg
|
||||
; CHECK-NOT: add %sp
|
||||
; CHECK: restore
|
||||
define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
|
||||
%r = call double @floatarg(float %f5, double %d2, double %d2, double %d2,
|
||||
float %f5, float %f5, float %f5, float %f5,
|
||||
@ -127,6 +139,8 @@ define void @mixedarg(i8 %a0, ; %i0
|
||||
; CHECK: fmovd %f2, %f6
|
||||
; CHECK: fmovd %f2, %f16
|
||||
; CHECK: call mixedarg
|
||||
; CHECK-NOT: add %sp
|
||||
; CHECK: restore
|
||||
define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) {
|
||||
call void @mixedarg(i8 undef,
|
||||
float undef,
|
||||
@ -155,6 +169,8 @@ define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0
|
||||
}
|
||||
|
||||
; CHECK: call_inreg_fi
|
||||
; Allocate space for 6 arguments, even when only 2 are used.
|
||||
; CHECK: save %sp, -176, %sp
|
||||
; CHECK: sllx %i1, 32, %o0
|
||||
; CHECK: fmovs %f5, %f1
|
||||
; CHECK: call inreg_fi
|
||||
|
Loading…
Reference in New Issue
Block a user