[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / fcall.h
index a952da1..7569c85 100644 (file)
 //    FCThrow(). This is because FCThrow() has to generate an unexecuted
 //    "return" statement for the code parser.
 //
-//  - If first and/or second argument of your FCall is 64-bit value on x86
-//    (ie INT64, UINT64 or DOUBLE), you must use "V" versions of FCDECL and 
-//    FCIMPL macros to enregister arguments correctly. For example, FCDECL3_IVI 
-//    must be used for FCalls that take 3 arguments and 2nd argument is INT64.
+//  - On x86, if first and/or second argument of your FCall cannot be passed
+//    in either of the __fastcall registers (ECX/EDX), you must use "V" versions
+//    of FCDECL and  FCIMPL macros to enregister arguments correctly. Some of the
+//    most common types that fit this requirement are 64-bit values (i.e. INT64 or
+//    UINT64) and floating-point values (i.e. FLOAT or DOUBLE). For example, FCDECL3_IVI 
+//    must be used for FCalls that take 3 arguments and 2nd argument is INT64 and
+//    FDECL2_VV must be used for FCalls that take 2 arguments where both are FLOAT.
 //
 //  - You may use structs for protecting multiple OBJECTREF's simultaneously.
 //    In these cases, you must use a variant of a helper method frame with PROTECT
 #include "gms.h"
 #include "runtimeexceptionkind.h"
 #include "debugreturn.h"
-#include "stackprobe.h"
 
 //==============================================================================================
 // These macros defeat compiler optimizations that might mix nonvolatile
@@ -374,16 +376,27 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 
 // Choose the appropriate calling convention for FCALL helpers on the basis of the JIT calling convention
 #ifdef __GNUC__
-#define F_CALL_CONV __attribute__((stdcall, regparm(3)))
-#else
+#define F_CALL_CONV __attribute__((cdecl, regparm(3)))
+
+// GCC fastcall convention (simulated via stdcall) is different from MSVC fastcall convention. GCC can use up
+// to 3 registers to store parameters. The registers used are EAX, EDX, ECX. Dummy parameters and reordering
+// of the actual parameters in the FCALL signature is used to make the calling convention to look like in MSVC.
+#define SWIZZLE_REGARG_ORDER
+#else // __GNUC__
 #define F_CALL_CONV __fastcall
-#endif
+#endif // !__GNUC__
+
+#define SWIZZLE_STKARG_ORDER
+#else // _TARGET_X86_
 
-#if defined(__GNUC__)
+//
+// non-x86 platforms don't have messed-up calling convention swizzling
+//
+#define F_CALL_CONV
+#endif // !_TARGET_X86_
 
-// GCC fastcall convention is different from MSVC fastcall convention. GCC can use up to 3 registers to
-// store parameters. The registers used are EAX, EDX, ECX. Dummy parameters and reordering of the 
-// actual parameters in the FCALL signature is used to make the calling convention to look like in MSVC.
+#ifdef SWIZZLE_STKARG_ORDER
+#ifdef SWIZZLE_REGARG_ORDER
 
 #define FCDECL0(rettype, funcname) rettype F_CALL_CONV funcname()
 #define FCDECL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1)
@@ -399,6 +412,7 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define FCDECL3_IVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1, a3, a2)
 #define FCDECL3_IVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, a3, a1, a2)
 #define FCDECL3_VVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a3, a2, a1)
+#define FCDECL3_VVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, int /* ECX */, a3, a2, a1)
 #define FCDECL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a4, a3)
 #define FCDECL5(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a5, a4, a3)
 #define FCDECL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a6, a5, a4, a3)
@@ -414,7 +428,7 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define FCDECL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a3, a1, a5, a4, a2)
 #define FCDECL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a3, a2, a5, a4, a1)
 
-#else // __GNUC__
+#else // SWIZZLE_REGARG_ORDER
 
 #define FCDECL0(rettype, funcname) rettype F_CALL_CONV funcname()
 #define FCDECL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(a1)
@@ -430,6 +444,7 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define FCDECL3_IVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a3, a2)
 #define FCDECL3_IVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a3, a2)
 #define FCDECL3_VVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a2, a1, a3)
+#define FCDECL3_VVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a3, a2, a1)
 #define FCDECL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(a1, a2, a4, a3)
 #define FCDECL5(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a1, a2, a5, a4, a3)
 #define FCDECL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype F_CALL_CONV funcname(a1, a2, a6, a5, a4, a3)
@@ -445,7 +460,7 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define FCDECL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a1, a3, a5, a4, a2)
 #define FCDECL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a2, a3, a5, a4, a1)
 
-#endif // __GNUC__
+#endif // !SWIZZLE_REGARG_ORDER
 
 #if 0
 //
@@ -469,40 +484,39 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define FCCALL12(funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) funcname(a1, a2, a12, a11, a10, a9, a8, a7, a6, a5, a4, a3)
 #endif // 0
 
-#else // !_TARGET_X86
+#else // !SWIZZLE_STKARG_ORDER
 
-#define F_CALL_CONV
-
-#define FCDECL0(rettype, funcname) rettype funcname()
-#define FCDECL1(rettype, funcname, a1) rettype funcname(a1)
-#define FCDECL1_V(rettype, funcname, a1) rettype funcname(a1)
-#define FCDECL2(rettype, funcname, a1, a2) rettype funcname(a1, a2)
-#define FCDECL2VA(rettype, funcname, a1, a2) rettype funcname(a1, a2, ...)
-#define FCDECL2_VV(rettype, funcname, a1, a2) rettype funcname(a1, a2)
-#define FCDECL2_VI(rettype, funcname, a1, a2) rettype funcname(a1, a2)
-#define FCDECL2_IV(rettype, funcname, a1, a2) rettype funcname(a1, a2)
-#define FCDECL3(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL3_IIV(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL3_VII(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL3_IVV(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL3_IVI(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL3_VVI(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3)
-#define FCDECL4(rettype, funcname, a1, a2, a3, a4) rettype funcname(a1, a2, a3, a4)
-#define FCDECL5(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5)
-#define FCDECL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype funcname(a1, a2, a3, a4, a5, a6)
-#define FCDECL7(rettype, funcname, a1, a2, a3, a4, a5, a6, a7) rettype funcname(a1, a2, a3, a4, a5, a6, a7)
-#define FCDECL8(rettype, funcname, a1, a2, a3, a4, a5, a6, a7, a8) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8)
-#define FCDECL9(rettype, funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9)
-#define FCDECL10(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
-#define FCDECL11(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)
-#define FCDECL12(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
-#define FCDECL13(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)
-#define FCDECL14(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) rettype funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)
-
-#define FCDECL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5)
-#define FCDECL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5)
-
-#endif // _TARGET_X86_ 
+#define FCDECL0(rettype, funcname) rettype F_CALL_CONV funcname()
+#define FCDECL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(a1)
+#define FCDECL1_V(rettype, funcname, a1) rettype F_CALL_CONV funcname(a1)
+#define FCDECL2(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2)
+#define FCDECL2VA(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2, ...)
+#define FCDECL2_VV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2)
+#define FCDECL2_VI(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2)
+#define FCDECL2_IV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2)
+#define FCDECL3(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_IIV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_VII(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_IVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_IVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_VVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL3_VVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3)
+#define FCDECL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(a1, a2, a3, a4)
+#define FCDECL5(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5)
+#define FCDECL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6)
+#define FCDECL7(rettype, funcname, a1, a2, a3, a4, a5, a6, a7) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7)
+#define FCDECL8(rettype, funcname, a1, a2, a3, a4, a5, a6, a7, a8) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8)
+#define FCDECL9(rettype, funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#define FCDECL10(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+#define FCDECL11(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)
+#define FCDECL12(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
+#define FCDECL13(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)
+#define FCDECL14(rettype,funcname, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)
+
+#define FCDECL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5)
+#define FCDECL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(a1, a2, a3, a4, a5)
+
+#endif // !SWIZZLE_STKARG_ORDER
 
 #define HELPER_FRAME_DECL(x) FrameWithCookie<HelperMethodFrame_##x##OBJ> __helperframe
 
@@ -559,7 +573,6 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 
 #define HELPER_METHOD_FRAME_BEGIN_EX(ret, helperFrame, gcpoll, allowGC)         \
         HELPER_METHOD_FRAME_BEGIN_EX_BODY(ret, helperFrame, gcpoll, allowGC)    \
-            TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,!allowGC)); \
             /* <TODO>TODO TURN THIS ON!!!   </TODO> */                    \
             /* gcpoll; */                                                       \
             INSTALL_MANAGED_EXCEPTION_DISPATCHER;                               \
@@ -568,8 +581,7 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define HELPER_METHOD_FRAME_BEGIN_EX_NOTHROW(ret, helperFrame, gcpoll, allowGC, probeFailExpr) \
         HELPER_METHOD_FRAME_BEGIN_EX_BODY(ret, helperFrame, gcpoll, allowGC)    \
             /* <TODO>TODO TURN THIS ON!!!   </TODO> */                    \
-            /* gcpoll; */                                                       \
-            BEGIN_SO_INTOLERANT_CODE_NOTHROW(GET_THREAD(), probeFailExpr);
+            /* gcpoll; */
 
 
 // The while(__helperframe.RestoreState() needs a bit of explanation.
@@ -596,11 +608,9 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 #define HELPER_METHOD_FRAME_END_EX(gcpoll,allowGC)                          \
             UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;                          \
             UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;                         \
-            TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,!allowGC)); \
         HELPER_METHOD_FRAME_END_EX_BODY(gcpoll,allowGC);
 
 #define HELPER_METHOD_FRAME_END_EX_NOTHROW(gcpoll,allowGC)                  \
-            END_SO_INTOLERANT_CODE;                                         \
         HELPER_METHOD_FRAME_END_EX_BODY(gcpoll,allowGC);
 
 #define HELPER_METHOD_FRAME_BEGIN_ATTRIB(attribs)                                       \
@@ -641,6 +651,18 @@ LPVOID __FCThrowArgument(LPVOID me, enum RuntimeExceptionKind reKind, LPCWSTR ar
 
 #define HELPER_METHOD_FRAME_BEGIN_2(arg1, arg2) HELPER_METHOD_FRAME_BEGIN_ATTRIB_2(Frame::FRAME_ATTR_NONE, arg1, arg2)
 
+#define HELPER_METHOD_FRAME_BEGIN_ATTRIB_3(attribs, arg1, arg2, arg3)                         \
+        static_assert(sizeof(arg1) == sizeof(OBJECTREF), "GC protecting structs of multiple OBJECTREFs requires a PROTECT variant of the HELPER METHOD FRAME macro");\
+        static_assert(sizeof(arg2) == sizeof(OBJECTREF), "GC protecting structs of multiple OBJECTREFs requires a PROTECT variant of the HELPER METHOD FRAME macro");\
+        static_assert(sizeof(arg3) == sizeof(OBJECTREF), "GC protecting structs of multiple OBJECTREFs requires a PROTECT variant of the HELPER METHOD FRAME macro");\
+        HELPER_METHOD_FRAME_BEGIN_EX(                                                   \
+            return,                                                                     \
+            HELPER_FRAME_DECL(3)(HELPER_FRAME_ARGS(attribs),                            \
+                (OBJECTREF*) &arg1, (OBJECTREF*) &arg2, (OBJECTREF*) &arg3),                                \
+            HELPER_METHOD_POLL(),TRUE)
+
+#define HELPER_METHOD_FRAME_BEGIN_3(arg1, arg2, arg3) HELPER_METHOD_FRAME_BEGIN_ATTRIB_3(Frame::FRAME_ATTR_NONE, arg1, arg2, arg3)
+
 #define HELPER_METHOD_FRAME_BEGIN_PROTECT(gc)                                           \
         HELPER_METHOD_FRAME_BEGIN_EX(                                                   \
             return,                                                                     \
@@ -842,8 +864,6 @@ private:
         {                                       \
             Thread *_pThread = GetThread();     \
             Thread::ObjectRefFlush(_pThread);    \
-            /*_ASSERTE (_pThread->IsSOTolerant() ||*/ \
-            /*       _pThread->HasThreadStateNC(Thread::TSNC_DisableSOCheckInHCALL)); */    \
         }                                       \
         FCallCheck __fCallCheck(__FILE__, __LINE__); \
         FCALL_TRANSITION_BEGIN(); \
@@ -933,15 +953,17 @@ extern int FC_NO_TAILCALL;
     FC_COMMON_PROLOG(__me, FCallAssert)
 
 
-#if defined(_DEBUG) && !defined(CROSSGEN_COMPILE)
-
+#if defined(_DEBUG) && !defined(CROSSGEN_COMPILE) && !defined(__GNUC__)
 // Build the list of all fcalls signatures. It is used in binder.cpp to verify 
 // compatibility of managed and unmanaged fcall signatures. The check is currently done 
 // for x86 only.
+#define CHECK_FCALL_SIGNATURE
+#endif
 
+#ifdef CHECK_FCALL_SIGNATURE
 struct FCSigCheck {
 public:
-    FCSigCheck(void* fnc, char* sig)
+    FCSigCheck(void* fnc, const char* sig)
     {
         LIMITED_METHOD_CONTRACT;
         func = fnc;
@@ -952,7 +974,7 @@ public:
 
     FCSigCheck* next;
     void* func;
-    char* signature;
+    const char* signature;
 
     static FCSigCheck* g_pFCSigCheck;
 };
@@ -960,16 +982,15 @@ public:
 #define FCSIGCHECK(funcname, signature) \
     static FCSigCheck UNIQUE_LABEL(FCSigCheck)(GetEEFuncEntryPointMacro(funcname), signature);
 
-#else
+#else // CHECK_FCALL_SIGNATURE
 
 #define FCSIGCHECK(funcname, signature)
 
-#endif
-
+#endif // !CHECK_FCALL_SIGNATURE
 
-#ifdef _TARGET_X86_
 
-#if defined(__GNUC__)
+#ifdef SWIZZLE_STKARG_ORDER
+#ifdef SWIZZLE_REGARG_ORDER
 
 #define FCIMPL0(rettype, funcname) rettype F_CALL_CONV funcname() { FCIMPL_PROLOG(funcname)
 #define FCIMPL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1) { FCIMPL_PROLOG(funcname)
@@ -984,6 +1005,7 @@ public:
 #define FCIMPL3_IVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1, a3, a2) { FCIMPL_PROLOG(funcname)
 #define FCIMPL3_IVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, a3, a1, a2) { FCIMPL_PROLOG(funcname)
 #define FCIMPL3_VVI(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a3, a2, a1) {  FCIMPL_PROLOG(funcname)
+#define FCIMPL3_VVV(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, int /* ECX */, a3, a2, a1) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a4, a3) { FCIMPL_PROLOG(funcname)
 #define FCIMPL5(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a5, a4, a3) { FCIMPL_PROLOG(funcname)
 #define FCIMPL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a6, a5, a4, a3) { FCIMPL_PROLOG(funcname)
@@ -999,7 +1021,7 @@ public:
 #define FCIMPL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a3, a1, a5, a4, a2) { FCIMPL_PROLOG(funcname)
 #define FCIMPL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype F_CALL_CONV funcname(int /* EAX */, a3, a2, a5, a4, a1) { FCIMPL_PROLOG(funcname)
 
-#else // __GNUC__
+#else // SWIZZLE_REGARG_ORDER
 
 #define FCIMPL0(rettype, funcname) FCSIGCHECK(funcname, #rettype) \
     rettype F_CALL_CONV funcname() { FCIMPL_PROLOG(funcname)
@@ -1029,6 +1051,8 @@ public:
     rettype F_CALL_CONV funcname(a1, a3, a2) { FCIMPL_PROLOG(funcname)
 #define FCIMPL3_VVI(rettype, funcname, a1, a2, a3) FCSIGCHECK(funcname, #rettype "," "V" #a1 "," "V" #a2 "," #a3) \
     rettype F_CALL_CONV funcname(a2, a1, a3) { FCIMPL_PROLOG(funcname)
+#define FCIMPL3_VVV(rettype, funcname, a1, a2, a3) FCSIGCHECK(funcname, #rettype "," "V" #a1 "," "V" #a2 "," "V" #a3) \
+    rettype F_CALL_CONV funcname(a3, a2, a1) { FCIMPL_PROLOG(funcname)
 #define FCIMPL4(rettype, funcname, a1, a2, a3, a4) FCSIGCHECK(funcname, #rettype "," #a1 "," #a2 "," #a3 "," #a4) \
     rettype F_CALL_CONV funcname(a1, a2, a4, a3) { FCIMPL_PROLOG(funcname)
 #define FCIMPL5(rettype, funcname, a1, a2, a3, a4, a5) FCSIGCHECK(funcname, #rettype "," #a1 "," #a2 "," #a3 "," #a4 "," #a5) \
@@ -1057,12 +1081,9 @@ public:
 #define FCIMPL5_VII(rettype, funcname, a1, a2, a3, a4, a5) FCSIGCHECK(funcname, #rettype "," "V" #a1 "," #a2 "," #a3 "," #a4 "," #a5) \
     rettype F_CALL_CONV funcname(a2, a3, a5, a4, a1) { FCIMPL_PROLOG(funcname)
 
-#endif // __GNUC__
+#endif // !SWIZZLE_REGARG_ORDER
 
-#else // !_TARGET_X86_ 
-//
-// non-x86 platforms don't have messed-up calling convention swizzling 
-//
+#else // SWIZZLE_STKARG_ORDER
 
 #define FCIMPL0(rettype, funcname) rettype funcname() { FCIMPL_PROLOG(funcname)
 #define FCIMPL1(rettype, funcname, a1) rettype funcname(a1) {  FCIMPL_PROLOG(funcname)
@@ -1078,6 +1099,7 @@ public:
 #define FCIMPL3_VII(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL3_IVI(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL3_VVI(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3) {  FCIMPL_PROLOG(funcname)
+#define FCIMPL3_VVV(rettype, funcname, a1, a2, a3) rettype funcname(a1, a2, a3) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL4(rettype, funcname, a1, a2, a3, a4) rettype funcname(a1, a2, a3, a4) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL5(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5) {  FCIMPL_PROLOG(funcname)
 #define FCIMPL6(rettype, funcname, a1, a2, a3, a4, a5, a6) rettype funcname(a1, a2, a3, a4, a5, a6) {  FCIMPL_PROLOG(funcname)
@@ -1093,7 +1115,7 @@ public:
 #define FCIMPL5_IVI(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5) { FCIMPL_PROLOG(funcname)
 #define FCIMPL5_VII(rettype, funcname, a1, a2, a3, a4, a5) rettype funcname(a1, a2, a3, a4, a5) { FCIMPL_PROLOG(funcname)
 
-#endif
+#endif // !SWIZZLE_STKARG_ORDER
 
 //==============================================================================================
 // Use this to terminte an FCIMPLEND.
@@ -1109,9 +1131,8 @@ public:
     // they do not remember the function they come from. Thus they will not
     // show up in a stack trace.  This is what you want for JIT helpers and the like
 
-#ifdef _TARGET_X86_
-
-#if defined(__GNUC__)
+#ifdef SWIZZLE_STKARG_ORDER
+#ifdef SWIZZLE_REGARG_ORDER
 
 #define HCIMPL0(rettype, funcname) rettype F_CALL_CONV funcname() { HCIMPL_PROLOG(funcname)
 #define HCIMPL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1) { HCIMPL_PROLOG(funcname)
@@ -1134,7 +1155,7 @@ public:
 #define HCCALL5(funcname, a1, a2, a3, a4, a5)   funcname(0, a2, a1, a5, a4, a3)
 #define HCCALL1_PTR(rettype, funcptr, a1)        rettype (F_CALL_CONV * funcptr)(int /* EAX */, int /* EDX */, a1)
 #define HCCALL2_PTR(rettype, funcptr, a1, a2)    rettype (F_CALL_CONV * funcptr)(int /* EAX */, a2, a1)
-#else
+#else // SWIZZLE_REGARG_ORDER
 
 #define HCIMPL0(rettype, funcname) rettype F_CALL_CONV funcname() { HCIMPL_PROLOG(funcname) 
 #define HCIMPL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(a1) { HCIMPL_PROLOG(funcname)
@@ -1157,13 +1178,8 @@ public:
 #define HCCALL5(funcname, a1, a2, a3, a4, a5)   funcname(a1, a2, a5, a4, a3)
 #define HCCALL1_PTR(rettype, funcptr, a1)        rettype (F_CALL_CONV * funcptr)(a1)
 #define HCCALL2_PTR(rettype, funcptr, a1, a2)    rettype (F_CALL_CONV * funcptr)(a1, a2)
-
-#endif
-
-#else // !_TARGET_X86_ 
-//
-// non-x86 platforms don't have messed-up calling convention swizzling 
-//
+#endif // !SWIZZLE_REGARG_ORDER
+#else // SWIZZLE_STKARG_ORDER
 
 #define HCIMPL0(rettype, funcname) rettype F_CALL_CONV funcname() { HCIMPL_PROLOG(funcname) 
 #define HCIMPL1(rettype, funcname, a1) rettype F_CALL_CONV funcname(a1) { HCIMPL_PROLOG(funcname)
@@ -1187,7 +1203,7 @@ public:
 #define HCCALL1_PTR(rettype, funcptr, a1)        rettype (F_CALL_CONV * funcptr)(a1)
 #define HCCALL2_PTR(rettype, funcptr, a1, a2)    rettype (F_CALL_CONV * funcptr)(a1, a2)
 
-#endif
+#endif // !SWIZZLE_STKARG_ORDER
 
 #define HCIMPLEND_RAW   }
 #define HCIMPLEND       FCALL_TRANSITION_END(); }
@@ -1317,14 +1333,8 @@ typedef UINT16 FC_UINT16_RET;
 
 
 // FC_TypedByRef should be used for TypedReferences in FCall signatures
-#if defined(UNIX_AMD64_ABI) && !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
-// Explicitly pass the TypedReferences by reference 
-#define FC_TypedByRef   TypedByRef&
-#define FC_DECIMAL      DECIMAL&
-#else
 #define FC_TypedByRef   TypedByRef
 #define FC_DECIMAL      DECIMAL
-#endif
 
 
 // The fcall entrypoints has to be at unique addresses. Use this helper macro to make 
@@ -1361,8 +1371,7 @@ typedef UINT16 FC_UINT16_RET;
 #define FCALL_CHECK \
         THROWS; \
         DISABLED(GC_TRIGGERS); /* FCALLS with HELPER frames have issues with GC_TRIGGERS */ \
-        MODE_COOPERATIVE; \
-        SO_TOLERANT
+        MODE_COOPERATIVE;
 
 //
 // FCALL_CONTRACT should be the following shortcut:
@@ -1372,7 +1381,6 @@ typedef UINT16 FC_UINT16_RET;
 // Since there is very little value in having runtime contracts in FCalls, FCALL_CONTRACT is defined as static contract only for performance reasons.
 //
 #define FCALL_CONTRACT \
-    STATIC_CONTRACT_SO_TOLERANT; \
     STATIC_CONTRACT_THROWS; \
     /* FCALLS are a special case contract wise, they are "NOTRIGGER, unless you setup a frame" */ \
     STATIC_CONTRACT_GC_NOTRIGGER; \