Repository: dotnet/runtime
File: src/coreclr/vm/callstubgenerator.cpp (C++)

Code before:
        {
            TypeHandle thRetType = sig.GetRetTypeHandleThrowing();
            MethodTable* pMTRetType = thRetType.AsMethodTable();

            if (pMTRetType->GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE && !isNativePrimitiveStructType(pMTRetType))
            {
                rewriteReturnTypeToForceRetBuf = true;
            }
        }
    }
#endif // defined(TARGET_WINDOWS)

    // Rewrite ExplicitThis to HasThis. This allows us to use ArgIterator which is unaware of ExplicitThis
    // in the places where it is needed such as computation of return buffers.
    if (sig.GetCallingConventionInfo() & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
    {
        printf("Managed ExplicitThis to HasThis conversion needed\n");
        rewriteMetaSigFromExplicitThisToHasThis = true;
    }

    SigBuilder sigBuilder;
    if (rewriteMetaSigFromExplicitThisToHasThis)
    {
        printf("Rewriting ExplicitThis to implicit this\n");
        sigBuilder.AppendByte(IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS);
        if ((sig.NumFixedArgs() == 0) || (sig.HasThis() && !sig.HasExplicitThis()))
        {
            ThrowHR(COR_E_BADIMAGEFORMAT);
        }
        sigBuilder.AppendData(sig.NumFixedArgs() - 1);
        TypeHandle thRetType = sig.GetRetTypeHandleThrowing();
#if defined(TARGET_WINDOWS)
        if (rewriteReturnTypeToForceRetBuf)
        {
            // Change the return type to type large enough it will always need to be returned via return buffer
            thRetType = CoreLibBinder::GetClass(CLASS__STACKFRAMEITERATOR);
            _ASSERTE(thRetType.IsValueType());
            _ASSERTE(thRetType.GetSize() > 64);
            sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
            sigBuilder.AppendPointer(thRetType.AsPtr());
        }
        else
#endif
        {
            SigPointer pReturn = sig.GetReturnProps();
            pReturn.ConvertToInternalExactlyOne(sig.GetModule(), sig.GetSigTypeContext(), &sigBuilder);
        }

        // Skip the explicit this argument
        sig.NextArg();


Review comment (bug):
Debug printf statements should not be left in production code. These statements will produce console output in release builds and should be removed or placed behind a debug-only compilation flag.
```suggestion
    {
#if LOG_COMPUTE_CALL_STUB
        printf("Managed ExplicitThis to HasThis conversion needed\n");
#endif
        rewriteMetaSigFromExplicitThisToHasThis = true;
    }

    SigBuilder sigBuilder;
    if (rewriteMetaSigFromExplicitThisToHasThis)
    {
#if LOG_COMPUTE_CALL_STUB
        printf("Rewriting ExplicitThis to implicit this\n");
#endif
```

Code after:
            TypeHandle thRetType = sig.GetRetTypeHandleThrowing();
            MethodTable* pMTRetType = thRetType.AsMethodTable();

            if (pMTRetType->GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE && !isNativePrimitiveStructType(pMTRetType))
            {
                rewriteReturnTypeToForceRetBuf = true;
            }
        }
    }
#endif // defined(TARGET_WINDOWS)

    // Rewrite ExplicitThis to HasThis. This allows us to use ArgIterator which is unaware of ExplicitThis
    // in the places where it is needed such as computation of return buffers.
    if (sig.GetCallingConventionInfo() & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
    {
#if LOG_COMPUTE_CALL_STUB
        printf("Managed ExplicitThis to HasThis conversion needed\n");
#endif // LOG_COMPUTE_CALL_STUB
        rewriteMetaSigFromExplicitThisToHasThis = true;
    }

    SigBuilder sigBuilder;
    if (rewriteMetaSigFromExplicitThisToHasThis)
    {
#if LOG_COMPUTE_CALL_STUB
        printf("Rewriting ExplicitThis to implicit this\n");
#endif // LOG_COMPUTE_CALL_STUB
        sigBuilder.AppendByte(IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS);
        if ((sig.NumFixedArgs() == 0) || (sig.HasThis() && !sig.HasExplicitThis()))
        {
            ThrowHR(COR_E_BADIMAGEFORMAT);
        }
        sigBuilder.AppendData(sig.NumFixedArgs() - 1);
        TypeHandle thRetType = sig.GetRetTypeHandleThrowing();
#if defined(TARGET_WINDOWS)
        if (rewriteReturnTypeToForceRetBuf)
        {
            // Change the return type to type large enough it will always need to be returned via return buffer
            thRetType = CoreLibBinder::GetClass(CLASS__STACKFRAMEITERATOR);
            _ASSERTE(thRetType.IsValueType());
            _ASSERTE(thRetType.GetSize() > 64);
            sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
            sigBuilder.AppendPointer(thRetType.AsPtr());
        }
        else
#endif
        {
            SigPointer pReturn = sig.GetReturnProps();
            pReturn.ConvertToInternalExactlyOne(sig.GetModule(), sig.GetSigTypeContext(), &sigBuilder);
        }