Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit ddb14ce

Browse files
committed
Passing arguments to varags functions under the SPARC v9 ABI.
Arguments after the fixed arguments never use the floating point registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179987 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 1e48093 commit ddb14ce

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,49 @@ SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
931931
return getDataLayout()->getTypeAllocSize(ElementTy);
932932
}
933933

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+
934977
// Lower a call for the 64-bit ABI.
935978
SDValue
936979
SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
@@ -954,6 +997,10 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
954997
// Keep stack frames 16-byte aligned.
955998
ArgsSize = RoundUpToAlignment(ArgsSize, 16);
956999

1000+
// Varargs calls require special treatment.
1001+
if (CLI.IsVarArg)
1002+
fixupVariableFloatArgs(ArgLocs, CLI.Outs);
1003+
9571004
// Adjust the stack pointer to make room for the arguments.
9581005
// FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
9591006
// with more than 6 arguments.

test/CodeGen/SPARC/varargs.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,16 @@ sw.default:
6060
}
6161

6262
declare void @llvm.va_start(i8*)
63+
64+
@.str = private unnamed_addr constant [4 x i8] c"abc\00", align 1
65+
66+
; CHECK: call_1d
67+
; The fixed-arg double goes in %d2, the second goes in %o2.
68+
; CHECK: sethi 1048576
69+
; CHECK: , %o2
70+
; CHECK: , %f2
71+
define i32 @call_1d() #0 {
72+
entry:
73+
%call = call double (i8*, double, ...)* @varargsfunc(i8* undef, double 1.000000e+00, double 2.000000e+00)
74+
ret i32 1
75+
}

0 commit comments

Comments
 (0)