summaryrefslogtreecommitdiff
path: root/lib/Target/X86
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86')
-rw-r--r--lib/Target/X86/X86CallingConv.h27
-rw-r--r--lib/Target/X86/X86CallingConv.td10
2 files changed, 37 insertions, 0 deletions
diff --git a/lib/Target/X86/X86CallingConv.h b/lib/Target/X86/X86CallingConv.h
index e76f9fda2d..040da3535e 100644
--- a/lib/Target/X86/X86CallingConv.h
+++ b/lib/Target/X86/X86CallingConv.h
@@ -29,6 +29,33 @@ inline bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &,
return false;
}
+inline bool CC_X86_CDeclMethod_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ // Swap the order of the first two parameters if the first parameter is sret.
+ if (ArgFlags.isSRet()) {
+ assert(ValNo == 0);
+ assert(ValVT == MVT::i32);
+ State.AllocateStack(8, 4);
+ State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 4, LocVT, LocInfo));
+
+ // Indicate that we need to swap the order of the first and second
+ // parameters by "allocating" register zero. There are no register
+ // parameters with cdecl methods, so we can use this to communicate to the
+ // next call.
+ State.AllocateReg(1);
+ return true;
+ } else if (ValNo == 1 && State.isAllocated(1)) {
+ assert(ValVT == MVT::i32 && "non-i32-sized this param unsupported");
+ // Stack was already allocated while processing sret.
+ State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 0, LocVT, LocInfo));
+ return true;
+ }
+
+ // All other args use the C calling convention.
+ return false;
+}
+
} // End llvm namespace
#endif
diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td
index 5b51a1e8e0..f40a42ee9b 100644
--- a/lib/Target/X86/X86CallingConv.td
+++ b/lib/Target/X86/X86CallingConv.td
@@ -485,6 +485,15 @@ def CC_X86_32_ThisCall_Win : CallingConv<[
CCDelegateTo<CC_X86_32_ThisCall_Common>
]>;
+def CC_X86_CDeclMethod : CallingConv<[
+ // Promote i8/i16 arguments to i32.
+ CCIfType<[i8, i16], CCPromoteToType<i32>>,
+
+ CCCustom<"CC_X86_CDeclMethod_SRet">,
+
+ CCDelegateTo<CC_X86_32_Common>
+]>;
+
def CC_X86_32_ThisCall : CallingConv<[
CCIfSubtarget<"isTargetCygMing()", CCDelegateTo<CC_X86_32_ThisCall_Mingw>>,
CCDelegateTo<CC_X86_32_ThisCall_Win>
@@ -574,6 +583,7 @@ def CC_Intel_OCL_BI : CallingConv<[
def CC_X86_32 : CallingConv<[
CCIfCC<"CallingConv::X86_FastCall", CCDelegateTo<CC_X86_32_FastCall>>,
CCIfCC<"CallingConv::X86_ThisCall", CCDelegateTo<CC_X86_32_ThisCall>>,
+ CCIfCC<"CallingConv::X86_CDeclMethod", CCDelegateTo<CC_X86_CDeclMethod>>,
CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_X86_32_FastCC>>,
CCIfCC<"CallingConv::GHC", CCDelegateTo<CC_X86_32_GHC>>,
CCIfCC<"CallingConv::HiPE", CCDelegateTo<CC_X86_32_HiPE>>,