Merge pull request #9794 from pgavlin/PutArgRegInit
[platform/upstream/coreclr.git] / src / debug / di / rstype.cpp
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: rstype.cpp
6 // 
7
8 //
9 // Define implementation of ICorDebugType
10 //*****************************************************************************
11
12
13 #include "stdafx.h"
14 #include "winbase.h"
15 #include "corpriv.h"
16
17
18 //-----------------------------------------------------------------------------
19 // Public method to get the static field from a type.
20 // 
21 // Parameters:
22 //   fieldDef - metadata token for which field on this type to retrieve.
23 //   pFrame - context for Thread/AppDomains statics.
24 //   ppValue - OUT: out-parameter to get value.
25 //
26 // Returns:
27 //   S_OK on success.
28 //
29 HRESULT CordbType::GetStaticFieldValue(mdFieldDef fieldDef,
30                                        ICorDebugFrame * pFrame,
31                                        ICorDebugValue ** ppValue)
32 {
33     PUBLIC_REENTRANT_API_ENTRY(this);
34     FAIL_IF_NEUTERED(this);
35     VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **);
36     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
37
38     HRESULT hr = S_OK;
39
40     IMetaDataImport * pImport = NULL;
41
42     EX_TRY
43     {
44         // Ensure we were actually passed a mdFieldDef. This is especially useful to protect
45         // against an accidental mdPropertyDef, because properties look like fields.
46         // 
47         if (TypeFromToken(fieldDef) != mdtFieldDef)
48         {
49             ThrowHR(E_INVALIDARG);   
50         }
51
52         pImport = m_pClass->GetModule()->GetMetaDataImporter(); // throws
53
54         if (((m_elementType != ELEMENT_TYPE_CLASS) && (m_elementType != ELEMENT_TYPE_VALUETYPE)) || (m_pClass == NULL))
55         {
56             ThrowHR(E_INVALIDARG);
57         }
58
59         
60
61         BOOL fSyncBlockField = FALSE;
62
63         // If non generic type, then degenerate to CordbClass implementation.
64         if (m_inst.m_cInst == 0)
65         {
66             hr = m_pClass->GetStaticFieldValue(fieldDef, pFrame, ppValue);
67         }
68         else
69         {
70             *ppValue = NULL;
71
72             // Validate the token.
73             if (!pImport->IsValidToken(fieldDef))
74             {
75                 ThrowHR(hr = E_INVALIDARG);
76             }
77
78             // Make sure we have enough info about the class.
79             hr = Init(FALSE);
80             IfFailThrow(hr);
81
82             // Lookup the field given its metadata token.
83             FieldData * pFieldData;
84
85             hr = GetFieldInfo(fieldDef, &pFieldData);
86
87             if (hr == CORDBG_E_ENC_HANGING_FIELD)
88             {
89                 // Generics + EnC is Not supported.
90                 hr = CORDBG_E_STATIC_VAR_NOT_AVAILABLE;
91             }
92
93             IfFailThrow(hr);
94
95             hr = CordbClass::GetStaticFieldValue2(m_pClass->GetModule(),
96                                                   pFieldData,
97                                                   fSyncBlockField,
98                                                   &m_inst,
99                                                   pFrame,
100                                                   ppValue);
101             // fall through to translate HR
102         }
103             
104     }
105     EX_CATCH_HRESULT(hr);
106     if (pImport != NULL)
107     {
108         hr = CordbClass::PostProcessUnavailableHRESULT(hr, pImport, fieldDef);
109     }
110     return hr;
111
112 }
113
114 // Combine E_T_s and rank together to get an id for the m_sharedtypes table
115 #define CORDBTYPE_ID(elementType,rank) ((unsigned int) elementType * (rank + 1) + 1)
116
117
118 //-----------------------------------------------------------------------------
119 // Constructor
120 // Builds a CordbType around a primitive.
121 //-----------------------------------------------------------------------------
122 CordbType::CordbType(CordbAppDomain *appdomain, CorElementType et, unsigned int rank)
123 : CordbBase(appdomain->GetProcess(), CORDBTYPE_ID(et,rank) , enumCordbType),
124   m_elementType(et),
125   m_appdomain(appdomain),
126   m_pClass(NULL),
127   m_rank(rank),
128   m_spinetypes(2),
129   m_objectSize(0),
130   m_fieldInfoNeedsInit(TRUE)
131 {
132     m_typeHandleExact = VMPTR_TypeHandle::NullPtr();
133
134     _ASSERTE(m_elementType != ELEMENT_TYPE_VALUETYPE);
135
136     HRESULT hr = S_OK;
137     EX_TRY
138     {
139         m_appdomain->AddToTypeList(this);
140     } 
141     EX_CATCH_HRESULT(hr);
142     SetUnrecoverableIfFailed(GetProcess(), hr);
143 }
144
145 //-----------------------------------------------------------------------------
146 // Constructor
147 // Builds a CordbType around a class. This is an Open CordbType.
148 // For a generic type, this CordbType will not have the generic parameters,
149 // but it will be a subordinate type to another Closed (instantiated) CordbType
150 //-----------------------------------------------------------------------------
151 CordbType::CordbType(CordbAppDomain *appdomain, CorElementType et, CordbClass *cls)
152 : CordbBase(appdomain->GetProcess(), et, enumCordbType),
153   m_elementType(et),
154   m_appdomain(appdomain),
155   m_pClass(cls),
156   m_rank(0),
157   m_spinetypes(2),
158   m_objectSize(0),
159   m_fieldInfoNeedsInit(TRUE)
160 {
161     m_typeHandleExact = VMPTR_TypeHandle::NullPtr();
162     _ASSERTE(m_elementType != ELEMENT_TYPE_VALUETYPE);
163
164     HRESULT hr = S_OK;
165     EX_TRY
166     {
167         m_appdomain->AddToTypeList(this);
168     } 
169     EX_CATCH_HRESULT(hr);
170     SetUnrecoverableIfFailed(GetProcess(), hr);
171 }
172
173 //-----------------------------------------------------------------------------
174 // Constructor 
175 // Builds a Partial-Type, instantiation is tycon's instantation plus tyarg.
176 // Eg, if tycon is "Dict<int>", and tyarg is "string", then this yields
177 // "Dict<int, string>"
178 //-----------------------------------------------------------------------------
179 CordbType::CordbType(CordbType *tycon, CordbType *tyarg)
180 : CordbBase(tycon->GetProcess(), (UINT_PTR)tyarg, enumCordbType),
181   m_elementType(tycon->m_elementType),
182   m_appdomain(tycon->m_appdomain),
183   m_pClass(tycon->m_pClass),
184   m_rank(tycon->m_rank),
185   m_spinetypes(2),
186   m_objectSize(0),
187   m_fieldInfoNeedsInit(TRUE)
188     // tyarg is added as part of instantiation -see below...
189 {
190     m_typeHandleExact = VMPTR_TypeHandle::NullPtr();
191     _ASSERTE(m_elementType != ELEMENT_TYPE_VALUETYPE);
192
193     HRESULT hr = S_OK;
194     EX_TRY
195     {
196         m_appdomain->AddToTypeList(this);
197     } 
198     EX_CATCH_HRESULT(hr);
199     SetUnrecoverableIfFailed(GetProcess(), hr);
200 }
201
202
203 ULONG STDMETHODCALLTYPE CordbType::AddRef()
204 {
205     // This AddRef/Release pair creates a weak ref-counted reference to the class for this
206     // type.  This avoids a circularity in ref-counted references between
207     // classes and types - if we had a circularity the objects would never get
208     // collected at all...
209     //if (m_class)
210     //  m_class->AddRef();
211     return (BaseAddRef());
212 }
213 ULONG STDMETHODCALLTYPE CordbType::Release()
214 {
215     //  if (m_class)
216     //  m_class->Release();
217     return (BaseRelease());
218 }
219
220 /*
221     A list of which resources owened by this object are accounted for.
222
223     HANDLED:
224         CordbClass *m_class;  Weakly referenced by increasing count directly in AddRef() and Release()
225         Instantiation   m_inst; // Internal pointers to CordbClass released in CordbClass::Neuter
226         CordbHashTable   m_spinetypes; // Neutered
227         CordbHashTable   m_fields; // Deleted in ~CordbType
228 */
229
230 //-----------------------------------------------------------------------------
231 // Cleanup memory for CordbTypes.
232 //-----------------------------------------------------------------------------
233 CordbType::~CordbType()
234 {
235     _ASSERTE(IsNeutered());    
236 }
237
238 //-----------------------------------------------------------------------------
239 // Neutered by CordbModule
240 // See CordbBase::Neuter for neuter semantics.
241 //-----------------------------------------------------------------------------
242 void CordbType::Neuter()
243 {
244     _ASSERTE(GetProcess()->GetProcessLock()->HasLock());
245
246     // We have some direct releases below. If we call Neuter twice, that could
247     // result in double-releases. So check if we're already neutered, and
248     // if so, no work left to do.
249     if (IsNeutered())
250     {
251         return;
252     }
253
254     for (unsigned int i = 0; i < m_inst.m_cInst; i++) 
255     {
256         m_inst.m_ppInst[i]->Release();
257     }
258
259     m_spinetypes.NeuterAndClear(GetProcess()->GetProcessLock());
260
261     if(m_inst.m_ppInst)
262     {
263         delete [] m_inst.m_ppInst;
264         m_inst.m_ppInst = NULL;
265     }
266     m_fieldList.Dealloc();
267
268     CordbBase::Neuter();
269 }
270
271 //-----------------------------------------------------------------------------
272 // Public method for IUnknown::QueryInterface.
273 // Has standard QI semantics.
274 //-----------------------------------------------------------------------------
275 HRESULT CordbType::QueryInterface(REFIID id, void **pInterface)
276 {
277     if (id == IID_ICorDebugType)
278         *pInterface = static_cast<ICorDebugType*>(this);
279     else if (id == IID_ICorDebugType2)
280         *pInterface = static_cast<ICorDebugType2*>(this);
281     else if (id == IID_IUnknown)
282         *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugType*>(this));
283     else
284     {
285         *pInterface = NULL;
286         return E_NOINTERFACE;
287     }
288
289     ExternalAddRef();
290     return S_OK;
291 }
292
293
294 //-----------------------------------------------------------------------------
295 // Make a simple type with no type arguments by specifying a CorElementType,
296 // e.g. ELEMENT_TYPE_I1
297 //
298 // CordbType's are effectively a full representation of
299 // structured types.  They are hashed via a combination of their constituent
300 // elements (e.g. CordbClass's or CordbType's) and the element type that is used to
301 // combine the elements, or if they have no elements then via
302 // the element type alone.  The following  is used to create all CordbTypes.
303 //
304 // An AppDomain holds a cache of CordbTypes for each of the basic CorElementTypes.
305 //
306 // Arguments:
307 //   pAppDomain - the AppDomain that the type lives in.
308 //   elementType - element_type to create the CordbType around.
309 //   ppResultType - OUT: out-parameter to get the CordbType.
310 //
311 // Returns:
312 //   S_OK on success.
313 //
314 //
315 HRESULT CordbType::MkType(CordbAppDomain * pAppDomain, 
316                           CorElementType elementType, 
317                           CordbType ** ppResultType)
318 {
319     _ASSERTE(pAppDomain != NULL);
320     _ASSERTE(ppResultType != NULL);
321
322     RSLockHolder lockHolder(pAppDomain->GetProcess()->GetProcessLock());
323
324     // Some points in the code create types via element types that are clearly objects but where
325     // no further information is given.  This is always done when creating a CordbValue, prior
326     // to actually going over to the EE to discover what kind of value it is.  In all these
327     // cases we can just use the type for "Object" - the code for dereferencing the value
328     // will update the type correctly once it has been determined.  We don't do this for ELEMENT_TYPE_STRING
329     // as that is actually a NullaryType and at other places in the code we will want exactly that type!
330     if ((elementType == ELEMENT_TYPE_CLASS) || 
331         (elementType == ELEMENT_TYPE_SZARRAY) || 
332         (elementType == ELEMENT_TYPE_ARRAY))
333     {
334         elementType = ELEMENT_TYPE_OBJECT;
335     }
336
337     switch (elementType)
338     {
339     // this one is included because we need a "seed" type to uniquely hash FNPTR types, 
340     // i.e. the nullary FNPTR type is used as the type constructor for all function pointer types, 
341     // when combined with an approproiate instantiation.
342     case ELEMENT_TYPE_FNPTR: 
343         // fall through ...
344
345     case ELEMENT_TYPE_VOID:
346     case ELEMENT_TYPE_BOOLEAN:
347     case ELEMENT_TYPE_CHAR:
348     case ELEMENT_TYPE_I1:
349     case ELEMENT_TYPE_U1:
350     case ELEMENT_TYPE_I2:
351     case ELEMENT_TYPE_U2:
352     case ELEMENT_TYPE_I4:
353     case ELEMENT_TYPE_U4:
354     case ELEMENT_TYPE_I8:
355     case ELEMENT_TYPE_U8:
356     case ELEMENT_TYPE_R4:
357     case ELEMENT_TYPE_R8:
358     case ELEMENT_TYPE_STRING:
359     case ELEMENT_TYPE_OBJECT:
360     case ELEMENT_TYPE_TYPEDBYREF:
361     case ELEMENT_TYPE_I:
362     case ELEMENT_TYPE_U:
363
364         *ppResultType = pAppDomain->m_sharedtypes.GetBase(CORDBTYPE_ID(elementType, 0));
365         
366         if (*ppResultType == NULL)
367         {
368             CordbType * pNewType = new (nothrow) CordbType(pAppDomain, elementType, (unsigned int) 0);
369
370             if (pNewType == NULL)
371             {
372                 return E_OUTOFMEMORY;
373             }
374
375             HRESULT hr = pAppDomain->m_sharedtypes.AddBase(pNewType);
376
377             if (SUCCEEDED(hr))
378             {
379                 *ppResultType = pNewType;
380             }
381             else 
382             {
383                 _ASSERTE(!"unexpected failure!");
384                 delete pNewType;
385             }
386
387             return hr;
388         }
389         return S_OK;
390
391     default:
392         _ASSERTE(!"unexpected element type!");
393         return E_FAIL;
394     }
395
396 }
397
398 //-----------------------------------------------------------------------------
399 // Internal method to make a type with exactly one type argument by specifying
400 // ELEMENT_TYPE_PTR, ELEMENT_TYPE_BYREF, ELEMENT_TYPE_SZARRAY or
401 // ELEMENT_TYPE_ARRAY.
402 //
403 // Arguments:
404 //   pAppDomain - appdomain containing the type.
405 //   elementType - element type to create around. This is limited to: ELEMENT_TYPE_PTR, 
406 //          ELEMENT_TYPE_BYREF, ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY.
407 //   rank - for non-arrays, this must be 0. For szarray, this must be 1. 
408 //          For multi-dimensional arrays, this is the rank.
409 //   pType - the single input type-parameter required for the specified element type.
410 //   ppResultType - OUT: the output parameter to get the corresponding CordbType
411 //
412 // Returns:
413 //   S_OK on success.
414 //
415 HRESULT CordbType::MkType(CordbAppDomain *pAppDomain, 
416                           CorElementType elementType, 
417                           ULONG rank, 
418                           CordbType * pType, 
419                           CordbType ** ppResultType)
420 {
421     _ASSERTE(pAppDomain != NULL);
422     _ASSERTE(ppResultType != NULL);
423
424     RSLockHolder lockHolder(pAppDomain->GetProcess()->GetProcessLock());
425
426     switch (elementType)
427     {
428
429     case ELEMENT_TYPE_PTR:
430     case ELEMENT_TYPE_BYREF:
431         _ASSERTE(rank == 0);
432         goto LUnary;
433
434     case ELEMENT_TYPE_SZARRAY:
435         _ASSERTE(rank == 1);
436         goto LUnary;
437
438     case ELEMENT_TYPE_ARRAY:
439 LUnary:
440         {
441             CordbType * pFoundType = pAppDomain->m_sharedtypes.GetBase(CORDBTYPE_ID(elementType, rank));
442
443             if (pFoundType == NULL)
444             {
445                 pFoundType = new (nothrow) CordbType(pAppDomain, elementType, rank);
446
447                 if (pFoundType == NULL)
448                 {
449                     return E_OUTOFMEMORY;
450                 }
451
452                 HRESULT hr = pAppDomain->m_sharedtypes.AddBase(pFoundType);
453
454                 if (FAILED(hr))
455                 {
456                     _ASSERTE(!"unexpected failure!");
457                     delete pFoundType;
458                     return hr;
459                 }
460             }
461
462             Instantiation inst(1, &pType);
463
464             return MkTyAppType(pAppDomain, pFoundType, &inst, ppResultType);
465
466         }
467
468     default:
469         _ASSERTE(!"unexpected element type!");
470         return E_FAIL;
471     }
472
473 }
474
475 //-----------------------------------------------------------------------------
476 // Internal method to make a type for an instantiation of a class or value type, or just for the
477 // class or value type if it accepts no type parameters.
478 // Creates a CordbType instantiation around an uninstantiated CordbType and TypeParameter list.
479 // In other words, this does:
480 // CordbType(List<T>) + Instantiation({T=int}) --> CordbType(List<int>)
481 //
482 // This will create the subordinate types. Eg, for Triple<x,y,z>, it will create:
483 // CordbType(Triple<x>), CordbType(Triple<x,y>), and CordbType(Triple<x,y,z)).
484 // The fully instantiated one (the last one) is returned via the out parameter *pRes.
485 //
486 // Arguments:
487 //   pAppDomain - the appdomain that the type lives in. 
488 //   pType - the open type to instantiate. Eg, CordbType(List<T>)
489 //   pInst - instantiation parameters.
490 //   ppResultType - OUT: out parameter to hold resulting type.
491 //
492 // Returns:
493 //  S_OK on success.
494 //
495 HRESULT CordbType::MkTyAppType(CordbAppDomain * pAppDomain, 
496                                CordbType * pType, 
497                                const Instantiation * pInst, 
498                                CordbType ** ppResultType)
499 {
500     _ASSERTE(pAppDomain == pType->GetAppDomain());
501
502     CordbType * pCordbType = pType;
503
504     // Loop through and create each of the subordinate types, building up to the final fully Closed type.
505     for (unsigned int i = 0; i < pInst->m_cClassTyPars; i++) 
506     {
507
508         CordbType * pCordbBaseType = pCordbType->m_spinetypes.GetBase((UINT_PTR) (pInst->m_ppInst[i]));
509
510         if (pCordbBaseType == NULL)
511         {
512             pCordbBaseType = new (nothrow) CordbType(pCordbType, pInst->m_ppInst[i]);
513
514             if (pCordbBaseType == NULL)
515             {
516                 return E_OUTOFMEMORY;
517             }
518
519             HRESULT hr = pCordbType->m_spinetypes.AddBase(pCordbBaseType);
520
521             if (FAILED(hr))
522             {
523                 _ASSERTE(!"unexpected failure!");
524                 delete pCordbBaseType;
525                 // @dbgtodo Microsoft leaks: Release the previously created types if this fails later in the loop
526                 return hr;
527             }
528
529             pCordbBaseType->m_inst.m_cInst = i + 1;
530             pCordbBaseType->m_inst.m_cClassTyPars = i + 1;
531             pCordbBaseType->m_inst.m_ppInst = new (nothrow) CordbType *[i+1];
532
533             if (pCordbBaseType->m_inst.m_ppInst == NULL) 
534             {
535                 delete pCordbBaseType;
536                 // @dbgtodo Microsoft leaks: Doesn't release the previously created types if this fails later in the loop
537                 return E_OUTOFMEMORY;
538             }
539             
540             for (unsigned int j = 0; j < (i + 1); j++) 
541             {
542                 // Constructed types include pointers across to other types - increase
543                 // the reference counts on these....
544                 pInst->m_ppInst[j]->AddRef();
545
546                 pCordbBaseType->m_inst.m_ppInst[j] = pInst->m_ppInst[j];
547             }
548         }
549         pCordbType = pCordbBaseType;
550     }
551
552     *ppResultType = pCordbType;
553     return S_OK;
554 }
555
556 //-----------------------------------------------------------------------------
557 // Creates a CordbType instantation around a cordbClass and TypeParameter list.
558 // In other words, this does:
559 // CordbClass(List<T>) + Instantiation({T=int}) --> CordbType(List<int>)
560 //
561 // This really just converts CordbClass(List<T>) --> CordbType(List<T>), and then calls CordbType::MkTyAppType
562 //
563 // Arguments:
564 //    pAppDomain - the AD that the class lives in.
565 //    elementType - element type of the class. Either ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE
566 //    pClass - the uninstantiated class (eg, List<T>). This function will fill out the tycon->m_type field
567 //             to an uninstantiated CordbType (eg CordbType(List<T>))
568 //    pInst - the list of type parameters to instantiate with.
569 //    ppResultType - OUT: the CordbType instantiated with the type parameters (eg, CordbType(List<int>))
570 //
571 // Returns:
572 //   S_OK on success.
573 //
574 HRESULT CordbType::MkType(CordbAppDomain * pAppDomain, 
575                           CorElementType elementType,  
576                           CordbClass * pClass, 
577                           const Instantiation * pInst, 
578                           CordbType ** ppResultType)
579 {
580     _ASSERTE(pAppDomain != NULL);
581     _ASSERTE(ppResultType != NULL);
582
583     switch (elementType)
584     {
585       // Normalize E_T_VALUETYPE away, so types do not record whether they are VCs or not, but CorDebugClass does.
586       // Update our view of whether a class is a VC based on the evidence we have here.
587     case ELEMENT_TYPE_VALUETYPE:
588
589       _ASSERTE(((pClass != NULL) && (!pClass->IsValueClassKnown() || pClass->IsValueClassNoInit())) || 
590                !"A non-value class is being used with ELEMENT_TYPE_VALUETYPE");
591
592       pClass->SetIsValueClass(true);
593       pClass->SetIsValueClassKnown(true);
594       // drop through
595
596     case ELEMENT_TYPE_CLASS:
597         {
598             // This probably isn't needed...
599             if (pClass == NULL)
600             {
601                 elementType = ELEMENT_TYPE_OBJECT;
602                 goto LReallyObject;
603             }
604
605             CordbType * pType = NULL;
606
607             pType = pClass->GetType();
608
609             if (pType == NULL)
610             {
611                 pType = new (nothrow) CordbType(pAppDomain, ELEMENT_TYPE_CLASS, pClass);
612
613                 if (pType == NULL)
614                 {
615                     return E_OUTOFMEMORY;
616                 }
617
618                 pClass->SetType(pType);
619             }
620
621             _ASSERTE(pClass->GetType() != NULL);
622
623             return CordbType::MkTyAppType(pAppDomain, pType, pInst, ppResultType);
624         }
625
626     default:
627 LReallyObject:
628         
629         _ASSERTE(pInst->m_cInst == 0);
630         return MkType(pAppDomain, elementType, ppResultType);
631
632     }
633 }
634
635 //-----------------------------------------------------------------------------
636 // Make a CordbType for a function pointer type (ELEMENT_TYPE_FNPTR).
637 // 
638 // Arguments:
639 //   pAppDomain - the Appdomian the type lives in.
640 //   elementType - must be ELEMENT_TYPE_FNPTR.
641 //   pInst - instantiation information.
642 //   ppResultType - OUT: out-parameter to hold resulting CordbType
643 //
644 // Return:
645 //   S_OK on success.
646 //
647 HRESULT CordbType::MkType(CordbAppDomain * pAppDomain, 
648                           CorElementType elementType, 
649                           const Instantiation * pInst, 
650                           CordbType ** ppResultType)
651 {
652     CordbType * pType;
653
654     _ASSERTE(elementType == ELEMENT_TYPE_FNPTR);
655
656     HRESULT hr = MkType(pAppDomain, elementType, &pType);
657
658     if (!SUCCEEDED(hr)) 
659     {
660         return hr;
661     }
662     return CordbType::MkTyAppType(pAppDomain, pType, pInst, ppResultType);
663 }
664
665
666 //-----------------------------------------------------------------------------
667 // Public API to get the CorElementType of the type.
668 // 
669 // Parameters:
670 //    pType - OUT: on return, gets the CorElementType
671 //
672 // Returns:
673 //    S_OK on success. CORDBG_E_CLASS_NOT_LOADED or synchronization errors on failure
674 //-----------------------------------------------------------------------------
675 HRESULT CordbType::GetType(CorElementType *pType)
676 {
677     PUBLIC_REENTRANT_API_ENTRY(this);
678     FAIL_IF_NEUTERED(this);
679     // See if this E_T_CLASS is really a value type?
680     if (m_elementType == ELEMENT_TYPE_CLASS)
681     {
682         _ASSERTE(m_pClass);
683         bool isVC = false;
684         // Determining if something is a VC or not can involve asking the EE.
685         // We could do it ourselves based on the metadata but it's non-trivial
686         // determining if a class has System.ValueType as a parent (we have
687         // to find and OpenScope the mscorlib.dll which we don't currently do
688         // on the right-side).  But the IsValueClass call can fail if the
689         // class is not yet loaded on the right side.  In that case we
690         // ignore the failure and return ELEMENT_TYPE_CLASS
691         HRESULT hr = S_OK;
692         EX_TRY
693         {
694             isVC = m_pClass->IsValueClass();
695         }
696         EX_CATCH_HRESULT(hr);
697         if (!FAILED(hr) && isVC)
698         {
699             *pType = ELEMENT_TYPE_VALUETYPE;
700             return S_OK;
701         }
702     }
703     *pType = m_elementType;
704     return S_OK;
705 }
706
707 //-----------------------------------------------------------------------------
708 // Public method to get the ICorDebugClass that matches this type.
709 // ICorDebugType has instantiated type-params (eg, List<int>), whereas 
710 // ICorDebugClass is open (eg, List<T>).
711 // 
712 // Parameters:
713 //    pClass - OUT: gets class on return.
714 // Returns:
715 //    S_OK on success. CORDBG_E_CLASS_NOT_LOADED if the class is not loaded.
716 //    Else some other error.
717 //-----------------------------------------------------------------------------
718 HRESULT CordbType::GetClass(ICorDebugClass **pClass)
719 {
720     PUBLIC_REENTRANT_API_ENTRY(this);
721     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
722
723     if ((m_pClass == NULL) && (m_elementType == ELEMENT_TYPE_STRING ||
724                                m_elementType == ELEMENT_TYPE_OBJECT))
725     {
726         Init(FALSE);
727     }
728     if (m_pClass == NULL)
729     {
730         *pClass = NULL;
731         return CORDBG_E_CLASS_NOT_LOADED;
732     }
733     *pClass = m_pClass;
734     m_pClass->ExternalAddRef();
735     return S_OK;
736 }
737
738 //-----------------------------------------------------------------------------
739 // Public method to get array rank. This is only valid for arrays.
740 // 
741 // Parameters:
742 //   pnRank - OUT: *pnRank is set to rank on return
743 //
744 // Return:
745 //   S_OK if success. E_INVALIDARG is this Type doesn't have a rank.
746 //-----------------------------------------------------------------------------
747 HRESULT CordbType::GetRank(ULONG32 *pnRank)
748 {
749     PUBLIC_REENTRANT_API_ENTRY(this);
750     VALIDATE_POINTER_TO_OBJECT(pnRank, ULONG32 *);
751
752     if (m_elementType != ELEMENT_TYPE_SZARRAY &&
753         m_elementType != ELEMENT_TYPE_ARRAY)
754         return E_INVALIDARG;
755
756     *pnRank = (ULONG32) m_rank;
757
758     return S_OK;
759 }
760
761 //-----------------------------------------------------------------------------
762 // Public convenience method to get the first type parameter.
763 // This is purely to avoid needing to call EnumerateTypeParameters for 
764 // the set of types that only have 1 type-parameter.
765 // 
766 // Parameters:
767 //    pType - OUT: get the ICorDebugType for the first type-parameter.
768 // Returns:
769 //    S_OK on success.
770 //-----------------------------------------------------------------------------
771 HRESULT CordbType::GetFirstTypeParameter(ICorDebugType **pType)
772 {
773     PUBLIC_REENTRANT_API_ENTRY(this);
774     VALIDATE_POINTER_TO_OBJECT(pType, ICorDebugType **);
775
776     // Since this is a public API, make sure there actually is at least 1 type-parameter.
777     if (m_inst.m_cInst == 0)
778     {
779         return E_INVALIDARG;
780     }
781
782     _ASSERTE(m_inst.m_ppInst != NULL);
783     _ASSERTE(m_inst.m_ppInst[0] != NULL);
784
785     *pType = m_inst.m_ppInst[0];
786     if (*pType)
787         (*pType)->AddRef();
788     return S_OK;
789 }
790
791 //-----------------------------------------------------------------------------
792 // Internal worker to create a CordbType around a CordbClass.
793 // Parameters:
794 //   appdomain - AD that the type lives in.
795 //   et - CorElementType of the incoming CordbClass
796 //   cl - CordbClass representing the type to build a CordbType for
797 //   pRes - OUT: out parameter to return the newly created CordbType object.
798 //
799 // Return:
800 //   S_OK on success. 
801 //-----------------------------------------------------------------------------
802 HRESULT CordbType::MkUnparameterizedType(CordbAppDomain *appdomain, CorElementType et, CordbClass *cl,CordbType **pRes)
803 {
804     // Pass in empty instantiation since CordbClass has no generic info.
805     // We should make some assert between et and cl->GetType().
806     Instantiation emptyInstantiation;
807
808     return CordbType::MkType(appdomain, et, cl, &emptyInstantiation, pRes);
809 }
810
811
812 //-----------------------------------------------------------------------------
813 // Internal helper to get the First type parameter.
814 // This is an internal convenience function for the public GetFirstTypeParameter.
815 //
816 // Parameters:
817 //   pRes - OUT: out-param to get the unary type-parameter.
818 //-----------------------------------------------------------------------------
819 void
820 CordbType::DestUnaryType(CordbType **pRes)
821 {
822     _ASSERTE(m_elementType == ELEMENT_TYPE_PTR
823         || m_elementType == ELEMENT_TYPE_BYREF
824         || m_elementType == ELEMENT_TYPE_ARRAY
825         || m_elementType == ELEMENT_TYPE_SZARRAY);
826     _ASSERTE(m_inst.m_cInst == 1);
827     _ASSERTE(m_inst.m_ppInst != NULL);
828     *pRes = m_inst.m_ppInst[0];
829 }
830
831
832
833 //-----------------------------------------------------------------------------
834 // Internal method to get the Class and type-parameters from a CordbType.
835 //-----------------------------------------------------------------------------
836 void
837 CordbType::DestConstructedType(CordbClass **cls, Instantiation *inst)
838 {
839     ASSERT(m_elementType == ELEMENT_TYPE_CLASS);
840     *cls = m_pClass;
841     *inst = m_inst;
842 }
843
844 //-----------------------------------------------------------------------------
845 // Internal method to get all the type-parameters for a FnPtr
846 //-----------------------------------------------------------------------------
847 void
848 CordbType::DestNaryType(Instantiation *inst)
849 {
850     ASSERT(m_elementType == ELEMENT_TYPE_FNPTR);
851     *inst = m_inst;
852 }
853
854
855 //-----------------------------------------------------------------------------
856 // CordbType::SigToType
857 // Internal helper to create a CordbType from a Metadata signature (SigParser)
858 // 
859 // This parses a metadata signature in the context of a module to return a CordbType.
860 // This heavily relies on the metadata and signature format. See ECMA Partition II for details.
861 // Since signatures may be recursive, this function can be called recursively.
862 // Since metadata signatures exist all over, this can be called in many different scenarios, including 
863 // resolving a TypeSpec, looking up a field.
864 // 
865 // pModule - module that the signature lives in.
866 // pSigParse - Signature, positioned at the point to read the Type from. 
867 //          This will not change the SigParser's current position.
868 // inst - instantiation containing Type Params for the context of the SigParser.
869 //            For a local var or argument lookup, this would be the type-params from the Frame. 
870 //            For a field lookup, this would be the type-params for the containing type.
871 // pRes - OUT: yields the CordbType for this signature.
872 //
873 // Returns:
874 //   S_OK on success
875 //-----------------------------------------------------------------------------
876 HRESULT
877 CordbType::SigToType(CordbModule * pModule, 
878                      SigParser * pSigParser, 
879                      const Instantiation * pInst, 
880                      CordbType ** ppResultType)
881 {
882     FAIL_IF_NEUTERED(pModule);
883     INTERNAL_SYNC_API_ENTRY(pModule->GetProcess());
884
885     _ASSERTE(pSigParser != NULL);
886
887
888     //
889     // Make a local copy of the SigParser since we are going to mutate it.
890     //
891     SigParser sigParser = *pSigParser;
892     
893     CorElementType elementType;
894     HRESULT hr;
895      
896     IfFailRet(sigParser.GetElemType(&elementType));
897
898     switch (elementType)
899     {
900     case ELEMENT_TYPE_VAR:
901     case ELEMENT_TYPE_MVAR:
902         {                        
903             ULONG tyvar_num;
904
905             IfFailRet(sigParser.GetData(&tyvar_num));
906
907
908             if (elementType == ELEMENT_TYPE_VAR)
909             {
910                 // ELEMENT_TYPE_VAR refers to an indexed type-parameter in the containing Type. 
911                 // Eg, we may be doing a field lookup on 'List<T> { T m_head}', and the field's return type 'T' is Type-parameter #0.
912                 // Or this maybe part of a base class's TypeSpec. 
913                 _ASSERTE (tyvar_num < (pInst->m_cClassTyPars));
914                 if (tyvar_num >= (pInst->m_cClassTyPars))
915                     return E_FAIL;
916
917                 _ASSERTE (pInst->m_ppInst != NULL);
918                 *ppResultType = pInst->m_ppInst[tyvar_num];
919             }
920             else
921             {
922                 //ELEMENT_TYPE_MVAR refers to an indexed type-parameter in the containing Method.
923                 // Eg, we may be in Class::Func<T> and refering to T. 
924                 // The Instantiation array has Type type-parameters first, and then any Method Type-parameters. 
925                 // The m_cClassTyPars field indicats where the split is between Type and Method type-parameters. Type type-params
926                 // come first.
927                 _ASSERTE(elementType == ELEMENT_TYPE_MVAR);
928                 
929
930                 _ASSERTE (tyvar_num < (pInst->m_cInst - pInst->m_cClassTyPars));
931                 if (tyvar_num >= (pInst->m_cInst - pInst->m_cClassTyPars))
932                     return E_FAIL;
933
934                 _ASSERTE (pInst->m_ppInst != NULL);
935                 *ppResultType = pInst->m_ppInst[tyvar_num + pInst->m_cClassTyPars];
936             }
937             
938             return S_OK;
939         }
940     case ELEMENT_TYPE_GENERICINST:
941         {
942             //ELEMENT_TYPE_GENERICINST is that start of a instantiated generic type.
943             //Format for the signature blob is:
944             //   1) CorElementType, Token - this is the uninstantiated type (eg, for Pair<int, string>, it would be token for Pair<T,U>)
945             //   2) int - Count of generic args - eg, for Pair<T,U>, it would be "2".
946             //   3) type1,type2, ... - meteadata representation for generic args. For example above, it would be Type(int), Type(string).
947
948
949             // ignore "WITH", look at next ELEMENT_TYPE to get CLASS or VALUE
950             
951             IfFailRet(sigParser.GetElemType(&elementType));
952
953             mdToken token;
954
955             IfFailRet(sigParser.GetToken(&token));
956
957             CordbClass * pClass;
958
959             IfFailRet( pModule->ResolveTypeRefOrDef(token, &pClass));
960
961             // The use of a class in a signature provides definite evidence as to whether it is a VC or not.
962             _ASSERTE(!pClass->IsValueClassKnown() || 
963                      (pClass->IsValueClassNoInit() ==  (elementType == ELEMENT_TYPE_VALUETYPE)) || 
964                      !"A value class is being used with ELEMENT_TYPE_GENERICINST");
965
966             pClass->SetIsValueClass(elementType ==  ELEMENT_TYPE_VALUETYPE);
967             pClass->SetIsValueClassKnown(true);
968
969             // Build up the array of generic arguments.
970             ULONG cArgs; // number of generic arguments in the type.
971
972             IfFailRet(sigParser.GetData(&cArgs));
973
974             S_UINT32 allocSize = S_UINT32( cArgs ) * S_UINT32( sizeof(CordbType *) );
975             
976             if (allocSize.IsOverflow())
977             {
978                 IfFailRet(E_OUTOFMEMORY);
979             }
980
981             CordbType ** ppTypeInstantiations = reinterpret_cast<CordbType **>(_alloca( allocSize.Value()));
982
983             for (unsigned int i = 0; i < cArgs;i++) 
984             {
985                 IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, &ppTypeInstantiations[i]));
986
987                 IfFailRet(sigParser.SkipExactlyOne());
988             }
989
990             // Now we have the Open type (eg, Pair<T,U>) and the instantiation list, so create the Closed CordbType..
991             Instantiation typeInstantiation(cArgs, ppTypeInstantiations);
992
993             return CordbType::MkType(pModule->GetAppDomain(), elementType, pClass, &typeInstantiation, ppResultType);
994         }
995     case ELEMENT_TYPE_CLASS:
996     case ELEMENT_TYPE_VALUETYPE:  // OK: this E_T_VALUETYPE comes from signature
997         {
998             // Path for non-generic types
999
1000             mdToken token;
1001             
1002             IfFailRet(sigParser.GetToken(&token));
1003
1004             CordbClass * pClass;
1005
1006             IfFailRet(pModule->ResolveTypeRefOrDef(token, &pClass));
1007
1008             // The use of a class in a signature provides definite evidence as to whether it is a VC or not.
1009
1010             _ASSERTE(!pClass->IsValueClassKnown() || 
1011                      (pClass->IsValueClassNoInit() ==  (elementType == ELEMENT_TYPE_VALUETYPE)) || 
1012                      !"A non-value class is being used with ELEMENT_TYPE_VALUETYPE");
1013
1014             pClass->SetIsValueClass(elementType ==  ELEMENT_TYPE_VALUETYPE);
1015             pClass->SetIsValueClassKnown(true);
1016
1017             return CordbType::MkUnparameterizedType(pModule->GetAppDomain(), elementType, pClass, ppResultType);
1018         }
1019     case ELEMENT_TYPE_SENTINEL:
1020     case ELEMENT_TYPE_MODIFIER:
1021     case ELEMENT_TYPE_PINNED:
1022         {
1023             IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, ppResultType));
1024             // Throw away SENTINELS on all CordbTypes...
1025             return S_OK;
1026         }
1027     case ELEMENT_TYPE_CMOD_REQD:
1028     case ELEMENT_TYPE_CMOD_OPT:
1029         {
1030             mdToken token;
1031
1032             IfFailRet(sigParser.GetToken(&token));
1033
1034             IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, ppResultType));
1035             // Throw away CMOD on all CordbTypes...
1036             return S_OK;
1037         }
1038
1039     case ELEMENT_TYPE_ARRAY:
1040         {
1041             CordbType * pType;
1042
1043             IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, &pType));
1044
1045             IfFailRet(sigParser.SkipExactlyOne());
1046
1047             ULONG rank;
1048
1049             IfFailRet(sigParser.GetData(&rank));
1050
1051             return CordbType::MkType(pModule->GetAppDomain(), elementType, rank, pType, ppResultType);
1052         }
1053     case ELEMENT_TYPE_SZARRAY:
1054         {
1055             CordbType * pType;
1056
1057             IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, &pType));
1058
1059             return CordbType::MkType(pModule->GetAppDomain(), elementType, 1, pType, ppResultType);
1060         }
1061
1062     case ELEMENT_TYPE_PTR:
1063     case ELEMENT_TYPE_BYREF:
1064         {
1065             CordbType * pType;
1066
1067             IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, &pType));
1068
1069             return CordbType::MkType(pModule->GetAppDomain(),elementType, 0, pType, ppResultType);
1070         }
1071
1072     case ELEMENT_TYPE_FNPTR:
1073         {
1074             ULONG cArgs;
1075
1076             IfFailRet(sigParser.GetData(&cArgs)); // Skip callingConv
1077
1078             IfFailRet(sigParser.GetData(&cArgs)); // Get number of parameters
1079
1080             S_UINT32 allocSize = ( S_UINT32(cArgs) + S_UINT32(1) ) * S_UINT32( sizeof(CordbType *) );
1081
1082             if (allocSize.IsOverflow())
1083             {
1084                 IfFailRet(E_OUTOFMEMORY);
1085             }
1086
1087             CordbType ** ppTypeInstantiations = (CordbType **) _alloca( allocSize.Value() );
1088
1089             for (unsigned int i = 0; i <= cArgs; i++) 
1090             {
1091                 IfFailRet(CordbType::SigToType(pModule, &sigParser, pInst, &ppTypeInstantiations[i]));
1092
1093                 IfFailRet(sigParser.SkipExactlyOne());
1094             }
1095
1096             Instantiation typeInstantiation(cArgs + 1, ppTypeInstantiations);
1097
1098             return CordbType::MkType(pModule->GetAppDomain(), elementType, &typeInstantiation, ppResultType);
1099         }
1100
1101     case ELEMENT_TYPE_VOID:
1102     case ELEMENT_TYPE_BOOLEAN:
1103     case ELEMENT_TYPE_CHAR:
1104     case ELEMENT_TYPE_I1:
1105     case ELEMENT_TYPE_U1:
1106     case ELEMENT_TYPE_I2:
1107     case ELEMENT_TYPE_U2:
1108     case ELEMENT_TYPE_I4:
1109     case ELEMENT_TYPE_U4:
1110     case ELEMENT_TYPE_I8:
1111     case ELEMENT_TYPE_U8:
1112     case ELEMENT_TYPE_R4:
1113     case ELEMENT_TYPE_R8:
1114     case ELEMENT_TYPE_STRING:
1115     case ELEMENT_TYPE_TYPEDBYREF:
1116     case ELEMENT_TYPE_OBJECT:
1117     case ELEMENT_TYPE_I:
1118     case ELEMENT_TYPE_U:
1119         return CordbType::MkType(pModule->GetAppDomain(), elementType, ppResultType);
1120
1121     default:
1122         _ASSERTE(!"unexpected element type!");
1123         return E_FAIL;
1124     }
1125 } // CordbType::SigToType
1126
1127 //-----------------------------------------------------------------------------
1128 // Marshal a DebuggerIPCE_BasicTypeData --> CordbType.
1129 //
1130 // This will build up a DebuggerIPCE_ExpandedTypeData and convert that into
1131 //  a CordbType. This may send additional IPC events if needed to
1132 // go from Basic --> Expanded data. Note that this is designed to handle generics. 
1133 // 
1134 // Parameters:
1135 //   pAppDomain - the AppDomain the type lives in.
1136 //   data - DebuggerIPCE_BasicTypeData from Left-Side containing type description.
1137 //   pRes - OUT: out-parameter to hold built type.
1138 //
1139 // Returns:
1140 //    S_OK on success.
1141 //-----------------------------------------------------------------------------
1142 HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_BasicTypeData *data, CordbType **pRes)
1143 {
1144     FAIL_IF_NEUTERED(pAppDomain);
1145     INTERNAL_SYNC_API_ENTRY(pAppDomain->GetProcess()); //
1146
1147
1148
1149     HRESULT hr = S_OK;
1150     CorElementType et = data->elementType;
1151     switch (et)
1152     {
1153         case ELEMENT_TYPE_ARRAY:
1154         case ELEMENT_TYPE_SZARRAY:
1155         case ELEMENT_TYPE_PTR:
1156         case ELEMENT_TYPE_BYREF:
1157             // For these element types the "Basic" type data only contains the type handle.
1158             // So we fetch some more data, and the go onto the "Expanded" case...
1159             {
1160                 EX_TRY
1161                 {
1162                     DebuggerIPCE_ExpandedTypeData typeInfo;
1163                     CordbProcess * pProcess = pAppDomain->GetProcess();
1164
1165                     {
1166                         RSLockHolder lockHolder(pProcess->GetProcessLock());
1167                         pProcess->GetDAC()->TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,  // could be generics
1168                                                                                              // which are never boxed
1169                                                                          pAppDomain->GetADToken(),
1170                                                                          data->vmTypeHandle,
1171                                                                          &typeInfo);
1172                     }
1173
1174                     IfFailThrow(CordbType::TypeDataToType(pAppDomain,&typeInfo, pRes));
1175                 }
1176                 EX_CATCH_HRESULT(hr);
1177                 return hr;
1178                 
1179             }
1180
1181         case ELEMENT_TYPE_FNPTR:
1182             {
1183                 DebuggerIPCE_ExpandedTypeData e;
1184                 e.elementType = et;
1185                 e.NaryTypeData.typeHandle = data->vmTypeHandle;
1186                 return CordbType::TypeDataToType(pAppDomain, &e, pRes);
1187             }
1188         default:
1189             // For all other element types the "Basic" view of a type
1190             // contains the same information as the "expanded"
1191             // view, so just reuse the code for the Expanded view...
1192             DebuggerIPCE_ExpandedTypeData e;
1193             e.elementType = et;
1194             e.ClassTypeData.metadataToken = data->metadataToken;
1195             e.ClassTypeData.vmDomainFile = data->vmDomainFile;
1196             e.ClassTypeData.vmModule = data->vmModule;
1197             e.ClassTypeData.typeHandle = data->vmTypeHandle;
1198             return CordbType::TypeDataToType(pAppDomain, &e, pRes);
1199     }
1200 }
1201
1202 //-----------------------------------------------------------------------------
1203 // Marshal DebuggerIPCE_ExpandedTypeData --> CordbType
1204 // The ExpandedTypeData just contains top level generic info, and so
1205 // the RS may need to send more IPC events to fill out details.
1206 //
1207 // Parameters:
1208 //   pAppDomain - the appdomain that all the types live in.
1209 //   data - data used to build up CordbType
1210 //   pRes - OUT: out param to get back CordbType on return.
1211 //   
1212 // Returns:
1213 //   S_OK on success.
1214 //-----------------------------------------------------------------------------
1215 HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_ExpandedTypeData *data, CordbType **pRes)
1216 {
1217     INTERNAL_SYNC_API_ENTRY(pAppDomain->GetProcess()); //
1218
1219     CorElementType et = data->elementType;
1220     HRESULT hr = S_OK;
1221     switch (et)
1222     {
1223
1224     case ELEMENT_TYPE_OBJECT:
1225     case ELEMENT_TYPE_VOID:
1226     case ELEMENT_TYPE_BOOLEAN:
1227     case ELEMENT_TYPE_CHAR:
1228     case ELEMENT_TYPE_I1:
1229     case ELEMENT_TYPE_U1:
1230     case ELEMENT_TYPE_I2:
1231     case ELEMENT_TYPE_U2:
1232     case ELEMENT_TYPE_I4:
1233     case ELEMENT_TYPE_U4:
1234     case ELEMENT_TYPE_I8:
1235     case ELEMENT_TYPE_U8:
1236     case ELEMENT_TYPE_R4:
1237     case ELEMENT_TYPE_R8:
1238     case ELEMENT_TYPE_STRING:
1239     case ELEMENT_TYPE_TYPEDBYREF:
1240     case ELEMENT_TYPE_I:
1241     case ELEMENT_TYPE_U:
1242 ETObject:
1243         // It's a primitive (therefore non-generic) type, so we can just create it immediately.
1244         IfFailRet (CordbType::MkType(pAppDomain, et, pRes));
1245         break;
1246
1247     case ELEMENT_TYPE_CLASS:
1248     case ELEMENT_TYPE_VALUETYPE:  // OK: this E_T_VALUETYPE comes from the EE
1249     {
1250         // 
1251         if (data->ClassTypeData.metadataToken == mdTokenNil) {
1252             et = ELEMENT_TYPE_OBJECT;
1253             goto ETObject;
1254         }
1255         CordbModule * pClassModule = NULL;
1256         EX_TRY
1257         {
1258             pClassModule = pAppDomain->LookupOrCreateModule(data->ClassTypeData.vmModule, data->ClassTypeData.vmDomainFile);
1259         }
1260         EX_CATCH_HRESULT(hr);
1261         if( pClassModule == NULL )
1262         {
1263             // We don't know anything about this module - shouldn't happen.
1264             // <TODO>This can be hit by the issue described in VSWhidbey 465120</TODO>
1265             _ASSERTE(!"Unrecognized module");
1266             return CORDBG_E_MODULE_NOT_LOADED;
1267         }
1268
1269         CordbClass *tycon;
1270         IfFailRet (pClassModule->LookupOrCreateClass(data->ClassTypeData.metadataToken,&tycon));
1271         if (!(data->ClassTypeData.typeHandle.IsNull()))
1272         {
1273             // It's a generic type. We have the typehandle, use that to query for the rest of
1274             // the tyeparameters and build up the instantiation for the CordbType.
1275
1276             IfFailRet (CordbType::InstantiateFromTypeHandle(pAppDomain, data->ClassTypeData.typeHandle, et, tycon, pRes));
1277             // Set the type handle regardless of how we found
1278             // the type.  For example if type was already
1279             // constructed without the type handle still set
1280             // it here.
1281             if (*pRes)
1282             {
1283                 (*pRes)->m_typeHandleExact = data->ClassTypeData.typeHandle;
1284             }
1285             break;
1286         }
1287         else
1288         {
1289             // Non generic type. Since we already have the CordbClass for it, we can trivially create the CordbType
1290             IfFailRet (CordbType::MkUnparameterizedType(pAppDomain, et,tycon,pRes));
1291             break;
1292         }
1293
1294     }
1295     case ELEMENT_TYPE_ARRAY:
1296     case ELEMENT_TYPE_SZARRAY:
1297     {
1298         CordbType *argty;
1299         IfFailRet (CordbType::TypeDataToType(pAppDomain, &(data->ArrayTypeData.arrayTypeArg), &argty));
1300         IfFailRet (CordbType::MkType(pAppDomain, et, data->ArrayTypeData.arrayRank, argty, pRes));
1301         break;
1302     }
1303
1304     case ELEMENT_TYPE_PTR:
1305     case ELEMENT_TYPE_BYREF:
1306     {
1307         CordbType *argty;
1308         IfFailRet (CordbType::TypeDataToType(pAppDomain, &(data->UnaryTypeData.unaryTypeArg), &argty));
1309         IfFailRet (CordbType::MkType(pAppDomain, et, 0, argty, pRes));
1310         break;
1311     }
1312     case ELEMENT_TYPE_FNPTR:
1313     {
1314         IfFailRet (CordbType::InstantiateFromTypeHandle(pAppDomain, data->NaryTypeData.typeHandle, et, NULL, pRes));
1315         if (*pRes)
1316         {
1317             (*pRes)->m_typeHandleExact = data->NaryTypeData.typeHandle;
1318         }
1319         break;
1320     }
1321     case ELEMENT_TYPE_END:
1322         *pRes = NULL;
1323         return E_FAIL;
1324
1325     default:
1326         _ASSERTE(!"unexpected element type!");
1327         return E_FAIL;
1328
1329     }
1330     return S_OK;
1331 }
1332
1333 //-----------------------------------------------------------------------------
1334 // CordbType::InstantiateFromTypeHandle
1335 // Internal helper method.
1336 // Builds (Left-Side) TypeHandle --> (Right-Side) CordbType
1337 // This is very useful when we get a typehandle from the LeftSide. A common
1338 // scenario is when we get an Object back from the LS, which happens when
1339 // we build the CordbType corresponding to a Cordb*Value. 
1340 // 
1341 // Parameters:
1342 //   pAppdomain      - the appdomain the type lives in.
1343 //   vmTypeHandle    - a Left-Side typehandle describing the type.
1344 //   elementType     - convenient way to indicate whether we've got ELEMENT_TYPE_FNPTR or 
1345 //                     something else. We should be able to retrieve this from the TypeHandle,
1346 //                     but our caller already has it available.
1347 //   typeConstructor - CordbClass corresponding to the typeHandle. This could be built
1348 //                     up from typehandle, but our caller already has it. 
1349 //                     Will be NULL for ELEMENT_TYPE_FNPTR
1350 //   pResultType     - OUT: out parameter to yield CordbType for the TypeHandle.
1351 //
1352 // Returns:
1353 //    S_OK on success.
1354 //-----------------------------------------------------------------------------
1355 HRESULT CordbType::InstantiateFromTypeHandle(CordbAppDomain * pAppDomain, 
1356                                              VMPTR_TypeHandle vmTypeHandle, 
1357                                              CorElementType   elementType, 
1358                                              CordbClass *     typeConstructor, 
1359                                              CordbType **     pResultType)
1360 {
1361     HRESULT hr = S_OK;
1362
1363     // Should already by synced by caller.
1364     INTERNAL_SYNC_API_ENTRY(pAppDomain->GetProcess()); //
1365     _ASSERTE((pAppDomain->GetProcess()->GetShim() == NULL) || (pAppDomain->GetProcess()->GetSynchronized()));
1366
1367     EX_TRY
1368     {
1369         CordbProcess * pProcess = pAppDomain->GetProcess();
1370         //
1371         // Step 1) Ask DacDbi interface for a list of type-parameters given a TypeHandle.
1372         //
1373
1374         TypeParamsList params;
1375         {
1376             RSLockHolder lockHolder(pProcess->GetProcessLock());
1377             pProcess->GetDAC()->GetTypeHandleParams(pAppDomain->GetADToken(), vmTypeHandle, &params);
1378         }
1379
1380         // convert the parameter type information to a list of CordbTypeInstances (one for each parameter)
1381         // note: typeList will be destroyed on exit, running destructors for each element. In this case, that
1382         // means it will simply assert IsNeutered.
1383         DacDbiArrayList<CordbType *> typeList;
1384         typeList.Alloc(params.Count());
1385         for (int i = 0; i < params.Count(); ++i)
1386         {
1387             IfFailThrow(TypeDataToType(pAppDomain, &(params[i]), &(typeList[i])));
1388         }
1389
1390         // now make an instance of CordbType from an instantiation  
1391         Instantiation instantiation(params.Count(), &(typeList[0]));
1392         if (elementType == ELEMENT_TYPE_FNPTR)
1393         {
1394             IfFailThrow(CordbType::MkType(pAppDomain, elementType, &instantiation, pResultType));
1395         }
1396         else
1397         {
1398             IfFailThrow(CordbType::MkType(pAppDomain, elementType, typeConstructor, &instantiation, pResultType));
1399         }
1400     }
1401     EX_CATCH_HRESULT(hr);
1402     return hr;
1403 } // CordbType::InstantiateFromTypeHandle
1404
1405 //-----------------------------------------------------------------------------
1406 // Initialize the CordbType.
1407 // This will involve a lot of queries to the Left-side.
1408 // This means finding the type-handle, getting / creating associated CordbClass,
1409 // filling out the instantiation, getting field info, etc.
1410 // 
1411 // Parameters:
1412 //   fForceInit - if false, may skip initialization if TypeHandle already known.
1413 //
1414 // Returns:
1415 //   S_OK if success, CORDBG_E_CLASS_NOT_LOADED, E_INVALIDARG, OOM on failure 
1416 //-----------------------------------------------------------------------------
1417 HRESULT CordbType::Init(BOOL fForceInit)
1418 {
1419     INTERNAL_SYNC_API_ENTRY(GetProcess()); //
1420
1421     HRESULT hr = S_OK;
1422
1423     if (m_pClass && m_pClass->GetLoadLevel() != CordbClass::FullInfo)
1424         fForceInit = TRUE;
1425
1426     // Step 1. initialize the type constructor (if one exists)
1427     // and the (class) type parameters....
1428     if (m_elementType == ELEMENT_TYPE_CLASS)
1429     {
1430
1431         // start by initing only enough so that we can determine whether
1432         // or not this is a generic class. When dealing with generic
1433         // type instantiations there is no guarantee the open generic
1434         // type is fully restored. If we load too eagerly it might fail
1435         // and we wouldn't actually need that extra data anyways.
1436         _ASSERTE(m_pClass != NULL);
1437         EX_TRY
1438         {
1439             m_pClass->Init(CordbClass::BasicInfo);
1440         }
1441         EX_CATCH_HRESULT(hr);
1442         IfFailRet(hr);
1443
1444         // non-generic classes need the class object to be fully inited
1445         // in the generic case we won't ever use that data
1446         if (!m_pClass->HasTypeParams())
1447         {
1448             EX_TRY
1449             {
1450                 m_pClass->Init(CordbClass::FullInfo);
1451             }
1452             EX_CATCH_HRESULT(hr);
1453             IfFailRet(hr);
1454
1455             return S_OK; // Non-generic, that's all - no clean-up required
1456         }
1457     }
1458
1459     _ASSERTE(m_elementType != ELEMENT_TYPE_CLASS || m_pClass->HasTypeParams());
1460
1461     for (unsigned int i = 0; i<m_inst.m_cClassTyPars; i++)
1462     {
1463         _ASSERTE(m_inst.m_ppInst != NULL);
1464         _ASSERTE(m_inst.m_ppInst[i] != NULL);
1465         IfFailRet( m_inst.m_ppInst[i]->Init(fForceInit) );
1466     }
1467
1468     // Step 2. Try to fetch the type handle if necessary (only
1469     // for instantiated class types, pointer types etc.)
1470     // We do this by preparing an event specifying the type and
1471     // then fetching the type handle from the left-side.  This
1472     // will not always succeed, as forcing the load of the type handle would be the
1473     // equivalent of doing a FuncEval, i.e. the instantiation may
1474     // not have been created.  But we try anyway to reduce the number of
1475     // failures.
1476     //
1477     // Note that in the normal case we will have the type handle from the EE
1478     // anyway, e.g. if the CordbType was created when reporting the type
1479     // of an actual object.
1480
1481      // Initialize m_typeHandleExact if it needs it
1482      if (m_elementType == ELEMENT_TYPE_ARRAY ||
1483          m_elementType == ELEMENT_TYPE_SZARRAY ||
1484          m_elementType == ELEMENT_TYPE_BYREF ||
1485          m_elementType == ELEMENT_TYPE_PTR ||
1486          m_elementType == ELEMENT_TYPE_FNPTR ||
1487          (m_elementType == ELEMENT_TYPE_CLASS && m_pClass->HasTypeParams()))
1488       {
1489          // It is OK if getting an exact type handle
1490          // fails with CORDBG_E_CLASS_NOT_LOADED.  In that case we leave
1491          // the type information incomplete and subsequent operations
1492          // will try to call Init() again.  The immediate operation will fail later if
1493          // TypeToBasicTypeData requests the exact type information for this type.
1494          hr = InitInstantiationTypeHandle(fForceInit);
1495          if (hr != CORDBG_E_CLASS_NOT_LOADED)
1496              IfFailRet(hr);
1497       }
1498
1499
1500      // For OBJECT and STRING we may not have a value for m_class
1501      // object.  Go try and get it.
1502      if (m_elementType == ELEMENT_TYPE_STRING ||
1503          m_elementType == ELEMENT_TYPE_OBJECT)
1504      {
1505          IfFailRet(InitStringOrObjectClass(fForceInit));
1506      }
1507
1508     // Step 3. Fetch the information that is specific to the type where necessary...
1509     // Now we have the type handle for the constructed type, we can ask for the size of
1510     // the object.  Only do this for constructed value types.
1511     //
1512     // Note that the exact and/or approximate type handles may not be available.
1513     if ((m_elementType == ELEMENT_TYPE_CLASS) && m_pClass->HasTypeParams())
1514     {
1515         IfFailRet(InitInstantiationFieldInfo(fForceInit));
1516     }
1517
1518     return S_OK;
1519 }
1520
1521 //-----------------------------------------------------------------------------
1522 // Internal function to communicate with Left-Side to get an exact TypeHandle 
1523 // (runtime type representation) for this CordbType.
1524 //
1525 // Parameters:
1526 //   fForceInit - if false, may skip initialization if TypeHandle already known.
1527 //
1528 // Returns:
1529 //   S_OK on success or failure HR E_INVALIDARG, OOM, CORDBG_E_CLASS_NOT_LOADED
1530 //   on failure
1531 //-----------------------------------------------------------------------------
1532 HRESULT CordbType::InitInstantiationTypeHandle(BOOL fForceInit)
1533 {
1534
1535     // Check if we've already done this Init
1536     if (!fForceInit && !m_typeHandleExact.IsNull())
1537         return S_OK;
1538
1539     HRESULT hr = S_OK;
1540
1541     // Create an array of DebuggerIPCE_BasicTypeData structures from the array of type parameters.
1542     // First, get a buffer to hold the information
1543     CordbProcess *pProcess = GetProcess();
1544     S_UINT32 bufferSize = S_UINT32(sizeof(DebuggerIPCE_BasicTypeData)) * 
1545                                    S_UINT32(m_inst.m_cClassTyPars);
1546     EX_TRY
1547     {
1548         if( bufferSize.IsOverflow() )
1549         {
1550             ThrowHR(E_INVALIDARG);
1551         }
1552         NewHolder<DebuggerIPCE_BasicTypeData> pArgTypeData(new DebuggerIPCE_BasicTypeData[bufferSize.Value()]); 
1553
1554         // We will have already called Init on each of the type parameters further above. Now we build a
1555         // list of type information for each type parameter.
1556         for (unsigned int i = 0; i < m_inst.m_cClassTyPars; i++)
1557         {
1558             _ASSERTE(m_inst.m_ppInst != NULL);
1559             _ASSERTE(m_inst.m_ppInst[i] != NULL);
1560             IfFailThrow(m_inst.m_ppInst[i]->TypeToBasicTypeData(&pArgTypeData[i]));
1561         }
1562           
1563         DebuggerIPCE_ExpandedTypeData typeData;
1564
1565         // get the top-level type information 
1566         TypeToExpandedTypeData(&typeData);
1567
1568         ArgInfoList argInfo(pArgTypeData, m_inst.m_cClassTyPars);
1569
1570         {
1571             // Get the TypeHandle based on the type data
1572             RSLockHolder lockHolder(GetProcess()->GetProcessLock());
1573             hr = pProcess->GetDAC()->GetExactTypeHandle(&typeData, &argInfo, m_typeHandleExact);
1574         }
1575     }
1576     EX_CATCH_HRESULT(hr);
1577
1578     return hr;
1579 } // CordbType::InitInstantiationTypeHandle
1580
1581 //-----------------------------------------------------------------------------
1582 // Internal helper for CordbType::Init to finish initialize types for
1583 // System.String or System.Object.
1584 //   This just needs to set the m_class field.
1585 //
1586 // Parameters:
1587 //    fForceInit - force re-initialization if already initialized.
1588 //
1589 // Returns:
1590 //    S_OK on success or CORDBG_E_CLASS_NOT_LOADED on failure.
1591 //    
1592 // Note: verification with IPC result may assert  
1593 //-----------------------------------------------------------------------------
1594
1595 HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit)
1596 {
1597     // This CordbType is a non-generic class, either System.String or System.Object.
1598     // Need to find the CordbClass instance (in the proper AppDomain) that matches that type.
1599
1600     // Check if we've already done this Init
1601     if (!fForceInit && m_pClass != NULL)
1602     {
1603         return S_OK;
1604     }
1605
1606     HRESULT hr = S_OK;
1607
1608     EX_TRY
1609     {
1610         //
1611         // Step 1a) Send a request to the DAC to map: CorElementType --> {token, Module} 
1612         //
1613         CordbProcess *pProcess = GetProcess();
1614         mdTypeDef metadataToken;
1615         VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr();
1616         VMPTR_Module vmModule = VMPTR_Module::NullPtr();
1617
1618         {
1619             RSLockHolder lockHolder(GetProcess()->GetProcessLock());
1620             pProcess->GetDAC()->GetSimpleType(m_appdomain->GetADToken(), 
1621                                               m_elementType,
1622                                               &metadataToken,
1623                                               &vmModule,
1624                                               &vmDomainFile);
1625         }
1626
1627         //
1628         // Step 2) Lookup CordbClass based off token + Module.
1629         //
1630         CordbModule * pTypeModule = m_appdomain->LookupOrCreateModule(vmModule, vmDomainFile);
1631         
1632         _ASSERTE(pTypeModule != NULL);
1633         IfFailThrow(pTypeModule->LookupOrCreateClass(metadataToken, &m_pClass));
1634
1635         _ASSERTE(m_pClass != NULL);
1636
1637         _ASSERTE(SUCCEEDED(hr));
1638         m_pClass->AddRef();
1639
1640     }
1641     EX_CATCH_HRESULT(hr);
1642     return hr;
1643 } // CordbType::InitStringOrObjectClass
1644
1645 //-----------------------------------------------------------------------------
1646 // Internal helper for CordbType::Init to get FieldInfos for a generic Type.
1647 // Non-generic types can use the FieldInfos off their associated CordbClass.
1648 //
1649 // Parameters:
1650 //    fForceInit - force re-initialization if already initialized?
1651 //
1652 // Returns:
1653 //    S_OK on success.
1654 //-----------------------------------------------------------------------------
1655 HRESULT CordbType::InitInstantiationFieldInfo(BOOL fForceInit)
1656 {
1657     HRESULT hr = S_OK;
1658
1659     // Check if we've already done this Init
1660     if (!m_fieldInfoNeedsInit && !fForceInit)
1661     {
1662         return hr;
1663     }
1664
1665     _ASSERTE(m_elementType == ELEMENT_TYPE_CLASS);
1666     _ASSERTE(m_pClass->HasTypeParams());
1667
1668     VMPTR_TypeHandle typeHandleApprox = m_typeHandleExact;
1669
1670     // If the exact type handle is not available then get the approximate type handle.
1671     if (typeHandleApprox.IsNull())
1672     {
1673         // set up a buffer to hold type parameter information for the type. (See
1674         // code:CordbType::GatherTypeData for more information). First, compute its size. 
1675         unsigned int typeDataNodeCount = 0;
1676         this->CountTypeDataNodes(&typeDataNodeCount);
1677
1678         EX_TRY
1679         {
1680             // allocate a buffer to hold the parameter data
1681             TypeInfoList typeData;
1682             
1683             typeData.Alloc(typeDataNodeCount); 
1684
1685             // fill the buffer
1686             DebuggerIPCE_TypeArgData * pCurrent = &(typeData[0]);
1687             GatherTypeData(this, &pCurrent);
1688
1689             // request the type handle from the DAC
1690             CordbProcess *pProcess = GetProcess();
1691             {
1692                 RSLockHolder lockHolder(pProcess->GetProcessLock());
1693                 typeHandleApprox = pProcess->GetDAC()->GetApproxTypeHandle(&typeData);
1694             }
1695         }
1696         EX_CATCH_HRESULT(hr);
1697         if(FAILED(hr)) return hr;
1698     }
1699
1700     // OK, now get the field info if we can.
1701     CordbProcess *pProcess = GetProcess();
1702     EX_TRY
1703     {
1704         {
1705             // this may be called multiple times. Each call will discard previous values in m_fieldList and reinitialize
1706             // the list with updated information
1707             RSLockHolder lockHolder(pProcess->GetProcessLock());
1708             pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainFile(),  
1709                                                           m_typeHandleExact, 
1710                                                           typeHandleApprox,
1711                                                           &m_fieldList,
1712                                                           &m_objectSize);
1713         }
1714     }
1715     EX_CATCH_HRESULT(hr);
1716
1717     return hr;
1718 }
1719
1720 HRESULT CordbType::ReturnedByValue()
1721 {
1722     HRESULT hr = S_OK;
1723
1724     if (!IsValueType())
1725         return S_OK;
1726
1727     
1728     ULONG32 unboxedSize = 0;
1729     IfFailRet(GetUnboxedObjectSize(&unboxedSize));
1730     
1731     if (unboxedSize > sizeof(SIZE_T))
1732         return S_FALSE;
1733
1734     mdToken mdClass = m_pClass->GetToken();
1735
1736     int fieldCount = 0;
1737     bool unsupported = false;
1738
1739     HCORENUM fields = 0;
1740     ULONG fetched = 0;
1741     mdToken mdField;
1742     IMetaDataImport *pImport = m_pClass->GetModule()->GetMetaDataImporter();
1743     IfFailRet(pImport->EnumFields(&fields, mdClass, &mdField, 1, &fetched));
1744
1745     while (hr == S_OK && fetched == 1)
1746     {
1747         DWORD attr = 0;
1748         PCCOR_SIGNATURE sigBlob = 0;
1749         ULONG sigLen = 0;
1750         hr = pImport->GetFieldProps(mdField, NULL, NULL, 0, NULL, &attr, &sigBlob, &sigLen, NULL, NULL, NULL);
1751         
1752         if (SUCCEEDED(hr))
1753         {
1754             // !static
1755             if ((attr & 0x10) == 0)
1756             {
1757                 if (fieldCount++)
1758                     break;
1759
1760                 CorElementType et;
1761                 SigParser parser(sigBlob, sigLen);
1762                 parser.GetByte(NULL);           // 0x6, field signature
1763                 parser.SkipCustomModifiers();
1764                 hr = parser.GetElemType(&et);
1765                 if (SUCCEEDED(hr))
1766                 {
1767                     switch (et)
1768                     {
1769                     case ELEMENT_TYPE_R4:
1770                     case ELEMENT_TYPE_R8:
1771                         unsupported = true;
1772                         break;
1773
1774                     case ELEMENT_TYPE_CLASS:
1775                     case ELEMENT_TYPE_STRING:
1776                     case ELEMENT_TYPE_PTR:
1777                         // OK
1778                         break;
1779
1780                     default:
1781                         if (!CorIsPrimitiveType(et))
1782                             unsupported = true;
1783                         break;
1784                     }
1785
1786                     if (unsupported)
1787                         break;
1788                 }
1789             }
1790             
1791             hr = pImport->EnumFields(&fields, mdClass, &mdField, 1, &fetched);
1792         }
1793         
1794         if (FAILED(hr))
1795         {
1796             pImport->CloseEnum(fields);
1797             return hr;
1798         }
1799     }
1800     
1801     pImport->CloseEnum(fields);
1802
1803     if (unsupported)
1804         return S_FALSE;
1805
1806     return fieldCount <= 1 ? S_OK : S_FALSE;
1807 }
1808
1809
1810 //-----------------------------------------------------------------------------
1811 // Internal helper to get the size (in bytes) of the unboxed object.
1812 // For a generic type, the size of the type depends on the size of the
1813 // type-parameters.
1814 // This is commonly used by Cordb*Value in their Initialization when they
1815 // need to cache the size of the Target object they refer to.
1816 //
1817 // This should only be called on Value-types and Primitives (eg, i4, FnPtr).
1818 // It should not be called on Reference types.
1819 //
1820 // Parameters:
1821 //   pObjectSize - OUT: out-parameter to get the size in bytes.
1822 //
1823 // Returns:
1824 //    S_OK on success.
1825 //-----------------------------------------------------------------------------
1826 HRESULT
1827 CordbType::GetUnboxedObjectSize(ULONG32 *pObjectSize)
1828 {
1829     INTERNAL_SYNC_API_ENTRY(GetProcess()); //
1830
1831     HRESULT hr = S_OK;
1832     bool isVC = false;
1833         
1834     EX_TRY
1835     {
1836         isVC = IsValueType();
1837     }
1838     EX_CATCH_HRESULT(hr);
1839
1840     IfFailRet(hr);
1841
1842     if (isVC)
1843     {
1844         *pObjectSize = 0;
1845
1846         hr = Init(FALSE);
1847
1848         if (!SUCCEEDED(hr))
1849             return hr;
1850
1851         *pObjectSize = (ULONG) ((!m_pClass->HasTypeParams()) ? m_pClass->ObjectSize() : this->m_objectSize);
1852
1853         return hr;
1854     }
1855     else
1856     {
1857         // Caller gaurantees that we're not a class. And the check above guarantees we're not a value-type.
1858         // So we're some sort of primitive, and thus we can determine size from the signature.
1859         // 
1860         // @dbgtodo inspection - We didn't have this assert in Whidbey, and it's firing in vararg 
1861         // scenarios even though it's returning the right value for reference types (i.e. 4 on x86 and 8 on
1862         // 64-bit).  Commenting it out for now.
1863         //_ASSERTE(m_elementType != ELEMENT_TYPE_CLASS);
1864
1865         // We need to use a temporary variable here -- attempting to cast among pointer types
1866         // (i.e., (PCCOR_SIGNATURE) &m_elementType) yields incorrect results on big-endian machines
1867         COR_SIGNATURE corSig = (COR_SIGNATURE) m_elementType;
1868         
1869         SigParser sigParser(&corSig, sizeof(corSig));
1870
1871         ULONG size;
1872
1873         IfFailRet(sigParser.PeekElemTypeSize(&size));
1874
1875         *pObjectSize = size;
1876         return hr;
1877     }
1878 }
1879
1880 VMPTR_DomainFile CordbType::GetDomainFile()
1881 {
1882     if (m_pClass != NULL)
1883     {
1884         CordbModule * pModule = m_pClass->GetModule();
1885         if (pModule)
1886         {
1887             return pModule->m_vmDomainFile; 
1888         }
1889         else 
1890         {
1891             return VMPTR_DomainFile::NullPtr();
1892         }
1893     }
1894     else 
1895     {
1896         return VMPTR_DomainFile::NullPtr();
1897     }
1898 }
1899
1900
1901 VMPTR_Module CordbType::GetModule()
1902 {
1903     if (m_pClass != NULL)
1904     {
1905         CordbModule * pModule = m_pClass->GetModule();
1906         if (pModule)
1907         {
1908             return pModule->GetRuntimeModule(); 
1909         }
1910         else 
1911         {
1912             return VMPTR_Module::NullPtr();
1913         }
1914     }
1915     else 
1916     {
1917         return VMPTR_Module::NullPtr();
1918     }
1919 }
1920 //-----------------------------------------------------------------------------
1921 // Internal method to Marshal:  CordbType --> DebuggerIPCE_BasicTypeData
1922 // Nb. CordbType::Init will call this.  The operation
1923 // fails if the exact type information has been requested but was not available
1924 //
1925 // Parameters:
1926 //   data - OUT: BasicTypeData instance to fill out.
1927 // 
1928 // Returns:
1929 //   S_OK on success, CORDBG_E_CLASS_NOT_LOADED on failure
1930 //-----------------------------------------------------------------------------
1931 HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data)
1932 {
1933     switch (m_elementType)
1934     {
1935     case ELEMENT_TYPE_ARRAY:
1936     case ELEMENT_TYPE_SZARRAY:
1937     case ELEMENT_TYPE_BYREF:
1938     case ELEMENT_TYPE_PTR:
1939         data->elementType = m_elementType;
1940         data->metadataToken = mdTokenNil;        
1941         data->vmDomainFile = VMPTR_DomainFile::NullPtr();
1942         data->vmTypeHandle = m_typeHandleExact;
1943         if (data->vmTypeHandle.IsNull())
1944         {
1945             return CORDBG_E_CLASS_NOT_LOADED;
1946         }
1947         _ASSERTE(!data->vmTypeHandle.IsNull());
1948         break;
1949
1950     case ELEMENT_TYPE_CLASS:
1951         _ASSERTE(m_pClass != NULL);
1952         data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS;
1953         data->metadataToken = m_pClass->MDToken();
1954             data->vmDomainFile = GetDomainFile();
1955         data->vmTypeHandle = m_typeHandleExact;
1956         if (m_pClass->HasTypeParams() && data->vmTypeHandle.IsNull())
1957         {
1958             return CORDBG_E_CLASS_NOT_LOADED;
1959         }
1960         break;
1961     default:
1962         // This includes all the "primitive" types, in which CorElementType is a sufficient description.
1963         data->elementType = m_elementType;
1964         data->metadataToken = mdTokenNil;
1965         data->vmDomainFile = VMPTR_DomainFile::NullPtr();
1966         data->vmTypeHandle = VMPTR_TypeHandle::NullPtr();
1967         break;
1968     }
1969     return S_OK;
1970 }
1971
1972 //-----------------------------------------------------------------------------
1973 // Internal method to marshal: CordbType --> ExpandedTypeData
1974 //
1975 // Nb. CordbType::Init need NOT have been called before this...
1976 // Also, this does not write the type arguments.  How this is done depends
1977 // depends on where this is called from.
1978 //
1979 // Parameters:
1980 //     data - OUT: outgoing ExpandedTypeData to fill in with stats about CordbType.
1981 //-----------------------------------------------------------------------------
1982 void CordbType::TypeToExpandedTypeData(DebuggerIPCE_ExpandedTypeData *data)
1983 {
1984
1985     switch (m_elementType)
1986     {
1987     case ELEMENT_TYPE_ARRAY:
1988     case ELEMENT_TYPE_SZARRAY:
1989
1990         data->ArrayTypeData.arrayRank = m_rank;
1991         data->elementType = m_elementType;
1992         break;
1993
1994     case ELEMENT_TYPE_BYREF:
1995     case ELEMENT_TYPE_PTR:
1996     case ELEMENT_TYPE_FNPTR:
1997
1998         data->elementType = m_elementType;
1999         break;
2000
2001     case ELEMENT_TYPE_CLASS:
2002         {
2003             data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS;
2004             data->ClassTypeData.metadataToken = m_pClass->GetToken();
2005             data->ClassTypeData.vmDomainFile = GetDomainFile();
2006             data->ClassTypeData.vmModule = GetModule();
2007             data->ClassTypeData.typeHandle = VMPTR_TypeHandle::NullPtr();
2008
2009             break;
2010         }
2011     case ELEMENT_TYPE_END:
2012         _ASSERTE(!"bad element type!");
2013
2014     default:
2015         data->elementType = m_elementType;
2016         break;
2017     }
2018 }
2019
2020
2021 void CordbType::TypeToTypeArgData(DebuggerIPCE_TypeArgData *data)
2022 {
2023   TypeToExpandedTypeData(&(data->data));
2024   data->numTypeArgs = m_inst.m_cClassTyPars;
2025 }
2026
2027
2028 //-----------------------------------------------------------------------------
2029 // Query if this CordbType represents a ValueType (Does not include primitives).
2030 // Since CordbType doesn't record ValueType status, this may involve querying
2031 // the CordbClass or even asking the Left-Side (if the CordbClass is not init)
2032 // 
2033 // Return Value:
2034 //   indicates whether this is a value type
2035 // Note:
2036 //    Throws.
2037 //-----------------------------------------------------------------------------
2038 bool CordbType::IsValueType()
2039 {
2040   if (m_elementType == ELEMENT_TYPE_CLASS)
2041   {
2042       return m_pClass->IsValueClass();
2043   }
2044   else 
2045         return false;
2046 }
2047
2048 //------------------------------------------------------------------------
2049 // If this is a ptr type, get the CordbType that it points to.
2050 // Eg, for CordbType("Int*") or CordbType("Int&"), returns CordbType("Int").
2051 // If not a ptr type, returns null.
2052 // Since it's all internal, no reference counting.
2053 // This is effectively a specialized version of DestUnaryType.
2054 //------------------------------------------------------------------------
2055 CordbType * CordbType::GetPointerElementType()
2056 {
2057     if ((m_elementType != ELEMENT_TYPE_PTR) && (m_elementType != ELEMENT_TYPE_BYREF))
2058     {
2059         return NULL;
2060     }
2061
2062     CordbType * pOut;
2063     DestUnaryType(&pOut);
2064
2065     _ASSERTE(pOut != NULL);
2066     return pOut;
2067 }
2068 //------------------------------------------------------------------------
2069 // Helper for IsGcRoot.
2070 // Determine if the element type is a non GC-root candidate.
2071 // Updating GC-roots requires coordinating with the GC's write-barrier.
2072 // Whereas non-GC roots can be updated more freely.
2073 // 
2074 // Parameters: 
2075 //   et - An element type.
2076 // Returns:
2077 //   True if variables of et can be used as a GC root.
2078 //------------------------------------------------------------------------
2079 static inline bool IsElementTypeNonGcRoot(CorElementType et)
2080 {
2081     // Functon ptrs are raw data, not GC-roots.
2082     if (et == ELEMENT_TYPE_FNPTR)
2083     {
2084         return true;
2085     }
2086
2087     // This is almost exactly if we're a primitive, but
2088     // primitives include some things that could be GC-roots, so we strip those out,
2089     return CorIsPrimitiveType(et)
2090         && (et != ELEMENT_TYPE_STRING) && (et != ELEMENT_TYPE_VOID); // exlcude these from primitives
2091
2092 }
2093 //------------------------------------------------------------------------
2094 // Helper for IsGcRoot
2095 // Non-gc roots include Value types + non-gc elemement types (like E_T_I4, E_T_FNPTR)
2096 // 
2097 // Parameters:
2098 //   pType - type to check whether it's a GC-root.
2099 // Returns:
2100 //   true if we know we're not a GC-root
2101 //   false if we still might be (so caller must do further checkin)
2102 //------------------------------------------------------------------------
2103 static inline bool _IsNonGCRootHelper(CordbType * pType)
2104 {
2105     _ASSERTE(pType != NULL);
2106
2107     CorElementType et = pType->GetElementType();
2108     if (IsElementTypeNonGcRoot(et))
2109     {
2110         return true;
2111     }
2112
2113     HRESULT hr = S_OK;
2114     bool fValueClass = false;
2115
2116     // If we are a value-type, then we can't be a Gc-root.
2117     EX_TRY
2118     {
2119         fValueClass = pType->IsValueType();
2120     }
2121     EX_CATCH_HRESULT(hr);
2122     if (FAILED(hr) || fValueClass)
2123     {
2124         return true;
2125     }
2126
2127     // Don't know
2128     return false;
2129 }
2130
2131 //-----------------------------------------------------------------------------
2132 // Is this type a GC-root. (Not to be confused w/ "does this contain embedded GC roots")
2133 // All object references are GC-roots. E_T_PTR are actually not GC-roots.
2134 //
2135 // Returns:
2136 //    True - if this is a GC-root.
2137 //    False - not a GC root.
2138 //-----------------------------------------------------------------------------
2139 bool CordbType::IsGCRoot()
2140 {
2141     // If it's a E_T_PTR type, then look at what it's a a pointer of.
2142     CordbType * pPtr = this->GetPointerElementType();
2143     if (pPtr == NULL)
2144     {
2145         // If non pointer, than we can just look at our current type.
2146         return !_IsNonGCRootHelper(this);
2147     }
2148
2149     return !_IsNonGCRootHelper(pPtr);
2150 }
2151
2152
2153 //------------------------------------------------------------------------
2154 // Public function to enumerate type-parameters.
2155 // Parameters:
2156 //    ppTypeParameterEnum - OUT: on return, get an enumerator.
2157 // Returns:
2158 //    S_OK on success.
2159 //------------------------------------------------------------------------
2160 HRESULT CordbType::EnumerateTypeParameters(ICorDebugTypeEnum **ppTypeParameterEnum)
2161 {
2162     PUBLIC_API_ENTRY(this);
2163     VALIDATE_POINTER_TO_OBJECT(ppTypeParameterEnum, ICorDebugTypeEnum **);
2164     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2165
2166
2167     CordbTypeEnum *icdTPE = CordbTypeEnum::Build(m_appdomain, m_appdomain->GetLongExitNeuterList(), this->m_inst.m_cInst, this->m_inst.m_ppInst);
2168     if ( icdTPE == NULL )
2169     {
2170         (*ppTypeParameterEnum) = NULL;
2171         return E_OUTOFMEMORY;
2172     }
2173
2174     (*ppTypeParameterEnum) = static_cast<ICorDebugTypeEnum*> (icdTPE);
2175     icdTPE->ExternalAddRef();
2176     return S_OK;
2177 }
2178
2179
2180 //-----------------------------------------------------------------------------
2181 // CordbType::GetBase
2182 // Public convenience method to get the instantiated base type.
2183 //
2184 // Parameters:
2185 //   ppType - OUT: yields the base type for the current type.
2186 //
2187 // Returns:
2188 //   S_OK if succeeded.
2189 //
2190 HRESULT CordbType::GetBase(ICorDebugType ** ppType)
2191 {
2192     PUBLIC_REENTRANT_API_ENTRY(this);
2193     ATT_ALLOW_LIVE_DO_STOPGO(this->GetProcess()); // @todo - can this by RequiredStopped?
2194
2195     HRESULT hr = S_OK;
2196
2197     LOG((LF_CORDB, LL_EVERYTHING, "CordbType::GetBase called\n"));
2198
2199     VALIDATE_POINTER_TO_OBJECT(ppType, ICorDebugType **);
2200
2201     if (m_elementType != ELEMENT_TYPE_CLASS)
2202     {
2203         return E_INVALIDARG;
2204     }
2205
2206     EX_TRY
2207     {
2208         CordbType * pType = NULL;
2209
2210         _ASSERTE(m_pClass != NULL);
2211
2212         // Get the supertype from metadata for m_class
2213         mdToken extendsToken;
2214
2215         IMetaDataImport * pImport = m_pClass->GetModule()->GetMetaDataImporter(); // throws
2216         
2217         hr = pImport->GetTypeDefProps(m_pClass->MDToken(), NULL, 0, NULL, NULL, &extendsToken);
2218         IfFailThrow(hr);
2219
2220         // Now create a CordbType instance for the base type that has the same type parameters as the derived type.
2221         if ((extendsToken == mdTypeDefNil) || (extendsToken == mdTypeRefNil) || (extendsToken == mdTokenNil))
2222         {
2223             // No base class.
2224             pType = NULL;
2225         }
2226         else if (TypeFromToken(extendsToken) == mdtTypeSpec)
2227         {
2228             // TypeSpec has a signature. So get the sig and convert it to a CordbType.
2229             // generic base class of a generic type is a TypeSpec.
2230             // If we have: 
2231             //    class Triple<T,U,V> derives from Pair<T,V>,
2232             // then the base class for Triple would be a TypeSpec: 
2233             //   Class(Pair<T,V>), 2 args, ELEMENT_TYPE_VAR #0, ELEMENT_TYPE_VAR#2.
2234             // m_inst provides the type-parameters to resolve the ELEMENT_TYPE_VAR types.
2235
2236             PCCOR_SIGNATURE pSig;
2237             ULONG sigSize;
2238
2239             // Get the signature for the constructed supertype...
2240             hr = pImport->GetTypeSpecFromToken(extendsToken, &pSig, &sigSize);
2241             IfFailThrow(hr);
2242
2243             _ASSERTE(pSig != NULL);
2244
2245             SigParser sigParser(pSig, sigSize);
2246
2247             // Instantiate the signature of the supertype using the type instantiation for
2248             // the current type....
2249             hr = SigToType(m_pClass->GetModule(), &sigParser, &m_inst, &pType);
2250             IfFailThrow(hr);
2251         }
2252         else if ((TypeFromToken(extendsToken) == mdtTypeRef) || (TypeFromToken(extendsToken) == mdtTypeDef))
2253         {        
2254             // TypeDef/TypeRef for non-generic base-class class.
2255             CordbClass * pSuperClass;
2256
2257             hr = m_pClass->GetModule()->ResolveTypeRefOrDef(extendsToken, &pSuperClass);
2258             IfFailThrow(hr);
2259
2260             _ASSERTE(pSuperClass != NULL);
2261             
2262             hr = MkUnparameterizedType(m_appdomain, ELEMENT_TYPE_CLASS, pSuperClass, &pType);
2263             IfFailThrow(hr);
2264         }
2265         else
2266         {
2267             pType = NULL;
2268             _ASSERTE(!"unexpected token!");
2269         }
2270
2271         // At this point, we've succeeded
2272         _ASSERTE(SUCCEEDED(hr));        
2273         
2274         (*ppType) = pType;
2275
2276         if (*ppType)
2277         {
2278             pType->AddRef();
2279         }
2280     }
2281     EX_CATCH_HRESULT(hr);
2282     return hr;
2283 }
2284
2285 //-----------------------------------------------------------------------------
2286 // CordbType::GetTypeID
2287 // Method to get the COR_TYPEID corresponding to this CordbType.
2288 //
2289 // Parameters:
2290 //   pId - OUT: gives the COR_TYPEID for this CordbType
2291 //
2292 // Returns:
2293 //   S_OK if succeeded.
2294 //   CORDBG_E_CLASS_NOT_LOADED if the type which this CordbType represents has
2295 //       not been loaded in the runtime.
2296 //  E_POINTER if pId is NULL
2297 //  CORDBG_E_UNSUPPORTED for unsupported types.
2298 //
2299 HRESULT CordbType::GetTypeID(COR_TYPEID *pId)
2300 {
2301     LOG((LF_CORDB, LL_INFO1000, "GetTypeID\n"));
2302     if (pId == NULL)
2303         return E_POINTER;
2304     
2305     HRESULT hr = S_OK;
2306
2307     PUBLIC_API_ENTRY(this);
2308     RSLockHolder stopGoLock(GetProcess()->GetStopGoLock());
2309     RSLockHolder procLock(GetProcess()->GetProcessLock());
2310
2311     EX_TRY
2312     {
2313         hr = Init(FALSE);
2314         IfFailThrow(hr);
2315
2316         VMPTR_TypeHandle vmTypeHandle;
2317             
2318         CorElementType et = GetElementType();
2319         switch (et)
2320         {
2321         case ELEMENT_TYPE_OBJECT:
2322         case ELEMENT_TYPE_VOID:
2323         case ELEMENT_TYPE_BOOLEAN:
2324         case ELEMENT_TYPE_CHAR:
2325         case ELEMENT_TYPE_I1:
2326         case ELEMENT_TYPE_U1:
2327         case ELEMENT_TYPE_I2:
2328         case ELEMENT_TYPE_U2:
2329         case ELEMENT_TYPE_I4:
2330         case ELEMENT_TYPE_U4:
2331         case ELEMENT_TYPE_I8:
2332         case ELEMENT_TYPE_U8:
2333         case ELEMENT_TYPE_R4:
2334         case ELEMENT_TYPE_R8:
2335         case ELEMENT_TYPE_STRING:
2336         case ELEMENT_TYPE_TYPEDBYREF:
2337         case ELEMENT_TYPE_I:
2338         case ELEMENT_TYPE_U:
2339             {
2340                 mdTypeDef mdToken;
2341                 VMPTR_Module vmModule = VMPTR_Module::NullPtr();
2342                 VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr();
2343
2344                 // get module and token of the simple type
2345                 GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(),
2346                                                       et,
2347                                                       &mdToken,
2348                                                       &vmModule,
2349                                                       &vmDomainFile);
2350                 
2351                 vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken);
2352             }
2353             break;
2354         case ELEMENT_TYPE_ARRAY:
2355         case ELEMENT_TYPE_SZARRAY:
2356             {
2357                 LOG((LF_CORDB, LL_INFO1000, "GetTypeID: parameterized type\n"));
2358                 if (m_typeHandleExact.IsNull())
2359                 {
2360                     hr = InitInstantiationTypeHandle(FALSE);
2361                     IfFailThrow(hr);
2362                 }
2363                 vmTypeHandle = m_typeHandleExact;
2364             }
2365             break;
2366         case ELEMENT_TYPE_CLASS:
2367             {
2368                 ICorDebugClass *pICDClass = NULL;
2369                 hr = GetClass(&pICDClass);
2370                 IfFailThrow(hr);
2371                 CordbClass *pClass = (CordbClass*)pICDClass;
2372                 _ASSERTE(pClass != NULL);
2373                 
2374                 if (pClass->HasTypeParams())
2375                 {
2376                     vmTypeHandle = m_typeHandleExact;
2377                 }
2378                 else
2379                 {
2380                     mdTypeDef mdToken;
2381                     hr = pClass->GetToken(&mdToken);
2382                     IfFailThrow(hr);
2383                     
2384                     VMPTR_Module vmModule = GetModule();
2385                     vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken);
2386                 }
2387             }
2388             break;
2389         case ELEMENT_TYPE_PTR:
2390         case ELEMENT_TYPE_BYREF:
2391         case ELEMENT_TYPE_FNPTR:
2392             IfFailThrow(CORDBG_E_UNSUPPORTED);
2393         default:
2394             _ASSERTE(!"unexpected element type!");
2395             IfFailThrow(CORDBG_E_UNSUPPORTED);
2396             break;
2397         }
2398
2399         GetProcess()->GetDAC()->GetTypeIDForType(vmTypeHandle, pId);
2400     }
2401     EX_CATCH_HRESULT(hr);
2402
2403     return hr;
2404 }
2405
2406 //-----------------------------------------------------------------------------
2407 // Get rich field information given a token.
2408 // 
2409 // Parameters:
2410 //    fldToken - metadata field token specifying a field on this Type.
2411 //    ppFieldData - OUT: get the rich field information for the given field
2412 //
2413 // Returns:
2414 //   S_OK on success. CORDBG_E_ENC_HANGING_FIELD for EnC fields (common case)
2415 //   Other errors on failure case.
2416 //-----------------------------------------------------------------------------
2417 HRESULT CordbType::GetFieldInfo(mdFieldDef fldToken, FieldData ** ppFieldData)
2418 {
2419     INTERNAL_SYNC_API_ENTRY(GetProcess()); //
2420     HRESULT hr = S_OK;
2421
2422     *ppFieldData = NULL;
2423
2424     EX_TRY
2425     {
2426         if (m_elementType != ELEMENT_TYPE_CLASS)
2427         {
2428             ThrowHR(E_INVALIDARG);
2429         }        
2430
2431         // Initialize so that the field information is up-to-date.
2432         hr = Init(FALSE);
2433         IfFailThrow(hr);
2434
2435         if (m_pClass->HasTypeParams())
2436         {
2437             if (m_fieldList.IsEmpty())
2438             {
2439                 ThrowHR(CORDBG_E_FIELD_NOT_AVAILABLE);
2440             }
2441             else
2442             {
2443                 // Use a static helper function in CordbClass, though we're really
2444                 // searching through this->m_fields
2445                 hr = CordbClass::SearchFieldInfo(m_pClass->GetModule(), 
2446                                                  &m_fieldList, 
2447                                                  m_pClass->MDToken(), 
2448                                                  fldToken, 
2449                                                  ppFieldData);
2450                 // fall through and return.
2451                 // Let possible CORDBG_E_ENC_HANGING_FIELD errors propogate
2452             }
2453         }
2454         else
2455         {
2456             hr = m_pClass->GetFieldInfo(fldToken, ppFieldData); // this is for non-generic types....
2457             // Let possible CORDBG_E_ENC_HANGING_FIELD errors propogate
2458         }
2459     }
2460     EX_CATCH_HRESULT(hr);
2461     _ASSERTE(SUCCEEDED(hr) == (*ppFieldData != NULL));
2462     return hr;
2463 }
2464
2465
2466 //-----------------------------------------------------------------------------
2467 // Class is a class somewhere on the hierarchy for m_type.  Search for
2468 // a CordbType corresponding to the CordbClass, but which has the type-parameters
2469 // from the current CordbType.
2470 // In other words, instantiate a CordbType from baseClass, using the type-params
2471 // in the current Type.
2472 // 
2473 // For example, given:
2474 //     class C<T>
2475 //     class D : C<int>
2476 // then if the CordbObjectValue is of type D and pClass is the class
2477 // for "C", then searching will set relevantType to C<int>.  This
2478 // type is then used to fetch fields from the object.
2479 //
2480 // Adds a reference to the resulting type.  Since this is for internal
2481 // use only we probably don't need todo this...
2482 //
2483 // Parameters:
2484 //   baseClass - open Type that needs to be instantiated with this CordbType's params.
2485 //   ppRes - OUT: out-parameter to get CordbType. ppRes->GetClass() should equal baseClass.
2486 //
2487 // Returns:
2488 //    S_OK on success. CORDBG_E_OBJECT_NEUTERED, CORDBG_E_CLASS_NOT_LOADED, E_INVALIDARG, OOM
2489 //-----------------------------------------------------------------------------
2490 HRESULT CordbType::GetParentType(CordbClass *baseClass, CordbType **ppRes)
2491 {
2492     INTERNAL_SYNC_API_ENTRY(GetProcess()); //
2493
2494     // Ensure that we're not trying to match up against a neutered class.
2495     if (baseClass->IsNeutered())
2496     {
2497         return CORDBG_E_OBJECT_NEUTERED;
2498     }
2499
2500     HRESULT hr = S_OK;
2501     _ASSERTE(ppRes);
2502     *ppRes = NULL;
2503     CordbType *res = this;
2504     res->AddRef();
2505     int safety = 20000; // no inheritance hierarchy is 20000 deep... we include this just in case there's a issue below and we don't terminate
2506     while (safety--)
2507     {
2508         if (res->m_pClass == NULL)
2509         {
2510             if (FAILED(hr = res->Init(FALSE)))
2511             {
2512                 res->Release();
2513                 return hr;
2514             }
2515         }
2516         _ASSERTE(res->m_pClass);
2517         if (res->m_pClass == baseClass)
2518         {
2519             // Found it!
2520             break;
2521         }
2522
2523         // Another way to determine if we're talking about the
2524         // same class...  Compare tokens and module.
2525         mdTypeDef tok;
2526         mdTypeDef targetTok;
2527         if (FAILED(hr = res->m_pClass->GetToken(&tok))
2528             || FAILED(hr = baseClass->GetToken(&targetTok)))
2529         {
2530             res->Release();
2531             return hr;
2532         }
2533         if (tok == targetTok && res->m_pClass->GetModule() == baseClass->GetModule())
2534         {
2535             // Found it!
2536             break;
2537         }
2538
2539         // OK, this is not the right class so look up the inheritance chain
2540         ICorDebugType *nextType = NULL;
2541         if (FAILED(hr = res->GetBase(&nextType)))
2542         {
2543             res->Release();
2544             return hr;
2545         }
2546
2547         res->Release(); // matches the AddRef above and/or the one implicit in GetBase, for all but last time around the loop
2548         res = static_cast<CordbType *> (nextType);
2549         if (!res || res->m_elementType == ELEMENT_TYPE_OBJECT)
2550         {
2551             // Did not find it...
2552             break;
2553         }
2554     }
2555     // We exit the loop above owning one reference to res.
2556     // Upon exit res will either be the appropriate type for the
2557     // class we're looking for or will be the CordbType for System.Object
2558     // or will be NULL
2559
2560     // If it's System.Object then assume something's gone wrong with
2561     // the way we did the search and bail out to an old fashioned
2562     // MkUnparameterizedType on the class given originally
2563     if (!res || res->m_elementType == ELEMENT_TYPE_OBJECT)
2564     {
2565         if (res)
2566             res->Release();  // matches the one left over from the loop
2567         IfFailRet(CordbType::MkUnparameterizedType(baseClass->GetAppDomain(), ELEMENT_TYPE_CLASS, baseClass, &res));
2568         res->AddRef();
2569     }
2570
2571
2572     *ppRes = res;
2573     return hr;
2574 }
2575
2576
2577 //-----------------------------------------------------------------------------
2578 // Walk a type tree, writing the number of type args including internal nodes.
2579 //
2580 // Parameters:
2581 //    count - IN/OUT: counter to update. 
2582 //-----------------------------------------------------------------------------
2583 void CordbType::CountTypeDataNodes(unsigned int *count)
2584 {
2585   (*count)++;
2586   for (unsigned int i = 0; i < this->m_inst.m_cClassTyPars; i++)
2587   {
2588       this->m_inst.m_ppInst[i]->CountTypeDataNodes(count);
2589   }
2590 }
2591
2592 //-----------------------------------------------------------------------------
2593 // Internal helper method.
2594 // Counts the total generic args (including sub-args) for an Instantiation.
2595 // Eg, for List<int, Pair<string, float>>, it would return 3.
2596 //
2597 // Parameters:
2598 //    genericArgsCount - size of the genericArgs array in elements.
2599 //    genericArgs - array of type parameters.
2600 //    count - IN/OUT - will increment with total number of generic args.
2601 //        caller must intialize this (likely to 0). 
2602 //-----------------------------------------------------------------------------
2603 void CordbType::CountTypeDataNodesForInstantiation(unsigned int genericArgsCount, ICorDebugType *genericArgs[], unsigned int *count)
2604 {    
2605     for (unsigned int i = 0; i < genericArgsCount; i++)
2606     {
2607         (static_cast<CordbType *>(genericArgs[i]))->CountTypeDataNodes(count);
2608     }
2609 }
2610
2611 //-----------------------------------------------------------------------------
2612 // Recursively walk a type tree, writing the type args into a linear.
2613 // Eg, for List<A, Pair<B, C>>, this will write the TypeArgData buffer
2614 // for { A, B, C }.
2615 //
2616 // Parameters:
2617 //   curr_tyargData - IN/OUT: Pointer into buffer of TypeArgData structures.
2618 //      Caller must ensure this buffer is large enough (probably by calling 
2619 //      CountTypeDataNodes).
2620 //      On output, set to the next element in the buffer.
2621 //-----------------------------------------------------------------------------
2622 void CordbType::GatherTypeData(CordbType *type, DebuggerIPCE_TypeArgData **curr_tyargData)
2623 {
2624   type->TypeToTypeArgData(*curr_tyargData);
2625   (*curr_tyargData)++;
2626   for (unsigned int i = 0; i < type->m_inst.m_cClassTyPars; i++)
2627   {
2628     GatherTypeData(type->m_inst.m_ppInst[i], curr_tyargData);
2629   }
2630 }
2631
2632 //-----------------------------------------------------------------------------
2633 // Flatten Instantiation into a linear buffer of TypeArgData 
2634 // Use CountTypeDataNodesForInstantiation on the instantiation to get a large 
2635 // enough buffer.
2636 //
2637 // Parameters:
2638 //    genericArgsCount - size of genericArgs array in elements.
2639 //    genericArgs - incoming array to walk
2640 //    curr_tyargData - IN/OUT: Pointer into buffer of TypeArgData structures.
2641 //      Caller must ensure this buffer is large enough (probably by calling 
2642 //      CountTypeDataNodes).
2643 //      On output, set to the next element in the buffer.
2644 //    
2645 //-----------------------------------------------------------------------------
2646 void CordbType::GatherTypeDataForInstantiation(unsigned int genericArgsCount, ICorDebugType *genericArgs[], DebuggerIPCE_TypeArgData **curr_tyargData)
2647 {
2648     for (unsigned int i = 0; i < genericArgsCount; i++)
2649     {
2650         GatherTypeData(static_cast<CordbType *> (genericArgs[i]), curr_tyargData);
2651     }
2652 }
2653
2654 #ifdef FEATURE_64BIT_ALIGNMENT
2655 // checks if the type requires 8-byte alignment. the algorithm used here
2656 // was adapted from AdjustArgPtrForAlignment() in bcltype/VarArgsNative.cpp
2657 HRESULT CordbType::RequiresAlign8(BOOL* isRequired)
2658 {
2659     if (isRequired == NULL)
2660         return E_INVALIDARG;
2661
2662     HRESULT hr = S_OK;
2663
2664     EX_TRY
2665     {
2666         *isRequired = FALSE;
2667
2668         ULONG32 size = 0;
2669         GetUnboxedObjectSize(&size);
2670
2671         if (size >= 8)
2672         {
2673             CorElementType type;
2674             GetType(&type);
2675
2676             if (type != ELEMENT_TYPE_TYPEDBYREF)
2677             {
2678                 if (type == ELEMENT_TYPE_VALUETYPE)
2679                 {
2680                     if (m_typeHandleExact.IsNull())
2681                         InitInstantiationTypeHandle(FALSE);
2682
2683                     *isRequired = GetProcess()->GetDAC()->RequiresAlign8(m_typeHandleExact);
2684                 }
2685                 else
2686                 {
2687                     *isRequired = TRUE;
2688                 }
2689             }
2690         }
2691     } 
2692     EX_CATCH_HRESULT(hr);
2693
2694     return hr;
2695 }
2696 #endif
2697
2698 /* ------------------------------------------------------------------------- *
2699  * TypeParameter Enumerator class
2700  * ------------------------------------------------------------------------- */
2701
2702 // Factory methods
2703 CordbTypeEnum* CordbTypeEnum::Build(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, CordbType **ppTypars)
2704 {
2705     return BuildImpl( pAppDomain, pNeuterList, cTypars, ppTypars );
2706 }
2707
2708 CordbTypeEnum* CordbTypeEnum::Build(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, RSSmartPtr<CordbType> *ppTypars)
2709 {
2710     return BuildImpl( pAppDomain, pNeuterList, cTypars, ppTypars );
2711 }
2712
2713 //-----------------------------------------------------------------------------
2714 // We need to support taking both an array of CordbType* and an array of RSSmartPtr<CordbType>, 
2715 // but the code is identical in both cases.  Rather than duplicate any code explicity, it's better to 
2716 // have the compiler do it for us using this template method.
2717 // Another option would be to create an IList<T> interface and implementations for both arrays 
2718 // of T* and arrays of RSSmartPtr<T>.  This would be more generally useful, but much more code.
2719 //-----------------------------------------------------------------------------
2720 template<class T> CordbTypeEnum* CordbTypeEnum::BuildImpl(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, T* ppTypars)
2721 {
2722     CordbTypeEnum* newEnum = new (nothrow) CordbTypeEnum( pAppDomain, pNeuterList );
2723     if( NULL == newEnum )
2724     {
2725         return NULL;
2726     }
2727
2728     _ASSERTE( newEnum->m_ppTypars == NULL );
2729     newEnum->m_ppTypars = new (nothrow) RSSmartPtr<CordbType> [cTypars];
2730     if( newEnum->m_ppTypars == NULL )
2731     {
2732         delete newEnum;
2733         return NULL;
2734     }
2735     
2736     newEnum->m_iMax = cTypars;
2737     for (unsigned int i = 0; i < cTypars; i++)
2738     {
2739         newEnum->m_ppTypars[i].Assign(ppTypars[i]);
2740     }
2741
2742     return newEnum;
2743 }
2744
2745 // Private, called only by Build above
2746 CordbTypeEnum::CordbTypeEnum(CordbAppDomain * pAppDomain, NeuterList * pNeuterList) :
2747     CordbBase(pAppDomain->GetProcess(), 0),
2748     m_ppTypars(NULL),
2749     m_iCurrent(0),
2750     m_iMax(0)
2751 {
2752     _ASSERTE(pAppDomain != NULL);
2753     _ASSERTE(pNeuterList != NULL);
2754
2755     m_pAppDomain =  pAppDomain;
2756
2757     HRESULT hr = S_OK;
2758     EX_TRY
2759     {
2760         pNeuterList->Add(GetProcess(), this);
2761     } 
2762     EX_CATCH_HRESULT(hr);
2763     SetUnrecoverableIfFailed(GetProcess(), hr);
2764 }
2765
2766 CordbTypeEnum::~CordbTypeEnum()
2767 {
2768     _ASSERTE(this->IsNeutered());
2769 }
2770
2771 void CordbTypeEnum::Neuter()
2772 {
2773     delete [] m_ppTypars;
2774     m_ppTypars = NULL;
2775     m_pAppDomain = NULL;
2776
2777     CordbBase::Neuter();
2778 }
2779
2780
2781 HRESULT CordbTypeEnum::QueryInterface(REFIID id, void **pInterface)
2782 {
2783     if (id == IID_ICorDebugEnum)
2784         *pInterface = static_cast<ICorDebugEnum*>(this);
2785     else if (id == IID_ICorDebugTypeEnum)
2786         *pInterface = static_cast<ICorDebugTypeEnum*>(this);
2787     else if (id == IID_IUnknown)
2788         *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugTypeEnum*>(this));
2789     else
2790     {
2791         *pInterface = NULL;
2792         return E_NOINTERFACE;
2793     }
2794
2795     ExternalAddRef();
2796     return S_OK;
2797 }
2798
2799 HRESULT CordbTypeEnum::Skip(ULONG celt)
2800 {
2801     PUBLIC_API_ENTRY(this);
2802     FAIL_IF_NEUTERED(this);
2803     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2804
2805     HRESULT hr = E_FAIL;
2806     if ( (m_iCurrent+celt) < m_iMax ||
2807          celt == 0)
2808     {
2809         m_iCurrent += celt;
2810         hr = S_OK;
2811     }
2812
2813     return hr;
2814 }
2815
2816 HRESULT CordbTypeEnum::Reset(void)
2817 {
2818     PUBLIC_API_ENTRY(this);
2819     FAIL_IF_NEUTERED(this);
2820     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2821
2822     m_iCurrent = 0;
2823     return S_OK;
2824 }
2825
2826 HRESULT CordbTypeEnum::Clone(ICorDebugEnum **ppEnum)
2827 {
2828     PUBLIC_API_ENTRY(this);
2829     FAIL_IF_NEUTERED(this);
2830     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2831
2832
2833     VALIDATE_POINTER_TO_OBJECT(ppEnum, ICorDebugEnum **);
2834
2835     HRESULT hr = S_OK;
2836
2837     CordbTypeEnum *pCVE = CordbTypeEnum::Build( m_pAppDomain, m_pAppDomain->GetLongExitNeuterList(), m_iMax, m_ppTypars );
2838     if ( pCVE == NULL )
2839     {
2840         (*ppEnum) = NULL;
2841         hr = E_OUTOFMEMORY;
2842         goto LExit;
2843     }
2844
2845     pCVE->AddRef();
2846     (*ppEnum) = (ICorDebugEnum*)pCVE;
2847
2848 LExit:
2849     return hr;
2850 }
2851
2852 HRESULT CordbTypeEnum::GetCount(ULONG *pcelt)
2853 {
2854     PUBLIC_API_ENTRY(this);
2855     FAIL_IF_NEUTERED(this);
2856     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2857
2858     VALIDATE_POINTER_TO_OBJECT(pcelt, ULONG *);
2859
2860     if( pcelt == NULL)
2861         return E_INVALIDARG;
2862
2863     (*pcelt) = m_iMax;
2864     return S_OK;
2865 }
2866
2867 //
2868 // In the event of failure, the current pointer will be left at
2869 // one element past the troublesome element.  Thus, if one were
2870 // to repeatedly ask for one element to iterate through the
2871 // array, you would iterate exactly m_iMax times, regardless
2872 // of individual failures.
2873 HRESULT CordbTypeEnum::Next(ULONG celt, ICorDebugType *values[], ULONG *pceltFetched)
2874 {
2875     PUBLIC_API_ENTRY(this);
2876     FAIL_IF_NEUTERED(this);
2877     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2878
2879
2880     VALIDATE_POINTER_TO_OBJECT_ARRAY(values, ICorDebugClass *,
2881         celt, true, true);
2882     VALIDATE_POINTER_TO_OBJECT_OR_NULL(pceltFetched, ULONG *);
2883
2884     if ((pceltFetched == NULL) && (celt != 1))
2885     {
2886         return E_INVALIDARG;
2887     }
2888
2889     if (celt == 0)
2890     {
2891         if (pceltFetched != NULL)
2892         {
2893             *pceltFetched = 0;
2894         }
2895         return S_OK;
2896     }
2897
2898     HRESULT hr = S_OK;
2899
2900     int iMax = min( m_iMax, m_iCurrent+celt);
2901     int i;
2902
2903     for (i = m_iCurrent; i < iMax; i++)
2904     {
2905          //printf("CordbTypeEnum::Next, returning = 0x%08x.\n", m_ppTypars[i]);
2906         values[i-m_iCurrent] = m_ppTypars[i];
2907         values[i-m_iCurrent]->AddRef();
2908     }
2909
2910     int count = (i - m_iCurrent);
2911
2912     if ( FAILED( hr ) )
2913     {   //we failed: +1 pushes us past troublesome element
2914         m_iCurrent += 1 + count;
2915     }
2916     else
2917     {
2918         m_iCurrent += count;
2919     }
2920
2921     if (pceltFetched != NULL)
2922     {
2923         *pceltFetched = count;
2924     }
2925
2926     //
2927     // If we reached the end of the enumeration, but not the end
2928     // of the number of requested items, we return S_FALSE.
2929     //
2930     if (((ULONG)count) < celt)
2931     {
2932         return S_FALSE;
2933     }
2934
2935     return hr;
2936 }
2937