diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 107 |
1 files changed, 85 insertions, 22 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 85731436c24..881d6d71a19 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -6831,6 +6831,9 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT, if (ArgFlags.isNest()) report_fatal_error("Nest arguments are unimplemented."); + if (ValVT.isVector() || LocVT.isVector()) + report_fatal_error("Vector arguments are unimplemented on AIX."); + const PPCSubtarget &Subtarget = static_cast<const PPCSubtarget &>( State.getMachineFunction().getSubtarget()); const bool IsPPC64 = Subtarget.isPPC64(); @@ -6875,18 +6878,33 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT, // This includes f64 in 64-bit mode for ABI compatibility. State.AllocateStack(IsPPC64 ? 8 : StoreSize, 4); if (unsigned Reg = State.AllocateReg(FPR)) - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::f64, LocInfo)); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); else report_fatal_error("Handling of placing parameters on the stack is " "unimplemented!"); - // f32 reserves 1 GPR in both PPC32 and PPC64. - // f64 reserves 2 GPRs in PPC32 and 1 GPR in PPC64. - for (unsigned i = 0; i < StoreSize; i += PtrByteSize) - State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32); + // AIX requires that GPRs are reserved for float arguments. + // Successfully reserved GPRs are only initialized for vararg calls. + MVT RegVT = IsPPC64 ? MVT::i64 : MVT::i32; + for (unsigned I = 0; I < StoreSize; I += PtrByteSize) { + if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32)) { + if (State.isVarArg()) { + // Custom handling is required for: + // f64 in PPC32 needs to be split into 2 GPRs. + // f32 in PPC64 needs to occupy only lower 32 bits of 64-bit GPR. + State.addLoc( + CCValAssign::getCustomReg(ValNo, ValVT, Reg, RegVT, LocInfo)); + } + } else if (State.isVarArg()) { + report_fatal_error("Handling of placing parameters on the stack is " + "unimplemented!"); + } + } + return false; } } + return true; } static const TargetRegisterClass *getRegClassForSVT(MVT::SimpleValueType SVT, @@ -7013,7 +7031,7 @@ SDValue PPCTargetLowering::LowerCall_AIX( CallConv == CallingConv::Cold || CallConv == CallingConv::Fast) && "Unexpected calling convention!"); - if (isVarArg || isPatchPoint) + if (isPatchPoint) report_fatal_error("This call type is unimplemented on AIX."); const PPCSubtarget& Subtarget = @@ -7032,7 +7050,8 @@ SDValue PPCTargetLowering::LowerCall_AIX( // [SP][CR][LR][2 x reserved][TOC]. // The LSA is 24 bytes (6x4) in PPC32 and 48 bytes (6x8) in PPC64. const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize(); - const unsigned PtrByteSize = Subtarget.isPPC64() ? 8 : 4; + const bool IsPPC64 = Subtarget.isPPC64(); + const unsigned PtrByteSize = IsPPC64 ? 8 : 4; CCInfo.AllocateStack(LinkageSize, PtrByteSize); CCInfo.AnalyzeCallOperands(Outs, CC_AIX); @@ -7052,26 +7071,70 @@ SDValue PPCTargetLowering::LowerCall_AIX( SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; - for (CCValAssign &VA : ArgLocs) { + for (unsigned I = 0, E = ArgLocs.size(); I != E;) { + CCValAssign &VA = ArgLocs[I++]; + + if (VA.isMemLoc()) + report_fatal_error("Handling of placing parameters on the stack is " + "unimplemented!"); + if (!VA.isRegLoc()) + report_fatal_error( + "Unexpected non-register location for function call argument."); + SDValue Arg = OutVals[VA.getValNo()]; - switch (VA.getLocInfo()) { - default: report_fatal_error("Unexpected argument extension type."); - case CCValAssign::Full: break; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); - break; - case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); - break; + if (!VA.needsCustom()) { + switch (VA.getLocInfo()) { + default: + report_fatal_error("Unexpected argument extension type."); + case CCValAssign::Full: + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + + continue; } - if (VA.isRegLoc()) - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + // Custom handling is used for GPR initializations for vararg float + // arguments. + assert(isVarArg && VA.getValVT().isFloatingPoint() && + VA.getLocVT().isInteger() && + "Unexpected custom register handling for calling convention."); - if (VA.isMemLoc()) - report_fatal_error("Handling of placing parameters on the stack is " - "unimplemented!"); + SDValue ArgAsInt = + DAG.getBitcast(MVT::getIntegerVT(VA.getValVT().getSizeInBits()), Arg); + + if (Arg.getValueType().getStoreSize() == VA.getLocVT().getStoreSize()) + // f32 in 32-bit GPR + // f64 in 64-bit GPR + RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgAsInt)); + else if (Arg.getValueType().getSizeInBits() < VA.getLocVT().getSizeInBits()) + // f32 in 64-bit GPR. + RegsToPass.push_back(std::make_pair( + VA.getLocReg(), DAG.getZExtOrTrunc(ArgAsInt, dl, VA.getLocVT()))); + else { + // f64 in two 32-bit GPRs + // The 2 GPRs are marked custom and expected to be adjacent in ArgLocs. + assert(Arg.getValueType() == MVT::f64 && isVarArg && !IsPPC64 && + "Unexpected custom register for argument!"); + CCValAssign &GPR1 = VA; + SDValue MSWAsI64 = DAG.getNode(ISD::SRL, dl, MVT::i64, ArgAsInt, + DAG.getConstant(32, dl, MVT::i8)); + RegsToPass.push_back(std::make_pair( + GPR1.getLocReg(), DAG.getZExtOrTrunc(MSWAsI64, dl, MVT::i32))); + assert(I != E && "A second custom GPR is expected!"); + CCValAssign &GPR2 = ArgLocs[I++]; + assert(GPR2.isRegLoc() && GPR2.getValNo() == GPR1.getValNo() && + GPR2.needsCustom() && "A second custom GPR is expected!"); + RegsToPass.push_back(std::make_pair( + GPR2.getLocReg(), DAG.getZExtOrTrunc(ArgAsInt, dl, MVT::i32))); + } } // For indirect calls, we need to save the TOC base to the stack for |