// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// CGENSYS.H -
//
// Generic header for choosing system-dependent helpers
//



#ifndef __cgensys_h__
#define __cgensys_h__

class MethodDesc;
class Stub;
class Thread;
class CrawlFrame;
struct EE_ILEXCEPTION_CLAUSE;
struct TransitionBlock;
struct VASigCookie;
class CLRToCOMCallMethodDesc;

#include <cgencpu.h>


#ifdef FEATURE_METADATA_UPDATER
void ResumeAtJit(PT_CONTEXT pContext, LPVOID oldFP);
#endif

#if defined(TARGET_X86)
void ResumeAtJitEH   (CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, Thread *pThread, BOOL unwindStack);
int  CallJitEHFilter (CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel, OBJECTREF thrownObj);
void CallJitEHFinally(CrawlFrame* pCf, BYTE* startPC, EE_ILEXCEPTION_CLAUSE *EHClausePtr, DWORD nestingLevel);
#endif // TARGET_X86

#ifdef FEATURE_COMINTEROP
extern "C" UINT32 STDCALL CLRToCOMWorker(TransitionBlock * pTransitionBlock, CLRToCOMCallMethodDesc * pMD);
extern "C" void GenericCLRToCOMCallStub(void);

extern "C" void GenericComCallStub(void);
#endif // FEATURE_COMINTEROP

// The GC mode for the thread that initially called ThePreStub().
enum class CallerGCMode
{
    Unknown,
    Coop,
    Preemptive    // (e.g. UnmanagedCallersOnlyAttribute)
};

// Non-CPU-specific helper functions called by the CPU-dependent code
extern "C" PCODE STDCALL PreStubWorker(TransitionBlock * pTransitionBlock, MethodDesc * pMD);

extern "C" void STDCALL VarargPInvokeStubWorker(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, MethodDesc * pMD);
extern "C" void STDCALL VarargPInvokeStub(void);
extern "C" void STDCALL VarargPInvokeStub_RetBuffArg(void);

extern "C" void STDCALL GenericPInvokeCalliStubWorker(TransitionBlock * pTransitionBlock, VASigCookie * pVASigCookie, PCODE pUnmanagedTarget);
extern "C" void STDCALL GenericPInvokeCalliHelper(void);

extern "C" PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBlock, TADDR pIndirection, DWORD sectionIndex, Module * pModule);
extern "C" void STDCALL ExternalMethodFixupPatchLabel(void);

extern "C" void STDCALL VirtualMethodFixupStub(void);
extern "C" void STDCALL VirtualMethodFixupPatchLabel(void);

#ifdef FEATURE_READYTORUN
extern "C" void STDCALL DelayLoad_MethodCall();

extern "C" void STDCALL DelayLoad_Helper();
extern "C" void STDCALL DelayLoad_Helper_Obj();
extern "C" void STDCALL DelayLoad_Helper_ObjObj();
#endif

#ifdef DACCESS_COMPILE

// Used by dac/strike to make sense of non-jit/non-jit-helper call targets
// generated by the runtime.
BOOL GetAnyThunkTarget (T_CONTEXT *pctx, TADDR *pTarget, TADDR *pTargetMethodDesc);

#endif // DACCESS_COMPILE

//
// ResetProcessorStateHolder saves/restores processor state around calls to
// CoreLib during exception handling.
//
class ResetProcessorStateHolder
{
#if defined(TARGET_AMD64)
    ULONG m_mxcsr;
#endif

public:

    ResetProcessorStateHolder ()
    {
#if defined(TARGET_AMD64)
        m_mxcsr = _mm_getcsr();
        _mm_setcsr(0x1f80);
#endif // TARGET_AMD64
    }

    ~ResetProcessorStateHolder ()
    {
#if defined(TARGET_AMD64)
        _mm_setcsr(m_mxcsr);
#endif // TARGET_AMD64
    }
};


#endif // !__cgensys_h__
