summaryrefslogtreecommitdiff
path: root/src/vm/memberload.h
blob: 5fd38b058fdc3120d60642608b80fbdc1098e6c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// File: memberload.h
//


//

//
// ============================================================================

#ifndef _MEMBERLOAD_H
#define _MEMBERLOAD_H


/*
 *  Include Files
 */
#include "eecontract.h"
#include "argslot.h"
#include "vars.hpp"
#include "cor.h"
#include "clrex.h"
#include "hash.h"
#include "crst.h"
#include "slist.h"
#include "typehandle.h"
#include "methodtable.h"
#include "typectxt.h"

//
// This enum represents the property methods that can be passed to FindPropertyMethod().
//

enum EnumPropertyMethods
{
    PropertyGet = 0,
    PropertySet = 1,
};


//
// This enum represents the event methods that can be passed to FindEventMethod().
//

enum EnumEventMethods
{
    EventAdd = 0,
    EventRemove = 1,
    EventRaise = 2,
};

// The MemberLoader logic is analogous to the ClassLoader logic, i.e. it turn 
// tokens into internal EE descriptors.
//
// The implementations of these functions currently lies in class.cpp.
class MemberLoader
{


public:
    static void DECLSPEC_NORETURN ThrowMissingMethodException(MethodTable* pMT,
                                            LPCSTR szMember,
                                            Module *pModule,
                                            PCCOR_SIGNATURE pSig,
                                            DWORD cSig,
                                            const SigTypeContext *pTypeContext);

    static void DECLSPEC_NORETURN ThrowMissingFieldException( MethodTable *pMT,
                                            LPCSTR szMember);

    static  MethodDesc* GetMethodDescFromMemberDefOrRefOrSpec(Module *pModule,
                                                              mdToken MemberRefOrDefOrSpec,
                                                              const SigTypeContext *pTypeContext, // Context for type parameters in any parent TypeSpec and in the instantiation in a MethodSpec 
                                                              BOOL strictMetadataChecks,  // Normally true - the zapper is one exception.  Throw an exception if no generic method args given for a generic method, otherwise return the 'generic' instantiation
                                                              BOOL allowInstParam);

    static  FieldDesc* GetFieldDescFromMemberDefOrRef(Module *pModule,
                                                      mdMemberRef MemberDefOrRef,
                                                      const SigTypeContext *pTypeContext,
                                                      BOOL strictMetadataChecks);

    static MethodDesc *GetMethodDescFromMethodDef(Module *pModule,
                                                  mdMethodDef MethodDef,            // MethodDef token
                                                  Instantiation classInst,          // Generic arguments for declaring class
                                                  Instantiation methodInst,         // Generic arguments for declaring method
                                                  BOOL forceRemotable = FALSE);     // force remotable MethodDesc
    //
    // Methods that actually do the work
    //

    static MethodDesc* GetMethodDescFromMethodDef(Module *pModule,
                                                  mdToken MethodDef,
                                                  BOOL strictMetadataChecks);

    static FieldDesc* GetFieldDescFromFieldDef(Module *pModule,
                                               mdToken FieldDef,
                                               BOOL strictMetadataChecks);

    static void GetDescFromMemberRef(Module * pModule,
                                     mdToken MemberRef,
                                     MethodDesc ** ppMD,
                                     FieldDesc ** ppFD,
                                     const SigTypeContext *pTypeContext,
                                     BOOL strictMetadataChecks,
                                     TypeHandle *ppTH,
                                     // Because of inheritance, the actual type stored in metadata may be sub-class of the 
                                     // class that defines the member. The semantics (verification, security checks, etc.) is based on 
                                     // the actual type in metadata. This JIT-EE interface passes in TRUE here to get the actual type.
                                     // If actualTypeRequired is false, returned *ppTH will be the MethodDesc::GetMethodTable/FieldDesc::GetEnclosingMethodTable
                                     // except when generics are involved. The actual type will be still returned for generics since it is required
                                     // for instantiation.
                                     // If actualTypeRequired is true, returned *ppTH will always be the actual type defined in metadata.
                                     BOOL actualTypeRequired = FALSE,
                                     PCCOR_SIGNATURE * ppTypeSig = NULL,    // Optionally, return generic signatures fetched from metadata during loading.
                                     ULONG * pcbTypeSig = NULL);

    static MethodDesc * GetMethodDescFromMemberRefAndType(Module * pModule, 
                                                          mdToken MemberRef, 
                                                          MethodTable * pMT);

    static FieldDesc * GetFieldDescFromMemberRefAndType(Module * pModule, 
                                                        mdToken MemberRef, 
                                                        MethodTable * pMT);

    static MethodDesc * GetMethodDescFromMethodSpec(Module * pModule, 
                                                    mdToken MethodSpec,
                                                    const SigTypeContext *pTypeContext,
                                                    BOOL strictMetadataChecks,                                                    
                                                    BOOL allowInstParam,
                                                    TypeHandle *ppTH,
                                                    BOOL actualTypeRequired = FALSE,    // See comment for GetDescFromMemberRef
                                                    PCCOR_SIGNATURE * ppTypeSig = NULL, // Optionally, return generic signatures fetched from metadata during loading.
                                                    ULONG * pcbTypeSig = NULL,
                                                    PCCOR_SIGNATURE * ppMethodSig = NULL,
                                                    ULONG * pcbMethodSig = NULL);

    //-------------------------------------------------------------------
    // METHOD AND FIELD LOOKUP BY NAME AND SIGNATURE
    //

    // Used by FindMethod and varieties
    enum FM_Flags
    {
        // Default behaviour is to scan all methods, virtual and non-virtual, of the current type
        // and all non-virtual methods of all parent types.

        // Default set of flags - this must always be zero.
        FM_Default             = 0x0000,

        // Case sensitivity
        FM_IgnoreCase          = 0x0001,                        // Name matching is case insensitive
        FM_IgnoreName          = (FM_IgnoreCase          << 1), // Ignore the name altogether

        // USE THE FOLLOWING WITH EXTREME CAUTION. We do not want to inadvertently
        // change binding semantics by using this without a really good reason.

        // Virtuals
        FM_ExcludeNonVirtual   = (FM_IgnoreName          << 1), // has mdVirtual set
        FM_ExcludeVirtual      = (FM_ExcludeNonVirtual   << 1), // does not have mdVirtual set.

        // Accessibility. 
        // NOTE: These appear in the exact same order as mdPrivateScope ... mdPublic in corhdr.h. This enables some
        //       bit masking to quickly determine if a method qualifies in FM_ShouldSkipMethod.
        FM_ExcludePrivateScope = (FM_ExcludeVirtual      << 1), // Member not referenceable.
        FM_ExcludePrivate      = (FM_ExcludePrivateScope << 1), // Accessible only by the parent type.
        FM_ExcludeFamANDAssem  = (FM_ExcludePrivate      << 1), // Accessible by sub-types only in this Assembly.
        FM_ExcludeAssem        = (FM_ExcludeFamANDAssem  << 1), // Accessibly by anyone in the Assembly.
        FM_ExcludeFamily       = (FM_ExcludeAssem        << 1), // Accessible only by type and sub-types.
        FM_ExcludeFamORAssem   = (FM_ExcludeFamily       << 1), // Accessibly by sub-types anywhere, plus anyone in assembly.
        FM_ExcludePublic       = (FM_ExcludeFamORAssem   << 1), // Accessibly by anyone who has visibility to this scope.
        FM_Unique = (FM_ExcludePublic   << 1),  // Make sure the method is unique for the class

        // This means that FindMethod will only consider mdPublic mdVirtual methods.
        // This is the only time when name/sig lookup will look past the first match.
        FM_ForInterface        = (FM_ExcludeNonVirtual |
                                  FM_ExcludePrivateScope |
                                  FM_ExcludePrivate |
                                  FM_ExcludeFamANDAssem |
                                  FM_ExcludeAssem |
                                  FM_ExcludeFamily |
                                  FM_ExcludeFamORAssem),
    };

private:
    // A mask to indicate that some filtering needs to be done.
    static const FM_Flags FM_SpecialAccessMask = (FM_Flags) (FM_ExcludePrivateScope |
                                                             FM_ExcludePrivate |
                                                             FM_ExcludeFamANDAssem |
                                                             FM_ExcludeAssem |
                                                             FM_ExcludeFamily |
                                                             FM_ExcludeFamORAssem |
                                                             FM_ExcludePublic);

    static const FM_Flags FM_SpecialVirtualMask = (FM_Flags) (FM_ExcludeNonVirtual |
                                                              FM_ExcludeVirtual);

    // Typedef for string comparition functions.
    typedef int (__cdecl *UTF8StringCompareFuncPtr)(const char *, const char *);

    static inline UTF8StringCompareFuncPtr FM_GetStrCompFunc(DWORD dwFlags)
        { LIMITED_METHOD_CONTRACT; return (dwFlags & FM_IgnoreCase) ? stricmpUTF8 : strcmp; }

    static BOOL FM_PossibleToSkipMethod(FM_Flags flags);
    static BOOL FM_ShouldSkipMethod(DWORD dwAttrs, FM_Flags flags);

public:
    static MethodDesc *FindMethod(
       MethodTable * pMT,
       LPCUTF8 pwzName,
       LPHARDCODEDMETASIG pwzSignature,
       FM_Flags flags = FM_Default);

    // typeHnd is the type handle associated with the class being looked up.
    // It has additional information in the case of a domain neutral class (Arrays)
    static MethodDesc *FindMethod(
       MethodTable * pMT,
       LPCUTF8 pszName, 
       PCCOR_SIGNATURE pSignature, 
       DWORD cSignature, 
       Module* pModule, 
       FM_Flags flags = FM_Default,
       const Substitution *pDefSubst = NULL);

    static MethodDesc *FindMethod(MethodTable * pMT, mdMethodDef mb);

    static MethodDesc *FindMethodByName(
       MethodTable * pMT,
       LPCUTF8 pszName,
       FM_Flags flags = FM_Default);

    static MethodDesc *FindPropertyMethod(
       MethodTable * pMT,
       LPCUTF8 pszName,
       EnumPropertyMethods Method,
       FM_Flags flags = FM_Default);

    static MethodDesc *FindEventMethod(
       MethodTable * pMT,
       LPCUTF8 pszName,
       EnumEventMethods Method,
       FM_Flags flags = FM_Default);

    static MethodDesc *FindMethodForInterfaceSlot(
       MethodTable * pMT,
       MethodTable *pInterface,
       WORD slotNum);

    // pSignature can be NULL to find any field with the given name
    static FieldDesc *FindField(
       MethodTable * pMT,
       LPCUTF8 pszName,
       PCCOR_SIGNATURE pSignature,
       DWORD cSignature,
       Module* pModule,
       BOOL bCaseSensitive = TRUE);

    static MethodDesc *FindConstructor(MethodTable * pMT, LPHARDCODEDMETASIG pwzSignature);
    static MethodDesc *FindConstructor(MethodTable * pMT, PCCOR_SIGNATURE pSignature,DWORD cSignature, Module* pModule);
};

#endif // MEMBERLOAD_H