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.
15 #include "clsload.hpp"
16 #include "sigparser.h"
20 #include "eecontract.h"
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
33 #define STACK_GROWS_UP_ON_ARGS_WALK
36 BOOL IsTypeRefOrDef(LPCSTR szClassName, Module *pModule, mdToken token);
38 struct ElementTypeInfo {
43 CorInfoGCType m_gc : 3;
46 extern const ElementTypeInfo gElementTypeInfo[];
48 unsigned GetSizeForCorElementType(CorElementType etyp);
49 const ElementTypeInfo* GetElementTypeInfo(CorElementType etyp);
54 typedef const struct HardCodedMetaSig *LPHARDCODEDMETASIG;
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
62 hasMethodVar = 0x0002,
63 hasSharableClassVar = 0x0004,
64 hasSharableMethodVar = 0x0008,
65 hasAnyVarsMask = 0x0003,
66 hasSharableVarsMask = 0x000c
69 //---------------------------------------------------------------------------------------
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);
75 void PromoteCarefully(promote_func fn,
78 uint32_t flags = GC_CALL_INTERIOR);
80 class LoaderAllocator;
81 void GcReportLoaderAllocator(promote_func* fn, ScanContext* sc, LoaderAllocator *pLoaderAllocator);
83 //---------------------------------------------------------------------------------------
85 // Encapsulates how compressed integers and typeref tokens are encoded into
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.
94 class SigPointer : public SigParser
100 SigPointer() { LIMITED_METHOD_DAC_CONTRACT; }
103 SigPointer(const SigPointer & sig) : SigParser(sig)
108 SigPointer(const SigParser & sig) : SigParser(sig)
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.
117 SigPointer(PCCOR_SIGNATURE ptr) : SigParser(ptr)
122 // Signature from a pointer and size.
124 SigPointer(PCCOR_SIGNATURE ptr, DWORD len) : SigParser(ptr, len)
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.
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 //=========================================================================
142 void ConvertToInternalExactlyOne(Module* pSigModule, SigTypeContext *pTypeContext, SigBuilder * pSigBuilder, BOOL bSkipCustomModifier = TRUE);
143 void ConvertToInternalSignature(Module* pSigModule, SigTypeContext *pTypeContext, SigBuilder * pSigBuilder, BOOL bSkipCustomModifier = TRUE);
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.
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.
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 //=========================================================================
159 // The CorElementTypes returned correspond
160 // to those returned by TypeHandle::GetSignatureCorElementType.
161 CorElementType PeekElemTypeClosed(Module *pModule, const SigTypeContext *pTypeContext) const;
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.
168 // SigPointer should be in a position that satisfies
169 // ptr.PeekElemTypeClosed(pTypeContext) = ELEMENT_TYPE_VALUETYPE
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".
175 // The token will only make sense in the context of the module where
176 // the signature occurs.
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;
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 //=========================================================================
191 // The CorElementTypes returned correspond
192 // to those returned by TypeHandle::GetInternalCorElementType.
193 CorElementType PeekElemTypeNormalized(Module* pModule, const SigTypeContext *pTypeContext, TypeHandle * pthValueType = NULL) const;
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;
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,
208 ClassLoader::LoadTypesFlag fLoadTypes,
209 const SigTypeContext *pTypeContext);
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);
219 //------------------------------------------------------------------------
220 // Assuming that the SigPointer points the start if an element type.
221 // Use SigTypeContext to fill in any type parameters
223 // Also advance the pointer to after the element type.
224 //------------------------------------------------------------------------
226 // OBSOLETE - Use GetTypeHandleThrowing()
227 TypeHandle GetTypeHandleNT(Module* pModule,
228 const SigTypeContext *pTypeContext) const;
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.
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>)
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;
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.
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;
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;
282 BOOL IsStringTypeHelper(Module* pModule, const SigTypeContext* pTypeContext, BOOL fThrow) const;
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;
294 BOOL IsClassHelper(Module* pModule, LPCUTF8 szClassName, const SigTypeContext* pTypeContext, BOOL fThrow) const;
297 //------------------------------------------------------------------------
298 // Tests for the existence of a custom modifier
299 //------------------------------------------------------------------------
300 BOOL HasCustomModifier(Module *pModule, LPCSTR szModName, CorElementType cmodtype) const;
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;
308 }; // class SigPointer
310 // forward declarations needed for the friends declared in Signature
313 #if defined(DACCESS_COMPILE)
314 class DacDbiInterfaceImpl;
315 #endif // DACCESS_COMPILE
317 //---------------------------------------------------------------------------------------
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.
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.
330 // We should move over to Signature instead of PCCOR_SIGNATURE.
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.
341 // create an empty Signature
344 // this is the primary constructor
345 Signature(PCCOR_SIGNATURE pSig,
348 // check whether the signature is empty, i.e. have a NULL PCCOR_SIGNATURE
349 BOOL IsEmpty() const;
351 // create a SigParser from the signature
352 SigParser CreateSigParser() const;
354 // create a SigPointer from the signature
355 SigPointer CreateSigPointer() const;
357 // pretty print the signature
358 void PrettyPrint(const CHAR * pszMethodName,
359 CQuickBytes * pqbOut,
360 IMDInternalImport * pIMDI) const;
362 // retrieve the raw PCCOR_SIGNATURE pointer
363 PCCOR_SIGNATURE GetRawSig() const;
365 // retrieve the length of the signature
366 DWORD GetRawSigLen() const;
369 PCCOR_SIGNATURE m_pSig;
371 }; // class Signature
375 #define MAX_CACHED_SIG_SIZE 3 // To excercize non-cached code path
377 #define MAX_CACHED_SIG_SIZE 15
381 //---------------------------------------------------------------------------------------
383 // A substitution represents the composition of several formal type instantiations
384 // It is used when matching formal signatures across the inheritance hierarchy.
386 // It has the form of a linked list:
387 // [mod_1, <inst_1>] ->
388 // [mod_2, <inst_2>] ->
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>
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>
398 // Any type variables in <inst_n> are treated as "free".
403 Module * m_pModule; // Module in which instantiation lives (needed to resolve typerefs)
404 SigPointer m_sigInst;
405 const Substitution * m_pNext;
410 LIMITED_METHOD_CONTRACT;
417 const SigPointer & sigInst,
418 const Substitution * pNextSubstitution)
420 LIMITED_METHOD_CONTRACT;
421 m_pModule = pModuleArg;
423 m_pNext = pNextSubstitution;
427 mdToken parentTypeDefOrRefOrSpec,
429 const Substitution * nextArg);
431 Substitution(const Substitution & subst)
433 LIMITED_METHOD_CONTRACT;
434 m_pModule = subst.m_pModule;
435 m_sigInst = subst.m_sigInst;
436 m_pNext = subst.m_pNext;
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;
445 void CopyToArray(Substitution * pTarget /* must have type Substitution[GetLength()] */ ) const;
447 }; // class Substitution
449 //---------------------------------------------------------------------------------------
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).
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),
464 { LIMITED_METHOD_CONTRACT; }
466 static BOOL Exists(TokenPairList *pList, mdToken token1, Module *pModule1, mdToken token2, Module *pModule2)
468 LIMITED_METHOD_CONTRACT;
469 while (pList != NULL)
471 if (pList->m_token1 == token1 && pList->m_pModule1 == pModule1 &&
472 pList->m_token2 == token2 && pList->m_pModule2 == pModule2)
475 if (pList->m_token1 == token2 && pList->m_pModule1 == pModule2 &&
476 pList->m_token2 == token1 && pList->m_pModule2 == pModule1)
479 pList = pList->m_pNext;
484 static BOOL InTypeEquivalenceForbiddenScope(TokenPairList *pList)
486 return (pList == NULL ? FALSE : pList->m_bInTypeEquivalenceForbiddenScope);
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);
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; }
503 mdToken m_token1, m_token2;
504 Module *m_pModule1, *m_pModule2;
505 BOOL m_bInTypeEquivalenceForbiddenScope;
506 TokenPairList *m_pNext;
507 }; // class TokenPairList
509 //---------------------------------------------------------------------------------------
520 //------------------------------------------------------------------
521 // Common init used by other constructors
522 //------------------------------------------------------------------
523 void Init(PCCOR_SIGNATURE szMetaSig,
526 const SigTypeContext *pTypeContext,
527 MetaSigKind kind = sigMember);
529 //------------------------------------------------------------------
530 // Constructor. Warning: Does NOT make a copy of szMetaSig.
532 // The instantiations are used to fill in type variables on calls
533 // to PeekArg, GetReturnType, GetNextArg, GetTypeHandle, GetRetTypeHandle and
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,
542 const SigTypeContext *pTypeContext,
543 MetaSigKind kind = sigMember)
546 Init(szMetaSig, cbMetaSig, pModule, pTypeContext, kind);
549 // this is just a variation of the previous constructor to ease the transition to Signature
550 MetaSig(const Signature & signature,
552 const SigTypeContext * pTypeContext,
553 MetaSigKind kind = sigMember)
556 Init(signature.GetRawSig(), signature.GetRawSigLen(), pModule, pTypeContext, kind);
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);
568 MetaSig(FieldDesc *pFD, TypeHandle declaringType = TypeHandle());
570 // Used to avoid touching metadata for mscorlib methods. Nb. only use for non-generic methods.
571 MetaSig(BinderMethodID id);
573 MetaSig(LPHARDCODEDMETASIG pwzMetaSig);
575 //------------------------------------------------------------------
576 // Returns type of current argument index. Returns ELEMENT_TYPE_END
577 // if already past end of arguments.
578 //------------------------------------------------------------------
579 CorElementType PeekArg() const;
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;
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();
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 //------------------------------------------------------------------
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
608 LIMITED_METHOD_CONTRACT;
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
618 LIMITED_METHOD_CONTRACT;
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 //------------------------------------------------------------------------
630 LIMITED_METHOD_DAC_CONTRACT;
634 //----------------------------------------------------------
635 // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_*
636 // defines in cor.h) - throws.
637 //----------------------------------------------------------
638 static BYTE GetCallingConvention(
640 const Signature &signature)
651 PCCOR_SIGNATURE pSig = signature.GetRawSig();
653 if (signature.GetRawSigLen() < 1)
655 ThrowHR(COR_E_BADIMAGEFORMAT);
657 return (BYTE)(IMAGE_CEE_CS_CALLCONV_MASK & CorSigUncompressCallingConv(/*modifies*/pSig));
660 //----------------------------------------------------------
661 // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_*
662 // defines in cor.h) - doesn't throw.
663 //----------------------------------------------------------
665 static HRESULT GetCallingConvention_NoThrow(
667 const Signature &signature,
668 BYTE *pbCallingConvention)
679 PCCOR_SIGNATURE pSig = signature.GetRawSig();
681 if (signature.GetRawSigLen() < 1)
683 *pbCallingConvention = 0;
684 return COR_E_BADIMAGEFORMAT;
686 *pbCallingConvention = (BYTE)(IMAGE_CEE_CS_CALLCONV_MASK & CorSigUncompressCallingConv(/*modifies*/pSig));
690 //----------------------------------------------------------
691 // Returns the calling convention (see IMAGE_CEE_CS_CALLCONV_*
693 //----------------------------------------------------------
694 BYTE GetCallingConvention()
696 LIMITED_METHOD_CONTRACT;
698 return m_CallConv & IMAGE_CEE_CS_CALLCONV_MASK;
701 //----------------------------------------------------------
702 // Returns the calling convention & flags (see IMAGE_CEE_CS_CALLCONV_*
704 //----------------------------------------------------------
705 BYTE GetCallingConventionInfo()
707 LIMITED_METHOD_DAC_CONTRACT;
712 //----------------------------------------------------------
713 // Has a 'this' pointer?
714 //----------------------------------------------------------
717 LIMITED_METHOD_CONTRACT;
719 return m_CallConv & IMAGE_CEE_CS_CALLCONV_HASTHIS;
722 //----------------------------------------------------------
723 // Has a explicit 'this' pointer?
724 //----------------------------------------------------------
725 BOOL HasExplicitThis()
727 LIMITED_METHOD_CONTRACT;
729 return m_CallConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS;
732 //----------------------------------------------------------
733 // Is a generic method with explicit arity?
734 //----------------------------------------------------------
735 BOOL IsGenericMethod()
737 LIMITED_METHOD_CONTRACT;
738 return m_CallConv & IMAGE_CEE_CS_CALLCONV_GENERIC;
741 //----------------------------------------------------------
743 //----------------------------------------------------------
748 return GetCallingConvention() == IMAGE_CEE_CS_CALLCONV_VARARG;
751 //----------------------------------------------------------
753 //----------------------------------------------------------
754 static BOOL IsVarArg(Module *pModule, const Signature &signature)
766 BYTE nCallingConvention;
768 hr = GetCallingConvention_NoThrow(pModule, signature, &nCallingConvention);
770 { // Invalid signatures are not VarArg
773 return nCallingConvention == IMAGE_CEE_CS_CALLCONV_VARARG;
776 Module* GetModule() const
778 LIMITED_METHOD_DAC_CONTRACT;
783 //----------------------------------------------------------
784 // Returns the unmanaged calling convention.
785 //----------------------------------------------------------
786 static BOOL GetUnmanagedCallingConvention(Module *pModule, PCCOR_SIGNATURE pSig, ULONG cSig, CorPinvokeMap *pPinvokeMapOut);
788 //------------------------------------------------------------------
789 // Like NextArg, but return only normalized type (enums flattned to
790 // underlying type ...
791 //------------------------------------------------------------------
793 NextArgNormalized(TypeHandle * pthValueType = NULL)
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()); }
805 m_pLastType = m_pWalk;
806 if (m_iCurArg == m_nArgs)
808 return ELEMENT_TYPE_END;
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)
817 THROW_BAD_FORMAT(BFA_BAD_SIGNATURE, (Module *)NULL);
819 IfFailThrowBF(m_pWalk.SkipExactlyOne(), BFA_BAD_SIGNATURE, (Module *)NULL);
822 } // NextArgNormalized
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();
828 //------------------------------------------------------------------------
829 // Compute element size from CorElementType and optional valuetype.
830 //------------------------------------------------------------------------
831 static UINT GetElemSize(CorElementType etype, TypeHandle thValueType);
833 UINT GetReturnTypeSize()
837 return m_pRetType.SizeOf(m_pModule, &m_typeContext);
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);
847 //------------------------------------------------------------------
848 // Is the return type 64 bit?
849 //------------------------------------------------------------------
850 BOOL Is64BitReturn() const
853 CorElementType rt = GetReturnTypeNormalized();
854 return (rt == ELEMENT_TYPE_I8 || rt == ELEMENT_TYPE_U8 || rt == ELEMENT_TYPE_R8);
857 //------------------------------------------------------------------
858 // Is the return type floating point?
859 //------------------------------------------------------------------
863 CorElementType rt = GetReturnTypeNormalized();
864 return (rt == ELEMENT_TYPE_R4 || rt == ELEMENT_TYPE_R8);
867 //------------------------------------------------------------------
868 // reset: goto start pos
869 //------------------------------------------------------------------
872 //------------------------------------------------------------------
873 // current position of the arg iterator
874 //------------------------------------------------------------------
877 LIMITED_METHOD_CONTRACT;
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;
888 BOOL IsReturnTypeVoid() const;
890 CorElementType GetReturnTypeNormalized(TypeHandle * pthValueType = NULL) const;
892 //------------------------------------------------------------------
893 // used to treat some sigs as special case vararg
894 // used by calli to unmanaged target
895 //------------------------------------------------------------------
896 BOOL IsTreatAsVarArg()
898 LIMITED_METHOD_DAC_CONTRACT;
900 return (m_flags & TREAT_AS_VARARG);
903 //------------------------------------------------------------------
904 // Determines if the current argument is System/String.
905 // Caller must determine first that the argument type is
906 // ELEMENT_TYPE_CLASS or ELEMENT_TYPE_STRING. This may be used during
908 //------------------------------------------------------------------
909 BOOL IsStringType() const;
911 //------------------------------------------------------------------
912 // Determines if the current argument is a particular class.
913 // Caller must determine first that the argument type
914 // is ELEMENT_TYPE_CLASS.
915 //------------------------------------------------------------------
916 BOOL IsClass(LPCUTF8 szClassName) const;
919 //------------------------------------------------------------------
920 // This method will return a TypeHandle for the last argument
922 // If NextArg() returns ELEMENT_TYPE_BYREF, you can also call GetByRefType()
923 // to get to the underlying type of the byref
924 //------------------------------------------------------------------
925 TypeHandle GetLastTypeHandleNT() const
928 return m_pLastType.GetTypeHandleNT(m_pModule, &m_typeContext);
931 //------------------------------------------------------------------
932 // This method will return a TypeHandle for the last argument
934 // If NextArg() returns ELEMENT_TYPE_BYREF, you can also call GetByRefType()
935 // to get to the underlying type of the byref
936 //------------------------------------------------------------------
937 TypeHandle GetLastTypeHandleThrowing(ClassLoader::LoadTypesFlag fLoadTypes = ClassLoader::LoadTypes,
938 ClassLoadLevel level = CLASS_LOADED,
939 BOOL dropGenericArgumentLevel = FALSE) const
942 return m_pLastType.GetTypeHandleThrowing(m_pModule, &m_typeContext, fLoadTypes,
943 level, dropGenericArgumentLevel);
946 //------------------------------------------------------------------
947 // Returns the TypeHandle for the return type of the signature
948 //------------------------------------------------------------------
949 TypeHandle GetRetTypeHandleNT() const
952 return m_pRetType.GetTypeHandleNT(m_pModule, &m_typeContext);
955 TypeHandle GetRetTypeHandleThrowing(ClassLoader::LoadTypesFlag fLoadTypes = ClassLoader::LoadTypes,
956 ClassLoadLevel level = CLASS_LOADED) const
959 return m_pRetType.GetTypeHandleThrowing(m_pModule, &m_typeContext, fLoadTypes, level);
962 //------------------------------------------------------------------
963 // Returns the base type of the byref type of the last argument examined
964 // which needs to have been ELEMENT_TYPE_BYREF.
965 // For object references, the class being accessed byref is also returned in *pTy.
966 // eg. for "int32 &", return value = ELEMENT_TYPE_I4, *pTy= ???
967 // for "System.Exception &", return value = ELEMENT_TYPE_CLASS, *pTy=System.Exception
968 // Note that byref to byref is not allowed, and so the return value
969 // can never be ELEMENT_TYPE_BYREF.
970 //------------------------------------------------------------------
971 CorElementType GetByRefType(TypeHandle* pTy) const;
973 // Compare types in two signatures, first applying
974 // - optional substitutions pSubst1 and pSubst2
975 // to class type parameters (E_T_VAR) in the respective signatures
979 PCCOR_SIGNATURE & pSig1,
980 PCCOR_SIGNATURE & pSig2,
981 PCCOR_SIGNATURE pEndSig1,
982 PCCOR_SIGNATURE pEndSig2,
985 const Substitution * pSubst1,
986 const Substitution * pSubst2,
987 TokenPairList * pVisited = NULL);
991 // If pTypeDef1 is C<...> and pTypeDef2 is C<...> (for possibly different instantiations)
992 // then check C<!0, ... !n> @ pSubst1 == C<!0, ..., !n> @ pSubst2, i.e.
993 // that the head type (C) is the same and that when the head type is treated
994 // as an uninstantiated type definition and we apply each of the substitutions
995 // then the same type results. This effectively checks that the two substitutions
997 static BOOL CompareTypeDefsUnderSubstitutions(MethodTable *pTypeDef1, MethodTable *pTypeDef2,
998 const Substitution* pSubst1, const Substitution* pSubst2,
999 TokenPairList *pVisited = NULL);
1002 // Compare two complete method signatures, first applying optional substitutions pSubst1 and pSubst2
1003 // to class type parameters (E_T_VAR) in the respective signatures
1004 static BOOL CompareMethodSigs(
1005 PCCOR_SIGNATURE pSig1,
1008 const Substitution* pSubst1,
1009 PCCOR_SIGNATURE pSig2,
1012 const Substitution* pSubst2,
1013 TokenPairList *pVisited = NULL
1016 // Nonthrowing version of CompareMethodSigs
1018 // Return S_OK if they match
1019 // S_FALSE if they don't match
1020 // FAILED if OOM or some other blocking error
1022 static HRESULT CompareMethodSigsNT(
1023 PCCOR_SIGNATURE pSig1,
1026 const Substitution* pSubst1,
1027 PCCOR_SIGNATURE pSig2,
1030 const Substitution* pSubst2,
1031 TokenPairList *pVisited = NULL
1034 static BOOL CompareFieldSigs(
1035 PCCOR_SIGNATURE pSig1,
1038 PCCOR_SIGNATURE pSig2,
1041 TokenPairList *pVisited = NULL
1044 static BOOL CompareMethodSigs(MetaSig &msig1,
1046 BOOL ignoreCallconv);
1048 // Is each set of constraints on the implementing method's type parameters a subset
1049 // of the corresponding set of constraints on the declared method's type parameters,
1050 // given a subsitution for the latter's (class) type parameters.
1051 // This is used by the class loader to verify type safety of method overriding and interface implementation.
1052 static BOOL CompareMethodConstraints(const Substitution *pSubst1,
1054 mdMethodDef tok1, //implementing method
1055 const Substitution *pSubst2,
1057 mdMethodDef tok2); //declared method
1060 static BOOL CompareVariableConstraints(const Substitution *pSubst1,
1061 Module *pModule1, mdGenericParam tok1, //overriding
1062 const Substitution *pSubst2,
1063 Module *pModule2, mdGenericParam tok2); //overridden
1065 static BOOL CompareTypeDefOrRefOrSpec(Module *pModule1, mdToken tok1,
1066 const Substitution *pSubst1,
1067 Module *pModule2, mdToken tok2,
1068 const Substitution *pSubst2,
1069 TokenPairList *pVisited);
1070 static BOOL CompareTypeSpecToToken(mdTypeSpec tk1,
1074 const Substitution *pSubst1,
1075 TokenPairList *pVisited);
1077 static BOOL CompareElementTypeToToken(PCCOR_SIGNATURE &pSig1,
1078 PCCOR_SIGNATURE pEndSig1, // end of sig1
1082 const Substitution* pSubst1,
1083 TokenPairList *pVisited);
1087 //------------------------------------------------------------------
1088 // Ensures that all the value types in the sig are loaded. This
1089 // should be called on sig's that have value types before they
1090 // are passed to Call(). This ensures that value classes will not
1091 // be loaded during the operation to determine the size of the
1092 // stack. Thus preventing the resulting GC hole.
1093 //------------------------------------------------------------------
1094 static void EnsureSigValueTypesLoaded(MethodDesc *pMD);
1096 // this walks the sig and checks to see if all types in the sig can be loaded
1097 static void CheckSigTypesCanBeLoaded(MethodDesc *pMD);
1099 const SigTypeContext *GetSigTypeContext() const { LIMITED_METHOD_CONTRACT; return &m_typeContext; }
1101 // Disallow copy constructor.
1102 MetaSig(MetaSig *pSig);
1104 void SetHasParamTypeArg()
1106 LIMITED_METHOD_CONTRACT;
1107 m_CallConv |= CORINFO_CALLCONV_PARAMTYPE;
1110 void SetTreatAsVarArg()
1112 LIMITED_METHOD_CONTRACT;
1113 m_flags |= TREAT_AS_VARARG;
1117 // These are protected because Reflection subclasses Metasig
1122 SIG_RET_TYPE_INITTED = 0x01,
1123 TREAT_AS_VARARG = 0x02, // used to treat some sigs as special case vararg
1124 // used by calli to unmanaged target
1128 SigTypeContext m_typeContext; // Instantiation for type parameters
1130 SigPointer m_pStart;
1132 SigPointer m_pLastType;
1133 SigPointer m_pRetType;
1137 // The following are cached so we don't the signature
1140 CorElementType m_corNormalizedRetType;
1146 BOOL IsTypeRefOrDef(LPCSTR szClassName, Module *pModule, mdToken token);
1148 #if defined(FEATURE_TYPEEQUIVALENCE) && !defined(DACCESS_COMPILE)
1150 // A helper struct representing data stored in the TypeIdentifierAttribute.
1151 struct TypeIdentifierData
1153 TypeIdentifierData() : m_cbScope(0), m_pchScope(NULL), m_cbIdentifierNamespace(0), m_pchIdentifierNamespace(NULL),
1154 m_cbIdentifierName(0), m_pchIdentifierName(NULL) {}
1156 HRESULT Init(Module *pModule, mdToken tk);
1157 BOOL IsEqual(const TypeIdentifierData & data) const;
1162 SIZE_T m_cbIdentifierNamespace;
1163 LPCUTF8 m_pchIdentifierNamespace;
1164 SIZE_T m_cbIdentifierName;
1165 LPCUTF8 m_pchIdentifierName;
1168 #endif // FEATURE_TYPEEQUIVALENCE && !DACCESS_COMPILE
1170 // fResolved is TRUE when one of the tokens is a resolved TypeRef. This is used to restrict
1171 // type equivalence checks for value types.
1172 BOOL CompareTypeTokens(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2, TokenPairList *pVisited = NULL);
1174 // Nonthrowing version of CompareTypeTokens.
1176 // Return S_OK if they match
1177 // S_FALSE if they don't match
1178 // FAILED if OOM or some other blocking error
1180 HRESULT CompareTypeTokensNT(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2);
1182 // TRUE if the two TypeDefs have the same layout and field marshal information.
1183 BOOL CompareTypeLayout(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2);
1184 BOOL CompareTypeDefsForEquivalence(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModule2, TokenPairList *pVisited);
1185 BOOL IsTypeDefEquivalent(mdToken tk, Module *pModule);
1186 BOOL IsTypeDefExternallyVisible(mdToken tk, Module *pModule, DWORD dwAttrs);
1188 void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc);
1190 #endif /* _H_SIGINFO */