summaryrefslogtreecommitdiff
path: root/src/vm/callhelpers.cpp
diff options
context:
space:
mode:
authorLubomir Litchev <llitchev@live.com>2015-02-19 11:42:30 -0800
committerLubomir Litchev <lubol@microsoft.com>2015-10-20 14:20:36 -0700
commit378e304f9e22b3c4d03c3b1b62c47b0aa58ceaf5 (patch)
treeb83aec8f77caeb9ca94c6d7505a548b93cdb7259 /src/vm/callhelpers.cpp
parent3015ff7afb4936a1c5c5856daa4e3482e6b390a9 (diff)
downloadcoreclr-378e304f9e22b3c4d03c3b1b62c47b0aa58ceaf5.tar.gz
coreclr-378e304f9e22b3c4d03c3b1b62c47b0aa58ceaf5.tar.bz2
coreclr-378e304f9e22b3c4d03c3b1b62c47b0aa58ceaf5.zip
Implementation of System V ABI struct passing.
This PR adds support for System V x86_64 ABI classification and calling convention to the VM and the Jit, including, but not limited to Ubuntu Linux and Mac OS X. The general rules outlined in the System V x86_64 ABI (described at http://www.x86-64.org/documentation/abi.pdf) are followed with a few little exceptions, described below: 1. The hidden argument for by-value passed structs is always after the ÎéÎíthisÎéÎí parameter (if there is one.). This is a difference with the Sysetem V ABI and affects only the internal jit calling conventions. For PInvoke calls the hidden argument is always the first parameter since there is no ÎéÎíthisÎéÎí parameter in this case. 2. Managed structs that have no fields are always passed by-value on the stack. 3. The jit proactively generates frame register frames (with RBP as a frame register) in order to aid the native OS tooling for stack unwinding and the like.
Diffstat (limited to 'src/vm/callhelpers.cpp')
-rw-r--r--src/vm/callhelpers.cpp10
1 files changed, 8 insertions, 2 deletions
diff --git a/src/vm/callhelpers.cpp b/src/vm/callhelpers.cpp
index a910c0ea30..137dbb8656 100644
--- a/src/vm/callhelpers.cpp
+++ b/src/vm/callhelpers.cpp
@@ -401,7 +401,7 @@ ARG_SLOT MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments)
// Record this call if required
g_IBCLogger.LogMethodDescAccess(m_pMD);
- //
+ //
// All types must already be loaded. This macro also sets up a FAULT_FORBID region which is
// also required for critical calls since we cannot inject any failure points between the
// caller of MethodDesc::CallDescr and the actual transition to managed code.
@@ -537,9 +537,12 @@ ARG_SLOT MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments)
// have at least one such argument we point the call worker at the floating point area of the
// frame (we leave it null otherwise since the worker can perform a useful optimization if it
// knows no floating point registers need to be set up).
- if ((ofs < 0) && (pFloatArgumentRegisters == NULL))
+ if (TransitionBlock::HasFloatRegister(ofs, m_argIt.GetArgLocDescForStructInRegs()) &&
+ (pFloatArgumentRegisters == NULL))
+ {
pFloatArgumentRegisters = (FloatArgumentRegisters*)(pTransitionBlock +
TransitionBlock::GetOffsetOfFloatArgumentRegisters());
+ }
#endif
#if CHECK_APP_DOMAIN_LEAKS
@@ -553,6 +556,9 @@ ARG_SLOT MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments)
}
#endif // CHECK_APP_DOMAIN_LEAKS
+#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+ _ASSERTE(ofs != TransitionBlock::StructInRegsOffset);
+#endif
PVOID pDest = pTransitionBlock + ofs;
UINT32 stackSize = m_argIt.GetArgSize();