forked from OSchip/llvm-project
Revert "Revert "[PowerPC][ELFv2ABI] Allocate parameter area on-demand to reduce stack frame size""
After inspection, it's an UB in our code base. Someone cast a var-arg function pointer to a non-var-arg one. :/ Re-commit r296771 to continue testing on the patch. Sorry for the trouble! llvm-svn: 297256
This commit is contained in:
parent
5dd24f5a2e
commit
c7472d912b
|
@ -5147,10 +5147,30 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned NumGPRs = array_lengthof(GPR);
|
const unsigned NumGPRs = array_lengthof(GPR);
|
||||||
const unsigned NumFPRs = 13;
|
const unsigned NumFPRs = useSoftFloat() ? 0 : 13;
|
||||||
const unsigned NumVRs = array_lengthof(VR);
|
const unsigned NumVRs = array_lengthof(VR);
|
||||||
const unsigned NumQFPRs = NumFPRs;
|
const unsigned NumQFPRs = NumFPRs;
|
||||||
|
|
||||||
|
// On ELFv2, we can avoid allocating the parameter area if all the arguments
|
||||||
|
// can be passed to the callee in registers.
|
||||||
|
// For the fast calling convention, there is another check below.
|
||||||
|
// Note: keep consistent with LowerFormalArguments_64SVR4()
|
||||||
|
bool HasParameterArea = !isELFv2ABI || isVarArg || CallConv == CallingConv::Fast;
|
||||||
|
if (!HasParameterArea) {
|
||||||
|
unsigned ParamAreaSize = NumGPRs * PtrByteSize;
|
||||||
|
unsigned AvailableFPRs = NumFPRs;
|
||||||
|
unsigned AvailableVRs = NumVRs;
|
||||||
|
unsigned NumBytesTmp = NumBytes;
|
||||||
|
for (unsigned i = 0; i != NumOps; ++i) {
|
||||||
|
if (Outs[i].Flags.isNest()) continue;
|
||||||
|
if (CalculateStackSlotUsed(Outs[i].VT, Outs[i].ArgVT, Outs[i].Flags,
|
||||||
|
PtrByteSize, LinkageSize, ParamAreaSize,
|
||||||
|
NumBytesTmp, AvailableFPRs, AvailableVRs,
|
||||||
|
Subtarget.hasQPX()))
|
||||||
|
HasParameterArea = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When using the fast calling convention, we don't provide backing for
|
// When using the fast calling convention, we don't provide backing for
|
||||||
// arguments that will be in registers.
|
// arguments that will be in registers.
|
||||||
unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
|
unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
|
||||||
|
@ -5218,13 +5238,18 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
|
|
||||||
unsigned NumBytesActuallyUsed = NumBytes;
|
unsigned NumBytesActuallyUsed = NumBytes;
|
||||||
|
|
||||||
// The prolog code of the callee may store up to 8 GPR argument registers to
|
// In the old ELFv1 ABI,
|
||||||
|
// the prolog code of the callee may store up to 8 GPR argument registers to
|
||||||
// the stack, allowing va_start to index over them in memory if its varargs.
|
// the stack, allowing va_start to index over them in memory if its varargs.
|
||||||
// Because we cannot tell if this is needed on the caller side, we have to
|
// Because we cannot tell if this is needed on the caller side, we have to
|
||||||
// conservatively assume that it is needed. As such, make sure we have at
|
// conservatively assume that it is needed. As such, make sure we have at
|
||||||
// least enough stack space for the caller to store the 8 GPRs.
|
// least enough stack space for the caller to store the 8 GPRs.
|
||||||
// FIXME: On ELFv2, it may be unnecessary to allocate the parameter area.
|
// In the ELFv2 ABI, we allocate the parameter area iff a callee
|
||||||
NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
|
// really requires memory operands, e.g. a vararg function.
|
||||||
|
if (HasParameterArea)
|
||||||
|
NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
|
||||||
|
else
|
||||||
|
NumBytes = LinkageSize;
|
||||||
|
|
||||||
// Tail call needs the stack to be aligned.
|
// Tail call needs the stack to be aligned.
|
||||||
if (getTargetMachine().Options.GuaranteedTailCallOpt &&
|
if (getTargetMachine().Options.GuaranteedTailCallOpt &&
|
||||||
|
@ -5443,6 +5468,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
if (CallConv == CallingConv::Fast)
|
if (CallConv == CallingConv::Fast)
|
||||||
ComputePtrOff();
|
ComputePtrOff();
|
||||||
|
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist to pass an argument in memory.");
|
||||||
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
||||||
true, isTailCall, false, MemOpChains,
|
true, isTailCall, false, MemOpChains,
|
||||||
TailCallArguments, dl);
|
TailCallArguments, dl);
|
||||||
|
@ -5528,6 +5555,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, ConstFour);
|
PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, ConstFour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist to pass an argument in memory.");
|
||||||
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
||||||
true, isTailCall, false, MemOpChains,
|
true, isTailCall, false, MemOpChains,
|
||||||
TailCallArguments, dl);
|
TailCallArguments, dl);
|
||||||
|
@ -5562,6 +5591,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
// GPRs when within range. For now, we always put the value in both
|
// GPRs when within range. For now, we always put the value in both
|
||||||
// locations (or even all three).
|
// locations (or even all three).
|
||||||
if (isVarArg) {
|
if (isVarArg) {
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist if we have a varargs call.");
|
||||||
// We could elide this store in the case where the object fits
|
// We could elide this store in the case where the object fits
|
||||||
// entirely in R registers. Maybe later.
|
// entirely in R registers. Maybe later.
|
||||||
SDValue Store =
|
SDValue Store =
|
||||||
|
@ -5594,6 +5625,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
if (CallConv == CallingConv::Fast)
|
if (CallConv == CallingConv::Fast)
|
||||||
ComputePtrOff();
|
ComputePtrOff();
|
||||||
|
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist to pass an argument in memory.");
|
||||||
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
||||||
true, isTailCall, true, MemOpChains,
|
true, isTailCall, true, MemOpChains,
|
||||||
TailCallArguments, dl);
|
TailCallArguments, dl);
|
||||||
|
@ -5614,6 +5647,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
case MVT::v4i1: {
|
case MVT::v4i1: {
|
||||||
bool IsF32 = Arg.getValueType().getSimpleVT().SimpleTy == MVT::v4f32;
|
bool IsF32 = Arg.getValueType().getSimpleVT().SimpleTy == MVT::v4f32;
|
||||||
if (isVarArg) {
|
if (isVarArg) {
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist if we have a varargs call.");
|
||||||
// We could elide this store in the case where the object fits
|
// We could elide this store in the case where the object fits
|
||||||
// entirely in R registers. Maybe later.
|
// entirely in R registers. Maybe later.
|
||||||
SDValue Store =
|
SDValue Store =
|
||||||
|
@ -5646,6 +5681,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
if (CallConv == CallingConv::Fast)
|
if (CallConv == CallingConv::Fast)
|
||||||
ComputePtrOff();
|
ComputePtrOff();
|
||||||
|
|
||||||
|
assert(HasParameterArea &&
|
||||||
|
"Parameter area must exist to pass an argument in memory.");
|
||||||
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset,
|
||||||
true, isTailCall, true, MemOpChains,
|
true, isTailCall, true, MemOpChains,
|
||||||
TailCallArguments, dl);
|
TailCallArguments, dl);
|
||||||
|
@ -5660,7 +5697,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(NumBytesActuallyUsed == ArgOffset);
|
assert((!HasParameterArea || NumBytesActuallyUsed == ArgOffset) &&
|
||||||
|
"mismatch in size of parameter area");
|
||||||
(void)NumBytesActuallyUsed;
|
(void)NumBytesActuallyUsed;
|
||||||
|
|
||||||
if (!MemOpChains.empty())
|
if (!MemOpChains.empty())
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
; For ELFv2 ABI, we can avoid allocating the parameter area in the stack frame of the caller function
|
||||||
|
; if all the arguments can be passed to the callee in registers.
|
||||||
|
; For ELFv1 ABI, we always need to allocate the parameter area.
|
||||||
|
|
||||||
|
; Tests for ELFv2 ABI
|
||||||
|
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=PPC64-ELFV2
|
||||||
|
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=PPC64-ELFV2
|
||||||
|
|
||||||
|
; Tests for ELFv1 ABI
|
||||||
|
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=PPC64-ELFV1
|
||||||
|
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=PPC64-ELFV1
|
||||||
|
|
||||||
|
; If the callee has at most eight integer args, parameter area can be ommited for ELFv2 ABI.
|
||||||
|
|
||||||
|
; PPC64-ELFV2-LABEL: WithoutParamArea1:
|
||||||
|
; PPC64-ELFV2-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV2: stdu 1, -32(1)
|
||||||
|
; PPC64-ELFV2: addi 1, 1, 32
|
||||||
|
; PPC64-ELFV2-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1-LABEL: WithoutParamArea1:
|
||||||
|
; PPC64-ELFV1-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1: stdu 1, -112(1)
|
||||||
|
; PPC64-ELFV1: addi 1, 1, 112
|
||||||
|
; PPC64-ELFV1-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
define signext i32 @WithoutParamArea1(i32 signext %a) local_unnamed_addr #0 {
|
||||||
|
entry:
|
||||||
|
%call = tail call signext i32 @onearg(i32 signext %a) #2
|
||||||
|
ret i32 %call
|
||||||
|
}
|
||||||
|
|
||||||
|
; PPC64-ELFV2-LABEL: WithoutParamArea2:
|
||||||
|
; PPC64-ELFV2-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV2: stdu 1, -32(1)
|
||||||
|
; PPC64-ELFV2: addi 1, 1, 32
|
||||||
|
; PPC64-ELFV2-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1-LABEL: WithoutParamArea2:
|
||||||
|
; PPC64-ELFV1-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1: stdu 1, -112(1)
|
||||||
|
; PPC64-ELFV1: addi 1, 1, 112
|
||||||
|
; PPC64-ELFV1-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
define signext i32 @WithoutParamArea2(i32 signext %a) local_unnamed_addr #0 {
|
||||||
|
entry:
|
||||||
|
%call = tail call signext i32 @eightargs(i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a) #2
|
||||||
|
ret i32 %call
|
||||||
|
}
|
||||||
|
|
||||||
|
; If the callee has more than eight integer args or variable number of args,
|
||||||
|
; parameter area cannot be ommited even for ELFv2 ABI
|
||||||
|
|
||||||
|
; PPC64-ELFV2-LABEL: WithParamArea1:
|
||||||
|
; PPC64-ELFV2-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV2: stdu 1, -96(1)
|
||||||
|
; PPC64-ELFV2: addi 1, 1, 96
|
||||||
|
; PPC64-ELFV2-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1-LABEL: WithParamArea1:
|
||||||
|
; PPC64-ELFV1-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1: stdu 1, -112(1)
|
||||||
|
; PPC64-ELFV1: addi 1, 1, 112
|
||||||
|
; PPC64-ELFV1-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
define signext i32 @WithParamArea1(i32 signext %a) local_unnamed_addr #0 {
|
||||||
|
entry:
|
||||||
|
%call = tail call signext i32 (i32, ...) @varargs(i32 signext %a, i32 signext %a) #2
|
||||||
|
ret i32 %call
|
||||||
|
}
|
||||||
|
|
||||||
|
; PPC64-ELFV2-LABEL: WithParamArea2:
|
||||||
|
; PPC64-ELFV2-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV2: stdu 1, -112(1)
|
||||||
|
; PPC64-ELFV2: addi 1, 1, 112
|
||||||
|
; PPC64-ELFV2-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1-LABEL: WithParamArea2:
|
||||||
|
; PPC64-ELFV1-NOT: stw {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
; PPC64-ELFV1: stdu 1, -128(1)
|
||||||
|
; PPC64-ELFV1: addi 1, 1, 128
|
||||||
|
; PPC64-ELFV1-NOT: lwz {{[0-9]+}}, -{{[0-9]+}}(1)
|
||||||
|
define signext i32 @WithParamArea2(i32 signext %a) local_unnamed_addr #0 {
|
||||||
|
entry:
|
||||||
|
%call = tail call signext i32 @nineargs(i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a, i32 signext %a) #2
|
||||||
|
ret i32 %call
|
||||||
|
}
|
||||||
|
|
||||||
|
declare signext i32 @onearg(i32 signext) local_unnamed_addr #1
|
||||||
|
declare signext i32 @eightargs(i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext) local_unnamed_addr #1
|
||||||
|
declare signext i32 @nineargs(i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext, i32 signext) local_unnamed_addr #1
|
||||||
|
declare signext i32 @varargs(i32 signext, ...) local_unnamed_addr #1
|
||||||
|
|
Loading…
Reference in New Issue