Implement support for byval arguments in Sparc backend.
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Fri, 21 Jan 2011 14:00:01 +0000 (14:00 +0000)
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Fri, 21 Jan 2011 14:00:01 +0000 (14:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123974 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/SparcISelLowering.cpp
test/CodeGen/SPARC/2011-01-21-ByValArgs.ll [new file with mode: 0644]

index 74d471e2c83ee3bd626d7e0d7c98bc7d253be2fa..f78d5fa5070fd071374b0f8cef188ac1018960e2 100644 (file)
@@ -313,6 +313,30 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
   // Keep stack frames 8-byte aligned.
   ArgsSize = (ArgsSize+7) & ~7;
 
+  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+
+  //Create local copies for byval args.
+  SmallVector<SDValue, 8> ByValArgs;
+  for (unsigned i = 0,  e = Outs.size(); i != e; ++i) {
+    ISD::ArgFlagsTy Flags = Outs[i].Flags;
+    if (!Flags.isByVal())
+      continue;
+
+    SDValue Arg = OutVals[i];
+    unsigned Size = Flags.getByValSize();
+    unsigned Align = Flags.getByValAlign();
+
+    int FI = MFI->CreateStackObject(Size, Align, false);
+    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy());
+    SDValue SizeNode = DAG.getConstant(Size, MVT::i32);
+
+    Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align,
+                          false,        //isVolatile,
+                          (Size <= 32), //AlwaysInline if size <= 32
+                          MachinePointerInfo(), MachinePointerInfo());
+    ByValArgs.push_back(FIPtr);
+  }
+
   Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));
 
   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
@@ -320,12 +344,18 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
 
   const unsigned StackOffset = 92;
   // Walk the register/memloc assignments, inserting copies/loads.
-  for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
+  for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
        i != e;
        ++i, ++realArgIdx) {
     CCValAssign &VA = ArgLocs[i];
     SDValue Arg = OutVals[realArgIdx];
 
+    ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
+
+    //Use local copy if it is a byval arg.
+    if (Flags.isByVal())
+      Arg = ByValArgs[byvalArgIdx++];
+
     // Promote the value if needed.
     switch (VA.getLocInfo()) {
     default: llvm_unreachable("Unknown loc info!");
diff --git a/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll b/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll
new file mode 100644 (file)
index 0000000..85c16e4
--- /dev/null
@@ -0,0 +1,18 @@
+;RUN: llc -march=sparc < %s | FileCheck %s
+
+%struct.foo_t = type { i32, i32, i32 }
+
+@s = internal unnamed_addr global %struct.foo_t { i32 10, i32 20, i32 30 }
+
+define i32 @test() nounwind {
+entry:
+;CHECK:     test
+;CHECK:     st
+;CHECK:     st
+;CHECK:     st
+;CHECK:     bar
+  %0 = tail call i32 @bar(%struct.foo_t* byval @s) nounwind
+  ret i32 %0
+}
+
+declare i32 @bar(%struct.foo_t* byval)