aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2007-08-20 15:18:24 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2007-08-20 15:18:24 +0000
commit21485be444bd132941faf4e5653ac34b3ec74040 (patch)
tree7314e95702a75eef525af3450134d4d353125fb6
parentcf8ba696b32fe46d874ac83c1e1c7ab9ad0f18da (diff)
Partial implementation of calling functions with byval arguments:
*) The needed information is propagated to the DAG *) The X86-64 backend detects it and aborts git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41179 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Target/TargetLowering.h3
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp10
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp22
3 files changed, 33 insertions, 2 deletions
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index e44f741224..510dd6e91f 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -841,9 +841,10 @@ public:
bool isInReg;
bool isSRet;
bool isNest;
+ bool isByVal;
ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
- isSRet(false), isNest(false) { };
+ isSRet(false), isNest(false), isByVal(false) { };
};
typedef std::vector<ArgListEntry> ArgListTy;
virtual std::pair<SDOperand, SDOperand>
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index a99640a170..78539d454e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2905,6 +2905,7 @@ void SelectionDAGLowering::LowerCallTo(Instruction &I,
Entry.isInReg = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::InReg);
Entry.isSRet = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::StructRet);
Entry.isNest = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::Nest);
+ Entry.isByVal = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::ByVal);
Args.push_back(Entry);
}
@@ -3967,6 +3968,15 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
Flags |= ISD::ParamFlags::InReg;
if (Args[i].isSRet)
Flags |= ISD::ParamFlags::StructReturn;
+ if (Args[i].isByVal) {
+ Flags |= ISD::ParamFlags::ByVal;
+ const PointerType *Ty = cast<PointerType>(Args[i].Ty);
+ const StructType *STy = cast<StructType>(Ty->getElementType());
+ unsigned StructAlign = Log2_32(getTargetData()->getABITypeAlignment(STy));
+ unsigned StructSize = getTargetData()->getTypeSize(STy);
+ Flags |= (StructAlign << ISD::ParamFlags::ByValAlignOffs);
+ Flags |= (StructSize << ISD::ParamFlags::ByValSizeOffs);
+ }
if (Args[i].isNest)
Flags |= ISD::ParamFlags::Nest;
Flags |= OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs;
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 179c47af25..f32e6f6ead 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1378,7 +1378,27 @@ X86TargetLowering::LowerX86_64CCCCallTo(SDOperand Op, SelectionDAG &DAG,
StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
- MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
+
+ 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));
+ }
}
}