diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 93 |
1 files changed, 78 insertions, 15 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index b2381077fa9..fcfe32bdfc6 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -4871,6 +4871,7 @@ PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, SDValue &Chain, bool isPPC64 = Subtarget.isPPC64(); bool isSVR4ABI = Subtarget.isSVR4ABI(); bool isELFv2ABI = Subtarget.isELFv2ABI(); + bool isAIXABI = Subtarget.isAIXABI(); EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); NodeTys.push_back(MVT::Other); // Returns a chain @@ -5049,17 +5050,18 @@ PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, SDValue &Chain, Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); - // All calls, in both the ELF V1 and V2 ABIs, need the TOC register live - // into the call. - // We do need to reserve X2 to appease the verifier for the PATCHPOINT. - if (isSVR4ABI && isPPC64) { + // All calls, in the AIX ABI and 64-bit ELF ABIs, need the TOC register + // live into the call. + // We do need to reserve R2/X2 to appease the verifier for the PATCHPOINT. + if ((isSVR4ABI && isPPC64) || isAIXABI) { setUsesTOCBasePtr(DAG); - // We cannot add X2 as an operand here for PATCHPOINT, because there is no - // way to mark dependencies as implicit here. We will add the X2 dependency - // in EmitInstrWithCustomInserter. + // We cannot add R2/X2 as an operand here for PATCHPOINT, because there is + // no way to mark dependencies as implicit here. + // We will add the R2/X2 dependency in EmitInstrWithCustomInserter. if (!isPatchPoint) - Ops.push_back(DAG.getRegister(PPC::X2, PtrVT)); + Ops.push_back(DAG.getRegister(isPPC64 ? PPC::X2 + : PPC::R2, PtrVT)); } return CallOpc; @@ -6596,9 +6598,6 @@ SDValue PPCTargetLowering::LowerCall_AIX( unsigned PtrByteSize = isPPC64 ? 8 : 4; unsigned NumOps = Outs.size(); - if (NumOps != 0) - report_fatal_error("Call lowering with parameters is not implemented " - "on AIX yet."); // Count how many bytes are to be pushed on the stack, including the linkage // area, parameter list area. @@ -6620,17 +6619,81 @@ SDValue PPCTargetLowering::LowerCall_AIX( Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl); SDValue CallSeqStart = Chain; - if (!isFunctionGlobalAddress(Callee) && - !isa<ExternalSymbolSDNode>(Callee)) - report_fatal_error("Handling of indirect call is unimplemented!"); + static const MCPhysReg GPR_32[] = { // 32-bit registers. + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10 + }; + static const MCPhysReg GPR_64[] = { // 64-bit registers. + PPC::X3, PPC::X4, PPC::X5, PPC::X6, + PPC::X7, PPC::X8, PPC::X9, PPC::X10 + }; + + const unsigned NumGPRs = isPPC64 ? array_lengthof(GPR_64) + : array_lengthof(GPR_32); + const MCPhysReg *GPR = isPPC64 ? GPR_64 : GPR_32; + unsigned GPR_idx = 0; SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; - SDValue InFlag; if (isTailCall) report_fatal_error("Handling of tail call is unimplemented!"); int SPDiff = 0; + for (unsigned i = 0; i != NumOps; ++i) { + SDValue Arg = OutVals[i]; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + // Promote integers if needed. + if (Arg.getValueType() == MVT::i1 || + (isPPC64 && Arg.getValueType() == MVT::i32)) { + unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + Arg = DAG.getNode(ExtOp, dl, PtrVT, Arg); + } + + // Note: "by value" is code for passing a structure by value, not + // basic types. + if (Flags.isByVal()) + report_fatal_error("Passing structure by value is unimplemented!"); + + switch (Arg.getSimpleValueType().SimpleTy) { + default: llvm_unreachable("Unexpected ValueType for argument!"); + case MVT::i1: + case MVT::i32: + case MVT::i64: + if (GPR_idx != NumGPRs) + RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); + else + report_fatal_error("Handling of placing parameters on the stack is " + "unimplemented!"); + break; + case MVT::f32: + case MVT::f64: + case MVT::v4f32: + case MVT::v4i32: + case MVT::v8i16: + case MVT::v16i8: + case MVT::v2f64: + case MVT::v2i64: + case MVT::v1i128: + case MVT::f128: + case MVT::v4f64: + case MVT::v4i1: + report_fatal_error("Handling of this parameter type is unimplemented!"); + } + } + + if (!isFunctionGlobalAddress(Callee) && + !isa<ExternalSymbolSDNode>(Callee)) + report_fatal_error("Handling of indirect call is unimplemented!"); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDValue InFlag; + for (auto Reg : RegsToPass) { + Chain = DAG.getCopyToReg(Chain, dl, Reg.first, Reg.second, InFlag); + InFlag = Chain.getValue(1); + } + return FinishCall(CallConv, dl, isTailCall, isVarArg, isPatchPoint, /* unused except on PPC64 ELFv1 */ false, DAG, RegsToPass, InFlag, Chain, CallSeqStart, Callee, SPDiff, |