[llvm] r179987 - Passing arguments to varags functions under the SPARC v9 ABI.

Jakob Stoklund Olesen stoklund at 2pi.dk
Sun Apr 21 14:36:49 PDT 2013


Author: stoklund
Date: Sun Apr 21 16:36:49 2013
New Revision: 179987

URL: http://llvm.org/viewvc/llvm-project?rev=179987&view=rev
Log:
Passing arguments to varags functions under the SPARC v9 ABI.

Arguments after the fixed arguments never use the floating point
registers.

Modified:
    llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
    llvm/trunk/test/CodeGen/SPARC/varargs.ll

Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=179987&r1=179986&r2=179987&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Sun Apr 21 16:36:49 2013
@@ -931,6 +931,49 @@ SparcTargetLowering::getSRetArgSize(Sele
   return getDataLayout()->getTypeAllocSize(ElementTy);
 }
 
+
+// Fixup floating point arguments in the ... part of a varargs call.
+//
+// The SPARC v9 ABI requires that floating point arguments are treated the same
+// as integers when calling a varargs function. This does not apply to the
+// fixed arguments that are part of the function's prototype.
+//
+// This function post-processes a CCValAssign array created by
+// AnalyzeCallOperands().
+static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
+                                   ArrayRef<ISD::OutputArg> Outs) {
+  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+    const CCValAssign &VA = ArgLocs[i];
+    // FIXME: What about f32 arguments? C promotes them to f64 when calling
+    // varargs functions.
+    if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64)
+      continue;
+    // The fixed arguments to a varargs function still go in FP registers.
+    if (Outs[VA.getValNo()].IsFixed)
+      continue;
+
+    // This floating point argument should be reassigned.
+    CCValAssign NewVA;
+
+    // Determine the offset into the argument array.
+    unsigned Offset = 8 * (VA.getLocReg() - SP::D0);
+    assert(Offset < 16*8 && "Offset out of range, bad register enum?");
+
+    if (Offset < 6*8) {
+      // This argument should go in %i0-%i5.
+      unsigned IReg = SP::I0 + Offset/8;
+      // Full register, just bitconvert into i64.
+      NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
+                                  IReg, MVT::i64, CCValAssign::BCvt);
+    } else {
+      // This needs to go to memory, we're out of integer registers.
+      NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
+                                  Offset, VA.getLocVT(), VA.getLocInfo());
+    }
+    ArgLocs[i] = NewVA;
+  }
+}
+
 // Lower a call for the 64-bit ABI.
 SDValue
 SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
@@ -954,6 +997,10 @@ SparcTargetLowering::LowerCall_64(Target
   // Keep stack frames 16-byte aligned.
   ArgsSize = RoundUpToAlignment(ArgsSize, 16);
 
+  // Varargs calls require special treatment.
+  if (CLI.IsVarArg)
+    fixupVariableFloatArgs(ArgLocs, CLI.Outs);
+
   // Adjust the stack pointer to make room for the arguments.
   // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
   // with more than 6 arguments.

Modified: llvm/trunk/test/CodeGen/SPARC/varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/varargs.ll?rev=179987&r1=179986&r2=179987&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/varargs.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/varargs.ll Sun Apr 21 16:36:49 2013
@@ -60,3 +60,16 @@ sw.default:
 }
 
 declare void @llvm.va_start(i8*)
+
+ at .str = private unnamed_addr constant [4 x i8] c"abc\00", align 1
+
+; CHECK: call_1d
+; The fixed-arg double goes in %d2, the second goes in %o2.
+; CHECK: sethi 1048576
+; CHECK: , %o2
+; CHECK: , %f2
+define i32 @call_1d() #0 {
+entry:
+  %call = call double (i8*, double, ...)* @varargsfunc(i8* undef, double 1.000000e+00, double 2.000000e+00)
+  ret i32 1
+}





More information about the llvm-commits mailing list