diff options
author | Strahinja Petrovic <strahinja.petrovic@rt-rk.com> | 2016-08-05 08:47:26 +0000 |
---|---|---|
committer | Strahinja Petrovic <strahinja.petrovic@rt-rk.com> | 2016-08-05 08:47:26 +0000 |
commit | 30e0ce8e9fc4598388fcd3c4d57894036cdd5903 (patch) | |
tree | ca5c55feadd0372d4ecc959e00f5213d96b8bc1d /llvm/lib/Target/PowerPC | |
parent | 928d7573ddace6e2bd0cd220d661c3e8cbae128e (diff) | |
download | bcm5719-llvm-30e0ce8e9fc4598388fcd3c4d57894036cdd5903.tar.gz bcm5719-llvm-30e0ce8e9fc4598388fcd3c4d57894036cdd5903.zip |
[PowerPC] fix passing long double arguments to function (soft-float)
This patch fixes passing long double type arguments to function in
soft float mode. If there is less than 4 argument registers free
(long double type is mapped in 4 gpr registers in soft float mode)
long double type argument must be passed through stack.
Differential Revision: https://reviews.llvm.org/D20114.
llvm-svn: 277804
Diffstat (limited to 'llvm/lib/Target/PowerPC')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCCallingConv.td | 6 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 7 |
3 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td b/llvm/lib/Target/PowerPC/PPCCallingConv.td index 53d2f77ff91..db6d087e8e5 100644 --- a/llvm/lib/Target/PowerPC/PPCCallingConv.td +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td @@ -26,6 +26,9 @@ class CCIfNotSubtarget<string F, CCAction A> class CCIfOrigArgWasNotPPCF128<CCAction A> : CCIf<"!static_cast<PPCCCState *>(&State)->WasOriginalArgPPCF128(ValNo)", A>; +class CCIfOrigArgWasPPCF128<CCAction A> + : CCIf<"static_cast<PPCCCState *>(&State)->WasOriginalArgPPCF128(ValNo)", + A>; //===----------------------------------------------------------------------===// // Return Value Calling Convention @@ -142,6 +145,9 @@ def CC_PPC32_SVR4_Common : CallingConv<[ CCIfType<[i32], CCIfSplit<CCIfNotSubtarget<"useSoftFloat()", CCCustom<"CC_PPC32_SVR4_Custom_AlignArgRegs">>>>, + CCIfSplit<CCIfSubtarget<"useSoftFloat()", + CCIfOrigArgWasPPCF128<CCCustom< + "CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128">>>>, // The 'nest' parameter, if any, is passed in R11. CCIfNest<CCAssignToReg<[R11]>>, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 472db99b0fc..2ccbcd9dd70 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2676,6 +2676,32 @@ bool llvm::CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, return false; } +bool +llvm::CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg ArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + const unsigned NumArgRegs = array_lengthof(ArgRegs); + + unsigned RegNum = State.getFirstUnallocated(ArgRegs); + int RegsLeft = NumArgRegs - RegNum; + + // Skip if there is not enough registers left for long double type (4 gpr regs + // in soft float mode) and put long double argument on the stack. + if (RegNum != NumArgRegs && RegsLeft < 4) { + for (int i = 0; i < RegsLeft; i++) { + State.AllocateReg(ArgRegs[RegNum + i]); + } + } + + return false; +} + bool llvm::CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index e3be8074e62..c12f9c664c9 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -953,6 +953,13 @@ namespace llvm { ISD::ArgFlagsTy &ArgFlags, CCState &State); + bool + CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, |