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 | // File: typedesc.h |
6 | // |
7 | |
8 | |
9 | // |
10 | |
11 | // |
12 | // ============================================================================ |
13 | |
14 | |
15 | #ifndef TYPEDESC_H |
16 | #define TYPEDESC_H |
17 | #include <specstrings.h> |
18 | |
19 | class TypeHandleList; |
20 | |
21 | /*************************************************************************/ |
22 | /* TypeDesc is a discriminated union of all types that can not be directly |
23 | represented by a simple MethodTable*. The discrimintor of the union at the present |
24 | time is the CorElementType numeration. The subclass of TypeDesc are |
25 | the possible variants of the union. |
26 | |
27 | |
28 | ParamTypeDescs only include byref, array and pointer types. They do NOT |
29 | include instantaitions of generic types, which are represented by MethodTables. |
30 | */ |
31 | |
32 | |
33 | typedef DPTR(class TypeDesc) PTR_TypeDesc; |
34 | |
35 | class TypeDesc |
36 | { |
37 | public: |
38 | #ifdef DACCESS_COMPILE |
39 | friend class NativeImageDumper; |
40 | #endif |
41 | #ifndef DACCESS_COMPILE |
42 | TypeDesc(CorElementType type) { |
43 | LIMITED_METHOD_CONTRACT; |
44 | |
45 | m_typeAndFlags = type; |
46 | } |
47 | #endif |
48 | |
49 | // This is the ELEMENT_TYPE* that would be used in the type sig for this type |
50 | // For enums this is the uderlying type |
51 | inline CorElementType GetInternalCorElementType() { |
52 | LIMITED_METHOD_DAC_CONTRACT; |
53 | |
54 | return (CorElementType) (m_typeAndFlags & 0xff); |
55 | } |
56 | |
57 | // Get the exact parent (superclass) of this type |
58 | TypeHandle GetParent(); |
59 | |
60 | // Returns the name of the array. Note that it returns |
61 | // the length of the returned string |
62 | static void ConstructName(CorElementType kind, |
63 | TypeHandle param, |
64 | int rank, |
65 | SString &ssBuff); |
66 | |
67 | void GetName(SString &ssBuf); |
68 | |
69 | //------------------------------------------------------------------- |
70 | // CASTING |
71 | // |
72 | // There are two variants of the "CanCastTo" method: |
73 | // |
74 | // CanCastTo |
75 | // - restore encoded pointers on demand |
76 | // - might throw, might trigger GC |
77 | // - return type is boolean (FALSE = cannot cast, TRUE = can cast) |
78 | // |
79 | // CanCastToNoGC |
80 | // - do not restore encoded pointers on demand |
81 | // - does not throw, does not trigger GC |
82 | // - return type is three-valued (CanCast, CannotCast, MaybeCast) |
83 | // - MaybeCast indicates that the test tripped on an encoded pointer |
84 | // so the caller should now call CanCastTo if it cares |
85 | // |
86 | |
87 | BOOL CanCastTo(TypeHandle type, TypeHandlePairList *pVisited); |
88 | TypeHandle::CastResult CanCastToNoGC(TypeHandle type); |
89 | |
90 | static BOOL CanCastParam(TypeHandle fromParam, TypeHandle toParam, TypeHandlePairList *pVisited); |
91 | static TypeHandle::CastResult CanCastParamNoGC(TypeHandle fromParam, TypeHandle toParam); |
92 | |
93 | #ifndef DACCESS_COMPILE |
94 | BOOL IsEquivalentTo(TypeHandle type COMMA_INDEBUG(TypeHandlePairList *pVisited)); |
95 | #endif |
96 | |
97 | // BYREF |
98 | BOOL IsByRef() { // BYREFS are often treated specially |
99 | WRAPPER_NO_CONTRACT; |
100 | |
101 | return(GetInternalCorElementType() == ELEMENT_TYPE_BYREF); |
102 | } |
103 | |
104 | // PTR |
105 | BOOL IsPointer() { |
106 | WRAPPER_NO_CONTRACT; |
107 | |
108 | return(GetInternalCorElementType() == ELEMENT_TYPE_PTR); |
109 | } |
110 | |
111 | // ARRAY, SZARRAY |
112 | BOOL IsArray(); |
113 | |
114 | // VAR, MVAR |
115 | BOOL IsGenericVariable(); |
116 | |
117 | // ELEMENT_TYPE_FNPTR |
118 | BOOL IsFnPtr(); |
119 | |
120 | // VALUETYPE |
121 | BOOL IsNativeValueType(); |
122 | |
123 | // Is actually ParamTypeDesc (ARRAY, SZARRAY, BYREF, PTR) |
124 | BOOL HasTypeParam(); |
125 | |
126 | #ifdef FEATURE_PREJIT |
127 | void Save(DataImage *image); |
128 | void Fixup(DataImage *image); |
129 | |
130 | BOOL NeedsRestore(DataImage *image) |
131 | { |
132 | WRAPPER_NO_CONTRACT; |
133 | return ComputeNeedsRestore(image, NULL); |
134 | } |
135 | |
136 | BOOL ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisited); |
137 | #endif |
138 | |
139 | void DoRestoreTypeKey(); |
140 | void Restore(); |
141 | BOOL IsRestored(); |
142 | BOOL IsRestored_NoLogging(); |
143 | void SetIsRestored(); |
144 | |
145 | inline BOOL HasUnrestoredTypeKey() const |
146 | { |
147 | LIMITED_METHOD_CONTRACT; |
148 | SUPPORTS_DAC; |
149 | |
150 | return (m_typeAndFlags & TypeDesc::enum_flag_UnrestoredTypeKey) != 0; |
151 | } |
152 | |
153 | BOOL HasTypeEquivalence() const |
154 | { |
155 | LIMITED_METHOD_CONTRACT; |
156 | return (m_typeAndFlags & TypeDesc::enum_flag_HasTypeEquivalence) != 0; |
157 | } |
158 | |
159 | BOOL IsFullyLoaded() const |
160 | { |
161 | LIMITED_METHOD_CONTRACT; |
162 | |
163 | return (m_typeAndFlags & TypeDesc::enum_flag_IsNotFullyLoaded) == 0; |
164 | } |
165 | |
166 | VOID SetIsFullyLoaded() |
167 | { |
168 | LIMITED_METHOD_CONTRACT; |
169 | FastInterlockAnd(&m_typeAndFlags, ~TypeDesc::enum_flag_IsNotFullyLoaded); |
170 | } |
171 | |
172 | ClassLoadLevel GetLoadLevel(); |
173 | |
174 | void DoFullyLoad(Generics::RecursionGraph *pVisited, ClassLoadLevel level, |
175 | DFLPendingList *pPending, BOOL *pfBailed, const InstantiationContext *pInstContext); |
176 | |
177 | // The module that defined the underlying type |
178 | PTR_Module GetModule(); |
179 | |
180 | // The ngen'ed module where this type-desc lives |
181 | PTR_Module GetZapModule(); |
182 | |
183 | // The module where this type lives for the purposes of loading and prejitting |
184 | // See ComputeLoaderModule for more information |
185 | PTR_Module GetLoaderModule(); |
186 | |
187 | // The assembly that defined this type (== GetModule()->GetAssembly()) |
188 | Assembly* GetAssembly(); |
189 | |
190 | PTR_MethodTable GetMethodTable(); // only meaningful for ParamTypeDesc |
191 | TypeHandle GetTypeParam(); // only meaningful for ParamTypeDesc |
192 | Instantiation GetClassOrArrayInstantiation(); // only meaningful for ParamTypeDesc; see above |
193 | |
194 | TypeHandle GetBaseTypeParam(); // only allowed for ParamTypeDesc, helper method used to avoid recursion |
195 | |
196 | // Note that if the TypeDesc, e.g. a function pointer type, involves parts that may |
197 | // come from either a SharedDomain or an AppDomain then special rules apply to GetDomain. |
198 | // It returns the SharedDomain if all the |
199 | // constituent parts of the type are SharedDomain (i.e. domain-neutral), |
200 | // and returns an AppDomain if any of the parts are from an AppDomain, |
201 | // i.e. are domain-bound. If any of the parts are domain-bound |
202 | // then they will all belong to the same domain. |
203 | PTR_BaseDomain GetDomain(); |
204 | |
205 | PTR_LoaderAllocator GetLoaderAllocator() |
206 | { |
207 | SUPPORTS_DAC; |
208 | |
209 | return GetLoaderModule()->GetLoaderAllocator(); |
210 | } |
211 | |
212 | protected: |
213 | // See methodtable.h for details of the flags with the same name there |
214 | enum |
215 | { |
216 | enum_flag_NeedsRestore = 0x00000100, // Only used during ngen |
217 | enum_flag_PreRestored = 0x00000200, // Only used during ngen |
218 | enum_flag_Unrestored = 0x00000400, |
219 | enum_flag_UnrestoredTypeKey = 0x00000800, |
220 | enum_flag_IsNotFullyLoaded = 0x00001000, |
221 | enum_flag_DependenciesLoaded = 0x00002000, |
222 | enum_flag_HasTypeEquivalence = 0x00004000 |
223 | }; |
224 | // |
225 | // Low-order 8 bits of this flag are used to store the CorElementType, which |
226 | // discriminates what kind of TypeDesc we are |
227 | // |
228 | // The remaining bits are available for flags |
229 | // |
230 | DWORD m_typeAndFlags; |
231 | }; |
232 | |
233 | |
234 | /*************************************************************************/ |
235 | // This variant is used for parameterized types that have exactly one argument |
236 | // type. This includes arrays, byrefs, pointers. |
237 | |
238 | typedef DPTR(class ParamTypeDesc) PTR_ParamTypeDesc; |
239 | |
240 | |
241 | class ParamTypeDesc : public TypeDesc { |
242 | friend class TypeDesc; |
243 | friend class JIT_TrialAlloc; |
244 | friend class CheckAsmOffsets; |
245 | #ifdef DACCESS_COMPILE |
246 | friend class NativeImageDumper; |
247 | #endif |
248 | |
249 | public: |
250 | #ifndef DACCESS_COMPILE |
251 | ParamTypeDesc(CorElementType type, MethodTable* pMT, TypeHandle arg) |
252 | : TypeDesc(type), m_Arg(arg), m_hExposedClassObject(0) { |
253 | |
254 | LIMITED_METHOD_CONTRACT; |
255 | |
256 | m_TemplateMT.SetValueMaybeNull(pMT); |
257 | |
258 | // ParamTypeDescs start out life not fully loaded |
259 | m_typeAndFlags |= TypeDesc::enum_flag_IsNotFullyLoaded; |
260 | |
261 | // Param type descs can only be equivalent if their constituent bits are equivalent. |
262 | if (arg.HasTypeEquivalence()) |
263 | { |
264 | m_typeAndFlags |= TypeDesc::enum_flag_HasTypeEquivalence; |
265 | } |
266 | |
267 | INDEBUGIMPL(Verify()); |
268 | } |
269 | #endif |
270 | |
271 | INDEBUGIMPL(BOOL Verify();) |
272 | |
273 | OBJECTREF GetManagedClassObject(); |
274 | |
275 | OBJECTREF GetManagedClassObjectIfExists() |
276 | { |
277 | CONTRACTL |
278 | { |
279 | NOTHROW; |
280 | GC_NOTRIGGER; |
281 | MODE_COOPERATIVE; |
282 | } |
283 | CONTRACTL_END; |
284 | |
285 | OBJECTREF objRet = NULL; |
286 | GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedClassObject, &objRet); |
287 | return objRet; |
288 | } |
289 | OBJECTREF GetManagedClassObjectFast() |
290 | { |
291 | LIMITED_METHOD_CONTRACT; |
292 | |
293 | OBJECTREF objRet = NULL; |
294 | LoaderAllocator::GetHandleValueFast(m_hExposedClassObject, &objRet); |
295 | return objRet; |
296 | } |
297 | |
298 | TypeHandle GetModifiedType() |
299 | { |
300 | LIMITED_METHOD_CONTRACT; |
301 | |
302 | return m_Arg; |
303 | } |
304 | |
305 | TypeHandle GetTypeParam(); |
306 | |
307 | #ifdef FEATURE_PREJIT |
308 | void Save(DataImage *image); |
309 | void Fixup(DataImage *image); |
310 | BOOL ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisited); |
311 | #endif |
312 | |
313 | BOOL OwnsTemplateMethodTable(); |
314 | |
315 | #ifdef DACCESS_COMPILE |
316 | void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
317 | #endif |
318 | |
319 | friend class StubLinkerCPU; |
320 | |
321 | #ifdef FEATURE_ARRAYSTUB_AS_IL |
322 | friend class ArrayOpLinker; |
323 | #endif |
324 | protected: |
325 | PTR_MethodTable GetTemplateMethodTableInternal() { |
326 | WRAPPER_NO_CONTRACT; |
327 | return ReadPointerMaybeNull(this, &ParamTypeDesc::m_TemplateMT); |
328 | } |
329 | |
330 | // the m_typeAndFlags field in TypeDesc tell what kind of parameterized type we have |
331 | RelativeFixupPointer<PTR_MethodTable> m_TemplateMT; // The shared method table, some variants do not use this field (it is null) |
332 | TypeHandle m_Arg; // The type that is being modified |
333 | LOADERHANDLE m_hExposedClassObject; // handle back to the internal reflection Type object |
334 | }; |
335 | |
336 | |
337 | /*************************************************************************/ |
338 | /* An ArrayTypeDesc represents a Array of some pointer type. */ |
339 | |
340 | class ArrayTypeDesc : public ParamTypeDesc |
341 | { |
342 | #ifdef DACCESS_COMPILE |
343 | friend class NativeImageDumper; |
344 | #endif |
345 | public: |
346 | #ifndef DACCESS_COMPILE |
347 | ArrayTypeDesc(MethodTable* arrayMT, TypeHandle elementType) : |
348 | ParamTypeDesc(arrayMT->IsMultiDimArray() ? ELEMENT_TYPE_ARRAY : ELEMENT_TYPE_SZARRAY, arrayMT, elementType) |
349 | #ifdef FEATURE_COMINTEROP |
350 | , m_pCCWTemplate(NULL) |
351 | #endif // FEATURE_COMINTEROP |
352 | { |
353 | STATIC_CONTRACT_SO_TOLERANT; |
354 | WRAPPER_NO_CONTRACT; |
355 | INDEBUG(Verify()); |
356 | } |
357 | |
358 | //private: TypeHandle m_Arg; // The type that is being modified |
359 | |
360 | |
361 | // placement new operator |
362 | void* operator new(size_t size, void* spot) { return (spot); } |
363 | |
364 | #endif |
365 | |
366 | TypeHandle GetArrayElementTypeHandle() { |
367 | WRAPPER_NO_CONTRACT; |
368 | SUPPORTS_DAC; |
369 | return GetTypeParam(); |
370 | } |
371 | |
372 | unsigned GetRank() { |
373 | WRAPPER_NO_CONTRACT; |
374 | SUPPORTS_DAC; |
375 | |
376 | if (GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY) |
377 | return 1; |
378 | else |
379 | return dac_cast<PTR_ArrayClass>(GetMethodTable()->GetClass())->GetRank(); |
380 | } |
381 | |
382 | MethodTable* GetParent() |
383 | { |
384 | WRAPPER_NO_CONTRACT; |
385 | |
386 | _ASSERTE(!m_TemplateMT.IsNull()); |
387 | _ASSERTE(GetTemplateMethodTableInternal()->IsArray()); |
388 | _ASSERTE(GetTemplateMethodTableInternal()->ParentEquals(g_pArrayClass)); |
389 | |
390 | return g_pArrayClass; |
391 | } |
392 | |
393 | #ifdef FEATURE_COMINTEROP |
394 | ComCallWrapperTemplate *GetComCallWrapperTemplate() |
395 | { |
396 | LIMITED_METHOD_CONTRACT; |
397 | return m_pCCWTemplate; |
398 | } |
399 | |
400 | BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate) |
401 | { |
402 | CONTRACTL |
403 | { |
404 | THROWS; |
405 | GC_NOTRIGGER; |
406 | MODE_ANY; |
407 | } |
408 | CONTRACTL_END; |
409 | |
410 | TypeHandle th(this); |
411 | g_IBCLogger.LogTypeMethodTableWriteableAccess(&th); |
412 | |
413 | return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pCCWTemplate), pTemplate, NULL) == NULL); |
414 | } |
415 | #endif // FEATURE_COMINTEROP |
416 | |
417 | INDEBUG(BOOL Verify();) |
418 | |
419 | #ifdef FEATURE_PREJIT |
420 | void Fixup(DataImage *image); |
421 | #endif |
422 | |
423 | PTR_MethodTable GetTemplateMethodTable() { |
424 | WRAPPER_NO_CONTRACT; |
425 | PTR_MethodTable ptrTemplateMT = GetTemplateMethodTableInternal(); |
426 | _ASSERTE(ptrTemplateMT->IsArray()); |
427 | return ptrTemplateMT; |
428 | } |
429 | |
430 | TADDR GetTemplateMethodTableMaybeTagged() { |
431 | WRAPPER_NO_CONTRACT; |
432 | return m_TemplateMT.GetValueMaybeTagged(dac_cast<TADDR>(this) + offsetof(ArrayTypeDesc, m_TemplateMT)); |
433 | } |
434 | |
435 | #ifdef FEATURE_COMINTEROP |
436 | ComCallWrapperTemplate *m_pCCWTemplate; |
437 | #endif // FEATURE_COMINTEROP |
438 | }; |
439 | |
440 | /*************************************************************************/ |
441 | // These are for verification of generic code and reflection over generic code. |
442 | // Each TypeVarTypeDesc represents a class or method type variable, as specified by a GenericParam entry. |
443 | // The type variables are tied back to the class or method that *defines* them. |
444 | // This is done through typedef or methoddef tokens. |
445 | |
446 | class TypeVarTypeDesc : public TypeDesc |
447 | { |
448 | #ifdef DACCESS_COMPILE |
449 | friend class NativeImageDumper; |
450 | #endif |
451 | public: |
452 | |
453 | #ifndef DACCESS_COMPILE |
454 | |
455 | TypeVarTypeDesc(PTR_Module pModule, mdToken typeOrMethodDef, unsigned int index, mdGenericParam token) : |
456 | TypeDesc(TypeFromToken(typeOrMethodDef) == mdtTypeDef ? ELEMENT_TYPE_VAR : ELEMENT_TYPE_MVAR) |
457 | { |
458 | CONTRACTL |
459 | { |
460 | NOTHROW; |
461 | GC_NOTRIGGER; |
462 | PRECONDITION(CheckPointer(pModule)); |
463 | PRECONDITION(TypeFromToken(typeOrMethodDef) == mdtTypeDef || TypeFromToken(typeOrMethodDef) == mdtMethodDef); |
464 | PRECONDITION(index >= 0); |
465 | PRECONDITION(TypeFromToken(token) == mdtGenericParam); |
466 | } |
467 | CONTRACTL_END; |
468 | |
469 | m_pModule.SetValue(pModule); |
470 | m_typeOrMethodDef = typeOrMethodDef; |
471 | m_token = token; |
472 | m_index = index; |
473 | m_hExposedClassObject = 0; |
474 | m_constraints = NULL; |
475 | m_numConstraints = (DWORD)-1; |
476 | } |
477 | #endif // #ifndef DACCESS_COMPILE |
478 | |
479 | // placement new operator |
480 | void* operator new(size_t size, void* spot) { LIMITED_METHOD_CONTRACT; return (spot); } |
481 | |
482 | PTR_Module GetModule() |
483 | { |
484 | LIMITED_METHOD_CONTRACT; |
485 | SUPPORTS_DAC; |
486 | |
487 | return ReadPointer(this, &TypeVarTypeDesc::m_pModule); |
488 | } |
489 | |
490 | unsigned int GetIndex() |
491 | { |
492 | LIMITED_METHOD_CONTRACT; |
493 | SUPPORTS_DAC; |
494 | return m_index; |
495 | } |
496 | |
497 | mdGenericParam GetToken() |
498 | { |
499 | LIMITED_METHOD_CONTRACT; |
500 | SUPPORTS_DAC; |
501 | return m_token; |
502 | } |
503 | |
504 | mdToken GetTypeOrMethodDef() |
505 | { |
506 | LIMITED_METHOD_CONTRACT; |
507 | SUPPORTS_DAC; |
508 | return m_typeOrMethodDef; |
509 | } |
510 | |
511 | OBJECTREF GetManagedClassObject(); |
512 | OBJECTREF GetManagedClassObjectIfExists() |
513 | { |
514 | CONTRACTL |
515 | { |
516 | NOTHROW; |
517 | GC_NOTRIGGER; |
518 | MODE_COOPERATIVE; |
519 | } |
520 | CONTRACTL_END; |
521 | |
522 | OBJECTREF objRet = NULL; |
523 | GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedClassObject, &objRet); |
524 | return objRet; |
525 | } |
526 | OBJECTREF GetManagedClassObjectFast() |
527 | { |
528 | LIMITED_METHOD_CONTRACT; |
529 | |
530 | OBJECTREF objRet = NULL; |
531 | LoaderAllocator::GetHandleValueFast(m_hExposedClassObject, &objRet); |
532 | return objRet; |
533 | } |
534 | |
535 | // Load the owning type. Note that the result is not guaranteed to be full loaded |
536 | MethodDesc * LoadOwnerMethod(); |
537 | TypeHandle LoadOwnerType(); |
538 | |
539 | BOOL ConstraintsLoaded() { LIMITED_METHOD_CONTRACT; return m_numConstraints != (DWORD)-1; } |
540 | |
541 | // Return NULL if no constraints are specified |
542 | // Return an array of type handles if constraints are specified, |
543 | // with the number of constraints returned in pNumConstraints |
544 | TypeHandle* GetCachedConstraints(DWORD *pNumConstraints); |
545 | TypeHandle* GetConstraints(DWORD *pNumConstraints, ClassLoadLevel level = CLASS_LOADED); |
546 | |
547 | // Load the constraints if not already loaded |
548 | void LoadConstraints(ClassLoadLevel level = CLASS_LOADED); |
549 | |
550 | // Check the constraints on this type parameter hold in the supplied context for the supplied type |
551 | BOOL SatisfiesConstraints(SigTypeContext *pTypeContext, TypeHandle thArg, |
552 | const InstantiationContext *pInstContext = NULL); |
553 | |
554 | // Check whether the constraints on this type force it to be a reference type (i.e. it is impossible |
555 | // to instantiate it with a value type). |
556 | BOOL ConstrainedAsObjRef(); |
557 | |
558 | // Check whether the constraints on this type force it to be a value type (i.e. it is impossible to |
559 | // instantiate it with a reference type). |
560 | BOOL ConstrainedAsValueType(); |
561 | |
562 | #ifdef FEATURE_PREJIT |
563 | void Save(DataImage *image); |
564 | void Fixup(DataImage *image); |
565 | #endif // FEATURE_PREJIT |
566 | |
567 | #ifdef DACCESS_COMPILE |
568 | void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
569 | #endif |
570 | |
571 | protected: |
572 | BOOL ConstrainedAsObjRefHelper(); |
573 | |
574 | // Module containing the generic definition, also the loader module for this type desc |
575 | RelativePointer<PTR_Module> m_pModule; |
576 | |
577 | // Declaring type or method |
578 | mdToken m_typeOrMethodDef; |
579 | |
580 | // Constraints, determined on first call to GetConstraints |
581 | Volatile<DWORD> m_numConstraints; // -1 until number has been determined |
582 | PTR_TypeHandle m_constraints; |
583 | |
584 | // slot index back to the internal reflection Type object |
585 | LOADERHANDLE m_hExposedClassObject; |
586 | |
587 | // token for GenericParam entry |
588 | mdGenericParam m_token; |
589 | |
590 | // index within declaring type or method, numbered from zero |
591 | unsigned int m_index; |
592 | }; |
593 | |
594 | /*************************************************************************/ |
595 | /* represents a function type. */ |
596 | |
597 | typedef SPTR(class FnPtrTypeDesc) PTR_FnPtrTypeDesc; |
598 | |
599 | class FnPtrTypeDesc : public TypeDesc |
600 | { |
601 | #ifdef DACCESS_COMPILE |
602 | friend class NativeImageDumper; |
603 | #endif |
604 | |
605 | public: |
606 | #ifndef DACCESS_COMPILE |
607 | FnPtrTypeDesc(BYTE callConv, DWORD numArgs, TypeHandle * retAndArgTypes) |
608 | : TypeDesc(ELEMENT_TYPE_FNPTR), m_NumArgs(numArgs), m_CallConv(callConv) |
609 | { |
610 | LIMITED_METHOD_CONTRACT; |
611 | for (DWORD i = 0; i <= numArgs; i++) |
612 | { |
613 | m_RetAndArgTypes[i] = retAndArgTypes[i]; |
614 | } |
615 | } |
616 | #endif //!DACCESS_COMPILE |
617 | |
618 | DWORD GetNumArgs() |
619 | { |
620 | LIMITED_METHOD_CONTRACT; |
621 | SUPPORTS_DAC; |
622 | return m_NumArgs; |
623 | } |
624 | |
625 | BYTE GetCallConv() |
626 | { |
627 | LIMITED_METHOD_CONTRACT; |
628 | SUPPORTS_DAC; |
629 | _ASSERTE(FitsIn<BYTE>(m_CallConv)); |
630 | return static_cast<BYTE>(m_CallConv); |
631 | } |
632 | |
633 | // Return a pointer to the types of the signature, return type followed by argument types |
634 | // The type handles are guaranteed to be fixed up |
635 | TypeHandle * GetRetAndArgTypes(); |
636 | // As above, but const version |
637 | const TypeHandle * GetRetAndArgTypes() const |
638 | { |
639 | WRAPPER_NO_CONTRACT; |
640 | return const_cast<FnPtrTypeDesc *>(this)->GetRetAndArgTypes(); |
641 | } |
642 | |
643 | // As above, but the type handles might be zap-encodings that need fixing up explicitly |
644 | PTR_TypeHandle GetRetAndArgTypesPointer() |
645 | { |
646 | LIMITED_METHOD_CONTRACT; |
647 | SUPPORTS_DAC; |
648 | |
649 | return PTR_TypeHandle(m_RetAndArgTypes); |
650 | } |
651 | |
652 | #ifndef DACCESS_COMPILE |
653 | // Returns TRUE if all return and argument types are externally visible. |
654 | BOOL IsExternallyVisible() const; |
655 | #endif //DACCESS_COMPILE |
656 | |
657 | #ifdef FEATURE_PREJIT |
658 | void Save(DataImage *image); |
659 | void Fixup(DataImage *image); |
660 | #endif //FEATURE_PREJIT |
661 | |
662 | #ifdef DACCESS_COMPILE |
663 | static ULONG32 DacSize(TADDR addr) |
664 | { |
665 | DWORD numArgs = *PTR_DWORD(addr + offsetof(FnPtrTypeDesc, m_NumArgs)); |
666 | return (offsetof(FnPtrTypeDesc, m_RetAndArgTypes) + |
667 | (numArgs * sizeof(TypeHandle))); |
668 | } |
669 | |
670 | void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
671 | #endif //DACCESS_COMPILE |
672 | |
673 | protected: |
674 | // Number of arguments |
675 | DWORD m_NumArgs; |
676 | |
677 | // Calling convention (actually just a single byte) |
678 | DWORD m_CallConv; |
679 | |
680 | // Return type first, then argument types |
681 | TypeHandle m_RetAndArgTypes[1]; |
682 | }; // class FnPtrTypeDesc |
683 | |
684 | #endif // TYPEDESC_H |
685 | |