@@ -931,6 +931,49 @@ SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
931
931
return getDataLayout ()->getTypeAllocSize (ElementTy);
932
932
}
933
933
934
+
935
+ // Fixup floating point arguments in the ... part of a varargs call.
936
+ //
937
+ // The SPARC v9 ABI requires that floating point arguments are treated the same
938
+ // as integers when calling a varargs function. This does not apply to the
939
+ // fixed arguments that are part of the function's prototype.
940
+ //
941
+ // This function post-processes a CCValAssign array created by
942
+ // AnalyzeCallOperands().
943
+ static void fixupVariableFloatArgs (SmallVectorImpl<CCValAssign> &ArgLocs,
944
+ ArrayRef<ISD::OutputArg> Outs) {
945
+ for (unsigned i = 0 , e = ArgLocs.size (); i != e; ++i) {
946
+ const CCValAssign &VA = ArgLocs[i];
947
+ // FIXME: What about f32 arguments? C promotes them to f64 when calling
948
+ // varargs functions.
949
+ if (!VA.isRegLoc () || VA.getLocVT () != MVT::f64 )
950
+ continue ;
951
+ // The fixed arguments to a varargs function still go in FP registers.
952
+ if (Outs[VA.getValNo ()].IsFixed )
953
+ continue ;
954
+
955
+ // This floating point argument should be reassigned.
956
+ CCValAssign NewVA;
957
+
958
+ // Determine the offset into the argument array.
959
+ unsigned Offset = 8 * (VA.getLocReg () - SP::D0);
960
+ assert (Offset < 16 *8 && " Offset out of range, bad register enum?" );
961
+
962
+ if (Offset < 6 *8 ) {
963
+ // This argument should go in %i0-%i5.
964
+ unsigned IReg = SP::I0 + Offset/8 ;
965
+ // Full register, just bitconvert into i64.
966
+ NewVA = CCValAssign::getReg (VA.getValNo (), VA.getValVT (),
967
+ IReg, MVT::i64 , CCValAssign::BCvt);
968
+ } else {
969
+ // This needs to go to memory, we're out of integer registers.
970
+ NewVA = CCValAssign::getMem (VA.getValNo (), VA.getValVT (),
971
+ Offset, VA.getLocVT (), VA.getLocInfo ());
972
+ }
973
+ ArgLocs[i] = NewVA;
974
+ }
975
+ }
976
+
934
977
// Lower a call for the 64-bit ABI.
935
978
SDValue
936
979
SparcTargetLowering::LowerCall_64 (TargetLowering::CallLoweringInfo &CLI,
@@ -954,6 +997,10 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
954
997
// Keep stack frames 16-byte aligned.
955
998
ArgsSize = RoundUpToAlignment (ArgsSize, 16 );
956
999
1000
+ // Varargs calls require special treatment.
1001
+ if (CLI.IsVarArg )
1002
+ fixupVariableFloatArgs (ArgLocs, CLI.Outs );
1003
+
957
1004
// Adjust the stack pointer to make room for the arguments.
958
1005
// FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
959
1006
// with more than 6 arguments.
0 commit comments