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
36BOOL IsTypeRefOrDef(LPCSTR szClassName, Module *pModule, mdToken token);
37
38struct 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};
46extern const ElementTypeInfo gElementTypeInfo[];
47
48unsigned GetSizeForCorElementType(CorElementType etyp);
49const ElementTypeInfo* GetElementTypeInfo(CorElementType etyp);
50
51class SigBuilder;
52class ArgDestination;
53
54typedef 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
58enum 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
71struct ScanContext;
72typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t);
73typedef void promote_carefully_func(promote_func*, PTR_PTR_Object, ScanContext*, uint32_t);
74
75void PromoteCarefully(promote_func fn,
76 PTR_PTR_Object obj,
77 ScanContext* sc,
78 uint32_t flags = GC_CALL_INTERIOR);
79
80class LoaderAllocator;
81void 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//
94class SigPointer : public SigParser
95{
96 friend class MetaSig;
97
98public:
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
202private:
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
217public:
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
258public:
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
281private:
282 BOOL IsStringTypeHelper(Module* pModule, const SigTypeContext* pTypeContext, BOOL fThrow) const;
283
284public:
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
293private:
294 BOOL IsClassHelper(Module* pModule, LPCUTF8 szClassName, const SigTypeContext* pTypeContext, BOOL fThrow) const;
295
296public:
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
311struct FrameInfo;
312struct VASigCookie;
313#if defined(DACCESS_COMPILE)
314class 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
338class Signature
339{
340public:
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
368private:
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//
400class Substitution
401{
402private:
403 Module * m_pModule; // Module in which instantiation lives (needed to resolve typerefs)
404 SigPointer m_sigInst;
405 const Substitution * m_pNext;
406
407public:
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//
455class TokenPairList
456{
457public:
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
493private:
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//
511class 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
1062private:
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
1088public:
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
1149BOOL 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.
1154struct 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
1162private:
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.
1175BOOL 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//
1183HRESULT CompareTypeTokensNT(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2);
1184
1185// TRUE if the two TypeDefs have the same layout and field marshal information.
1186BOOL CompareTypeLayout(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2);
1187BOOL CompareTypeDefsForEquivalence(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2, TokenPairList *pVisited);
1188BOOL IsTypeDefEquivalent(mdToken tk, Module *pModule);
1189BOOL IsTypeDefExternallyVisible(mdToken tk, Module *pModule, DWORD dwAttrs);
1190
1191void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc);
1192
1193#endif /* _H_SIGINFO */
1194