diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2009-08-05 19:04:42 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2009-08-05 19:04:42 +0000 |
commit | 567d14f07cd62bfb9dd0edd90144a0a840450f7a (patch) | |
tree | 77a15f2bdf6d6dadb6c39916191385dfd0038118 /lib/Target/ARM/ARMISelLowering.cpp | |
parent | ab90b28adcd802c4d4eaa29d49549a371b93b355 (diff) |
Missed pieces for ARM HardFP ABI.
Patch by Sandeep Patel!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78225 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index af18c2770f..61a08db29f 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -662,27 +662,28 @@ static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, /// CCAssignFnForNode - Selects the correct CCAssignFn for a the /// given CallingConvention value. CCAssignFn *ARMTargetLowering::CCAssignFnForNode(unsigned CC, - bool Return) const { + bool Return, + bool isVarArg) const { switch (CC) { default: - llvm_unreachable("Unsupported calling convention"); + llvm_unreachable("Unsupported calling convention"); case CallingConv::C: case CallingConv::Fast: - // Use target triple & subtarget features to do actual dispatch. - if (Subtarget->isAAPCS_ABI()) { - if (Subtarget->hasVFP2() && - FloatABIType == FloatABI::Hard) - return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); - else - return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); - } else - return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + // Use target triple & subtarget features to do actual dispatch. + if (Subtarget->isAAPCS_ABI()) { + if (Subtarget->hasVFP2() && + FloatABIType == FloatABI::Hard && !isVarArg) + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + else + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + } else + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); case CallingConv::ARM_AAPCS_VFP: - return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); case CallingConv::ARM_AAPCS: - return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); case CallingConv::ARM_APCS: - return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); } } @@ -700,7 +701,8 @@ ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, - CCAssignFnForNode(CallConv, /* Return*/ true)); + CCAssignFnForNode(CallConv, /* Return*/ true, + isVarArg)); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { @@ -832,7 +834,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, - CCAssignFnForNode(CallConv, /* Return*/ false)); + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); @@ -873,7 +876,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, break; } - // f64 and v2f64 are passed in i32 pairs and must be split into pieces + // f64 and v2f64 might be passed in i32 pairs and must be split into pieces if (VA.needsCustom()) { if (VA.getLocVT() == MVT::v2f64) { SDValue Op0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, @@ -1034,7 +1037,8 @@ ARMTargetLowering::LowerReturn(SDValue Chain, *DAG.getContext()); // Analyze outgoing return values. - CCInfo.AnalyzeReturn(Outs, CCAssignFnForNode(CallConv, /* Return */ true)); + CCInfo.AnalyzeReturn(Outs, CCAssignFnForNode(CallConv, /* Return */ true, + isVarArg)); // If this is the first return lowered for this function, add // the regs to the liveout set for the function. @@ -1422,7 +1426,8 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, - CCAssignFnForNode(CallConv, /* Return*/ false)); + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); SmallVector<SDValue, 16> ArgValues; @@ -1455,18 +1460,23 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, } else { TargetRegisterClass *RC; - if (FloatABIType == FloatABI::Hard && RegVT == MVT::f32) + bool IsHardFloatCC = (CallConv == CallingConv::ARM_AAPCS_VFP); + + if (IsHardFloatCC && RegVT == MVT::f32) RC = ARM::SPRRegisterClass; - else if (FloatABIType == FloatABI::Hard && RegVT == MVT::f64) + else if (IsHardFloatCC && RegVT == MVT::f64) RC = ARM::DPRRegisterClass; + else if (IsHardFloatCC && RegVT == MVT::v2f64) + RC = ARM::QPRRegisterClass; else if (AFI->isThumb1OnlyFunction()) RC = ARM::tGPRRegisterClass; else RC = ARM::GPRRegisterClass; assert((RegVT == MVT::i32 || RegVT == MVT::f32 || - (FloatABIType == FloatABI::Hard && RegVT == MVT::f64)) && - "RegVT not supported by formal arguments Lowering"); + (IsHardFloatCC && + ((RegVT == MVT::f64) || (RegVT == MVT::v2f64)))) && + "RegVT not supported by FORMAL_ARGUMENTS Lowering"); // Transform the arguments in physical registers into virtual ones. unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); |