From fdd3ade005c7bd60f3dc74a49db82f91654e99ae Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Mon, 17 Mar 2008 02:13:43 +0000 Subject: [PATCH] Next round of PPC32 ABI changes. Allow for gcc behavior where a callee thinks a param will be present in memory, even though the ABI doc says it doesn't have to be. Handle complex long long and complex double (4 and 8 return regs). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48439 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCCallingConv.td | 2 +- lib/Target/PowerPC/PPCISelLowering.cpp | 77 ++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/lib/Target/PowerPC/PPCCallingConv.td b/lib/Target/PowerPC/PPCCallingConv.td index b73711baedb..6b6ae0778e8 100644 --- a/lib/Target/PowerPC/PPCCallingConv.td +++ b/lib/Target/PowerPC/PPCCallingConv.td @@ -22,7 +22,7 @@ class CCIfSubtarget // Return-value convention for PowerPC def RetCC_PPC : CallingConv<[ - CCIfType<[i32], CCAssignToReg<[R3, R4]>>, + CCIfType<[i32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>, CCIfType<[i64], CCAssignToReg<[X3, X4]>>, CCIfType<[f32], CCAssignToReg<[F1]>>, diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 5bea470eb0d..c6885cf7b8a 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1922,6 +1922,18 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, } continue; } + // Copy entire object into memory. There are cases where gcc-generated + // code assumes it is there, even if it could be put entirely into + // registers. (This is not what the doc says.) + SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, PtrOff, + CallSeqStart.Val->getOperand(0), + Flags, DAG, Size); + // This must go outside the CALLSEQ_START..END. + SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, + CallSeqStart.Val->getOperand(1)); + DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val); + Chain = CallSeqStart = NewCallSeqStart; + // And copy the pieces of it that fit into registers. for (unsigned j=0; jgetOperand(0), - Flags, DAG, Size - j); - // This must go outside the CALLSEQ_START..END. - SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, - CallSeqStart.Val->getOperand(1)); - DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val); - Chain = CallSeqStart = NewCallSeqStart; - ArgOffset += ((Size - j + 3)/4)*4; + ArgOffset += ((Size - j + PtrByteSize-1)/PtrByteSize)*PtrByteSize; break; } } @@ -2181,7 +2184,7 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, if (Op.Val->getValueType(0) != MVT::Other) InFlag = Chain.getValue(1); - SDOperand ResultVals[3]; + SDOperand ResultVals[9]; unsigned NumResults = 0; NodeTys.clear(); @@ -2190,7 +2193,57 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, default: assert(0 && "Unexpected ret value!"); case MVT::Other: break; case MVT::i32: - if (Op.Val->getValueType(1) == MVT::i32) { + // There are 8 result regs for Complex double, and 4 for Complex long long. + if (Op.Val->getNumValues()>=8 && Op.Val->getValueType(7) == MVT::i32) { + Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1); + ResultVals[0] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[1] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R5, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[2] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R6, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[3] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R7, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[4] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R8, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[5] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R9, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[6] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R10, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[7] = Chain.getValue(0); + NumResults = 8; + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + } else if (Op.Val->getNumValues()>=4 && + Op.Val->getValueType(3) == MVT::i32) { + Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1); + ResultVals[0] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[1] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R5, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[2] = Chain.getValue(0); + Chain = DAG.getCopyFromReg(Chain, PPC::R6, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals[3] = Chain.getValue(0); + NumResults = 4; + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + NodeTys.push_back(MVT::i32); + } else if (Op.Val->getValueType(1) == MVT::i32) { Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1); ResultVals[0] = Chain.getValue(0); Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32,