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 | // |
5 | // siginfo.hpp |
6 | // |
7 | |
8 | |
9 | #ifndef _H_SIGINFO |
10 | #define _H_SIGINFO |
11 | |
12 | |
13 | #include "util.hpp" |
14 | #include "vars.hpp" |
15 | #include "clsload.hpp" |
16 | #include "zapsig.h" |
17 | #include "threads.h" |
18 | |
19 | #include "eecontract.h" |
20 | #include "typectxt.h" |
21 | #include "sigparser.h" |
22 | |
23 | //--------------------------------------------------------------------------------------- |
24 | // These macros define how arguments are mapped to the stack in the managed calling convention. |
25 | // We assume to be walking a method's signature left-to-right, in the virtual calling convention. |
26 | // See MethodDesc::Call for details on this virtual calling convention. |
27 | // These macros tell us whether the arguments we see as we proceed with the signature walk are mapped |
28 | // to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack. |
29 | //--------------------------------------------------------------------------------------- |
30 | #if defined(_TARGET_X86_) |
31 | #define STACK_GROWS_DOWN_ON_ARGS_WALK |
32 | #else |
33 | #define STACK_GROWS_UP_ON_ARGS_WALK |
34 | #endif |
35 | |
36 | BOOL IsTypeRefOrDef(LPCSTR szClassName, Module *pModule, mdToken token); |
37 | |
38 | struct ElementTypeInfo { |
39 | #ifdef _DEBUG |
40 | int m_elementType; |
41 | #endif |
42 | int m_cbSize; |
43 | CorInfoGCType m_gc : 3; |
44 | int m_enregister : 1; |
45 | }; |
46 | extern const ElementTypeInfo gElementTypeInfo[]; |
47 | |
48 | unsigned GetSizeForCorElementType(CorElementType etyp); |
49 | const ElementTypeInfo* GetElementTypeInfo(CorElementType etyp); |
50 | |
51 | class SigBuilder; |
52 | class ArgDestination; |
53 | |
54 | typedef const struct HardCodedMetaSig *LPHARDCODEDMETASIG; |
55 | |
56 | //@GENERICS: flags returned from IsPolyType indicating the presence or absence of class and |
57 | // method type parameters in a type whose instantiation cannot be determined at JIT-compile time |
58 | enum VarKind |
59 | { |
60 | hasNoVars = 0x0000, |
61 | hasClassVar = 0x0001, |
62 | hasMethodVar = 0x0002, |
63 | hasSharableClassVar = 0x0004, |
64 | hasSharableMethodVar = 0x0008, |
65 | hasAnyVarsMask = 0x0003, |
66 | hasSharableVarsMask = 0x000c |
67 | }; |
68 | |
69 | //--------------------------------------------------------------------------------------- |
70 | |
71 | struct ScanContext; |
72 | typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t); |
73 | typedef void promote_carefully_func(promote_func*, PTR_PTR_Object, ScanContext*, uint32_t); |
74 | |
75 | void PromoteCarefully(promote_func fn, |
76 | PTR_PTR_Object obj, |
77 | ScanContext* sc, |
78 | uint32_t flags = GC_CALL_INTERIOR); |
79 | |
80 | class LoaderAllocator; |
81 | void GcReportLoaderAllocator(promote_func* fn, ScanContext* sc, LoaderAllocator *pLoaderAllocator); |
82 | |
83 | //--------------------------------------------------------------------------------------- |
84 | // |
85 | // Encapsulates how compressed integers and typeref tokens are encoded into |
86 | // a bytestream. |
87 | // |
88 | // As you use this class please understand the implicit normalizations |
89 | // on the CorElementType's returned by the various methods, especially |
90 | // for variable types (e.g. !0 in generic signatures), string types |
91 | // (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types |
92 | // (e.g. List<int>) and enums. |
93 | // |
94 | class SigPointer : public SigParser |
95 | { |
96 | friend class MetaSig; |
97 | |
98 | public: |
99 | // Constructor. |
100 | SigPointer() { LIMITED_METHOD_DAC_CONTRACT; } |
101 | |
102 | // Copy constructor. |
103 | SigPointer(const SigPointer & sig) : SigParser(sig) |
104 | { |
105 | WRAPPER_NO_CONTRACT; |
106 | } |
107 | |
108 | SigPointer(const SigParser & sig) : SigParser(sig) |
109 | { |
110 | WRAPPER_NO_CONTRACT; |
111 | } |
112 | |
113 | // Signature from a pointer. INSECURE!!! |
114 | // WARNING: Should not be used as it is insecure, because we do not have size of the signature and |
115 | // therefore we can read behind the end of buffer/file. |
116 | FORCEINLINE |
117 | SigPointer(PCCOR_SIGNATURE ptr) : SigParser(ptr) |
118 | { |
119 | WRAPPER_NO_CONTRACT; |
120 | } |
121 | |
122 | // Signature from a pointer and size. |
123 | FORCEINLINE |
124 | SigPointer(PCCOR_SIGNATURE ptr, DWORD len) : SigParser(ptr, len) |
125 | { |
126 | WRAPPER_NO_CONTRACT; |
127 | } |
128 | |
129 | |
130 | //========================================================================= |
131 | // The RAW interface for reading signatures. You see exactly the signature, |
132 | // apart from custom modifiers which for historical reasons tend to get eaten. |
133 | // |
134 | // DO NOT USE THESE METHODS UNLESS YOU'RE TOTALLY SURE YOU WANT |
135 | // THE RAW signature. You nearly always want GetElemTypeClosed() or |
136 | // PeekElemTypeClosed() or one of the MetaSig functions. See the notes above. |
137 | // These functions will return E_T_INTERNAL, E_T_VAR, E_T_MVAR and such |
138 | // so the caller must be able to deal with those |
139 | //========================================================================= |
140 | |
141 | |
142 | void ConvertToInternalExactlyOne(Module* pSigModule, SigTypeContext *pTypeContext, SigBuilder * pSigBuilder, BOOL bSkipCustomModifier = TRUE); |
143 | void ConvertToInternalSignature(Module* pSigModule, SigTypeContext *pTypeContext, SigBuilder * pSigBuilder, BOOL bSkipCustomModifier = TRUE); |
144 | |
145 | |
146 | //========================================================================= |
147 | // The CLOSED interface for reading signatures. With the following |
148 | // methods you see the signature "as if" all type variables are |
149 | // replaced by the given instantiations. However, no type loads happen. |
150 | // |
151 | // In general this is what you want to use if the signature may include |
152 | // generic type variables. Even if you know it doesn't you can always |
153 | // pass in NULL for the instantiations and put a comment to that effect. |
154 | // |
155 | // The CLOSED api also hides E_T_INTERNAL by return E_T_CLASS or E_T_VALUETYPE |
156 | // appropriately (as directed by the TypeHandle following E_T_INTERNAL) |
157 | //========================================================================= |
158 | |
159 | // The CorElementTypes returned correspond |
160 | // to those returned by TypeHandle::GetSignatureCorElementType. |
161 | CorElementType PeekElemTypeClosed(Module *pModule, const SigTypeContext *pTypeContext) const; |
162 | |
163 | //------------------------------------------------------------------------ |
164 | // Fetch the token for a CLASS, VALUETYPE or GENRICINST, or a type |
165 | // variable instantiatied to be one of these, taking into account |
166 | // the given instantiations. |
167 | // |
168 | // SigPointer should be in a position that satisfies |
169 | // ptr.PeekElemTypeClosed(pTypeContext) = ELEMENT_TYPE_VALUETYPE |
170 | // |
171 | // A type ref or def is returned. For an instantiated generic struct |
172 | // this will return the token for the generic class, e.g. for a signature |
173 | // for "struct Pair<int,int>" this will return a token for "Pair". |
174 | // |
175 | // The token will only make sense in the context of the module where |
176 | // the signature occurs. |
177 | // |
178 | // WARNING: This api will return a mdTokenNil for a E_T_VALUETYPE obtained |
179 | // from a E_T_INTERNAL, as the token is meaningless in that case |
180 | // Users of this api must be prepared to deal with a null token |
181 | //------------------------------------------------------------------------ |
182 | mdTypeRef PeekValueTypeTokenClosed(Module *pModule, const SigTypeContext *pTypeContext, Module **ppModuleOfToken) const; |
183 | |
184 | |
185 | //========================================================================= |
186 | // The INTERNAL-NORMALIZED interface for reading signatures. You see |
187 | // information concerning the signature, but taking into account normalizations |
188 | // performed for layout of data, e.g. enums and one-field VCs. |
189 | //========================================================================= |
190 | |
191 | // The CorElementTypes returned correspond |
192 | // to those returned by TypeHandle::GetInternalCorElementType. |
193 | CorElementType PeekElemTypeNormalized(Module* pModule, const SigTypeContext *pTypeContext, TypeHandle * pthValueType = NULL) const; |
194 | |
195 | //------------------------------------------------------------------------ |
196 | // Assumes that the SigPointer points to the start of an element type. |
197 | // Returns size of that element in bytes. This is the minimum size that a |
198 | // field of this type would occupy inside an object. |
199 | //------------------------------------------------------------------------ |
200 | UINT SizeOf(Module* pModule, const SigTypeContext *pTypeContext) const; |
201 | |
202 | private: |
203 | |
204 | // SigPointer should be just after E_T_VAR or E_T_MVAR |
205 | TypeHandle GetTypeVariable(CorElementType et,const SigTypeContext *pTypeContext); |
206 | TypeHandle GetTypeVariableThrowing(Module *pModule, |
207 | CorElementType et, |
208 | ClassLoader::LoadTypesFlag fLoadTypes, |
209 | const SigTypeContext *pTypeContext); |
210 | |
211 | // Parse type following E_T_GENERICINST |
212 | TypeHandle GetGenericInstType(Module * pModule, |
213 | ClassLoader::LoadTypesFlag = ClassLoader::LoadTypes, |
214 | ClassLoadLevel level = CLASS_LOADED, |
215 | const ZapSig::Context *pZapSigContext = NULL); |
216 | |
217 | public: |
218 | |
219 | //------------------------------------------------------------------------ |
220 | // Assuming that the SigPointer points the start if an element type. |
221 | // Use SigTypeContext to fill in any type parameters |
222 | // |
223 | // Also advance the pointer to after the element type. |
224 | //------------------------------------------------------------------------ |
225 | |
226 | // OBSOLETE - Use GetTypeHandleThrowing() |
227 | TypeHandle GetTypeHandleNT(Module* pModule, |
228 | const SigTypeContext *pTypeContext) const; |
229 | |
230 | // pTypeContext indicates how to instantiate any generic type parameters we come |
231 | // However, first we implicitly apply the substitution pSubst to the metadata if pSubst is supplied. |
232 | // That is, if the metadata contains a type variable "!0" then we first look up |
233 | // !0 in pSubst to produce another item of metdata and continue processing. |
234 | // If pSubst is empty then we look up !0 in the pTypeContext to produce a final |
235 | // type handle. If any of these are out of range we throw an exception. |
236 | // |
237 | // The level is the level to which the result type will be loaded (see classloadlevel.h) |
238 | // If dropGenericArgumentLevel is TRUE, and the metadata represents an instantiated generic type, |
239 | // then generic arguments to the generic type will be loaded one level lower. (This is used by the |
240 | // class loader to avoid looping on definitions such as class C : D<C>) |
241 | // |
242 | // If dropGenericArgumentLevel is TRUE and |
243 | // level=CLASS_LOAD_APPROXPARENTS, then the instantiated |
244 | // generic type is "approximated" in the following way: |
245 | // - for generic interfaces, the generic type (uninstantiated) is returned |
246 | // - for other generic instantiations, System.Object is used in place of any reference types |
247 | // occurring in the type arguments |
248 | // This semantics is used by the class loader to load tricky recursive definitions in phases |
249 | // (e.g. class C : D<C>, or struct S : I<S>) |
250 | TypeHandle GetTypeHandleThrowing(Module* pModule, |
251 | const SigTypeContext *pTypeContext, |
252 | ClassLoader::LoadTypesFlag fLoadTypes = ClassLoader::LoadTypes, |
253 | ClassLoadLevel level = CLASS_LOADED, |
254 | BOOL dropGenericArgumentLevel = FALSE, |
255 | const Substitution *pSubst = NULL, |
256 | const ZapSig::Context *pZapSigContext = NULL) const; |
257 | |
258 | public: |
259 | //------------------------------------------------------------------------ |
260 | // Does this type contain class or method type parameters whose instantiation cannot |
261 | // be determined at JIT-compile time from the instantiations in the method context? |
262 | // Return a combination of hasClassVar and hasMethodVar flags. |
263 | // |
264 | // Example: class C<A,B> containing instance method m<T,U> |
265 | // Suppose that the method context is C<float,string>::m<double,object> |
266 | // Then the type Dict<!0,!!0> is considered to have *no* "polymorphic" type parameters because |
267 | // !0 is known to be float and !!0 is known to be double |
268 | // But Dict<!1,!!1> has polymorphic class *and* method type parameters because both |
269 | // !1=string and !!1=object are reference types and so code using these can be shared with |
270 | // other reference instantiations. |
271 | //------------------------------------------------------------------------ |
272 | VarKind IsPolyType(const SigTypeContext *pTypeContext) const; |
273 | |
274 | //------------------------------------------------------------------------ |
275 | // Tests if the element type is a System.String. Accepts |
276 | // either ELEMENT_TYPE_STRING or ELEMENT_TYPE_CLASS encoding. |
277 | //------------------------------------------------------------------------ |
278 | BOOL IsStringType(Module* pModule, const SigTypeContext *pTypeContext) const; |
279 | BOOL IsStringTypeThrowing(Module* pModule, const SigTypeContext *pTypeContext) const; |
280 | |
281 | private: |
282 | BOOL IsStringTypeHelper(Module* pModule, const SigTypeContext* pTypeContext, BOOL fThrow) const; |
283 | |
284 | public: |
285 | |
286 | |
287 | //------------------------------------------------------------------------ |
288 | // Tests if the element class name is szClassName. |
289 | //------------------------------------------------------------------------ |
290 | BOOL IsClass(Module* pModule, LPCUTF8 szClassName, const SigTypeContext *pTypeContext = NULL) const; |
291 | BOOL IsClassThrowing(Module* pModule, LPCUTF8 szClassName, const SigTypeContext *pTypeContext = NULL) const; |
292 | |
293 | private: |
294 | BOOL IsClassHelper(Module* pModule, LPCUTF8 szClassName, const SigTypeContext* pTypeContext, BOOL fThrow) const; |
295 | |
296 | public: |
297 | //------------------------------------------------------------------------ |
298 | // Tests for the existence of a custom modifier |
299 | //------------------------------------------------------------------------ |
300 | BOOL HasCustomModifier(Module *pModule, LPCSTR szModName, CorElementType cmodtype) const; |
301 | |
302 | //------------------------------------------------------------------------ |
303 | // Tests for ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE followed by a TypeDef, |
304 | // and returns the TypeDef |
305 | //------------------------------------------------------------------------ |
306 | BOOL IsTypeDef(mdTypeDef* pTypeDef) const; |
307 | |
308 | }; // class SigPointer |
309 | |
310 | // forward declarations needed for the friends declared in Signature |
311 | struct FrameInfo; |
312 | struct VASigCookie; |
313 | #if defined(DACCESS_COMPILE) |
314 | class DacDbiInterfaceImpl; |
315 | #endif // DACCESS_COMPILE |
316 | |
317 | //--------------------------------------------------------------------------------------- |
318 | // |
319 | // Currently, PCCOR_SIGNATURE is used all over the runtime to represent a signature, which is just |
320 | // an array of bytes. The problem with PCCOR_SIGNATURE is that it doesn't tell you the length of |
321 | // the signature (i.e. the number of bytes in the array). This is particularly troublesome for DAC, |
322 | // which needs to know how much memory to grab from out of process. This class is an encapsulation |
323 | // over PCCOR_SIGNATURE AND the length of the signature it points to. |
324 | // |
325 | // Notes: |
326 | // This class is meant to be read-only. Moreover, preferrably we should never read the raw |
327 | // PCCOR_SIGNATURE pointer directly, but there are likely some cases where it is inevitable. |
328 | // We should keep these to a minimum. |
329 | // |
330 | // We should move over to Signature instead of PCCOR_SIGNATURE. |
331 | // |
332 | // To get a Signature, you can create one yourself by using a constructor. However, it's recommended |
333 | // that you check whether the Signature should be constructed at a lower level. For example, instead of |
334 | // creating a Signature in FramedMethodFrame::PromoteCallerStackWalker(), we should add a member function |
335 | // to MethodDesc to return a Signature. |
336 | // |
337 | |
338 | class Signature |
339 | { |
340 | public: |
341 | // create an empty Signature |
342 | Signature(); |
343 | |
344 | // this is the primary constructor |
345 | Signature(PCCOR_SIGNATURE pSig, |
346 | DWORD cbSig); |
347 | |
348 | // check whether the signature is empty, i.e. have a NULL PCCOR_SIGNATURE |
349 | BOOL IsEmpty() const; |
350 | |
351 | // create a SigParser from the signature |
352 | SigParser CreateSigParser() const; |
353 | |
354 | // create a SigPointer from the signature |
355 | SigPointer CreateSigPointer() const; |
356 | |
357 | // pretty print the signature |
358 | void PrettyPrint(const CHAR * pszMethodName, |
359 | CQuickBytes * pqbOut, |
360 | IMDInternalImport * pIMDI) const; |
361 | |
362 | // retrieve the raw PCCOR_SIGNATURE pointer |
363 | PCCOR_SIGNATURE GetRawSig() const; |
364 | |
365 | // retrieve the length of the signature |
366 | DWORD GetRawSigLen() const; |
367 | |
368 | private: |
369 | PCCOR_SIGNATURE m_pSig; |
370 | DWORD m_cbSig; |
371 | }; // class Signature |
372 | |
373 | |
374 | #ifdef _DEBUG |
375 | #define MAX_CACHED_SIG_SIZE 3 // To excercize non-cached code path |
376 | #else |
377 | #define MAX_CACHED_SIG_SIZE 15 |
378 | #endif |
379 | |
380 | |
381 | //--------------------------------------------------------------------------------------- |
382 | // |
383 | // A substitution represents the composition of several formal type instantiations |
384 | // It is used when matching formal signatures across the inheritance hierarchy. |
385 | // |
386 | // It has the form of a linked list: |
387 | // [mod_1, <inst_1>] -> |
388 | // [mod_2, <inst_2>] -> |
389 | // ... |
390 | // [mod_n, <inst_n>] |
391 | // |
392 | // Here the types in <inst_1> must be resolved in the scope of module mod_1 but |
393 | // may contain type variables instantiated by <inst_2> |
394 | // ... |
395 | // and the types in <inst_(n-1)> must be resolved in the scope of mould mod_(n-1) but |
396 | // may contain type variables instantiated by <inst_n> |
397 | // |
398 | // Any type variables in <inst_n> are treated as "free". |
399 | // |
400 | class Substitution |
401 | { |
402 | private: |
403 | Module * m_pModule; // Module in which instantiation lives (needed to resolve typerefs) |
404 | SigPointer m_sigInst; |
405 | const Substitution * m_pNext; |
406 | |
407 | public: |
408 | Substitution() |
409 | { |
410 | LIMITED_METHOD_CONTRACT; |
411 | m_pModule = NULL; |
412 | m_pNext = NULL; |
413 | } |
414 | |
415 | Substitution( |
416 | Module * pModuleArg, |
417 | const SigPointer & sigInst, |
418 | const Substitution * pNextSubstitution) |
419 | { |
420 | LIMITED_METHOD_CONTRACT; |
421 | m_pModule = pModuleArg; |
422 | m_sigInst = sigInst; |
423 | m_pNext = pNextSubstitution; |
424 | } |
425 | |
426 | Substitution( |
427 | mdToken parentTypeDefOrRefOrSpec, |
428 | Module * pModuleArg, |
429 | const Substitution * nextArg); |
430 | |
431 | Substitution(const Substitution & subst) |
432 | { |
433 | LIMITED_METHOD_CONTRACT; |
434 | m_pModule = subst.m_pModule; |
435 | m_sigInst = subst.m_sigInst; |
436 | m_pNext = subst.m_pNext; |
437 | } |
438 | void DeleteChain(); |
439 | |
440 | Module * GetModule() const { LIMITED_METHOD_DAC_CONTRACT; return m_pModule; } |
441 | const Substitution * GetNext() const { LIMITED_METHOD_DAC_CONTRACT; return m_pNext; } |
442 | const SigPointer & GetInst() const { LIMITED_METHOD_DAC_CONTRACT; return m_sigInst; } |
443 | DWORD GetLength() const; |
444 | |
445 | void CopyToArray(Substitution * pTarget /* must have type Substitution[GetLength()] */ ) const; |
446 | |
447 | }; // class Substitution |
448 | |
449 | //--------------------------------------------------------------------------------------- |
450 | // |
451 | // Linked list that records what tokens are currently being compared for equivalence. This prevents |
452 | // infinite recursion when types refer to each other in a cycle, e.g. a delegate that takes itself as |
453 | // a parameter or a struct that declares a field of itself (illegal but we don't know at this point). |
454 | // |
455 | class TokenPairList |
456 | { |
457 | public: |
458 | // Chain using this constructor when comparing two typedefs for equivalence. |
459 | TokenPairList(mdToken token1, Module *pModule1, mdToken token2, Module *pModule2, TokenPairList *pNext) |
460 | : m_token1(token1), m_token2(token2), |
461 | m_pModule1(pModule1), m_pModule2(pModule2), |
462 | m_bInTypeEquivalenceForbiddenScope(pNext == NULL ? FALSE : pNext->m_bInTypeEquivalenceForbiddenScope), |
463 | m_pNext(pNext) |
464 | { LIMITED_METHOD_CONTRACT; } |
465 | |
466 | static BOOL Exists(TokenPairList *pList, mdToken token1, Module *pModule1, mdToken token2, Module *pModule2) |
467 | { |
468 | LIMITED_METHOD_CONTRACT; |
469 | while (pList != NULL) |
470 | { |
471 | if (pList->m_token1 == token1 && pList->m_pModule1 == pModule1 && |
472 | pList->m_token2 == token2 && pList->m_pModule2 == pModule2) |
473 | return TRUE; |
474 | |
475 | if (pList->m_token1 == token2 && pList->m_pModule1 == pModule2 && |
476 | pList->m_token2 == token1 && pList->m_pModule2 == pModule1) |
477 | return TRUE; |
478 | |
479 | pList = pList->m_pNext; |
480 | } |
481 | return FALSE; |
482 | } |
483 | |
484 | static BOOL InTypeEquivalenceForbiddenScope(TokenPairList *pList) |
485 | { |
486 | return (pList == NULL ? FALSE : pList->m_bInTypeEquivalenceForbiddenScope); |
487 | } |
488 | |
489 | // Chain using this method when comparing type specs. |
490 | static TokenPairList AdjustForTypeSpec(TokenPairList *pTemplate, Module *pTypeSpecModule, PCCOR_SIGNATURE pTypeSpecSig, DWORD cbTypeSpecSig); |
491 | static TokenPairList AdjustForTypeEquivalenceForbiddenScope(TokenPairList *pTemplate); |
492 | |
493 | private: |
494 | TokenPairList(TokenPairList *pTemplate) |
495 | : m_token1(pTemplate ? pTemplate->m_token1 : mdTokenNil), |
496 | m_token2(pTemplate ? pTemplate->m_token2 : mdTokenNil), |
497 | m_pModule1(pTemplate ? pTemplate->m_pModule1 : NULL), |
498 | m_pModule2(pTemplate ? pTemplate->m_pModule2 : NULL), |
499 | m_bInTypeEquivalenceForbiddenScope(pTemplate ? pTemplate->m_bInTypeEquivalenceForbiddenScope : FALSE), |
500 | m_pNext(pTemplate ? pTemplate->m_pNext : NULL) |
501 | { LIMITED_METHOD_CONTRACT; } |
502 | |
503 | mdToken m_token1, m_token2; |
504 | Module *m_pModule1, *m_pModule2; |
505 | BOOL m_bInTypeEquivalenceForbiddenScope; |
506 | TokenPairList *m_pNext; |
507 | }; // class TokenPairList |
508 | |
509 | //--------------------------------------------------------------------------------------- |
510 | // |
511 | class MetaSig |
512 | { |
513 | public: |
514 | enum MetaSigKind { |
515 | sigMember, |
516 | sigLocalVars, |
517 | sigField, |
518 | }; |
519 | |
520 | //------------------------------------------------------------------ |
521 | // Common init used by other constructors |
522 | //------------------------------------------------------------------ |
523 | void Init(PCCOR_SIGNATURE szMetaSig, |
524 | DWORD cbMetaSig, |
525 | Module* pModule, |
526 | const SigTypeContext *pTypeContext, |
527 | MetaSigKind kind = sigMember); |
528 | |
529 | //------------------------------------------------------------------ |
530 | // Constructor. Warning: Does NOT make a copy of szMetaSig. |
531 | // |
532 | // The instantiations are used to fill in type variables on calls |
533 | // to PeekArg, GetReturnType, GetNextArg, GetTypeHandle, GetRetTypeHandle and |
534 | // so on. |
535 | // |
536 | // Please make sure you know what you're doing by leaving classInst and methodInst to default NULL |
537 | // Are you sure the signature cannot contain type parameters (E_T_VAR, E_T_MVAR)? |
538 | //------------------------------------------------------------------ |
539 | MetaSig(PCCOR_SIGNATURE szMetaSig, |
540 | DWORD cbMetaSig, |
541 | Module* pModule, |
542 | const SigTypeContext *pTypeContext, |
543 | MetaSigKind kind = sigMember) |
544 | { |
545 | WRAPPER_NO_CONTRACT; |
546 | Init(szMetaSig, cbMetaSig, pModule, pTypeContext, kind); |
547 | } |
548 | |
549 | // this is just a variation of the previous constructor to ease the transition to Signature |
550 | MetaSig(const Signature & signature, |
551 | Module * pModule, |
552 | const SigTypeContext * pTypeContext, |
553 | MetaSigKind kind = sigMember) |
554 | { |
555 | WRAPPER_NO_CONTRACT; |
556 | Init(signature.GetRawSig(), signature.GetRawSigLen(), pModule, pTypeContext, kind); |
557 | } |
558 | |
559 | // The following create MetaSigs for parsing the signature of the given method. |
560 | // They are identical except that they give slightly different |
561 | // type contexts. (Note the type context will only be relevant if we |
562 | // are parsing a method on an array type or on a generic type.) |
563 | // See TypeCtxt.h for more details. |
564 | // If declaringType is omitted then a *representative* instantiation may be obtained from pMD or pFD |
565 | MetaSig(MethodDesc *pMD, TypeHandle declaringType = TypeHandle()); |
566 | MetaSig(MethodDesc *pMD, Instantiation classInst, Instantiation methodInst); |
567 | |
568 | MetaSig(FieldDesc *pFD, TypeHandle declaringType = TypeHandle()); |
569 | |
570 | // Used to avoid touching metadata for mscorlib methods. Nb. only use for non-generic methods. |
571 | MetaSig(BinderMethodID id); |
572 | |
573 | MetaSig(LPHARDCODEDMETASIG pwzMetaSig); |
574 | |
575 | //------------------------------------------------------------------ |
576 | // Returns type of current argument index. Returns ELEMENT_TYPE_END |
577 | // if already past end of arguments. |
578 | //------------------------------------------------------------------ |
579 | CorElementType PeekArg() const; |
580 | |
581 | //------------------------------------------------------------------ |
582 | // Returns type of current argument index. Returns ELEMENT_TYPE_END |
583 | // if already past end of arguments. |
584 | //------------------------------------------------------------------ |
585 | CorElementType PeekArgNormalized(TypeHandle * pthValueType = NULL) const; |
586 | |
587 | //------------------------------------------------------------------ |
588 | // Returns type of current argument, then advances the argument |
589 | // index. Returns ELEMENT_TYPE_END if already past end of arguments. |
590 | // This method updates m_pLastType |
591 | //------------------------------------------------------------------ |
592 | CorElementType NextArg(); |
593 | |
594 | //------------------------------------------------------------------ |
595 | // Advance the argument index. Can be used with GetArgProps() to |
596 | // to iterate when you do not have a valid type context. |
597 | // This method updates m_pLastType |
598 | //------------------------------------------------------------------ |
599 | void SkipArg(); |
600 | |
601 | //------------------------------------------------------------------ |
602 | // Returns a read-only SigPointer for the m_pLastType set by one |
603 | // of NextArg() or SkipArg() |
604 | // This allows extracting more information for complex types. |
605 | //------------------------------------------------------------------ |
606 | const SigPointer & GetArgProps() const |
607 | { |
608 | LIMITED_METHOD_CONTRACT; |
609 | return m_pLastType; |
610 | } |
611 | |
612 | //------------------------------------------------------------------ |
613 | // Returns a read-only SigPointer for the return type. |
614 | // This allows extracting more information for complex types. |
615 | //------------------------------------------------------------------ |
616 | const SigPointer & GetReturnProps() const |
617 | { |
618 | LIMITED_METHOD_CONTRACT; |
619 | return m_pRetType; |
620 | } |
621 | |
622 | |
623 | //------------------------------------------------------------------------ |
624 | // Returns # of arguments. Does not count the return value. |
625 | // Does not count the "this" argument (which is not reflected om the |
626 | // sig.) 64-bit arguments are counted as one argument. |
627 | //------------------------------------------------------------------------ |
628 | UINT NumFixedArgs() |
629 | { |
630 | LIMITED_METHOD_DAC_CONTRACT; |
631 | return m_nArgs; |
632 | } |
633 | |
634 | //---------------------------------------------------------- |
635 | // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_* |
636 | // defines in cor.h) - throws. |
637 | //---------------------------------------------------------- |
638 | static BYTE GetCallingConvention( |
639 | Module *pModule, |
640 | const Signature &signature) |
641 | { |
642 | CONTRACTL |
643 | { |
644 | THROWS; |
645 | GC_NOTRIGGER; |
646 | MODE_ANY; |
647 | SUPPORTS_DAC; |
648 | } |
649 | CONTRACTL_END |
650 | |
651 | PCCOR_SIGNATURE pSig = signature.GetRawSig(); |
652 | |
653 | if (signature.GetRawSigLen() < 1) |
654 | { |
655 | ThrowHR(COR_E_BADIMAGEFORMAT); |
656 | } |
657 | return (BYTE)(IMAGE_CEE_CS_CALLCONV_MASK & CorSigUncompressCallingConv(/*modifies*/pSig)); |
658 | } |
659 | |
660 | //---------------------------------------------------------- |
661 | // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_* |
662 | // defines in cor.h) - doesn't throw. |
663 | //---------------------------------------------------------- |
664 | __checkReturn |
665 | static HRESULT GetCallingConvention_NoThrow( |
666 | Module *pModule, |
667 | const Signature &signature, |
668 | BYTE *pbCallingConvention) |
669 | { |
670 | CONTRACTL |
671 | { |
672 | NOTHROW; |
673 | GC_NOTRIGGER; |
674 | MODE_ANY; |
675 | SUPPORTS_DAC; |
676 | } |
677 | CONTRACTL_END |
678 | |
679 | PCCOR_SIGNATURE pSig = signature.GetRawSig(); |
680 | |
681 | if (signature.GetRawSigLen() < 1) |
682 | { |
683 | *pbCallingConvention = 0; |
684 | return COR_E_BADIMAGEFORMAT; |
685 | } |
686 | *pbCallingConvention = (BYTE)(IMAGE_CEE_CS_CALLCONV_MASK & CorSigUncompressCallingConv(/*modifies*/pSig)); |
687 | return S_OK; |
688 | } |
689 | |
690 | //---------------------------------------------------------- |
691 | // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_* |
692 | // defines in cor.h) |
693 | //---------------------------------------------------------- |
694 | BYTE GetCallingConvention() |
695 | { |
696 | LIMITED_METHOD_CONTRACT; |
697 | SUPPORTS_DAC; |
698 | return m_CallConv & IMAGE_CEE_CS_CALLCONV_MASK; |
699 | } |
700 | |
701 | //---------------------------------------------------------- |
702 | // Returns the calling convention & flags (see IMAGE_CEE_CS_CALLCONV_* |
703 | // defines in cor.h) |
704 | //---------------------------------------------------------- |
705 | BYTE GetCallingConventionInfo() |
706 | { |
707 | LIMITED_METHOD_DAC_CONTRACT; |
708 | |
709 | return m_CallConv; |
710 | } |
711 | |
712 | //---------------------------------------------------------- |
713 | // Has a 'this' pointer? |
714 | //---------------------------------------------------------- |
715 | BOOL HasThis() |
716 | { |
717 | LIMITED_METHOD_CONTRACT; |
718 | |
719 | return m_CallConv & IMAGE_CEE_CS_CALLCONV_HASTHIS; |
720 | } |
721 | |
722 | //---------------------------------------------------------- |
723 | // Has a explicit 'this' pointer? |
724 | //---------------------------------------------------------- |
725 | BOOL HasExplicitThis() |
726 | { |
727 | LIMITED_METHOD_CONTRACT; |
728 | |
729 | return m_CallConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS; |
730 | } |
731 | |
732 | //---------------------------------------------------------- |
733 | // Is a generic method with explicit arity? |
734 | //---------------------------------------------------------- |
735 | BOOL IsGenericMethod() |
736 | { |
737 | LIMITED_METHOD_CONTRACT; |
738 | return m_CallConv & IMAGE_CEE_CS_CALLCONV_GENERIC; |
739 | } |
740 | |
741 | //---------------------------------------------------------- |
742 | // Is vararg? |
743 | //---------------------------------------------------------- |
744 | BOOL IsVarArg() |
745 | { |
746 | WRAPPER_NO_CONTRACT; |
747 | SUPPORTS_DAC; |
748 | return GetCallingConvention() == IMAGE_CEE_CS_CALLCONV_VARARG; |
749 | } |
750 | |
751 | //---------------------------------------------------------- |
752 | // Is vararg? |
753 | //---------------------------------------------------------- |
754 | static BOOL IsVarArg(Module *pModule, const Signature &signature) |
755 | { |
756 | CONTRACTL |
757 | { |
758 | NOTHROW; |
759 | GC_NOTRIGGER; |
760 | MODE_ANY; |
761 | SUPPORTS_DAC; |
762 | } |
763 | CONTRACTL_END |
764 | |
765 | HRESULT hr; |
766 | BYTE nCallingConvention; |
767 | |
768 | hr = GetCallingConvention_NoThrow(pModule, signature, &nCallingConvention); |
769 | if (FAILED(hr)) |
770 | { // Invalid signatures are not VarArg |
771 | return FALSE; |
772 | } |
773 | return nCallingConvention == IMAGE_CEE_CS_CALLCONV_VARARG; |
774 | } |
775 | |
776 | Module* GetModule() const |
777 | { |
778 | LIMITED_METHOD_DAC_CONTRACT; |
779 | |
780 | return m_pModule; |
781 | } |
782 | |
783 | //---------------------------------------------------------- |
784 | // Returns the unmanaged calling convention. |
785 | //---------------------------------------------------------- |
786 | static BOOL GetUnmanagedCallingConvention(Module *pModule, PCCOR_SIGNATURE pSig, ULONG cSig, CorPinvokeMap *pPinvokeMapOut); |
787 | |
788 | //------------------------------------------------------------------ |
789 | // Like NextArg, but return only normalized type (enums flattned to |
790 | // underlying type ... |
791 | //------------------------------------------------------------------ |
792 | CorElementType |
793 | NextArgNormalized(TypeHandle * pthValueType = NULL) |
794 | { |
795 | CONTRACTL |
796 | { |
797 | if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS; |
798 | if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS; |
799 | if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); } |
800 | MODE_ANY; |
801 | SUPPORTS_DAC; |
802 | } |
803 | CONTRACTL_END |
804 | |
805 | m_pLastType = m_pWalk; |
806 | if (m_iCurArg == m_nArgs) |
807 | { |
808 | return ELEMENT_TYPE_END; |
809 | } |
810 | else |
811 | { |
812 | m_iCurArg++; |
813 | CorElementType mt = m_pWalk.PeekElemTypeNormalized(m_pModule, &m_typeContext, pthValueType); |
814 | // We should not hit ELEMENT_TYPE_END in the middle of the signature |
815 | if (mt == ELEMENT_TYPE_END) |
816 | { |
817 | THROW_BAD_FORMAT(BFA_BAD_SIGNATURE, (Module *)NULL); |
818 | } |
819 | IfFailThrowBF(m_pWalk.SkipExactlyOne(), BFA_BAD_SIGNATURE, (Module *)NULL); |
820 | return mt; |
821 | } |
822 | } // NextArgNormalized |
823 | |
824 | // Tests if the return type is an object ref. Loads types |
825 | // if needed (though it shouldn't really need to) |
826 | BOOL IsObjectRefReturnType(); |
827 | |
828 | //------------------------------------------------------------------------ |
829 | // Compute element size from CorElementType and optional valuetype. |
830 | //------------------------------------------------------------------------ |
831 | static UINT GetElemSize(CorElementType etype, TypeHandle thValueType); |
832 | |
833 | UINT GetReturnTypeSize() |
834 | { |
835 | WRAPPER_NO_CONTRACT; |
836 | SUPPORTS_DAC; |
837 | return m_pRetType.SizeOf(m_pModule, &m_typeContext); |
838 | } |
839 | |
840 | //------------------------------------------------------------------ |
841 | // Perform type-specific GC promotion on the value (based upon the |
842 | // last type retrieved by NextArg()). |
843 | //------------------------------------------------------------------ |
844 | VOID GcScanRoots(ArgDestination *pValue, promote_func *fn, |
845 | ScanContext* sc, promote_carefully_func *fnc = NULL); |
846 | |
847 | //------------------------------------------------------------------ |
848 | // Is the return type 64 bit? |
849 | //------------------------------------------------------------------ |
850 | BOOL Is64BitReturn() const |
851 | { |
852 | WRAPPER_NO_CONTRACT; |
853 | CorElementType rt = GetReturnTypeNormalized(); |
854 | return (rt == ELEMENT_TYPE_I8 || rt == ELEMENT_TYPE_U8 || rt == ELEMENT_TYPE_R8); |
855 | } |
856 | |
857 | //------------------------------------------------------------------ |
858 | // Is the return type floating point? |
859 | //------------------------------------------------------------------ |
860 | BOOL HasFPReturn() |
861 | { |
862 | WRAPPER_NO_CONTRACT; |
863 | CorElementType rt = GetReturnTypeNormalized(); |
864 | return (rt == ELEMENT_TYPE_R4 || rt == ELEMENT_TYPE_R8); |
865 | } |
866 | |
867 | //------------------------------------------------------------------ |
868 | // reset: goto start pos |
869 | //------------------------------------------------------------------ |
870 | VOID Reset(); |
871 | |
872 | //------------------------------------------------------------------ |
873 | // current position of the arg iterator |
874 | //------------------------------------------------------------------ |
875 | UINT GetArgNum() |
876 | { |
877 | LIMITED_METHOD_CONTRACT; |
878 | return m_iCurArg; |
879 | } |
880 | |
881 | //------------------------------------------------------------------ |
882 | // Returns CorElementType of return value, taking into account |
883 | // any instantiations due to generics. Does not load types. |
884 | // Does not return normalized type. |
885 | //------------------------------------------------------------------ |
886 | CorElementType GetReturnType() const; |
887 | |
888 | BOOL IsReturnTypeVoid() const; |
889 | |
890 | |
891 | enum RETURNTYPE {RETOBJ, RETBYREF, RETNONOBJ, RETVALUETYPE}; |
892 | |
893 | CorElementType GetReturnTypeNormalized(TypeHandle * pthValueType = NULL) const; |
894 | |
895 | //------------------------------------------------------------------ |
896 | // used to treat some sigs as special case vararg |
897 | // used by calli to unmanaged target |
898 | //------------------------------------------------------------------ |
899 | BOOL IsTreatAsVarArg() |
900 | { |
901 | LIMITED_METHOD_DAC_CONTRACT; |
902 | |
903 | return (m_flags & TREAT_AS_VARARG); |
904 | } |
905 | |
906 | //------------------------------------------------------------------ |
907 | // Determines if the current argument is System/String. |
908 | // Caller must determine first that the argument type is |
909 | // ELEMENT_TYPE_CLASS or ELEMENT_TYPE_STRING. This may be used during |
910 | // GC. |
911 | //------------------------------------------------------------------ |
912 | BOOL IsStringType() const; |
913 | |
914 | //------------------------------------------------------------------ |
915 | // Determines if the current argument is a particular class. |
916 | // Caller must determine first that the argument type |
917 | // is ELEMENT_TYPE_CLASS. |
918 | //------------------------------------------------------------------ |
919 | BOOL IsClass(LPCUTF8 szClassName) const; |
920 | |
921 | |
922 | //------------------------------------------------------------------ |
923 | // This method will return a TypeHandle for the last argument |
924 | // examined. |
925 | // If NextArg() returns ELEMENT_TYPE_BYREF, you can also call GetByRefType() |
926 | // to get to the underlying type of the byref |
927 | //------------------------------------------------------------------ |
928 | TypeHandle GetLastTypeHandleNT() const |
929 | { |
930 | WRAPPER_NO_CONTRACT; |
931 | return m_pLastType.GetTypeHandleNT(m_pModule, &m_typeContext); |
932 | } |
933 | |
934 | //------------------------------------------------------------------ |
935 | // This method will return a TypeHandle for the last argument |
936 | // examined. |
937 | // If NextArg() returns ELEMENT_TYPE_BYREF, you can also call GetByRefType() |
938 | // to get to the underlying type of the byref |
939 | //------------------------------------------------------------------ |
940 | TypeHandle GetLastTypeHandleThrowing(ClassLoader::LoadTypesFlag fLoadTypes = ClassLoader::LoadTypes, |
941 | ClassLoadLevel level = CLASS_LOADED, |
942 | BOOL dropGenericArgumentLevel = FALSE) const |
943 | { |
944 | WRAPPER_NO_CONTRACT; |
945 | return m_pLastType.GetTypeHandleThrowing(m_pModule, &m_typeContext, fLoadTypes, |
946 | level, dropGenericArgumentLevel); |
947 | } |
948 | |
949 | //------------------------------------------------------------------ |
950 | // Returns the TypeHandle for the return type of the signature |
951 | //------------------------------------------------------------------ |
952 | TypeHandle GetRetTypeHandleNT() const |
953 | { |
954 | WRAPPER_NO_CONTRACT; |
955 | return m_pRetType.GetTypeHandleNT(m_pModule, &m_typeContext); |
956 | } |
957 | |
958 | TypeHandle GetRetTypeHandleThrowing(ClassLoader::LoadTypesFlag fLoadTypes = ClassLoader::LoadTypes, |
959 | ClassLoadLevel level = CLASS_LOADED) const |
960 | { |
961 | WRAPPER_NO_CONTRACT; |
962 | return m_pRetType.GetTypeHandleThrowing(m_pModule, &m_typeContext, fLoadTypes, level); |
963 | } |
964 | |
965 | //------------------------------------------------------------------ |
966 | // Returns the base type of the byref type of the last argument examined |
967 | // which needs to have been ELEMENT_TYPE_BYREF. |
968 | // For object references, the class being accessed byref is also returned in *pTy. |
969 | // eg. for "int32 &", return value = ELEMENT_TYPE_I4, *pTy= ??? |
970 | // for "System.Exception &", return value = ELEMENT_TYPE_CLASS, *pTy=System.Exception |
971 | // Note that byref to byref is not allowed, and so the return value |
972 | // can never be ELEMENT_TYPE_BYREF. |
973 | //------------------------------------------------------------------ |
974 | CorElementType GetByRefType(TypeHandle* pTy) const; |
975 | |
976 | // Compare types in two signatures, first applying |
977 | // - optional substitutions pSubst1 and pSubst2 |
978 | // to class type parameters (E_T_VAR) in the respective signatures |
979 | static |
980 | BOOL |
981 | CompareElementType( |
982 | PCCOR_SIGNATURE & pSig1, |
983 | PCCOR_SIGNATURE & pSig2, |
984 | PCCOR_SIGNATURE pEndSig1, |
985 | PCCOR_SIGNATURE pEndSig2, |
986 | Module * pModule1, |
987 | Module * pModule2, |
988 | const Substitution * pSubst1, |
989 | const Substitution * pSubst2, |
990 | TokenPairList * pVisited = NULL); |
991 | |
992 | |
993 | |
994 | // If pTypeDef1 is C<...> and pTypeDef2 is C<...> (for possibly different instantiations) |
995 | // then check C<!0, ... !n> @ pSubst1 == C<!0, ..., !n> @ pSubst2, i.e. |
996 | // that the head type (C) is the same and that when the head type is treated |
997 | // as an uninstantiated type definition and we apply each of the substitutions |
998 | // then the same type results. This effectively checks that the two substitutions |
999 | // are equivalent. |
1000 | static BOOL CompareTypeDefsUnderSubstitutions(MethodTable *pTypeDef1, MethodTable *pTypeDef2, |
1001 | const Substitution* pSubst1, const Substitution* pSubst2, |
1002 | TokenPairList *pVisited = NULL); |
1003 | |
1004 | |
1005 | // Compare two complete method signatures, first applying optional substitutions pSubst1 and pSubst2 |
1006 | // to class type parameters (E_T_VAR) in the respective signatures |
1007 | static BOOL CompareMethodSigs( |
1008 | PCCOR_SIGNATURE pSig1, |
1009 | DWORD cSig1, |
1010 | Module* pModule1, |
1011 | const Substitution* pSubst1, |
1012 | PCCOR_SIGNATURE pSig2, |
1013 | DWORD cSig2, |
1014 | Module* pModule2, |
1015 | const Substitution* pSubst2, |
1016 | TokenPairList *pVisited = NULL |
1017 | ); |
1018 | |
1019 | // Nonthrowing version of CompareMethodSigs |
1020 | // |
1021 | // Return S_OK if they match |
1022 | // S_FALSE if they don't match |
1023 | // FAILED if OOM or some other blocking error |
1024 | // |
1025 | static HRESULT CompareMethodSigsNT( |
1026 | PCCOR_SIGNATURE pSig1, |
1027 | DWORD cSig1, |
1028 | Module* pModule1, |
1029 | const Substitution* pSubst1, |
1030 | PCCOR_SIGNATURE pSig2, |
1031 | DWORD cSig2, |
1032 | Module* pModule2, |
1033 | const Substitution* pSubst2, |
1034 | TokenPairList *pVisited = NULL |
1035 | ); |
1036 | |
1037 | static BOOL CompareFieldSigs( |
1038 | PCCOR_SIGNATURE pSig1, |
1039 | DWORD cSig1, |
1040 | Module* pModule1, |
1041 | PCCOR_SIGNATURE pSig2, |
1042 | DWORD cSig2, |
1043 | Module* pModule2, |
1044 | TokenPairList *pVisited = NULL |
1045 | ); |
1046 | |
1047 | static BOOL CompareMethodSigs(MetaSig &msig1, |
1048 | MetaSig &msig2, |
1049 | BOOL ignoreCallconv); |
1050 | |
1051 | // Is each set of constraints on the implementing method's type parameters a subset |
1052 | // of the corresponding set of constraints on the declared method's type parameters, |
1053 | // given a subsitution for the latter's (class) type parameters. |
1054 | // This is used by the class loader to verify type safety of method overriding and interface implementation. |
1055 | static BOOL CompareMethodConstraints(const Substitution *pSubst1, |
1056 | Module *pModule1, |
1057 | mdMethodDef tok1, //implementing method |
1058 | const Substitution *pSubst2, |
1059 | Module *pModule2, |
1060 | mdMethodDef tok2); //declared method |
1061 | |
1062 | private: |
1063 | static BOOL CompareVariableConstraints(const Substitution *pSubst1, |
1064 | Module *pModule1, mdGenericParam tok1, //overriding |
1065 | const Substitution *pSubst2, |
1066 | Module *pModule2, mdGenericParam tok2); //overridden |
1067 | |
1068 | static BOOL CompareTypeDefOrRefOrSpec(Module *pModule1, mdToken tok1, |
1069 | const Substitution *pSubst1, |
1070 | Module *pModule2, mdToken tok2, |
1071 | const Substitution *pSubst2, |
1072 | TokenPairList *pVisited); |
1073 | static BOOL CompareTypeSpecToToken(mdTypeSpec tk1, |
1074 | mdToken tk2, |
1075 | Module *pModule1, |
1076 | Module *pModule2, |
1077 | const Substitution *pSubst1, |
1078 | TokenPairList *pVisited); |
1079 | |
1080 | static BOOL CompareElementTypeToToken(PCCOR_SIGNATURE &pSig1, |
1081 | PCCOR_SIGNATURE pEndSig1, // end of sig1 |
1082 | mdToken tk2, |
1083 | Module* pModule1, |
1084 | Module* pModule2, |
1085 | const Substitution* pSubst1, |
1086 | TokenPairList *pVisited); |
1087 | |
1088 | public: |
1089 | |
1090 | //------------------------------------------------------------------ |
1091 | // Ensures that all the value types in the sig are loaded. This |
1092 | // should be called on sig's that have value types before they |
1093 | // are passed to Call(). This ensures that value classes will not |
1094 | // be loaded during the operation to determine the size of the |
1095 | // stack. Thus preventing the resulting GC hole. |
1096 | //------------------------------------------------------------------ |
1097 | static void EnsureSigValueTypesLoaded(MethodDesc *pMD); |
1098 | |
1099 | // this walks the sig and checks to see if all types in the sig can be loaded |
1100 | static void CheckSigTypesCanBeLoaded(MethodDesc *pMD); |
1101 | |
1102 | const SigTypeContext *GetSigTypeContext() const { LIMITED_METHOD_CONTRACT; return &m_typeContext; } |
1103 | |
1104 | // Disallow copy constructor. |
1105 | MetaSig(MetaSig *pSig); |
1106 | |
1107 | void SetHasParamTypeArg() |
1108 | { |
1109 | LIMITED_METHOD_CONTRACT; |
1110 | m_CallConv |= CORINFO_CALLCONV_PARAMTYPE; |
1111 | } |
1112 | |
1113 | void SetTreatAsVarArg() |
1114 | { |
1115 | LIMITED_METHOD_CONTRACT; |
1116 | m_flags |= TREAT_AS_VARARG; |
1117 | } |
1118 | |
1119 | |
1120 | // These are protected because Reflection subclasses Metasig |
1121 | protected: |
1122 | |
1123 | enum MetaSigFlags |
1124 | { |
1125 | SIG_RET_TYPE_INITTED = 0x01, |
1126 | TREAT_AS_VARARG = 0x02, // used to treat some sigs as special case vararg |
1127 | // used by calli to unmanaged target |
1128 | }; |
1129 | |
1130 | Module* m_pModule; |
1131 | SigTypeContext m_typeContext; // Instantiation for type parameters |
1132 | |
1133 | SigPointer m_pStart; |
1134 | SigPointer m_pWalk; |
1135 | SigPointer m_pLastType; |
1136 | SigPointer m_pRetType; |
1137 | UINT32 m_nArgs; |
1138 | UINT32 m_iCurArg; |
1139 | |
1140 | // The following are cached so we don't the signature |
1141 | // multiple times |
1142 | |
1143 | CorElementType m_corNormalizedRetType; |
1144 | BYTE m_flags; |
1145 | BYTE m_CallConv; |
1146 | }; // class MetaSig |
1147 | |
1148 | |
1149 | BOOL IsTypeRefOrDef(LPCSTR szClassName, Module *pModule, mdToken token); |
1150 | |
1151 | #if defined(FEATURE_TYPEEQUIVALENCE) && !defined(DACCESS_COMPILE) |
1152 | |
1153 | // A helper struct representing data stored in the TypeIdentifierAttribute. |
1154 | struct TypeIdentifierData |
1155 | { |
1156 | TypeIdentifierData() : m_cbScope(0), m_pchScope(NULL), m_cbIdentifierNamespace(0), m_pchIdentifierNamespace(NULL), |
1157 | m_cbIdentifierName(0), m_pchIdentifierName(NULL) {} |
1158 | |
1159 | HRESULT Init(Module *pModule, mdToken tk); |
1160 | BOOL IsEqual(const TypeIdentifierData & data) const; |
1161 | |
1162 | private: |
1163 | SIZE_T m_cbScope; |
1164 | LPCUTF8 m_pchScope; |
1165 | SIZE_T m_cbIdentifierNamespace; |
1166 | LPCUTF8 m_pchIdentifierNamespace; |
1167 | SIZE_T m_cbIdentifierName; |
1168 | LPCUTF8 m_pchIdentifierName; |
1169 | }; |
1170 | |
1171 | #endif // FEATURE_TYPEEQUIVALENCE && !DACCESS_COMPILE |
1172 | |
1173 | // fResolved is TRUE when one of the tokens is a resolved TypeRef. This is used to restrict |
1174 | // type equivalence checks for value types. |
1175 | BOOL CompareTypeTokens(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2, TokenPairList *pVisited = NULL); |
1176 | |
1177 | // Nonthrowing version of CompareTypeTokens. |
1178 | // |
1179 | // Return S_OK if they match |
1180 | // S_FALSE if they don't match |
1181 | // FAILED if OOM or some other blocking error |
1182 | // |
1183 | HRESULT CompareTypeTokensNT(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2); |
1184 | |
1185 | // TRUE if the two TypeDefs have the same layout and field marshal information. |
1186 | BOOL CompareTypeLayout(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2); |
1187 | BOOL CompareTypeDefsForEquivalence(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2, TokenPairList *pVisited); |
1188 | BOOL IsTypeDefEquivalent(mdToken tk, Module *pModule); |
1189 | BOOL IsTypeDefExternallyVisible(mdToken tk, Module *pModule, DWORD dwAttrs); |
1190 | |
1191 | void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc); |
1192 | |
1193 | #endif /* _H_SIGINFO */ |
1194 | |