1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// ECALL.H -
5//
6// Handles our private native calling interface.
7//
8
9
10
11
12#ifndef _ECALL_H_
13#define _ECALL_H_
14
15#include "fcall.h"
16
17class MethodDesc;
18
19// CoreCLR defines fewer FCalls so make the hashtable even smaller.
20#define FCALL_HASH_SIZE 127
21
22typedef DPTR(struct ECHash) PTR_ECHash;
23
24struct ECHash
25{
26 PTR_ECHash m_pNext;
27 PCODE m_pImplementation;
28 PTR_MethodDesc m_pMD; // for reverse mapping
29};
30
31#ifdef DACCESS_COMPILE
32GVAL_DECL(TADDR, gLowestFCall);
33GVAL_DECL(TADDR, gHighestFCall);
34GARY_DECL(PTR_ECHash, gFCallMethods, FCALL_HASH_SIZE);
35#endif
36
37enum {
38 FCFuncFlag_EndOfArray = 0x01,
39 FCFuncFlag_HasSignature = 0x02,
40 FCFuncFlag_Unreferenced = 0x04, // Suppress unused fcall check
41 FCFuncFlag_QCall = 0x08, // QCall - mscorlib.dll to mscorwks.dll transition implemented as PInvoke
42};
43
44struct ECFunc {
45 UINT_PTR m_dwFlags;
46
47 LPVOID m_pImplementation;
48
49 LPCSTR m_szMethodName;
50 LPHARDCODEDMETASIG m_pMethodSig; // Optional field. It is valid only if HasSignature() is set.
51
52 bool IsEndOfArray() { LIMITED_METHOD_CONTRACT; return !!(m_dwFlags & FCFuncFlag_EndOfArray); }
53 bool HasSignature() { LIMITED_METHOD_CONTRACT; return !!(m_dwFlags & FCFuncFlag_HasSignature); }
54 bool IsUnreferenced(){ LIMITED_METHOD_CONTRACT; return !!(m_dwFlags & FCFuncFlag_Unreferenced); }
55 bool IsQCall() { LIMITED_METHOD_CONTRACT; return !!(m_dwFlags & FCFuncFlag_QCall); }
56 CorInfoIntrinsics IntrinsicID() { LIMITED_METHOD_CONTRACT; return (CorInfoIntrinsics)((INT8)(m_dwFlags >> 16)); }
57 int DynamicID() { LIMITED_METHOD_CONTRACT; return (int) ((INT8)(m_dwFlags >> 24)); }
58
59 ECFunc* NextInArray()
60 {
61 LIMITED_METHOD_CONTRACT;
62
63 return (ECFunc*)((BYTE*)this +
64 (HasSignature() ? sizeof(ECFunc) : offsetof(ECFunc, m_pMethodSig)));
65 }
66};
67
68struct ECClass
69{
70 LPCSTR m_szClassName;
71 LPCSTR m_szNameSpace;
72 const LPVOID * m_pECFunc;
73};
74
75//=======================================================================
76// Collects code and data pertaining to the ECall interface.
77//=======================================================================
78class ECall
79{
80 public:
81 //---------------------------------------------------------
82 // One-time init
83 //---------------------------------------------------------
84 static void Init();
85
86 static PCODE GetFCallImpl(MethodDesc* pMD, BOOL * pfSharedOrDynamicFCallImpl = NULL);
87 static MethodDesc* MapTargetBackToMethod(PCODE pTarg, PCODE * ppAdjustedEntryPoint = NULL);
88 static DWORD GetIDForMethod(MethodDesc *pMD);
89 static CorInfoIntrinsics GetIntrinsicID(MethodDesc *pMD);
90
91 // Some fcalls (delegate ctors and tlbimpl ctors) shared one implementation.
92 // We should never patch vtable for these since they have 1:N mapping between
93 // MethodDesc and the actual implementation
94 static BOOL IsSharedFCallImpl(PCODE pImpl);
95
96 static BOOL CheckUnusedECalls(SetSHash<DWORD>& usedIDs);
97
98 static void DynamicallyAssignFCallImpl(PCODE impl, DWORD index);
99
100 static void PopulateManagedStringConstructors();
101#ifdef DACCESS_COMPILE
102 // Enumerates all gFCallMethods for minidumps.
103 static void EnumFCallMethods();
104#endif // DACCESS_COMPILE
105
106#define DYNAMICALLY_ASSIGNED_FCALLS() \
107 DYNAMICALLY_ASSIGNED_FCALL_IMPL(FastAllocateString, FramedAllocateString) \
108 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharArrayManaged, NULL) \
109 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharArrayStartLengthManaged, NULL) \
110 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharCountManaged, NULL) \
111 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharPtrManaged, NULL) \
112 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharPtrStartLengthManaged, NULL) \
113 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorReadOnlySpanOfCharManaged, NULL) \
114 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorSBytePtrManaged, NULL) \
115 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorSBytePtrStartLengthManaged, NULL) \
116 DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorSBytePtrStartLengthEncodingManaged, NULL) \
117 DYNAMICALLY_ASSIGNED_FCALL_IMPL(InternalGetCurrentThread, NULL) \
118
119 enum
120 {
121 #undef DYNAMICALLY_ASSIGNED_FCALL_IMPL
122 #define DYNAMICALLY_ASSIGNED_FCALL_IMPL(id,defaultimpl) id,
123
124 DYNAMICALLY_ASSIGNED_FCALLS()
125
126 NUM_DYNAMICALLY_ASSIGNED_FCALL_IMPLEMENTATIONS,
127 InvalidDynamicFCallId = -1
128 };
129
130
131 static LPVOID GetQCallImpl(MethodDesc * pMD);
132};
133
134#ifdef FEATURE_COMINTEROP
135extern "C" FCDECL1(VOID, FCComCtor, LPVOID pV);
136#endif
137
138#endif // _ECALL_H_
139