diff options
Diffstat (limited to 'src/inc/sigparser.h')
-rw-r--r-- | src/inc/sigparser.h | 985 |
1 files changed, 985 insertions, 0 deletions
diff --git a/src/inc/sigparser.h b/src/inc/sigparser.h new file mode 100644 index 0000000000..2c8cf8b165 --- /dev/null +++ b/src/inc/sigparser.h @@ -0,0 +1,985 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// sigparser.h +// + +// + +#ifndef _H_SIGPARSER +#define _H_SIGPARSER + +#include "utilcode.h" +#include "corhdr.h" +#include "corinfo.h" +#include "corpriv.h" + +//--------------------------------------------------------------------------------------- +// These macros define how arguments are mapped to the stack in the managed calling convention. +// We assume to be walking a method's signature left-to-right, in the virtual calling convention. +// See MethodDesc::Call for details on this virtual calling convention. +// These macros tell us whether the arguments we see as we proceed with the signature walk are mapped +// to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack. +//--------------------------------------------------------------------------------------- +#if defined(_TARGET_X86_) +#define STACK_GROWS_DOWN_ON_ARGS_WALK +#else +#define STACK_GROWS_UP_ON_ARGS_WALK +#endif + + +//------------------------------------------------------------------------ +// Encapsulates how compressed integers and typeref tokens are encoded into +// a bytestream. +// +// As you use this class please understand the implicit normalizations +// on the CorElementType's returned by the various methods, especially +// for variable types (e.g. !0 in generic signatures), string types +// (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types +// (e.g. List<int>) and enums. +//------------------------------------------------------------------------ +class SigParser +{ + protected: + // This type is performance critical - do not add fields to it. + // (If you must, check for managed types that may use a SigParser or SigPointer inline, like ArgIterator.) + PCCOR_SIGNATURE m_ptr; + DWORD m_dwLen; + + //------------------------------------------------------------------------ + // Skips specified number of bytes WITHOUT VALIDATION. Only to be used + // when it is known that it won't overflow the signature buffer. + //------------------------------------------------------------------------ + FORCEINLINE void SkipBytes(ULONG cb) + { + SUPPORTS_DAC; + _ASSERT(cb <= m_dwLen); + m_ptr += cb; + m_dwLen -= cb; + } + + public: + //------------------------------------------------------------------------ + // Constructor. + //------------------------------------------------------------------------ + SigParser() { + LIMITED_METHOD_DAC_CONTRACT; + m_ptr = NULL; + m_dwLen = 0; + } + + SigParser(const SigParser &sig); + + //------------------------------------------------------------------------ + // Initialize + //------------------------------------------------------------------------ + FORCEINLINE SigParser(PCCOR_SIGNATURE ptr) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + // We don't know the size of the signature, so we'll say it's "big enough" + m_dwLen = 0xffffffff; + } + + FORCEINLINE SigParser(PCCOR_SIGNATURE ptr, DWORD len) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + m_dwLen = len; + } + + inline void SetSig(PCCOR_SIGNATURE ptr) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + // We don't know the size of the signature, so we'll say it's "big enough" + m_dwLen = 0xffffffff; + } + + inline void SetSig(PCCOR_SIGNATURE ptr, DWORD len) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + m_dwLen = len; + } + + + inline BOOL IsNull() const + { + LIMITED_METHOD_CONTRACT; + + return (m_ptr == NULL); + } + + // Returns represented signature as pointer and size. + void + GetSignature( + PCCOR_SIGNATURE * pSig, + DWORD * pcbSigSize) + { + *pSig = m_ptr; + *pcbSigSize = m_dwLen; + } + + + //========================================================================= + // The RAW interface for reading signatures. You see exactly the signature, + // apart from custom modifiers which for historical reasons tend to get eaten. + // + // DO NOT USE THESE METHODS UNLESS YOU'RE TOTALLY SURE YOU WANT + // THE RAW signature. You nearly always want GetElemTypeClosed() or + // PeekElemTypeClosed() or one of the MetaSig functions. See the notes above. + // These functions will return E_T_INTERNAL, E_T_VAR, E_T_MVAR and such + // so the caller must be able to deal with those + //========================================================================= + + //------------------------------------------------------------------------ + // Remove one compressed integer (using CorSigUncompressData) from + // the head of the stream and return it. + //------------------------------------------------------------------------ + __checkReturn + FORCEINLINE HRESULT GetData(ULONG* data) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + ULONG sizeOfData = 0; + ULONG tempData; + + if (data == NULL) + data = &tempData; + + HRESULT hr = CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); + + if (SUCCEEDED(hr)) + { + SkipBytes(sizeOfData); + } + + return hr; + } + + + //------------------------------------------------------------------------- + // Remove one byte and return it. + //------------------------------------------------------------------------- + __checkReturn + FORCEINLINE HRESULT GetByte(BYTE *data) + { + LIMITED_METHOD_CONTRACT; + + if (m_dwLen > 0) + { + if (data != NULL) + *data = *m_ptr; + + SkipBytes(1); + + return S_OK; + } + + if (data != NULL) + *data = 0; + return META_E_BAD_SIGNATURE; + } + + //------------------------------------------------------------------------- + // Peek at value of one byte and return it. + //------------------------------------------------------------------------- + __checkReturn + FORCEINLINE HRESULT PeekByte(BYTE *data) + { + LIMITED_METHOD_CONTRACT; + + if (m_dwLen > 0) + { + if (data != NULL) + *data = *m_ptr; + + return S_OK; + } + + if (data != NULL) + *data = 0; + return META_E_BAD_SIGNATURE; + } + + //------------------------------------------------------------------------- + // The element type as defined in CorElementType. No normalization for + // generics (E_T_VAR, E_T_MVAR,..) or dynamic methods (E_T_INTERNAL occurs) + //------------------------------------------------------------------------- + __checkReturn + HRESULT GetElemTypeSlow(CorElementType * etype) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + CorElementType tmpEType; + + if (etype == NULL) + etype = &tmpEType; + + SigParser sigTemp(*this); + + HRESULT hr = sigTemp.SkipCustomModifiers(); + + if (SUCCEEDED(hr)) + { + BYTE bElemType = 0; + hr = sigTemp.GetByte(&bElemType); + *etype = (CorElementType)bElemType; + + if (SUCCEEDED(hr)) + { + *this = sigTemp; + return S_OK; + } + } + + *etype = ELEMENT_TYPE_END; + + return META_E_BAD_SIGNATURE; + } + + // Inlined version + __checkReturn + FORCEINLINE HRESULT GetElemType(CorElementType * etype) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (m_dwLen > 0) + { + CorElementType typ = (CorElementType) * m_ptr; + + if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte + { + if (etype != NULL) + { + * etype = typ; + } + + SkipBytes(1); + + return S_OK; + } + } + + // Slower/normal path + return GetElemTypeSlow(etype); + } + + // Note: Calling convention is always one byte, not four bytes + __checkReturn + HRESULT GetCallingConvInfo(ULONG * data) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + ULONG tmpData; + + if (data == NULL) + data = &tmpData; + + HRESULT hr = CorSigUncompressCallingConv(m_ptr, m_dwLen, data); + if (SUCCEEDED(hr)) + { + SkipBytes(1); + } + + return hr; + } + + __checkReturn + HRESULT GetCallingConv(ULONG* data) // @REVISIT_TODO: Calling convention is one byte, not four. + { + WRAPPER_NO_CONTRACT; + ULONG info; + HRESULT hr = GetCallingConvInfo(&info); + + if (SUCCEEDED(hr) && data != NULL) + { + *data = IMAGE_CEE_CS_CALLCONV_MASK & info; + } + + return hr; + } + + //------------------------------------------------------------------------ + // Non-destructive read of compressed integer. + //------------------------------------------------------------------------ + __checkReturn + HRESULT PeekData(ULONG *data) const + { + WRAPPER_NO_CONTRACT; + _ASSERTE(data != NULL); + + ULONG sizeOfData = 0; + return CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); + } + + + //------------------------------------------------------------------------ + // Non-destructive read of element type. + // + // This routine makes it look as if the String type is encoded + // via ELEMENT_TYPE_CLASS followed by a token for the String class, + // rather than the ELEMENT_TYPE_STRING. This is partially to avoid + // rewriting client code which depended on this behavior previously. + // But it also seems like the right thing to do generally. + // No normalization for generics (E_T_VAR, E_T_MVAR,..) or + // dynamic methods (E_T_INTERNAL occurs) + //------------------------------------------------------------------------ + __checkReturn + HRESULT PeekElemTypeSlow(CorElementType *etype) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(etype != NULL); + + SigParser sigTemp(*this); + HRESULT hr = sigTemp.GetElemType(etype); + if (SUCCEEDED(hr) && (*etype == ELEMENT_TYPE_STRING || *etype == ELEMENT_TYPE_OBJECT)) + *etype = ELEMENT_TYPE_CLASS; + + return hr; + } + + // inline version + __checkReturn + FORCEINLINE HRESULT PeekElemType(CorElementType *etype) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(etype != NULL); + + if (m_dwLen > 0) + { + CorElementType typ = (CorElementType) * m_ptr; + + if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte + { + if ((typ == ELEMENT_TYPE_STRING) || (typ == ELEMENT_TYPE_OBJECT)) + { + *etype = ELEMENT_TYPE_CLASS; + } + else + { + *etype = typ; + } + + return S_OK; + } + } + + return PeekElemTypeSlow(etype); + } + + //------------------------------------------------------------------------- + // Returns the raw size of the type next in the signature, or returns + // E_INVALIDARG for base types that have variables sizes. + //------------------------------------------------------------------------- + __checkReturn + HRESULT PeekElemTypeSize(ULONG *pSize) + { + WRAPPER_NO_CONTRACT; + HRESULT hr = S_OK; + + DWORD dwSize = 0; + + if (pSize == NULL) + { + pSize = &dwSize; + } + + SigParser sigTemp(*this); + + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + *pSize = 0; + + BYTE bElementType = 0; + hr = sigTemp.GetByte(&bElementType); + + if (FAILED(hr)) + { + return hr; + } + + switch (bElementType) + { + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R8: + #ifdef _WIN64 + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + #endif // WIN64 + + *pSize = 8; + break; + + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_R4: + #ifndef _WIN64 + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + #endif // _WIN64 + + *pSize = 4; + break; + + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_CHAR: + *pSize = 2; + break; + + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_BOOLEAN: + *pSize = 1; + break; + + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_BYREF: + case ELEMENT_TYPE_CLASS: + case ELEMENT_TYPE_OBJECT: + case ELEMENT_TYPE_FNPTR: + case ELEMENT_TYPE_TYPEDBYREF: + case ELEMENT_TYPE_ARRAY: + case ELEMENT_TYPE_SZARRAY: + *pSize = sizeof(void *); + break; + + case ELEMENT_TYPE_VOID: + break; + + case ELEMENT_TYPE_END: + case ELEMENT_TYPE_CMOD_REQD: + case ELEMENT_TYPE_CMOD_OPT: + _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); + return E_INVALIDARG; + + case ELEMENT_TYPE_VALUETYPE: + _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); + return E_INVALIDARG; + + default: + + _ASSERTE( !"CorSigGetElementTypeSize given invalid signature to size!" ); + return META_E_BAD_SIGNATURE; + } + + return hr; + } + + //------------------------------------------------------------------------ + // Is this at the Sentinal (the ... in a varargs signature) that marks + // the begining of varguments that are not decared at the target + + bool AtSentinel() const + { + if (m_dwLen > 0) + return *m_ptr == ELEMENT_TYPE_SENTINEL; + else + return false; + } + + //------------------------------------------------------------------------ + // Removes a compressed metadata token and returns it. + // WARNING: dynamic methods do not have tokens so this api is completely + // broken in that case. Make sure you call this function if + // you are absolutely sure E_T_INTERNAL was not in the sig + //------------------------------------------------------------------------ + __checkReturn + FORCEINLINE + HRESULT GetToken(mdToken * token) + { + WRAPPER_NO_CONTRACT; + DWORD dwLen; + mdToken tempToken; + + if (token == NULL) + token = &tempToken; + + HRESULT hr = CorSigUncompressToken(m_ptr, m_dwLen, token, &dwLen); + + if (SUCCEEDED(hr)) + { + SkipBytes(dwLen); + } + + return hr; + } + + //------------------------------------------------------------------------ + // Removes a pointer value and returns it. Used for ELEMENT_TYPE_INTERNAL. + __checkReturn + FORCEINLINE + HRESULT GetPointer(void ** pPtr) + { + WRAPPER_NO_CONTRACT; + + if (m_dwLen < sizeof(void *)) + { // Not enough data to read a pointer + if (pPtr != NULL) + { + *pPtr = NULL; + } + return META_E_BAD_SIGNATURE; + } + if (pPtr != NULL) + { + *pPtr = *(void * UNALIGNED *)m_ptr; + } + SkipBytes(sizeof(void *)); + + return S_OK; + } + + //------------------------------------------------------------------------ + // Tests if two SigParsers point to the same location in the stream. + //------------------------------------------------------------------------ + FORCEINLINE BOOL Equals(SigParser sp) const + { + LIMITED_METHOD_CONTRACT; + + return m_ptr == sp.m_ptr; + } + + __checkReturn + HRESULT SkipCustomModifiers() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + HRESULT hr = S_OK; + + SigParser sigTemp(*this); + + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + BYTE bElementType = 0; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + while ((ELEMENT_TYPE_CMOD_REQD == bElementType) || + (ELEMENT_TYPE_CMOD_OPT == bElementType)) + { + sigTemp.SkipBytes(1); + + mdToken token; + + hr = sigTemp.GetToken(&token); + + if (FAILED(hr)) + return hr; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + } + + // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types + // that we support while parsing various signatures + if (bElementType >= ELEMENT_TYPE_MAX) + { + switch (bElementType) + { + case ELEMENT_TYPE_VAR_ZAPSIG: + case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: + case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: + case ELEMENT_TYPE_CANON_ZAPSIG: + case ELEMENT_TYPE_MODULE_ZAPSIG: + case ELEMENT_TYPE_PINNED: + break; + default: + return META_E_BAD_SIGNATURE; + } + } + + *this = sigTemp; + return hr; + }// SkipCustomModifiers + + __checkReturn + HRESULT SkipFunkyAndCustomModifiers() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + SigParser sigTemp(*this); + HRESULT hr = S_OK; + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + BYTE bElementType = 0; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + while (ELEMENT_TYPE_CMOD_REQD == bElementType || + ELEMENT_TYPE_CMOD_OPT == bElementType || + ELEMENT_TYPE_MODIFIER == bElementType || + ELEMENT_TYPE_PINNED == bElementType) + { + sigTemp.SkipBytes(1); + + mdToken token; + + hr = sigTemp.GetToken(&token); + + if (FAILED(hr)) + return hr; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + } + + // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types + // that we support while parsing various signatures + if (bElementType >= ELEMENT_TYPE_MAX) + { + switch (bElementType) + { + case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: + case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: + case ELEMENT_TYPE_CANON_ZAPSIG: + case ELEMENT_TYPE_MODULE_ZAPSIG: + case ELEMENT_TYPE_PINNED: + break; + default: + return META_E_BAD_SIGNATURE; + } + } + + *this = sigTemp; + return hr; + }// SkipFunkyAndCustomModifiers + + + __checkReturn + HRESULT SkipAnyVASentinel() + { + WRAPPER_NO_CONTRACT; + + HRESULT hr = S_OK; + BYTE bElementType = 0; + + hr = PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + if (bElementType == ELEMENT_TYPE_SENTINEL) + { + SkipBytes(1); + } + + return hr; + }// SkipAnyVASentinel + + //------------------------------------------------------------------------ + // Assumes that the SigParser points to the start of an element type + // (i.e. function parameter, function return type or field type.) + // Advances the pointer to the first data after the element type. + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipExactlyOne(); + + //------------------------------------------------------------------------ + // Skip only the method header of the signature, not the signature of + // the arguments. + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipMethodHeaderSignature(ULONG *pcArgs); + + //------------------------------------------------------------------------ + // Skip a sub signature (as immediately follows an ELEMENT_TYPE_FNPTR). + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipSignature(); + +public: + + //------------------------------------------------------------------------ + // Return pointer + // PLEASE DON'T USE THIS. + // + // Return the internal pointer. It's hard to resist, but please try + // not to use this. Certainly don't use it if there's any chance of the + // signature containing generic type variables. + // + // It's currently only used for working on the + // signatures stored in TypeSpec tokens (we should add a new abstraction, + // i.e. on MetaSig for this) and a couple of places to do with COM + // and native interop signature parsing. + // <REVISIT_TODO>We should try to get rid of these uses as well. </REVISIT_TODO> + //------------------------------------------------------------------------ + PCCOR_SIGNATURE GetPtr() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_ptr; + } + +}; // class SigParser + +//------------------------------------------------------------------------ +FORCEINLINE +SigParser::SigParser( + const SigParser &sig) + : m_ptr(sig.m_ptr), m_dwLen(sig.m_dwLen) +{ + LIMITED_METHOD_DAC_CONTRACT; +} + +/*****************************************************************/ +/* CorTypeInfo is a single global table that you can hang information + about ELEMENT_TYPE_* */ + +class CorTypeInfo +{ +protected: + struct CorTypeInfoEntry + { + LPCUTF8 nameSpace; + LPCUTF8 className; + CorElementType type : 8; + unsigned size : 8; + CorInfoGCType gcType : 3; + unsigned isArray : 1; + unsigned isPrim : 1; + unsigned isFloat : 1; + unsigned isModifier : 1; + unsigned isGenVar : 1; + // 1 more byte here to use for 32-bit + }; + +protected: + FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo(CorElementType type) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; +#ifdef MODE_ANY + MODE_ANY; +#endif + } + CONTRACTL_END; + + if (type >= (CorElementType)_countof(info)) + { + ThrowHR(COR_E_BADIMAGEFORMAT); + } + return info[type]; + } + FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo_NoThrow(CorElementType type) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (type >= (CorElementType)_countof(info)) + { + return info[ELEMENT_TYPE_END]; + } + return info[type]; + } + +public: + + FORCEINLINE static LPCUTF8 GetName(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).className; + } + + FORCEINLINE static LPCUTF8 GetNamespace(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).nameSpace; + } + + static void CheckConsistency() + { + LIMITED_METHOD_CONTRACT; + + for (int i = 0; i < (int)_countof(info); i++) + { + _ASSERTE(info[i].type == i); + } + } + + FORCEINLINE static CorInfoGCType GetGCType(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).gcType; + } + FORCEINLINE static CorInfoGCType GetGCType_NoThrow(CorElementType type) + { + LIMITED_METHOD_DAC_CONTRACT; + + return GetTypeInfo_NoThrow(type).gcType; + } + + static BOOL IsObjRef(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType(type) == TYPE_GC_REF); + } + static BOOL IsObjRef_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType_NoThrow(type) == TYPE_GC_REF); + } + + FORCEINLINE static BOOL IsGenericVariable(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isGenVar; + } + FORCEINLINE static BOOL IsGenericVariable_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isGenVar; + } + + FORCEINLINE static BOOL IsArray(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isArray; + } + FORCEINLINE static BOOL IsArray_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isArray; + } + + FORCEINLINE static BOOL IsFloat(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isFloat; + } + FORCEINLINE static BOOL IsFloat_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isFloat; + } + + FORCEINLINE static BOOL IsModifier(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isModifier; + } + FORCEINLINE static BOOL IsModifier_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isModifier; + } + + FORCEINLINE static BOOL IsPrimitiveType(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isPrim; + } + FORCEINLINE static BOOL IsPrimitiveType_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isPrim; + } + + FORCEINLINE static unsigned Size(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).size; + } + FORCEINLINE static unsigned Size_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).size; + } + + static CorElementType FindPrimitiveType(LPCUTF8 name); + +protected: + static const CorTypeInfoEntry info[ELEMENT_TYPE_MAX]; + +}; // class CorTypeInfo + + +// Returns the address of the payload inside the stackelem +inline void* StackElemEndianessFixup(void* pStackElem, UINT cbSize) { + LIMITED_METHOD_CONTRACT; + + BYTE *pRetVal = (BYTE*)pStackElem; + +#if BIGENDIAN + switch (cbSize) + { + case 1: + pRetVal += sizeof(void*)-1; + break; + case 2: + pRetVal += sizeof(void*)-2; + break; +#ifdef _WIN64 + case 4: + pRetVal += sizeof(void*)-4; + break; +#endif + default: + // nothing to do + break; + } +#endif + + return pRetVal; +} + +#endif /* _H_SIGINFOBASE */ |