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// sigparser.h
6//
7
8//
9
10#ifndef _H_SIGPARSER
11#define _H_SIGPARSER
12
13#include "utilcode.h"
14#include "corhdr.h"
15#include "corinfo.h"
16#include "corpriv.h"
17
18//---------------------------------------------------------------------------------------
19// These macros define how arguments are mapped to the stack in the managed calling convention.
20// We assume to be walking a method's signature left-to-right, in the virtual calling convention.
21// See MethodDesc::Call for details on this virtual calling convention.
22// These macros tell us whether the arguments we see as we proceed with the signature walk are mapped
23// to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack.
24//---------------------------------------------------------------------------------------
25#if defined(_TARGET_X86_)
26#define STACK_GROWS_DOWN_ON_ARGS_WALK
27#else
28#define STACK_GROWS_UP_ON_ARGS_WALK
29#endif
30
31
32//------------------------------------------------------------------------
33// Encapsulates how compressed integers and typeref tokens are encoded into
34// a bytestream.
35//
36// As you use this class please understand the implicit normalizations
37// on the CorElementType's returned by the various methods, especially
38// for variable types (e.g. !0 in generic signatures), string types
39// (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types
40// (e.g. List<int>) and enums.
41//------------------------------------------------------------------------
42class SigParser
43{
44 protected:
45 // This type is performance critical - do not add fields to it.
46 // (If you must, check for managed types that may use a SigParser or SigPointer inline, like ArgIterator.)
47 PCCOR_SIGNATURE m_ptr;
48 DWORD m_dwLen;
49
50 //------------------------------------------------------------------------
51 // Skips specified number of bytes WITHOUT VALIDATION. Only to be used
52 // when it is known that it won't overflow the signature buffer.
53 //------------------------------------------------------------------------
54 FORCEINLINE void SkipBytes(ULONG cb)
55 {
56 SUPPORTS_DAC;
57 _ASSERT(cb <= m_dwLen);
58 m_ptr += cb;
59 m_dwLen -= cb;
60 }
61
62 public:
63 //------------------------------------------------------------------------
64 // Constructor.
65 //------------------------------------------------------------------------
66 SigParser() {
67 LIMITED_METHOD_DAC_CONTRACT;
68 m_ptr = NULL;
69 m_dwLen = 0;
70 }
71
72 SigParser(const SigParser &sig);
73
74 //------------------------------------------------------------------------
75 // Initialize
76 //------------------------------------------------------------------------
77 FORCEINLINE SigParser(PCCOR_SIGNATURE ptr)
78 {
79 LIMITED_METHOD_CONTRACT;
80
81 m_ptr = ptr;
82 // We don't know the size of the signature, so we'll say it's "big enough"
83 m_dwLen = 0xffffffff;
84 }
85
86 FORCEINLINE SigParser(PCCOR_SIGNATURE ptr, DWORD len)
87 {
88 LIMITED_METHOD_CONTRACT;
89
90 m_ptr = ptr;
91 m_dwLen = len;
92 }
93
94 inline void SetSig(PCCOR_SIGNATURE ptr)
95 {
96 LIMITED_METHOD_CONTRACT;
97
98 m_ptr = ptr;
99 // We don't know the size of the signature, so we'll say it's "big enough"
100 m_dwLen = 0xffffffff;
101 }
102
103 inline void SetSig(PCCOR_SIGNATURE ptr, DWORD len)
104 {
105 LIMITED_METHOD_CONTRACT;
106
107 m_ptr = ptr;
108 m_dwLen = len;
109 }
110
111
112 inline BOOL IsNull() const
113 {
114 LIMITED_METHOD_CONTRACT;
115
116 return (m_ptr == NULL);
117 }
118
119 // Returns represented signature as pointer and size.
120 void
121 GetSignature(
122 PCCOR_SIGNATURE * pSig,
123 DWORD * pcbSigSize)
124 {
125 *pSig = m_ptr;
126 *pcbSigSize = m_dwLen;
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 // Remove one compressed integer (using CorSigUncompressData) from
143 // the head of the stream and return it.
144 //------------------------------------------------------------------------
145 __checkReturn
146 FORCEINLINE HRESULT GetData(ULONG* data)
147 {
148 WRAPPER_NO_CONTRACT;
149 SUPPORTS_DAC;
150
151 ULONG sizeOfData = 0;
152 ULONG tempData;
153
154 if (data == NULL)
155 data = &tempData;
156
157 HRESULT hr = CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData);
158
159 if (SUCCEEDED(hr))
160 {
161 SkipBytes(sizeOfData);
162 }
163
164 return hr;
165 }
166
167
168 //-------------------------------------------------------------------------
169 // Remove one byte and return it.
170 //-------------------------------------------------------------------------
171 __checkReturn
172 FORCEINLINE HRESULT GetByte(BYTE *data)
173 {
174 LIMITED_METHOD_CONTRACT;
175
176 if (m_dwLen > 0)
177 {
178 if (data != NULL)
179 *data = *m_ptr;
180
181 SkipBytes(1);
182
183 return S_OK;
184 }
185
186 if (data != NULL)
187 *data = 0;
188 return META_E_BAD_SIGNATURE;
189 }
190
191 //-------------------------------------------------------------------------
192 // Peek at value of one byte and return it.
193 //-------------------------------------------------------------------------
194 __checkReturn
195 FORCEINLINE HRESULT PeekByte(BYTE *data)
196 {
197 LIMITED_METHOD_CONTRACT;
198
199 if (m_dwLen > 0)
200 {
201 if (data != NULL)
202 *data = *m_ptr;
203
204 return S_OK;
205 }
206
207 if (data != NULL)
208 *data = 0;
209 return META_E_BAD_SIGNATURE;
210 }
211
212 //-------------------------------------------------------------------------
213 // The element type as defined in CorElementType. No normalization for
214 // generics (E_T_VAR, E_T_MVAR,..) or dynamic methods (E_T_INTERNAL occurs)
215 //-------------------------------------------------------------------------
216 __checkReturn
217 HRESULT GetElemTypeSlow(CorElementType * etype)
218 {
219 WRAPPER_NO_CONTRACT;
220 SUPPORTS_DAC;
221
222 CorElementType tmpEType;
223
224 if (etype == NULL)
225 etype = &tmpEType;
226
227 SigParser sigTemp(*this);
228
229 HRESULT hr = sigTemp.SkipCustomModifiers();
230
231 if (SUCCEEDED(hr))
232 {
233 BYTE bElemType = 0;
234 hr = sigTemp.GetByte(&bElemType);
235 *etype = (CorElementType)bElemType;
236
237 if (SUCCEEDED(hr))
238 {
239 *this = sigTemp;
240 return S_OK;
241 }
242 }
243
244 *etype = ELEMENT_TYPE_END;
245
246 return META_E_BAD_SIGNATURE;
247 }
248
249 // Inlined version
250 __checkReturn
251 FORCEINLINE HRESULT GetElemType(CorElementType * etype)
252 {
253 WRAPPER_NO_CONTRACT;
254 SUPPORTS_DAC;
255
256 if (m_dwLen > 0)
257 {
258 CorElementType typ = (CorElementType) * m_ptr;
259
260 if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte
261 {
262 if (etype != NULL)
263 {
264 * etype = typ;
265 }
266
267 SkipBytes(1);
268
269 return S_OK;
270 }
271 }
272
273 // Slower/normal path
274 return GetElemTypeSlow(etype);
275 }
276
277 // Note: Calling convention is always one byte, not four bytes
278 __checkReturn
279 HRESULT GetCallingConvInfo(ULONG * data)
280 {
281 WRAPPER_NO_CONTRACT;
282 SUPPORTS_DAC;
283
284 ULONG tmpData;
285
286 if (data == NULL)
287 data = &tmpData;
288
289 HRESULT hr = CorSigUncompressCallingConv(m_ptr, m_dwLen, data);
290 if (SUCCEEDED(hr))
291 {
292 SkipBytes(1);
293 }
294
295 return hr;
296 }
297
298 __checkReturn
299 HRESULT GetCallingConv(ULONG* data) // @REVISIT_TODO: Calling convention is one byte, not four.
300 {
301 WRAPPER_NO_CONTRACT;
302 ULONG info;
303 HRESULT hr = GetCallingConvInfo(&info);
304
305 if (SUCCEEDED(hr) && data != NULL)
306 {
307 *data = IMAGE_CEE_CS_CALLCONV_MASK & info;
308 }
309
310 return hr;
311 }
312
313 //------------------------------------------------------------------------
314 // Non-destructive read of compressed integer.
315 //------------------------------------------------------------------------
316 __checkReturn
317 HRESULT PeekData(ULONG *data) const
318 {
319 WRAPPER_NO_CONTRACT;
320 _ASSERTE(data != NULL);
321
322 ULONG sizeOfData = 0;
323 return CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData);
324 }
325
326
327 //------------------------------------------------------------------------
328 // Non-destructive read of element type.
329 //
330 // This routine makes it look as if the String type is encoded
331 // via ELEMENT_TYPE_CLASS followed by a token for the String class,
332 // rather than the ELEMENT_TYPE_STRING. This is partially to avoid
333 // rewriting client code which depended on this behavior previously.
334 // But it also seems like the right thing to do generally.
335 // No normalization for generics (E_T_VAR, E_T_MVAR,..) or
336 // dynamic methods (E_T_INTERNAL occurs)
337 //------------------------------------------------------------------------
338 __checkReturn
339 HRESULT PeekElemTypeSlow(CorElementType *etype) const
340 {
341 WRAPPER_NO_CONTRACT;
342 SUPPORTS_DAC;
343
344 _ASSERTE(etype != NULL);
345
346 SigParser sigTemp(*this);
347 HRESULT hr = sigTemp.GetElemType(etype);
348 if (SUCCEEDED(hr) && (*etype == ELEMENT_TYPE_STRING || *etype == ELEMENT_TYPE_OBJECT))
349 *etype = ELEMENT_TYPE_CLASS;
350
351 return hr;
352 }
353
354 // inline version
355 __checkReturn
356 FORCEINLINE HRESULT PeekElemType(CorElementType *etype) const
357 {
358 WRAPPER_NO_CONTRACT;
359 SUPPORTS_DAC;
360
361 _ASSERTE(etype != NULL);
362
363 if (m_dwLen > 0)
364 {
365 CorElementType typ = (CorElementType) * m_ptr;
366
367 if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte
368 {
369 if ((typ == ELEMENT_TYPE_STRING) || (typ == ELEMENT_TYPE_OBJECT))
370 {
371 *etype = ELEMENT_TYPE_CLASS;
372 }
373 else
374 {
375 *etype = typ;
376 }
377
378 return S_OK;
379 }
380 }
381
382 return PeekElemTypeSlow(etype);
383 }
384
385 //-------------------------------------------------------------------------
386 // Returns the raw size of the type next in the signature, or returns
387 // E_INVALIDARG for base types that have variables sizes.
388 //-------------------------------------------------------------------------
389 __checkReturn
390 HRESULT PeekElemTypeSize(ULONG *pSize)
391 {
392 WRAPPER_NO_CONTRACT;
393 HRESULT hr = S_OK;
394
395 DWORD dwSize = 0;
396
397 if (pSize == NULL)
398 {
399 pSize = &dwSize;
400 }
401
402 SigParser sigTemp(*this);
403
404 hr = sigTemp.SkipAnyVASentinel();
405
406 if (FAILED(hr))
407 {
408 return hr;
409 }
410
411 *pSize = 0;
412
413 BYTE bElementType = 0;
414 hr = sigTemp.GetByte(&bElementType);
415
416 if (FAILED(hr))
417 {
418 return hr;
419 }
420
421 switch (bElementType)
422 {
423 case ELEMENT_TYPE_I8:
424 case ELEMENT_TYPE_U8:
425 case ELEMENT_TYPE_R8:
426 #ifdef _WIN64
427 case ELEMENT_TYPE_I:
428 case ELEMENT_TYPE_U:
429 #endif // WIN64
430
431 *pSize = 8;
432 break;
433
434 case ELEMENT_TYPE_I4:
435 case ELEMENT_TYPE_U4:
436 case ELEMENT_TYPE_R4:
437 #ifndef _WIN64
438 case ELEMENT_TYPE_I:
439 case ELEMENT_TYPE_U:
440 #endif // _WIN64
441
442 *pSize = 4;
443 break;
444
445 case ELEMENT_TYPE_I2:
446 case ELEMENT_TYPE_U2:
447 case ELEMENT_TYPE_CHAR:
448 *pSize = 2;
449 break;
450
451 case ELEMENT_TYPE_I1:
452 case ELEMENT_TYPE_U1:
453 case ELEMENT_TYPE_BOOLEAN:
454 *pSize = 1;
455 break;
456
457 case ELEMENT_TYPE_STRING:
458 case ELEMENT_TYPE_PTR:
459 case ELEMENT_TYPE_BYREF:
460 case ELEMENT_TYPE_CLASS:
461 case ELEMENT_TYPE_OBJECT:
462 case ELEMENT_TYPE_FNPTR:
463 case ELEMENT_TYPE_TYPEDBYREF:
464 case ELEMENT_TYPE_ARRAY:
465 case ELEMENT_TYPE_SZARRAY:
466 *pSize = sizeof(void *);
467 break;
468
469 case ELEMENT_TYPE_VOID:
470 break;
471
472 case ELEMENT_TYPE_END:
473 case ELEMENT_TYPE_CMOD_REQD:
474 case ELEMENT_TYPE_CMOD_OPT:
475 _ASSERTE(!"Asked for the size of an element that doesn't have a size!");
476 return E_INVALIDARG;
477
478 case ELEMENT_TYPE_VALUETYPE:
479 _ASSERTE(!"Asked for the size of an element that doesn't have a size!");
480 return E_INVALIDARG;
481
482 default:
483
484 _ASSERTE( !"CorSigGetElementTypeSize given invalid signature to size!" );
485 return META_E_BAD_SIGNATURE;
486 }
487
488 return hr;
489 }
490
491 //------------------------------------------------------------------------
492 // Is this at the Sentinal (the ... in a varargs signature) that marks
493 // the begining of varguments that are not decared at the target
494
495 bool AtSentinel() const
496 {
497 if (m_dwLen > 0)
498 return *m_ptr == ELEMENT_TYPE_SENTINEL;
499 else
500 return false;
501 }
502
503 //------------------------------------------------------------------------
504 // Removes a compressed metadata token and returns it.
505 // WARNING: dynamic methods do not have tokens so this api is completely
506 // broken in that case. Make sure you call this function if
507 // you are absolutely sure E_T_INTERNAL was not in the sig
508 //------------------------------------------------------------------------
509 __checkReturn
510 FORCEINLINE
511 HRESULT GetToken(mdToken * token)
512 {
513 WRAPPER_NO_CONTRACT;
514 DWORD dwLen;
515 mdToken tempToken;
516
517 if (token == NULL)
518 token = &tempToken;
519
520 HRESULT hr = CorSigUncompressToken(m_ptr, m_dwLen, token, &dwLen);
521
522 if (SUCCEEDED(hr))
523 {
524 SkipBytes(dwLen);
525 }
526
527 return hr;
528 }
529
530 //------------------------------------------------------------------------
531 // Removes a pointer value and returns it. Used for ELEMENT_TYPE_INTERNAL.
532 __checkReturn
533 FORCEINLINE
534 HRESULT GetPointer(void ** pPtr)
535 {
536 WRAPPER_NO_CONTRACT;
537
538 if (m_dwLen < sizeof(void *))
539 { // Not enough data to read a pointer
540 if (pPtr != NULL)
541 {
542 *pPtr = NULL;
543 }
544 return META_E_BAD_SIGNATURE;
545 }
546 if (pPtr != NULL)
547 {
548 *pPtr = *(void * UNALIGNED *)m_ptr;
549 }
550 SkipBytes(sizeof(void *));
551
552 return S_OK;
553 }
554
555 //------------------------------------------------------------------------
556 // Tests if two SigParsers point to the same location in the stream.
557 //------------------------------------------------------------------------
558 FORCEINLINE BOOL Equals(SigParser sp) const
559 {
560 LIMITED_METHOD_CONTRACT;
561
562 return m_ptr == sp.m_ptr;
563 }
564
565 __checkReturn
566 HRESULT SkipCustomModifiers()
567 {
568 WRAPPER_NO_CONTRACT;
569 SUPPORTS_DAC;
570
571 HRESULT hr = S_OK;
572
573 SigParser sigTemp(*this);
574
575 hr = sigTemp.SkipAnyVASentinel();
576
577 if (FAILED(hr))
578 {
579 return hr;
580 }
581
582 BYTE bElementType = 0;
583
584 hr = sigTemp.PeekByte(&bElementType);
585 if (FAILED(hr))
586 return hr;
587
588 while ((ELEMENT_TYPE_CMOD_REQD == bElementType) ||
589 (ELEMENT_TYPE_CMOD_OPT == bElementType))
590 {
591 sigTemp.SkipBytes(1);
592
593 mdToken token;
594
595 hr = sigTemp.GetToken(&token);
596
597 if (FAILED(hr))
598 return hr;
599
600 hr = sigTemp.PeekByte(&bElementType);
601 if (FAILED(hr))
602 return hr;
603 }
604
605 // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types
606 // that we support while parsing various signatures
607 if (bElementType >= ELEMENT_TYPE_MAX)
608 {
609 switch (bElementType)
610 {
611 case ELEMENT_TYPE_VAR_ZAPSIG:
612 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
613 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
614 case ELEMENT_TYPE_CANON_ZAPSIG:
615 case ELEMENT_TYPE_MODULE_ZAPSIG:
616 case ELEMENT_TYPE_PINNED:
617 break;
618 default:
619 return META_E_BAD_SIGNATURE;
620 }
621 }
622
623 *this = sigTemp;
624 return hr;
625 }// SkipCustomModifiers
626
627 __checkReturn
628 HRESULT SkipFunkyAndCustomModifiers()
629 {
630 WRAPPER_NO_CONTRACT;
631 SUPPORTS_DAC;
632
633 SigParser sigTemp(*this);
634 HRESULT hr = S_OK;
635 hr = sigTemp.SkipAnyVASentinel();
636
637 if (FAILED(hr))
638 {
639 return hr;
640 }
641
642 BYTE bElementType = 0;
643
644 hr = sigTemp.PeekByte(&bElementType);
645 if (FAILED(hr))
646 return hr;
647
648 while (ELEMENT_TYPE_CMOD_REQD == bElementType ||
649 ELEMENT_TYPE_CMOD_OPT == bElementType ||
650 ELEMENT_TYPE_MODIFIER == bElementType ||
651 ELEMENT_TYPE_PINNED == bElementType)
652 {
653 sigTemp.SkipBytes(1);
654
655 mdToken token;
656
657 hr = sigTemp.GetToken(&token);
658
659 if (FAILED(hr))
660 return hr;
661
662 hr = sigTemp.PeekByte(&bElementType);
663 if (FAILED(hr))
664 return hr;
665 }
666
667 // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types
668 // that we support while parsing various signatures
669 if (bElementType >= ELEMENT_TYPE_MAX)
670 {
671 switch (bElementType)
672 {
673 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
674 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
675 case ELEMENT_TYPE_CANON_ZAPSIG:
676 case ELEMENT_TYPE_MODULE_ZAPSIG:
677 case ELEMENT_TYPE_PINNED:
678 break;
679 default:
680 return META_E_BAD_SIGNATURE;
681 }
682 }
683
684 *this = sigTemp;
685 return hr;
686 }// SkipFunkyAndCustomModifiers
687
688
689 __checkReturn
690 HRESULT SkipAnyVASentinel()
691 {
692 WRAPPER_NO_CONTRACT;
693
694 HRESULT hr = S_OK;
695 BYTE bElementType = 0;
696
697 hr = PeekByte(&bElementType);
698 if (FAILED(hr))
699 return hr;
700
701 if (bElementType == ELEMENT_TYPE_SENTINEL)
702 {
703 SkipBytes(1);
704 }
705
706 return hr;
707 }// SkipAnyVASentinel
708
709 //------------------------------------------------------------------------
710 // Assumes that the SigParser points to the start of an element type
711 // (i.e. function parameter, function return type or field type.)
712 // Advances the pointer to the first data after the element type.
713 //------------------------------------------------------------------------
714 __checkReturn
715 HRESULT SkipExactlyOne();
716
717 //------------------------------------------------------------------------
718 // Skip only the method header of the signature, not the signature of
719 // the arguments.
720 //------------------------------------------------------------------------
721 __checkReturn
722 HRESULT SkipMethodHeaderSignature(ULONG *pcArgs);
723
724 //------------------------------------------------------------------------
725 // Skip a sub signature (as immediately follows an ELEMENT_TYPE_FNPTR).
726 //------------------------------------------------------------------------
727 __checkReturn
728 HRESULT SkipSignature();
729
730public:
731
732 //------------------------------------------------------------------------
733 // Return pointer
734 // PLEASE DON'T USE THIS.
735 //
736 // Return the internal pointer. It's hard to resist, but please try
737 // not to use this. Certainly don't use it if there's any chance of the
738 // signature containing generic type variables.
739 //
740 // It's currently only used for working on the
741 // signatures stored in TypeSpec tokens (we should add a new abstraction,
742 // i.e. on MetaSig for this) and a couple of places to do with COM
743 // and native interop signature parsing.
744 // <REVISIT_TODO>We should try to get rid of these uses as well. </REVISIT_TODO>
745 //------------------------------------------------------------------------
746 PCCOR_SIGNATURE GetPtr() const
747 {
748 LIMITED_METHOD_DAC_CONTRACT;
749 return m_ptr;
750 }
751
752}; // class SigParser
753
754//------------------------------------------------------------------------
755FORCEINLINE
756SigParser::SigParser(
757 const SigParser &sig)
758 : m_ptr(sig.m_ptr), m_dwLen(sig.m_dwLen)
759{
760 LIMITED_METHOD_DAC_CONTRACT;
761}
762
763/*****************************************************************/
764/* CorTypeInfo is a single global table that you can hang information
765 about ELEMENT_TYPE_* */
766
767class CorTypeInfo
768{
769protected:
770 struct CorTypeInfoEntry
771 {
772 LPCUTF8 nameSpace;
773 LPCUTF8 className;
774 CorElementType type : 8;
775 unsigned size : 8;
776 CorInfoGCType gcType : 3;
777 unsigned isArray : 1;
778 unsigned isPrim : 1;
779 unsigned isFloat : 1;
780 unsigned isModifier : 1;
781 unsigned isGenVar : 1;
782 // 1 more byte here to use for 32-bit
783 };
784
785protected:
786 FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo(CorElementType type)
787 {
788 CONTRACTL
789 {
790 THROWS;
791 GC_NOTRIGGER;
792 SUPPORTS_DAC;
793#ifdef MODE_ANY
794 MODE_ANY;
795#endif
796 }
797 CONTRACTL_END;
798
799 if (type >= (CorElementType)_countof(info))
800 {
801 ThrowHR(COR_E_BADIMAGEFORMAT);
802 }
803 return info[type];
804 }
805 FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo_NoThrow(CorElementType type)
806 {
807 LIMITED_METHOD_DAC_CONTRACT;
808
809 if (type >= (CorElementType)_countof(info))
810 {
811 return info[ELEMENT_TYPE_END];
812 }
813 return info[type];
814 }
815
816public:
817
818 FORCEINLINE static LPCUTF8 GetName(CorElementType type)
819 {
820 WRAPPER_NO_CONTRACT;
821
822 return GetTypeInfo(type).className;
823 }
824
825 FORCEINLINE static LPCUTF8 GetNamespace(CorElementType type)
826 {
827 WRAPPER_NO_CONTRACT;
828
829 return GetTypeInfo(type).nameSpace;
830 }
831
832 static void CheckConsistency()
833 {
834 LIMITED_METHOD_CONTRACT;
835
836 for (int i = 0; i < (int)_countof(info); i++)
837 {
838 _ASSERTE(info[i].type == i);
839 }
840 }
841
842 FORCEINLINE static CorInfoGCType GetGCType(CorElementType type)
843 {
844 WRAPPER_NO_CONTRACT;
845
846 return GetTypeInfo(type).gcType;
847 }
848 FORCEINLINE static CorInfoGCType GetGCType_NoThrow(CorElementType type)
849 {
850 LIMITED_METHOD_DAC_CONTRACT;
851
852 return GetTypeInfo_NoThrow(type).gcType;
853 }
854
855 static BOOL IsObjRef(CorElementType type)
856 {
857 WRAPPER_NO_CONTRACT;
858 SUPPORTS_DAC;
859
860 return (GetGCType(type) == TYPE_GC_REF);
861 }
862 static BOOL IsObjRef_NoThrow(CorElementType type)
863 {
864 WRAPPER_NO_CONTRACT;
865 SUPPORTS_DAC;
866
867 return (GetGCType_NoThrow(type) == TYPE_GC_REF);
868 }
869
870 FORCEINLINE static BOOL IsGenericVariable(CorElementType type)
871 {
872 WRAPPER_NO_CONTRACT;
873
874 return GetTypeInfo(type).isGenVar;
875 }
876 FORCEINLINE static BOOL IsGenericVariable_NoThrow(CorElementType type)
877 {
878 WRAPPER_NO_CONTRACT;
879
880 return GetTypeInfo_NoThrow(type).isGenVar;
881 }
882
883 FORCEINLINE static BOOL IsArray(CorElementType type)
884 {
885 WRAPPER_NO_CONTRACT;
886
887 return GetTypeInfo(type).isArray;
888 }
889 FORCEINLINE static BOOL IsArray_NoThrow(CorElementType type)
890 {
891 WRAPPER_NO_CONTRACT;
892
893 return GetTypeInfo_NoThrow(type).isArray;
894 }
895
896 FORCEINLINE static BOOL IsFloat(CorElementType type)
897 {
898 WRAPPER_NO_CONTRACT;
899
900 return GetTypeInfo(type).isFloat;
901 }
902 FORCEINLINE static BOOL IsFloat_NoThrow(CorElementType type)
903 {
904 WRAPPER_NO_CONTRACT;
905
906 return GetTypeInfo_NoThrow(type).isFloat;
907 }
908
909 FORCEINLINE static BOOL IsModifier(CorElementType type)
910 {
911 WRAPPER_NO_CONTRACT;
912
913 return GetTypeInfo(type).isModifier;
914 }
915 FORCEINLINE static BOOL IsModifier_NoThrow(CorElementType type)
916 {
917 WRAPPER_NO_CONTRACT;
918
919 return GetTypeInfo_NoThrow(type).isModifier;
920 }
921
922 FORCEINLINE static BOOL IsPrimitiveType(CorElementType type)
923 {
924 WRAPPER_NO_CONTRACT;
925
926 return GetTypeInfo(type).isPrim;
927 }
928 FORCEINLINE static BOOL IsPrimitiveType_NoThrow(CorElementType type)
929 {
930 WRAPPER_NO_CONTRACT;
931
932 return GetTypeInfo_NoThrow(type).isPrim;
933 }
934
935 FORCEINLINE static unsigned Size(CorElementType type)
936 {
937 WRAPPER_NO_CONTRACT;
938
939 return GetTypeInfo(type).size;
940 }
941 FORCEINLINE static unsigned Size_NoThrow(CorElementType type)
942 {
943 WRAPPER_NO_CONTRACT;
944
945 return GetTypeInfo_NoThrow(type).size;
946 }
947
948 static CorElementType FindPrimitiveType(LPCUTF8 name);
949
950protected:
951 static const CorTypeInfoEntry info[ELEMENT_TYPE_MAX];
952
953}; // class CorTypeInfo
954
955
956// Returns the address of the payload inside the stackelem
957inline void* StackElemEndianessFixup(void* pStackElem, UINT cbSize) {
958 LIMITED_METHOD_CONTRACT;
959
960 BYTE *pRetVal = (BYTE*)pStackElem;
961
962#if BIGENDIAN
963 switch (cbSize)
964 {
965 case 1:
966 pRetVal += sizeof(void*)-1;
967 break;
968 case 2:
969 pRetVal += sizeof(void*)-2;
970 break;
971#ifdef _WIN64
972 case 4:
973 pRetVal += sizeof(void*)-4;
974 break;
975#endif
976 default:
977 // nothing to do
978 break;
979 }
980#endif
981
982 return pRetVal;
983}
984
985#endif /* _H_SIGINFOBASE */
986