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

Code before:

template <typename GcInfoEncoding> void TGcInfoDecoder<GcInfoEncoding>::ReportRegisterToGC(
                                int             regNum,
                                unsigned        gcFlags,
                                PREGDISPLAY     pRD,
                                unsigned        flags,
                                GCEnumCallback  pCallBack,
                                void *          hCallBack)
{
    _ASSERTE( !"NYI" );
}

template <typename GcInfoEncoding> OBJECTREF* TGcInfoDecoder<GcInfoEncoding>::GetCapturedRegister(
    int             regNum,
    PREGDISPLAY     pRD
    )
{
    _ASSERTE( !"NYI" );
    return nullptr;
}

#endif // Unknown platform

#ifdef FEATURE_INTERPRETER

uintptr_t ZeroValue = 0;

template <> OBJECTREF* TGcInfoDecoder<InterpreterGcInfoEncoding>::GetStackSlot(
                        INT32           spOffset,
                        GcStackSlotBase spBase,
                        PREGDISPLAY     pRD
                        )
{
    OBJECTREF* pObjRef = NULL;

    if( GC_SP_REL == spBase )
    {
        _ASSERTE(!"GC_SP_REL is invalid for interpreter frames");
    }
    else if( GC_CALLER_SP_REL == spBase )
    {
        _ASSERTE(!"GC_CALLER_SP_REL is invalid for interpreter frames");
    }
    else
    {
        // Interpreter-TODO: Enhance GcInfoEncoder/Decoder to allow omitting the stack slot base register for interpreted
        //  methods, since only one base (fp) is ever used for interpreter locals. See Interpreter-TODO in DecodeSlotTable.
        _ASSERTE( GC_FRAMEREG_REL == spBase );
        uint8_t* fp = (uint8_t *)GetFP(pRD->pCurrentContext);
        _ASSERTE(fp);
        pObjRef = (OBJECTREF*)(fp + spOffset);

Review comment (suggestion):
This global variable should be declared as 'static const uintptr_t ZeroValue = 0;'. Making it const prevents accidental modification, and making it static limits its linkage to this translation unit, which is appropriate since it's only used as a sentinel value within this file.
```suggestion
static const uintptr_t ZeroValue = 0;
```

Code after:
    return false;
}

template <typename GcInfoEncoding> void TGcInfoDecoder<GcInfoEncoding>::ReportRegisterToGC(
                                int             regNum,
                                unsigned        gcFlags,
                                PREGDISPLAY     pRD,
                                unsigned        flags,
                                GCEnumCallback  pCallBack,
                                void *          hCallBack)
{
    _ASSERTE( !"NYI" );
}

template <typename GcInfoEncoding> OBJECTREF* TGcInfoDecoder<GcInfoEncoding>::GetCapturedRegister(
    int             regNum,
    PREGDISPLAY     pRD
    )
{
    _ASSERTE( !"NYI" );
    return nullptr;
}

#endif // Unknown platform

#ifdef FEATURE_INTERPRETER

template <> OBJECTREF* TGcInfoDecoder<InterpreterGcInfoEncoding>::GetStackSlot(
                        INT32           spOffset,
                        GcStackSlotBase spBase,
                        PREGDISPLAY     pRD
                        )
{
    OBJECTREF* pObjRef = NULL;

    if( GC_SP_REL == spBase )
    {
        _ASSERTE(!"GC_SP_REL is invalid for interpreter frames");
    }
    else if( GC_CALLER_SP_REL == spBase )
    {
        _ASSERTE(!"GC_CALLER_SP_REL is invalid for interpreter frames");
    }
    else
    {
        // Interpreter-TODO: Enhance GcInfoEncoder/Decoder to allow omitting the stack slot base register for interpreted
        //  methods, since only one base (fp) is ever used for interpreter locals. See Interpreter-TODO in DecodeSlotTable.
        _ASSERTE( GC_FRAMEREG_REL == spBase );
        uint8_t* fp = (uint8_t *)GetFP(pRD->pCurrentContext);
        _ASSERTE(fp);
        pObjRef = (OBJECTREF*)(fp + spOffset);