summaryrefslogtreecommitdiff
path: root/src/inc/sigparser.h
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/inc/sigparser.h
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/inc/sigparser.h')
-rw-r--r--src/inc/sigparser.h985
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 */