Skip to content

Commit

Permalink
Remove the varargs-based mdarray helper. (#62855)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkoritzinsky committed Dec 16, 2021
1 parent d5f5950 commit 562d1e7
Show file tree
Hide file tree
Showing 19 changed files with 67 additions and 209 deletions.
1 change: 0 additions & 1 deletion docs/design/coreclr/botr/readytorun-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,6 @@ enum ReadyToRunHelper
READYTORUN_HELPER_Unbox = 0x5A,
READYTORUN_HELPER_Unbox_Nullable = 0x5B,
READYTORUN_HELPER_NewMultiDimArr = 0x5C,
READYTORUN_HELPER_NewMultiDimArr_NonVarArg = 0x5D,

// Helpers used with generic handle lookup cases
READYTORUN_HELPER_NewObject = 0x60,
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,7 @@ enum CorInfoHelpFunc
CORINFO_HELP_NEWSFAST_ALIGN8, // allocator for small, non-finalizer, non-array object, 8 byte aligned
CORINFO_HELP_NEWSFAST_ALIGN8_VC,// allocator for small, value class, 8 byte aligned
CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, // allocator for small, finalizable, non-array object, 8 byte aligned
CORINFO_HELP_NEW_MDARR, // multi-dim array helper (with or without lower bounds - dimensions passed in as vararg)
CORINFO_HELP_NEW_MDARR_NONVARARG,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array)
CORINFO_HELP_NEW_MDARR,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array)
CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation
CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays
CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays
Expand Down Expand Up @@ -622,7 +621,6 @@ enum CorInfoHelpSig
CORINFO_HELP_SIG_8_STACK,
CORINFO_HELP_SIG_12_STACK,
CORINFO_HELP_SIG_16_STACK,
CORINFO_HELP_SIG_8_VA, //2 arguments plus varargs

CORINFO_HELP_SIG_EBPCALL, //special calling convention that uses EDX and
//EBP as arguments
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 29ff53ef-3c61-4fc4-bdab-82e39a3d7970 */
0x29ff53ef,
0x3c61,
0x4fc4,
{0xbd, 0xab, 0x82, 0xe3, 0x9a, 0x3d, 0x79, 0x70}
constexpr GUID JITEEVersionIdentifier = { /* 1d61ee87-b3be-48ae-a12e-2fb9b5b1cee7 */
0x1d61ee87,
0xb3be,
0x48ae,
{0xa1, 0x2e, 0x2f, 0xb9, 0xb5, 0xb1, 0xce, 0xe7}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@
DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_New, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_VC, NULL, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_8_VA)
JITHELPER(CORINFO_HELP_NEW_MDARR_NONVARARG, JIT_NewMDArrNonVarArg,CORINFO_HELP_SIG_4_STACK)
JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_4_STACK)
JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ enum ReadyToRunHelper
READYTORUN_HELPER_Unbox = 0x5A,
READYTORUN_HELPER_Unbox_Nullable = 0x5B,
READYTORUN_HELPER_NewMultiDimArr = 0x5C,
READYTORUN_HELPER_NewMultiDimArr_NonVarArg = 0x5D,

// Helpers used with generic handle lookup cases
READYTORUN_HELPER_NewObject = 0x60,
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/inc/readytorunhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ HELPER(READYTORUN_HELPER_Box_Nullable, CORINFO_HELP_BOX_NULLABLE,
HELPER(READYTORUN_HELPER_Unbox, CORINFO_HELP_UNBOX, )
HELPER(READYTORUN_HELPER_Unbox_Nullable, CORINFO_HELP_UNBOX_NULLABLE, )
HELPER(READYTORUN_HELPER_NewMultiDimArr, CORINFO_HELP_NEW_MDARR, )
HELPER(READYTORUN_HELPER_NewMultiDimArr_NonVarArg, CORINFO_HELP_NEW_MDARR_NONVARARG, )

HELPER(READYTORUN_HELPER_NewObject, CORINFO_HELP_NEWFAST, )
HELPER(READYTORUN_HELPER_NewArray, CORINFO_HELP_NEWARR_1_DIRECT, )
Expand Down
130 changes: 41 additions & 89 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3364,7 +3364,7 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig)
#endif
)
{
if (newArrayCall->AsCall()->gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEW_MDARR_NONVARARG))
if (newArrayCall->AsCall()->gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEW_MDARR))
{
return nullptr;
}
Expand Down Expand Up @@ -7427,107 +7427,59 @@ void Compiler::impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORI

GenTree* node;

//
// There are two different JIT helpers that can be used to allocate
// multi-dimensional arrays:
//
// - CORINFO_HELP_NEW_MDARR - takes the array dimensions as varargs.
// This variant is deprecated. It should be eventually removed.
//
// - CORINFO_HELP_NEW_MDARR_NONVARARG - takes the array dimensions as
// pointer to block of int32s. This variant is more portable.
//
// The non-varargs helper is enabled for CoreRT only for now. Enabling this
// unconditionally would require ReadyToRun version bump.
//
CLANG_FORMAT_COMMENT_ANCHOR;

if (!opts.IsReadyToRun() || IsTargetAbi(CORINFO_CORERT_ABI))
// Reuse the temp used to pass the array dimensions to avoid bloating
// the stack frame in case there are multiple calls to multi-dim array
// constructors within a single method.
if (lvaNewObjArrayArgs == BAD_VAR_NUM)
{
lvaNewObjArrayArgs = lvaGrabTemp(false DEBUGARG("NewObjArrayArgs"));
lvaTable[lvaNewObjArrayArgs].lvType = TYP_BLK;
lvaTable[lvaNewObjArrayArgs].lvExactSize = 0;
}

// Reuse the temp used to pass the array dimensions to avoid bloating
// the stack frame in case there are multiple calls to multi-dim array
// constructors within a single method.
if (lvaNewObjArrayArgs == BAD_VAR_NUM)
{
lvaNewObjArrayArgs = lvaGrabTemp(false DEBUGARG("NewObjArrayArgs"));
lvaTable[lvaNewObjArrayArgs].lvType = TYP_BLK;
lvaTable[lvaNewObjArrayArgs].lvExactSize = 0;
}

// Increase size of lvaNewObjArrayArgs to be the largest size needed to hold 'numArgs' integers
// for our call to CORINFO_HELP_NEW_MDARR_NONVARARG.
lvaTable[lvaNewObjArrayArgs].lvExactSize =
max(lvaTable[lvaNewObjArrayArgs].lvExactSize, pCallInfo->sig.numArgs * sizeof(INT32));

// The side-effects may include allocation of more multi-dimensional arrays. Spill all side-effects
// to ensure that the shared lvaNewObjArrayArgs local variable is only ever used to pass arguments
// to one allocation at a time.
impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("impImportNewObjArray"));

//
// The arguments of the CORINFO_HELP_NEW_MDARR_NONVARARG helper are:
// - Array class handle
// - Number of dimension arguments
// - Pointer to block of int32 dimensions - address of lvaNewObjArrayArgs temp.
//

node = gtNewLclvNode(lvaNewObjArrayArgs, TYP_BLK);
node = gtNewOperNode(GT_ADDR, TYP_I_IMPL, node);

// Pop dimension arguments from the stack one at a time and store it
// into lvaNewObjArrayArgs temp.
for (int i = pCallInfo->sig.numArgs - 1; i >= 0; i--)
{
GenTree* arg = impImplicitIorI4Cast(impPopStack().val, TYP_INT);

GenTree* dest = gtNewLclvNode(lvaNewObjArrayArgs, TYP_BLK);
dest = gtNewOperNode(GT_ADDR, TYP_I_IMPL, dest);
dest = gtNewOperNode(GT_ADD, TYP_I_IMPL, dest,
new (this, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, sizeof(INT32) * i));
dest = gtNewOperNode(GT_IND, TYP_INT, dest);

node = gtNewOperNode(GT_COMMA, node->TypeGet(), gtNewAssignNode(dest, arg), node);
}
// Increase size of lvaNewObjArrayArgs to be the largest size needed to hold 'numArgs' integers
// for our call to CORINFO_HELP_NEW_MDARR.
lvaTable[lvaNewObjArrayArgs].lvExactSize =
max(lvaTable[lvaNewObjArrayArgs].lvExactSize, pCallInfo->sig.numArgs * sizeof(INT32));

GenTreeCall::Use* args = gtNewCallArgs(node);
// The side-effects may include allocation of more multi-dimensional arrays. Spill all side-effects
// to ensure that the shared lvaNewObjArrayArgs local variable is only ever used to pass arguments
// to one allocation at a time.
impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("impImportNewObjArray"));

// pass number of arguments to the helper
args = gtPrependNewCallArg(gtNewIconNode(pCallInfo->sig.numArgs), args);
//
// The arguments of the CORINFO_HELP_NEW_MDARR helper are:
// - Array class handle
// - Number of dimension arguments
// - Pointer to block of int32 dimensions - address of lvaNewObjArrayArgs temp.
//

args = gtPrependNewCallArg(classHandle, args);
node = gtNewLclvNode(lvaNewObjArrayArgs, TYP_BLK);
node = gtNewOperNode(GT_ADDR, TYP_I_IMPL, node);

node = gtNewHelperCallNode(CORINFO_HELP_NEW_MDARR_NONVARARG, TYP_REF, args);
}
else
// Pop dimension arguments from the stack one at a time and store it
// into lvaNewObjArrayArgs temp.
for (int i = pCallInfo->sig.numArgs - 1; i >= 0; i--)
{
//
// The varargs helper needs the type and method handles as last
// and last-1 param (this is a cdecl call, so args will be
// pushed in reverse order on the CPU stack)
//
GenTree* arg = impImplicitIorI4Cast(impPopStack().val, TYP_INT);

GenTreeCall::Use* args = gtNewCallArgs(classHandle);
GenTree* dest = gtNewLclvNode(lvaNewObjArrayArgs, TYP_BLK);
dest = gtNewOperNode(GT_ADDR, TYP_I_IMPL, dest);
dest = gtNewOperNode(GT_ADD, TYP_I_IMPL, dest,
new (this, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, sizeof(INT32) * i));
dest = gtNewOperNode(GT_IND, TYP_INT, dest);

// pass number of arguments to the helper
args = gtPrependNewCallArg(gtNewIconNode(pCallInfo->sig.numArgs), args);
node = gtNewOperNode(GT_COMMA, node->TypeGet(), gtNewAssignNode(dest, arg), node);
}

args = impPopCallArgs(pCallInfo->sig.numArgs, &pCallInfo->sig, args);
GenTreeCall::Use* args = gtNewCallArgs(node);

node = gtNewHelperCallNode(CORINFO_HELP_NEW_MDARR, TYP_REF, args);
// pass number of arguments to the helper
args = gtPrependNewCallArg(gtNewIconNode(pCallInfo->sig.numArgs), args);

// varargs, so we pop the arguments
node->gtFlags |= GTF_CALL_POP_ARGS;
args = gtPrependNewCallArg(classHandle, args);

#ifdef DEBUG
// At the present time we don't track Caller pop arguments
// that have GC references in them
for (GenTreeCall::Use& use : GenTreeCall::UseList(args))
{
assert(use.GetNode()->TypeGet() != TYP_REF);
}
#endif
}
node = gtNewHelperCallNode(CORINFO_HELP_NEW_MDARR, TYP_REF, args);

for (GenTreeCall::Use& use : node->AsCall()->Args())
{
Expand Down
25 changes: 11 additions & 14 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9802,6 +9802,12 @@ void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueN
}
break;

case VNF_JitNewMdArr:
{
generateUniqueVN = true;
}
break;

case VNF_Box:
case VNF_BoxNullable:
{
Expand Down Expand Up @@ -10207,6 +10213,10 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc)
vnf = VNF_JitNewArr;
break;

case CORINFO_HELP_NEW_MDARR:
vnf = VNF_JitNewMdArr;
break;

case CORINFO_HELP_READYTORUN_NEWARR_1:
vnf = VNF_JitReadyToRunNewArr;
break;
Expand Down Expand Up @@ -10433,20 +10443,7 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call)
}
else
{
// TODO-CQ: this is a list of helpers we're going to treat as non-pure,
// because they raise complications. Eventually, we need to handle those complications...
bool needsFurtherWork = false;
switch (helpFunc)
{
case CORINFO_HELP_NEW_MDARR:
// This is a varargs helper. We need to represent the array shape in the VN world somehow.
needsFurtherWork = true;
break;
default:
break;
}

if (!needsFurtherWork && (pure || isAlloc))
if (pure || isAlloc)
{
VNFunc vnf = fgValueNumberJitHelperMethodVNFunc(helpFunc);

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/valuenumfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ ValueNumFuncDef(GetStaticAddrTLS, 1, false, true, false)

ValueNumFuncDef(JitNew, 2, false, true, false)
ValueNumFuncDef(JitNewArr, 3, false, true, false)
ValueNumFuncDef(JitNewMdArr, 4, false, true, false)
ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false)
ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false)
ValueNumFuncDef(Box, 3, false, false, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ public enum ReadyToRunHelper
Unbox = 0x5A,
Unbox_Nullable = 0x5B,
NewMultiDimArr = 0x5C,
NewMultiDimArr_NonVarArg = 0x5D,

// Helpers used with generic handle lookup cases
NewObject = 0x60,
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ which is the right helper to use to allocate an object of a given type. */
CORINFO_HELP_NEWSFAST_ALIGN8, // allocator for small, non-finalizer, non-array object, 8 byte aligned
CORINFO_HELP_NEWSFAST_ALIGN8_VC,// allocator for small, value class, 8 byte aligned
CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, // allocator for small, finalizable, non-array object, 8 byte aligned
CORINFO_HELP_NEW_MDARR, // multi-dim array helper (with or without lower bounds - dimensions passed in as vararg)
CORINFO_HELP_NEW_MDARR_NONVARARG,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array)
CORINFO_HELP_NEW_MDARR,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array)
CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation
CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays
CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id,
mangledName = "RhUnboxNullable";
break;

case ReadyToRunHelper.NewMultiDimArr_NonVarArg:
case ReadyToRunHelper.NewMultiDimArr:
methodDesc = context.GetHelperEntryPoint("ArrayHelpers", "NewObjArray");
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ private void ImportCall(ILOpcode opcode, int token)
{
// RyuJIT is going to call the "MdArray" creation helper even if this is an SzArray,
// hence the IsArray check above. Note that the MdArray helper can handle SzArrays.
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.NewMultiDimArr_NonVarArg), reason);
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.NewMultiDimArr), reason);
return;
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,9 +704,6 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR:
id = ReadyToRunHelper.NewMultiDimArr;
break;
case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR_NONVARARG:
id = ReadyToRunHelper.NewMultiDimArr_NonVarArg;
break;
case CorInfoHelpFunc.CORINFO_HELP_NEWFAST:
id = ReadyToRunHelper.NewObject;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1726,10 +1726,6 @@ private void ParseHelper(StringBuilder builder)
builder.Append("NEW_MULTI_DIM_ARR");
break;

case ReadyToRunHelper.NewMultiDimArr_NonVarArg:
builder.Append("NEW_MULTI_DIM_ARR__NON_VAR_ARG");
break;

case ReadyToRunHelper.MonitorEnter:
builder.Append("MONITOR_ENTER");
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
case CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE:
id = ReadyToRunHelper.Unbox_Nullable;
break;
case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR_NONVARARG:
id = ReadyToRunHelper.NewMultiDimArr_NonVarArg;
case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR:
id = ReadyToRunHelper.NewMultiDimArr;
break;
case CorInfoHelpFunc.CORINFO_HELP_NEWFAST:
id = ReadyToRunHelper.NewObject;
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/fcall.h
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,6 @@ struct FCSigCheck {
#define HCIMPL2_RAW(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1) {
#define HCIMPL2_VV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, int /* ECX */, a2, a1) { HCIMPL_PROLOG(funcname)
#define HCIMPL2_IV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(int /* EAX */, int /* EDX */, a1, a2) { HCIMPL_PROLOG(funcname)
#define HCIMPL2VA(rettype, funcname, a1, a2) rettype F_CALL_VA_CONV funcname(a1, a2, ...) { HCIMPL_PROLOG(funcname)
#define HCIMPL3(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a3) { HCIMPL_PROLOG(funcname)
#define HCIMPL3_RAW(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a3) {
#define HCIMPL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1, a4, a3) { HCIMPL_PROLOG(funcname)
Expand All @@ -1168,7 +1167,6 @@ struct FCSigCheck {
#define HCIMPL2_RAW(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2) {
#define HCIMPL2_VV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a2, a1) { HCIMPL_PROLOG(funcname)
#define HCIMPL2_IV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2) { HCIMPL_PROLOG(funcname)
#define HCIMPL2VA(rettype, funcname, a1, a2) rettype F_CALL_VA_CONV funcname(a1, a2, ...) { HCIMPL_PROLOG(funcname)
#define HCIMPL3(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3) { HCIMPL_PROLOG(funcname)
#define HCIMPL3_RAW(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3) {
#define HCIMPL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(a1, a2, a4, a3) { HCIMPL_PROLOG(funcname)
Expand All @@ -1194,7 +1192,6 @@ struct FCSigCheck {
#define HCIMPL2_RAW(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2) {
#define HCIMPL2_VV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2) { HCIMPL_PROLOG(funcname)
#define HCIMPL2_IV(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2) { HCIMPL_PROLOG(funcname)
#define HCIMPL2VA(rettype, funcname, a1, a2) rettype F_CALL_VA_CONV funcname(a1, a2, ...) { HCIMPL_PROLOG(funcname)
#define HCIMPL3(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3) { HCIMPL_PROLOG(funcname)
#define HCIMPL3_RAW(rettype, funcname, a1, a2, a3) rettype F_CALL_CONV funcname(a1, a2, a3) {
#define HCIMPL4(rettype, funcname, a1, a2, a3, a4) rettype F_CALL_CONV funcname(a1, a2, a3, a4) { HCIMPL_PROLOG(funcname)
Expand Down
Loading

0 comments on commit 562d1e7

Please sign in to comment.