diff options
Diffstat (limited to 'lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index ec8bd1f8b3..975eb239c9 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -415,7 +415,7 @@ static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, ARM::NoRegister }; unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 4); - if (Reg == 0) + if (Reg == 0) return false; // we didn't handle it unsigned i; @@ -487,6 +487,33 @@ static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, State); } +/// CCAssignFnForNode - Selects the correct CCAssignFn for a the +/// given CallingConvention value. +CCAssignFn *ARMTargetLowering::CCAssignFnForNode(unsigned CC, + bool Return) const { + switch (CC) { + default: + assert(0 && "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); + case CallingConv::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); + case CallingConv::ARM_APCS: + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + } +} + /// LowerCallResult - Lower the result values of an ISD::CALL into the /// appropriate copies out of appropriate physical registers. This assumes that /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call @@ -501,7 +528,8 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall, SmallVector<CCValAssign, 16> RVLocs; bool isVarArg = TheCall->isVarArg(); CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs); - CCInfo.AnalyzeCallResult(TheCall, RetCC_ARM); + CCInfo.AnalyzeCallResult(TheCall, + CCAssignFnForNode(CallingConv, /* Return*/ true)); SmallVector<SDValue, 8> ResultVals; @@ -586,8 +614,6 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { MVT RetVT = TheCall->getRetValType(0); SDValue Chain = TheCall->getChain(); unsigned CC = TheCall->getCallingConv(); - assert((CC == CallingConv::C || - CC == CallingConv::Fast) && "unknown calling convention"); bool isVarArg = TheCall->isVarArg(); SDValue Callee = TheCall->getCallee(); DebugLoc dl = TheCall->getDebugLoc(); @@ -595,7 +621,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); - CCInfo.AnalyzeCallOperands(TheCall, CC_ARM); + CCInfo.AnalyzeCallOperands(TheCall, CCAssignFnForNode(CC, /* Return*/ false)); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); @@ -788,7 +814,7 @@ SDValue ARMTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs); // Analyze return values of ISD::RET. - CCInfo.AnalyzeReturn(Op.getNode(), RetCC_ARM); + CCInfo.AnalyzeReturn(Op.getNode(), CCAssignFnForNode(CC, /* Return */ true)); // If this is the first return lowered for this function, add // the regs to the liveout set for the function. @@ -1085,7 +1111,8 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) { // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); - CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_ARM); + CCInfo.AnalyzeFormalArguments(Op.getNode(), + CCAssignFnForNode(CC, /* Return*/ false)); SmallVector<SDValue, 16> ArgValues; |