Initial support for calling functions with byval arguments on x86-64
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 31 Aug 2007 15:06:30 +0000 (15:06 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 31 Aug 2007 15:06:30 +0000 (15:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41643 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/byval2.ll [new file with mode: 0644]

index 85c9691e5e0824124d5e0fe7f221d1df8068b8b1..084c8468ad9a4b505067e47a51af00692f930e75 100644 (file)
@@ -1036,6 +1036,34 @@ X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) {
                      &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
 }
 
+SDOperand
+X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
+                                    const SDOperand &StackPtr,
+                                    const CCValAssign &VA,
+                                    SDOperand Chain,
+                                    SDOperand Arg) {
+  SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
+  PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+  SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
+  unsigned Flags    = cast<ConstantSDNode>(FlagsOp)->getValue();
+  if (Flags & ISD::ParamFlags::ByVal) {
+    unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
+                           ISD::ParamFlags::ByValAlignOffs);
+
+    assert (Align >= 8);
+    unsigned  Size = (Flags & ISD::ParamFlags::ByValSize) >>
+        ISD::ParamFlags::ByValSizeOffs;
+
+    SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
+    SDOperand  SizeNode = DAG.getConstant(Size, MVT::i32);
+
+    return DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, PtrOff, Arg, SizeNode,
+                       AlignNode);
+  } else {
+    return DAG.getStore(Chain, Arg, PtrOff, NULL, 0);
+  }
+}
+
 SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
                                                unsigned CC) {
   SDOperand Chain     = Op.getOperand(0);
@@ -1375,29 +1403,9 @@ X86TargetLowering::LowerX86_64CCCCallTo(SDOperand Op, SelectionDAG &DAG,
       assert(VA.isMemLoc());
       if (StackPtr.Val == 0)
         StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
-      SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
-      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
 
-      SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
-      unsigned Flags    = cast<ConstantSDNode>(FlagsOp)->getValue();
-      if (Flags & ISD::ParamFlags::ByVal) {
-        unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
-                               ISD::ParamFlags::ByValAlignOffs);
-        unsigned  Size = (Flags & ISD::ParamFlags::ByValSize) >>
-            ISD::ParamFlags::ByValSizeOffs;
-
-        SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
-        SDOperand  SizeNode = DAG.getConstant(Size, MVT::i32);
-
-        assert(0 && "Not Implemented");
-
-        SDOperand Copy = DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, PtrOff,
-                                     Arg, SizeNode, AlignNode);
-        MemOpChains.push_back(Copy);
-      }
-      else {
-        MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
-      }
+      MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain,
+                                             Arg));
     }
   }
   
index 24ca1ea44bfa2c88307b93f9989efd4795955691..41eaec27832ee0d90d085536594b5dd5a24c5857 100644 (file)
@@ -19,6 +19,7 @@
 #include "X86RegisterInfo.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/CallingConvLower.h"
 
 namespace llvm {
   namespace X86ISD {
@@ -378,6 +379,12 @@ namespace llvm {
     SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
                             unsigned CallingConv, SelectionDAG &DAG);
         
+
+    SDOperand LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
+                               const SDOperand &StackPtr,
+                               const CCValAssign &VA, SDOperand Chain,
+                               SDOperand Arg);
+
     // C and StdCall Calling Convention implementation.
     SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
                                 bool isStdCall = false);
diff --git a/test/CodeGen/X86/byval2.ll b/test/CodeGen/X86/byval2.ll
new file mode 100644 (file)
index 0000000..04d3483
--- /dev/null
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | llc -march=x86-64 | grep rep.movsl | count 2
+
+%struct.s = type { i64, i64, i64 }
+
+define void @g(i64 %a, i64 %b, i64 %c) {
+entry:
+       %d = alloca %struct.s, align 16
+       %tmp = getelementptr %struct.s* %d, i32 0, i32 0
+       store i64 %a, i64* %tmp, align 16
+       %tmp2 = getelementptr %struct.s* %d, i32 0, i32 1
+       store i64 %b, i64* %tmp2, align 16
+       %tmp4 = getelementptr %struct.s* %d, i32 0, i32 2
+       store i64 %c, i64* %tmp4, align 16
+       call void @f( %struct.s* %d byval)
+       call void @f( %struct.s* %d byval)
+       ret void
+}
+
+declare void @f(%struct.s* byval)