Repository: dotnet/runtime
File: src/coreclr/interpreter/compiler.cpp (C++)

Code before:
    int *callArgs = (int*) AllocMemPool((3 + 1) * sizeof(int));
    callArgs[0] = thisVar;
    callArgs[1] = typeVar;
    callArgs[2] = methodVar;
    callArgs[3] = CALL_ARGS_TERMINATOR;

    AddIns(INTOP_CALL);
    m_pLastNewIns->data[0] = GetMethodDataItemIndex(getVirtualFunctionPtrHelper);
    m_pLastNewIns->SetDVar(dVar);
    m_pLastNewIns->SetSVar(CALL_ARGS_SVAR);
    m_pLastNewIns->flags |= INTERP_INST_FLAG_CALL;
    m_pLastNewIns->info.pCallInfo = (InterpCallInfo*)AllocMemPool0(sizeof (InterpCallInfo));
    m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;
}

void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunctionPointerVar, CORINFO_SIG_INFO* callSiteSig)
{
    AddIns(isTailCall ? INTOP_CALLI_TAIL : INTOP_CALLI);
    m_pLastNewIns->data[0] = GetDataItemIndex(calliCookie);
    // data[1] is set to 1 if the calli is calling a pinvoke, 0 otherwise
    bool suppressGCTransition = false;
    m_compHnd->getUnmanagedCallConv(nullptr, callSiteSig, &suppressGCTransition);
    bool isPInvoke = (callSiteSig->callConv != CORINFO_CALLCONV_DEFAULT && callSiteSig->callConv != CORINFO_CALLCONV_VARARG);
    if (isPInvoke && m_compHnd->pInvokeMarshalingRequired(NULL, callSiteSig))
    {
        BADCODE("PInvoke marshalling is not supported in interpreted code");
    }
    m_pLastNewIns->data[1] = (suppressGCTransition ? (int32_t)CalliFlags::SuppressGCTransition : 0) |
                             (isPInvoke ? (int32_t)CalliFlags::PInvoke : 0);
    m_pLastNewIns->SetSVars2(CALL_ARGS_SVAR, callIFunctionPointerVar);
}

void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli)
{
    uint32_t token = getU4LittleEndian(m_ip + 1);
    bool isVirtual = (*m_ip == CEE_CALLVIRT);
    bool isDelegateInvoke = false;

    CORINFO_RESOLVED_TOKEN resolvedCallToken;
    CORINFO_CALL_INFO callInfo;
    bool doCallInsteadOfNew = false;

    int callIFunctionPointerVar = -1;
    void* calliCookie = NULL;

    if (isCalli)
    {
        // Suppress uninitialized use warning.
        memset(&resolvedCallToken, 0, sizeof(resolvedCallToken));
        memset(&callInfo, 0, sizeof(callInfo));


Review comment (suggestion):
```suggestion
        BADCODE("PInvoke marshalling for calli is not supported in interpreted code");
```

Code after:
    int *callArgs = (int*) AllocMemPool((3 + 1) * sizeof(int));
    callArgs[0] = thisVar;
    callArgs[1] = typeVar;
    callArgs[2] = methodVar;
    callArgs[3] = CALL_ARGS_TERMINATOR;

    AddIns(INTOP_CALL);
    m_pLastNewIns->data[0] = GetMethodDataItemIndex(getVirtualFunctionPtrHelper);
    m_pLastNewIns->SetDVar(dVar);
    m_pLastNewIns->SetSVar(CALL_ARGS_SVAR);
    m_pLastNewIns->flags |= INTERP_INST_FLAG_CALL;
    m_pLastNewIns->info.pCallInfo = (InterpCallInfo*)AllocMemPool0(sizeof (InterpCallInfo));
    m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;
}

void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunctionPointerVar, CORINFO_SIG_INFO* callSiteSig)
{
    AddIns(isTailCall ? INTOP_CALLI_TAIL : INTOP_CALLI);
    m_pLastNewIns->data[0] = GetDataItemIndex(calliCookie);
    // data[1] is set to 1 if the calli is calling a pinvoke, 0 otherwise
    bool suppressGCTransition = false;
    CorInfoCallConv callConv = (CorInfoCallConv)(callSiteSig->callConv & IMAGE_CEE_CS_CALLCONV_MASK);
    bool isPInvoke = (callConv != CORINFO_CALLCONV_DEFAULT && callConv != CORINFO_CALLCONV_VARARG);
    if (isPInvoke)
    {
        if (m_compHnd->pInvokeMarshalingRequired(NULL, callSiteSig))
        {
            BADCODE("PInvoke marshalling for calli is not supported in interpreted code");
        }
        m_compHnd->getUnmanagedCallConv(nullptr, callSiteSig, &suppressGCTransition);
    }
    m_pLastNewIns->data[1] = (suppressGCTransition ? (int32_t)CalliFlags::SuppressGCTransition : 0) |
                             (isPInvoke ? (int32_t)CalliFlags::PInvoke : 0);
    m_pLastNewIns->SetSVars2(CALL_ARGS_SVAR, callIFunctionPointerVar);
}

void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli)
{
    uint32_t token = getU4LittleEndian(m_ip + 1);
    bool isVirtual = (*m_ip == CEE_CALLVIRT);
    bool isDelegateInvoke = false;

    CORINFO_RESOLVED_TOKEN resolvedCallToken;
    CORINFO_CALL_INFO callInfo;
    bool doCallInsteadOfNew = false;

    int callIFunctionPointerVar = -1;
    void* calliCookie = NULL;

    if (isCalli)
    {