[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / typestring.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 // typestring.cpp
6 // ---------------------------------------------------------------------------
7 //
8
9 //
10 // This module contains a helper function used to produce string
11 // representations of types, with options to control the appearance of
12 // namespace and assembly information.  Its primary use is in
13 // reflection (Type.Name, Type.FullName, Type.ToString, etc) but over
14 // time it could replace the use of TypeHandle.GetName etc for
15 // diagnostic messages.
16 //
17 // See the header file for more details
18 // ---------------------------------------------------------------------------
19
20
21 #include "common.h"
22 #include "class.h"
23 #include "typehandle.h"
24 #include "sstring.h"
25 #include "sigformat.h"
26 #include "typeparse.h"
27 #include "typestring.h"
28 #include "ex.h"
29 #include "typedesc.h"
30
31 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
32 TypeNameBuilder * QCALLTYPE TypeNameBuilder::_CreateTypeNameBuilder()
33
34     QCALL_CONTRACT;
35
36     TypeNameBuilder * retVal = NULL;
37     BEGIN_QCALL;
38     retVal = new TypeNameBuilder();
39     END_QCALL;
40
41     return retVal;
42
43
44 void QCALLTYPE TypeNameBuilder::_ReleaseTypeNameBuilder(TypeNameBuilder * pTnb) 
45 {
46     QCALL_CONTRACT;
47
48     BEGIN_QCALL;
49     delete pTnb;
50     END_QCALL;
51
52
53 void QCALLTYPE TypeNameBuilder::_ToString(TypeNameBuilder * pTnb, QCall::StringHandleOnStack retString)
54 {
55     QCALL_CONTRACT;
56
57     BEGIN_QCALL;
58     retString.Set(*pTnb->GetString());
59     END_QCALL;
60
61
62 void QCALLTYPE TypeNameBuilder::_AddName(TypeNameBuilder * pTnb, LPCWSTR wszName) 
63 {
64     QCALL_CONTRACT;
65
66     BEGIN_QCALL;
67     pTnb->AddName(wszName); 
68     END_QCALL;
69
70
71 void QCALLTYPE TypeNameBuilder::_AddAssemblySpec(TypeNameBuilder * pTnb, LPCWSTR wszAssemblySpec) 
72 {
73     QCALL_CONTRACT;
74
75     BEGIN_QCALL;
76     pTnb->AddAssemblySpec(wszAssemblySpec); 
77     END_QCALL;
78
79
80 void QCALLTYPE TypeNameBuilder::_OpenGenericArguments(TypeNameBuilder * pTnb) 
81 {
82     QCALL_CONTRACT;
83
84     BEGIN_QCALL;
85     pTnb->OpenGenericArguments(); 
86     END_QCALL;
87
88
89 void QCALLTYPE TypeNameBuilder::_CloseGenericArguments(TypeNameBuilder * pTnb) 
90 {
91     QCALL_CONTRACT;
92
93     BEGIN_QCALL;
94     pTnb->CloseGenericArguments(); 
95     END_QCALL;
96
97
98 void QCALLTYPE TypeNameBuilder::_OpenGenericArgument(TypeNameBuilder * pTnb) 
99 {
100     QCALL_CONTRACT;
101
102     BEGIN_QCALL;
103     pTnb->OpenGenericArgument(); 
104     END_QCALL;
105
106
107 void QCALLTYPE TypeNameBuilder::_CloseGenericArgument(TypeNameBuilder * pTnb) 
108 {
109     QCALL_CONTRACT;
110
111     BEGIN_QCALL;
112     pTnb->CloseGenericArgument(); 
113     END_QCALL;
114
115
116 void QCALLTYPE TypeNameBuilder::_AddPointer(TypeNameBuilder * pTnb) 
117 {
118     QCALL_CONTRACT;
119
120     BEGIN_QCALL;
121     pTnb->AddPointer(); 
122     END_QCALL;
123
124
125 void QCALLTYPE TypeNameBuilder::_AddByRef(TypeNameBuilder * pTnb) 
126 {
127     QCALL_CONTRACT;
128
129     BEGIN_QCALL;
130     pTnb->AddByRef(); 
131     END_QCALL;
132
133
134 void QCALLTYPE TypeNameBuilder::_AddSzArray(TypeNameBuilder * pTnb) 
135 {
136     QCALL_CONTRACT;
137
138     BEGIN_QCALL;
139     pTnb->AddSzArray(); 
140     END_QCALL;
141
142
143 void QCALLTYPE TypeNameBuilder::_AddArray(TypeNameBuilder * pTnb, DWORD dwRank) 
144 {
145     QCALL_CONTRACT;
146
147     BEGIN_QCALL;
148     pTnb->AddArray(dwRank); 
149     END_QCALL;
150 }
151     
152 void QCALLTYPE TypeNameBuilder::_Clear(TypeNameBuilder * pTnb) 
153 {
154     QCALL_CONTRACT;
155
156     BEGIN_QCALL;
157     pTnb->Clear(); 
158     END_QCALL;
159
160
161 #endif
162
163 //
164 // TypeNameBuilder
165 //
166 TypeNameBuilder::TypeNameBuilder(SString* pStr, ParseState parseState /*= ParseStateSTART*/) : 
167     m_pStr(NULL)
168
169     CONTRACTL
170     {
171         THROWS;
172         GC_NOTRIGGER;
173         MODE_ANY;
174     }
175     CONTRACTL_END;
176     Clear(); 
177     m_pStr = pStr;
178     m_parseState = parseState; 
179 }
180
181 void TypeNameBuilder::PushOpenGenericArgument()
182 {
183     WRAPPER_NO_CONTRACT;
184
185     m_stack.Push(m_pStr->GetCount());
186 }
187
188 void TypeNameBuilder::PopOpenGenericArgument()
189 {
190     CONTRACTL
191     {
192         THROWS;
193         GC_NOTRIGGER;
194         MODE_ANY;
195     }
196     CONTRACTL_END;
197
198     COUNT_T index = m_stack.Pop();
199         
200     if (!m_bHasAssemblySpec)
201         m_pStr->Delete(m_pStr->Begin() + index - 1, 1);
202     
203     m_bHasAssemblySpec = FALSE;
204 }
205
206 /* This method escapes szName and appends it to this TypeNameBuilder */
207 void TypeNameBuilder::EscapeName(LPCWSTR szName)
208 {
209     CONTRACTL
210     {
211         THROWS;
212         GC_NOTRIGGER;
213         MODE_ANY;
214     }
215     CONTRACTL_END;
216
217     if (TypeString::ContainsReservedChar(szName))
218     {
219         while (* szName)
220         {
221             WCHAR c = * szName ++;
222
223             if (IsTypeNameReservedChar(c))
224                 Append(W('\\'));
225         
226             Append(c);
227         }
228     }
229     else
230     {
231         Append(szName);
232     }
233 }
234
235 void TypeNameBuilder::EscapeAssemblyName(LPCWSTR szName)
236 {
237     WRAPPER_NO_CONTRACT; 
238
239     Append(szName);
240 }
241
242 void TypeNameBuilder::EscapeEmbeddedAssemblyName(LPCWSTR szName)
243 {
244     CONTRACTL
245     {
246         THROWS;
247         GC_NOTRIGGER;
248         MODE_ANY;
249     }
250     CONTRACTL_END;
251
252     LPCWSTR itr = szName;
253     bool bContainsReservedChar = false;
254     
255     while (*itr)
256     {
257         if (W(']') == *itr++)
258         {
259             bContainsReservedChar = true;
260             break;
261         }
262     }
263     
264     if (bContainsReservedChar)
265     {
266         itr = szName;
267         while (*itr)
268         {
269             WCHAR c = *itr++;
270             if (c == ']')
271                 Append(W('\\'));
272
273             Append(c);
274         }
275     }
276     else
277     {
278         Append(szName);
279     }
280 }
281
282 HRESULT TypeNameBuilder::OpenGenericArgument() 
283
284     CONTRACTL
285     {
286         THROWS;
287         GC_NOTRIGGER;
288         MODE_ANY;
289     }
290     CONTRACTL_END;
291
292     if (!CheckParseState(ParseStateSTART))
293         return Fail();
294
295     if (m_instNesting == 0)
296         return Fail();
297
298     HRESULT hr = S_OK;
299
300     m_parseState = ParseStateSTART;
301     m_bNestedName = FALSE;
302
303     if (!m_bFirstInstArg)
304         Append(W(','));
305
306     m_bFirstInstArg = FALSE;
307
308     if (m_bUseAngleBracketsForGenerics)
309         Append(W('<'));
310     else
311         Append(W('['));
312     PushOpenGenericArgument();
313     
314     return hr;
315 }
316
317 HRESULT TypeNameBuilder::AddName(LPCWSTR szName) 
318
319     CONTRACTL
320     {
321         THROWS;
322         GC_NOTRIGGER;
323         MODE_ANY;
324     }
325     CONTRACTL_END;
326
327     if (!szName)
328         return Fail();
329     
330     if (!CheckParseState(ParseStateSTART | ParseStateNAME))
331         return Fail();
332
333     HRESULT hr = S_OK;
334
335     m_parseState = ParseStateNAME;
336
337     if (m_bNestedName)
338         Append(W('+')); 
339
340     m_bNestedName = TRUE;
341
342     EscapeName(szName); 
343
344     return hr;
345 }
346
347 HRESULT TypeNameBuilder::AddName(LPCWSTR szName, LPCWSTR szNamespace) 
348
349     CONTRACTL
350     {
351         THROWS;
352         GC_NOTRIGGER;
353         MODE_ANY;
354     }
355     CONTRACTL_END;
356
357     if (!szName)
358         return Fail();
359     
360     if (!CheckParseState(ParseStateSTART | ParseStateNAME))
361         return Fail();
362
363     HRESULT hr = S_OK;
364
365     m_parseState = ParseStateNAME;
366
367     if (m_bNestedName)
368         Append(W('+')); 
369
370     m_bNestedName = TRUE;
371
372     if (szNamespace && *szNamespace)
373     {
374         EscapeName(szNamespace); 
375         Append(W('.'));
376     }
377
378     EscapeName(szName); 
379
380     return hr;
381 }
382
383 HRESULT TypeNameBuilder::OpenGenericArguments() 
384
385     WRAPPER_NO_CONTRACT; 
386     
387     if (!CheckParseState(ParseStateNAME))
388         return Fail();
389
390     HRESULT hr = S_OK;
391
392     m_parseState = ParseStateSTART;
393     m_instNesting ++;
394     m_bFirstInstArg = TRUE;
395
396     if (m_bUseAngleBracketsForGenerics)
397         Append(W('<'));
398     else
399         Append(W('['));
400
401     return hr;
402 }
403
404 HRESULT TypeNameBuilder::CloseGenericArguments() 
405
406     CONTRACTL
407     {
408         THROWS;
409         GC_NOTRIGGER;
410         MODE_ANY;
411     }
412     CONTRACTL_END;
413
414     if (!m_instNesting)
415         return Fail();
416     if (!CheckParseState(ParseStateSTART))
417         return Fail();
418
419     HRESULT hr = S_OK;
420
421     m_parseState = ParseStateGENARGS;
422
423     m_instNesting --;
424
425     if (m_bFirstInstArg)
426     {
427         m_pStr->Truncate(m_pStr->End() - 1);
428     }    
429     else
430     {
431         if (m_bUseAngleBracketsForGenerics)
432             Append(W('>')); 
433         else
434             Append(W(']')); 
435     }
436
437     return hr;
438 }
439
440 HRESULT TypeNameBuilder::AddPointer() 
441
442     WRAPPER_NO_CONTRACT; 
443     
444     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
445         return Fail();
446
447     m_parseState = ParseStatePTRARR;
448     
449     Append(W('*')); 
450
451     return S_OK;
452 }
453
454 HRESULT TypeNameBuilder::AddByRef() 
455
456     WRAPPER_NO_CONTRACT;
457
458     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
459         return Fail();
460
461     m_parseState = ParseStateBYREF;
462     
463     Append(W('&'));
464
465     return S_OK;
466 }
467
468 HRESULT TypeNameBuilder::AddSzArray() 
469
470     WRAPPER_NO_CONTRACT; 
471     
472     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
473         return Fail();
474
475     m_parseState = ParseStatePTRARR;
476     
477     Append(W("[]")); 
478
479     return S_OK;
480
481
482 HRESULT TypeNameBuilder::AddArray(DWORD rank)
483 {
484     CONTRACTL
485     {
486         THROWS;
487         GC_NOTRIGGER;
488         MODE_ANY;
489     }
490     CONTRACTL_END;
491     
492     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
493         return Fail();
494
495     m_parseState = ParseStatePTRARR;
496         
497     if (rank <= 0)
498         return E_INVALIDARG;
499
500     if (rank == 1)
501         Append(W("[*]"));
502     else if (rank > 64)
503     {
504         // Only taken in an error path, runtime will not load arrays of more than 32 dimentions
505         WCHAR wzDim[128];
506         _snwprintf_s(wzDim, 128, _TRUNCATE, W("[%d]"), rank);
507         Append(wzDim);
508     }
509     else
510     {
511         WCHAR* wzDim = new (nothrow) WCHAR[rank+3];
512             
513         if(wzDim == NULL) // allocation failed, do it the long way (each Append -> memory realloc)
514         {
515             Append(W('['));
516             for(COUNT_T i = 1; i < rank; i ++)
517                 Append(W(','));
518             Append(W(']'));
519         }
520         else             // allocation OK, do it the fast way
521         {
522             WCHAR* pwz = wzDim+1;
523             *wzDim = '[';
524             for(COUNT_T i = 1; i < rank; i++, pwz++) *pwz=',';
525             *pwz = ']';
526             *(++pwz) = 0;
527             Append(wzDim);
528             delete [] wzDim;
529         }
530     }
531
532     return S_OK;
533 }
534
535 HRESULT TypeNameBuilder::CloseGenericArgument()
536 {
537     CONTRACTL
538     {
539         THROWS;
540         GC_NOTRIGGER;
541         MODE_ANY;
542     }
543     CONTRACTL_END;
544     
545     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
546         return Fail();
547
548     if (m_instNesting == 0)
549         return Fail();
550     
551     m_parseState = ParseStateSTART;
552     
553     if (m_bHasAssemblySpec)
554     {
555         if (m_bUseAngleBracketsForGenerics)
556             Append(W('>')); 
557         else
558             Append(W(']')); 
559     }
560
561     PopOpenGenericArgument();
562
563     return S_OK;
564 }
565
566 HRESULT TypeNameBuilder::AddAssemblySpec(LPCWSTR szAssemblySpec)
567 {
568     CONTRACTL
569     {
570         THROWS;
571         GC_NOTRIGGER;
572         MODE_ANY;
573     }
574     CONTRACTL_END;
575
576     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF))
577         return Fail();
578
579     HRESULT hr = S_OK;
580     
581     m_parseState = ParseStateASSEMSPEC;
582
583     if (szAssemblySpec && *szAssemblySpec)
584     {
585         Append(W(", "));
586         
587         if (m_instNesting > 0)
588         {
589             EscapeEmbeddedAssemblyName(szAssemblySpec);
590         }
591         else
592         {
593             EscapeAssemblyName(szAssemblySpec);
594         }
595
596         m_bHasAssemblySpec = TRUE;
597         hr = S_OK;
598     }
599
600     return hr;
601 }
602
603 HRESULT TypeNameBuilder::ToString(BSTR* pszStringRepresentation)
604 {
605     WRAPPER_NO_CONTRACT;
606
607     if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
608         return Fail();
609
610     if (m_instNesting)
611         return Fail();
612
613     *pszStringRepresentation = SysAllocString(m_pStr->GetUnicode());
614
615     return S_OK;
616 }
617
618 HRESULT TypeNameBuilder::Clear()
619 {
620     CONTRACTL
621     {
622         THROWS; // TypeNameBuilder::Stack::Clear might throw.
623         GC_NOTRIGGER;
624         MODE_ANY;
625     }
626     CONTRACTL_END;
627
628     if (m_pStr)
629     {   
630         m_pStr->Clear();
631     }
632     m_bNestedName = FALSE;
633     m_instNesting = 0;
634     m_bFirstInstArg = FALSE;
635     m_parseState = ParseStateSTART;
636     m_bHasAssemblySpec = FALSE;
637     m_bUseAngleBracketsForGenerics = FALSE;
638     m_stack.Clear();
639     
640     return S_OK;
641 }
642
643
644
645 // Append the name of the type td to the string
646 // The following flags in the FormatFlags argument are significant: FormatNamespace 
647 void TypeString::AppendTypeDef(SString& ss, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
648 {
649     CONTRACT_VOID
650     {
651         MODE_ANY;
652         GC_NOTRIGGER;
653         THROWS;
654     }
655     CONTRACT_END
656
657     {
658         TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
659         AppendTypeDef(tnb, pImport, td, format);    
660     }
661
662     RETURN;
663 }
664
665
666 void TypeString::AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format) 
667 {
668     CONTRACT_VOID
669     {
670         MODE_ANY;
671         GC_NOTRIGGER;
672         THROWS;
673         PRECONDITION(CheckPointer(pImport));
674         PRECONDITION(TypeFromToken(td) == mdtTypeDef);
675     }
676     CONTRACT_END
677
678     LPCUTF8 szName;
679     LPCUTF8 szNameSpace;
680     IfFailThrow(pImport->GetNameOfTypeDef(td, &szName, &szNameSpace));
681     
682     const WCHAR *wszNameSpace = NULL;
683
684     InlineSString<128> ssName(SString::Utf8, szName);
685     InlineSString<128> ssNameSpace;
686
687     if (format & FormatNamespace)
688     {
689         ssNameSpace.SetUTF8(szNameSpace);
690         wszNameSpace = ssNameSpace.GetUnicode();
691     }
692
693     tnb.AddName(ssName.GetUnicode(), wszNameSpace);
694
695     RETURN;
696 }
697
698 void TypeString::AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
699 {
700     CONTRACT_VOID
701     {
702         MODE_ANY;
703         GC_NOTRIGGER;
704         THROWS;
705         PRECONDITION(CheckPointer(pImport));
706         PRECONDITION(TypeFromToken(td) == mdtTypeDef);
707     }
708     CONTRACT_END
709     
710     DWORD dwAttr;
711     IfFailThrow(pImport->GetTypeDefProps(td, &dwAttr, NULL));
712     
713     StackSArray<mdTypeDef> arNames;
714     arNames.Append(td);
715     if (format & FormatNamespace && IsTdNested(dwAttr)) 
716     {   
717         while (SUCCEEDED(pImport->GetNestedClassProps(td, &td))) 
718             arNames.Append(td);
719     }   
720     
721     for(SCOUNT_T i = arNames.GetCount() - 1; i >= 0; i --)
722         AppendTypeDef(tnb, pImport, arNames[i], format);
723     
724     RETURN;
725 }
726
727 // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
728 // and enclose each parameter in square brackets to disambiguate the commas
729 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
730 void TypeString::AppendInst(SString& ss, Instantiation inst, DWORD format) 
731 {
732     CONTRACT_VOID
733     {
734         MODE_ANY;
735         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
736         THROWS;
737     }
738     CONTRACT_END
739
740     {
741         TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
742         if ((format & FormatAngleBrackets) != 0)
743             tnb.SetUseAngleBracketsForGenerics(TRUE);
744         AppendInst(tnb, inst, format);
745     }
746
747     RETURN;
748 }
749
750 void TypeString::AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format) 
751 {
752     CONTRACT_VOID
753     {
754         MODE_ANY;
755         THROWS;
756         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
757         PRECONDITION(!inst.IsEmpty());
758     }
759     CONTRACT_END
760
761     tnb.OpenGenericArguments();
762
763     for (DWORD i = 0; i < inst.GetNumArgs(); i++) 
764     {
765         tnb.OpenGenericArgument();
766
767         TypeHandle thArg = inst[i];
768
769         if ((format & FormatFullInst) != 0 && !thArg.IsGenericVariable()) 
770         {
771             AppendType(tnb, thArg, Instantiation(), format | FormatNamespace | FormatAssembly);
772         }
773         else
774         {
775             AppendType(tnb, thArg, Instantiation(), format & (FormatNamespace | FormatAngleBrackets
776 #ifdef _DEBUG
777                                                | FormatDebug
778 #endif
779                                                ));
780         }
781
782         tnb.CloseGenericArgument();
783     }
784
785     tnb.CloseGenericArguments();
786
787     RETURN;
788 }
789
790 void TypeString::AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank)
791 {
792     CONTRACTL
793     {
794         MODE_ANY;
795         THROWS;
796         GC_NOTRIGGER;
797         PRECONDITION(CorTypeInfo::IsModifier(kind));
798     }
799     CONTRACTL_END
800
801     switch (kind)
802     {
803     case ELEMENT_TYPE_BYREF :
804         tnb.AddByRef();
805         break;
806     case ELEMENT_TYPE_PTR :
807         tnb.AddPointer();
808         break;
809     case ELEMENT_TYPE_SZARRAY :
810         tnb.AddSzArray();
811         break;
812     case ELEMENT_TYPE_ARRAY :        
813         tnb.AddArray(rank);
814         break;
815     default :
816         break;
817     }
818 }
819
820 // Append a representation of the type t to the string s
821 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
822
823 void TypeString::AppendType(SString& ss, TypeHandle ty, DWORD format) 
824 {
825     CONTRACT_VOID
826     {
827         MODE_ANY;
828         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
829         THROWS;        
830     }
831     CONTRACT_END
832     
833     AppendType(ss, ty, Instantiation(), format);
834
835     RETURN;
836 }
837
838 void TypeString::AppendType(SString& ss, TypeHandle ty, Instantiation typeInstantiation, DWORD format) 
839 {
840     CONTRACT_VOID
841     {
842         MODE_ANY;
843         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
844         THROWS;        
845     }
846     CONTRACT_END
847
848     {
849         TypeNameBuilder tnb(&ss);
850         if ((format & FormatAngleBrackets) != 0)
851             tnb.SetUseAngleBracketsForGenerics(TRUE);
852         AppendType(tnb, ty, typeInstantiation, format);
853     }
854
855     RETURN;
856 }
857
858 void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation typeInstantiation, DWORD format) 
859 {
860     CONTRACT_VOID
861     {
862         MODE_ANY;
863         
864         /* This method calls Assembly::GetDisplayName. Since that function
865         uses Fusion which takes some Crsts in some places, it is GC_TRIGGERS. 
866         It could be made GC_NOTRIGGER by factoring out Assembly::GetDisplayName.
867         However, its better to leave stuff as GC_TRIGGERS unless really needed, 
868         as GC_NOTRIGGER ties your hands up. */
869         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
870         THROWS;        
871     }
872     CONTRACT_END
873
874     BOOL bToString = (format & (FormatNamespace|FormatFullInst|FormatAssembly)) == FormatNamespace;
875
876     // It's null!
877     if (ty.IsNull())
878     {
879         tnb.AddName(W("(null)"));
880     }
881     else
882     // It's not restored yet!
883     if (ty.IsEncodedFixup())
884     {
885         tnb.AddName(W("(fixup)"));
886     }
887     else
888
889     // It's an array, with format 
890     //   element_ty[] (1-d, SZARRAY) 
891     //   element_ty[*] (1-d, ARRAY)
892     //   element_ty[,] (2-d, ARRAY) etc
893     // or a pointer (*) or byref (&)
894     if (ty.HasTypeParam() || (!ty.IsTypeDesc() && ty.AsMethodTable()->IsArray())) 
895     {
896         if (ty.GetSignatureCorElementType() != ELEMENT_TYPE_VALUETYPE)
897         {
898             DWORD rank;
899             TypeHandle elemType;
900             if (ty.HasTypeParam())
901             {
902                 rank = ty.IsArray() ? ty.AsArray()->GetRank() : 0; 
903                 elemType = ty.GetTypeParam();
904             }
905             else
906             {
907                 MethodTable *pMT = ty.GetMethodTable();
908                 PREFIX_ASSUME(pMT != NULL);
909                 rank = pMT->GetRank();
910                 elemType = pMT->GetApproxArrayElementTypeHandle();
911             }
912
913             _ASSERTE(!elemType.IsNull());
914             AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
915             AppendParamTypeQualifier(tnb, ty.GetSignatureCorElementType(), rank);
916         }
917         else
918         {
919             tnb.Append(W("VALUETYPE"));
920             TypeHandle elemType = ty.GetTypeParam();
921             AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
922         }
923     }
924
925     // ...or type parameter
926     else if (ty.IsGenericVariable()) 
927     {
928         PTR_TypeVarTypeDesc tyvar = dac_cast<PTR_TypeVarTypeDesc>(ty.AsTypeDesc());
929
930         mdGenericParam token = tyvar->GetToken();
931         
932         LPCSTR szName = NULL;
933         mdToken mdOwner;
934         
935         IfFailThrow(ty.GetModule()->GetMDImport()->GetGenericParamProps(token, NULL, NULL, &mdOwner, NULL, &szName));
936
937         _ASSERTE(TypeFromToken(mdOwner) == mdtTypeDef || TypeFromToken(mdOwner) == mdtMethodDef);
938             
939         LPCSTR szPrefix;
940         if (!(format & FormatGenericParam))
941             szPrefix = "";
942         else if (TypeFromToken(mdOwner) == mdtTypeDef)
943             szPrefix = "!";
944         else
945             szPrefix = "!!";
946
947         SmallStackSString pName(SString::Utf8, szPrefix);
948         pName.AppendUTF8(szName);
949         tnb.AddName(pName.GetUnicode());
950             
951         format &= ~FormatAssembly;
952     }
953     
954     // ...or function pointer
955     else if (ty.IsFnPtrType())
956     {
957         // Don't attempt to format this currently, it may trigger GC due to fixups.
958         tnb.AddName(W("(fnptr)"));
959     }
960
961     // ...otherwise it's just a plain type def or an instantiated type
962     else 
963     {
964         // Get the TypeDef token and attributes
965         IMDInternalImport *pImport = ty.GetMethodTable()->GetMDImport();
966         mdTypeDef td = ty.GetCl();
967         if (IsNilToken(td)) {
968             // This type does not exist in metadata. Simply append "dynamicClass".
969             tnb.AddName(W("(dynamicClass)"));
970         }
971         else
972         {
973 #ifdef _DEBUG
974             if (format & FormatDebug)
975             {
976                 WCHAR wzAddress[128];
977                 _snwprintf_s(wzAddress, 128, _TRUNCATE, W("(%p)"), dac_cast<TADDR>(ty.AsPtr()));
978                 tnb.AddName(wzAddress);
979             }
980 #endif
981             AppendNestedTypeDef(tnb, pImport, td, format);
982         }
983
984         // Append the instantiation
985         if ((format & (FormatNamespace|FormatAssembly)) && ty.HasInstantiation() && (!ty.IsGenericTypeDefinition() || bToString))
986         {
987             if (typeInstantiation.IsEmpty())
988                 AppendInst(tnb, ty.GetInstantiation(), format);
989             else
990                 AppendInst(tnb, typeInstantiation, format);
991         }
992     }
993
994     // Now append the assembly
995     if (format & FormatAssembly) 
996     {
997         Assembly* pAssembly = ty.GetAssembly();
998         _ASSERTE(pAssembly != NULL);
999
1000         StackSString pAssemblyName;
1001 #ifdef DACCESS_COMPILE
1002         pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1003 #else
1004         pAssembly->GetDisplayName(pAssemblyName,
1005                                   ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1006                                   (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1007 #endif
1008
1009         tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1010
1011     }
1012
1013     RETURN;
1014 }
1015
1016 void TypeString::AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1017 {
1018     CONTRACTL
1019     {
1020         MODE_ANY;
1021         GC_TRIGGERS;
1022         THROWS;
1023         PRECONDITION(CheckPointer(pMD));
1024         PRECONDITION(pMD->IsRestored_NoLogging());
1025         PRECONDITION(s.Check());
1026     }
1027     CONTRACTL_END
1028
1029     AppendMethodImpl(s, pMD, typeInstantiation, format);
1030 }
1031
1032 void TypeString::AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format)
1033 {
1034     CONTRACTL
1035     {
1036         MODE_ANY;
1037         GC_TRIGGERS;
1038         SUPPORTS_DAC;
1039         THROWS;
1040         PRECONDITION(CheckPointer(pMD));
1041         PRECONDITION(pMD->IsRestored_NoLogging());
1042         PRECONDITION(s.Check());
1043     }
1044     CONTRACTL_END
1045
1046     AppendMethodImpl(s, pMD, Instantiation(), format);
1047 }
1048
1049 void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1050 {
1051     CONTRACTL
1052     {
1053         MODE_ANY;
1054         GC_TRIGGERS;
1055         SUPPORTS_DAC;
1056         THROWS;
1057         PRECONDITION(CheckPointer(pMD));
1058         PRECONDITION(pMD->IsRestored_NoLogging());
1059         PRECONDITION(ss.Check());
1060     }
1061     CONTRACTL_END
1062
1063     {
1064         TypeHandle th;
1065         
1066         if (pMD->IsDynamicMethod())
1067         {
1068             if (pMD->IsLCGMethod())
1069             {
1070                 SString sss(SString::Literal, "DynamicClass");
1071                 ss += sss;
1072             }
1073             else if (pMD->IsILStub())
1074             {
1075                 SString sss(SString::Literal, ILStubResolver::GetStubClassName(pMD));
1076                 ss += sss;
1077             }
1078         }
1079         else 
1080         {
1081             th = TypeHandle(pMD->GetMethodTable());
1082             AppendType(ss, th, typeInstantiation, format);
1083         }
1084         
1085         SString sss1(SString::Literal, NAMESPACE_SEPARATOR_STR);
1086         ss += sss1;
1087         SString sss2(SString::Utf8, pMD->GetName());
1088         ss += sss2;
1089
1090         if (pMD->HasMethodInstantiation() && !pMD->IsGenericMethodDefinition())
1091         {
1092             AppendInst(ss, pMD->GetMethodInstantiation(), format);
1093         }
1094         
1095         if (format & FormatSignature)
1096         {
1097             // @TODO: The argument list should be formatted nicely using AppendType()
1098             
1099             SigFormat sigFormatter(pMD, th);
1100             const char* sigStr = sigFormatter.GetCStringParmsOnly();
1101             SString sss(SString::Utf8, sigStr);
1102             ss += sss;
1103         }
1104         
1105         if (format & FormatStubInfo) {
1106             if (pMD->IsInstantiatingStub())
1107             {
1108                 SString sss(SString::Literal, "{inst-stub}");
1109                 ss += sss;
1110             }
1111             if (pMD->IsUnboxingStub())
1112             {
1113                 SString sss(SString::Literal, "{unbox-stub}");
1114                 ss += sss;
1115             }
1116             if (pMD->IsSharedByGenericMethodInstantiations())
1117             {
1118                 SString sss(SString::Literal, "{method-shared}");
1119                 ss += sss;
1120             }
1121             else if (pMD->IsSharedByGenericInstantiations())
1122             {
1123                 SString sss(SString::Literal, "{shared}");
1124                 ss += sss;
1125             }
1126             if (pMD->RequiresInstMethodTableArg())
1127             {
1128                 SString sss(SString::Literal, "{requires-mt-arg}");
1129                 ss += sss;
1130             }
1131             if (pMD->RequiresInstMethodDescArg())
1132             {
1133                 SString sss(SString::Literal, "{requires-mdesc-arg}");
1134                 ss += sss;
1135             }
1136         }
1137     }
1138 }
1139
1140 void TypeString::AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format /* = FormatNamespace */)
1141 {
1142     CONTRACTL
1143     {
1144         MODE_ANY;
1145         GC_TRIGGERS;
1146         THROWS;
1147         PRECONDITION(CheckPointer(pFD));
1148         PRECONDITION(s.Check());
1149     }
1150     CONTRACTL_END;
1151
1152     {
1153         TypeHandle th(pFD->GetApproxEnclosingMethodTable());
1154         AppendType(s, th, typeInstantiation, format);
1155
1156         s.AppendUTF8(NAMESPACE_SEPARATOR_STR);
1157         s.AppendUTF8(pFD->GetName());
1158     }
1159 }
1160
1161 #ifdef _DEBUG
1162 void TypeString::AppendMethodDebug(SString& ss, MethodDesc *pMD)
1163 {
1164     CONTRACTL
1165     {
1166         MODE_ANY;
1167         GC_TRIGGERS;
1168         NOTHROW;
1169         PRECONDITION(CheckPointer(pMD));
1170         PRECONDITION(pMD->IsRestored_NoLogging());
1171         PRECONDITION(ss.Check());
1172     }
1173     CONTRACTL_END
1174
1175 #ifndef DACCESS_COMPILE
1176     EX_TRY
1177     {
1178         AppendMethodInternal(ss, pMD, FormatSignature | FormatNamespace);
1179     }
1180     EX_CATCH
1181     {
1182         // This function is only used as diagnostic aid in debug builds.
1183         // If we run out of memory or hit some other problem,
1184         // tough luck for the debugger.
1185
1186         // Should we set ss to Empty
1187     }
1188     EX_END_CATCH(SwallowAllExceptions);
1189 #endif
1190 }
1191
1192 void TypeString::AppendTypeDebug(SString& ss, TypeHandle t)
1193 {
1194     CONTRACTL
1195     {
1196         MODE_ANY;
1197         GC_NOTRIGGER;
1198         NOTHROW;
1199         PRECONDITION(CheckPointer(t));
1200         PRECONDITION(ss.Check());
1201     }
1202     CONTRACTL_END
1203
1204 #ifndef DACCESS_COMPILE
1205     {
1206         EX_TRY
1207         {
1208             AppendType(ss, t, FormatNamespace | FormatDebug);
1209         }
1210         EX_CATCH
1211         {
1212             // This function is only used as diagnostic aid in debug builds. 
1213             // If we run out of memory or hit some other problem,
1214             // tough luck for the debugger.
1215         }
1216         EX_END_CATCH(SwallowAllExceptions);
1217     }
1218 #endif
1219 }
1220
1221 void TypeString::AppendTypeKeyDebug(SString& ss, TypeKey *pTypeKey)
1222 {
1223     CONTRACTL
1224     {
1225         MODE_ANY;
1226         GC_NOTRIGGER;
1227         NOTHROW;
1228         PRECONDITION(CheckPointer(pTypeKey));
1229         PRECONDITION(ss.Check());
1230     }
1231     CONTRACTL_END
1232
1233 #ifndef DACCESS_COMPILE
1234     {
1235         EX_TRY
1236         {
1237             AppendTypeKey(ss, pTypeKey, FormatNamespace | FormatDebug);
1238         }
1239         EX_CATCH
1240         {
1241             // This function is only used as diagnostic aid in debug builds. 
1242             // If we run out of memory or hit some other problem,
1243             // tough luck for the debugger.
1244         }
1245         EX_END_CATCH(SwallowAllExceptions);
1246     }
1247 #endif 
1248 }
1249
1250 #endif // _DEBUG
1251
1252
1253 void TypeString::AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format)
1254 {
1255     CONTRACT_VOID
1256     {
1257         MODE_ANY;
1258         THROWS;
1259         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1260         PRECONDITION(CheckPointer(pTypeKey));
1261     }
1262     CONTRACT_END
1263
1264     Module *pModule = NULL;
1265
1266     // It's an array, with format 
1267     //   element_ty[] (1-d, SZARRAY) 
1268     //   element_ty[*] (1-d, ARRAY)
1269     //   element_ty[,] (2-d, ARRAY) etc
1270     // or a pointer (*) or byref (&)
1271     CorElementType kind = pTypeKey->GetKind();
1272     if (CorTypeInfo::IsModifier(kind))
1273     {
1274         DWORD rank = 0;
1275         TypeHandle elemType = pTypeKey->GetElementType();
1276         if (CorTypeInfo::IsArray(kind))
1277         {
1278             rank = pTypeKey->GetRank();
1279         }
1280
1281         AppendType(tnb, elemType, Instantiation(), format);
1282         AppendParamTypeQualifier(tnb, kind, rank);
1283         pModule = elemType.GetModule();
1284     }
1285     else if (kind == ELEMENT_TYPE_VALUETYPE)
1286     {
1287         tnb.Append(W("VALUETYPE"));
1288         TypeHandle elemType = pTypeKey->GetElementType();
1289         AppendType(tnb, elemType, Instantiation(), format);
1290         pModule = elemType.GetModule();
1291     }
1292     else if (kind == ELEMENT_TYPE_FNPTR)
1293     {
1294         RETURN;
1295     }
1296
1297     // ...otherwise it's just a plain type def or an instantiated type
1298     else 
1299     {
1300         // Get the TypeDef token and attributes
1301         pModule = pTypeKey->GetModule();
1302         if (pModule != NULL)
1303         {
1304             IMDInternalImport *pImport = pModule->GetMDImport();
1305             mdTypeDef td = pTypeKey->GetTypeToken();
1306             _ASSERTE(!IsNilToken(td));
1307
1308             AppendNestedTypeDef(tnb, pImport, td, format);
1309
1310             // Append the instantiation
1311             if ((format & (FormatNamespace|FormatAssembly)) && pTypeKey->HasInstantiation())
1312                 AppendInst(tnb, pTypeKey->GetInstantiation(), format);
1313         }
1314
1315     }
1316
1317     // Now append the assembly
1318     if (pModule != NULL && (format & FormatAssembly))
1319     {
1320         Assembly* pAssembly = pModule->GetAssembly();
1321         _ASSERTE(pAssembly != NULL);
1322
1323         StackSString pAssemblyName;
1324 #ifdef DACCESS_COMPILE
1325         pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1326 #else
1327         pAssembly->GetDisplayName(pAssemblyName,
1328                                   ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1329                                   (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1330 #endif
1331         tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1332     }            
1333
1334     RETURN;
1335 }
1336
1337 void TypeString::AppendTypeKey(SString& ss, TypeKey *pTypeKey, DWORD format)
1338 {
1339     CONTRACT_VOID
1340     {
1341         MODE_ANY;
1342         if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1343         THROWS;
1344         PRECONDITION(CheckPointer(pTypeKey));
1345     }
1346     CONTRACT_END
1347
1348     {
1349         TypeNameBuilder tnb(&ss);
1350         AppendTypeKey(tnb, pTypeKey, format);
1351     }
1352
1353     RETURN;
1354 }
1355
1356 /*static*/
1357 void TypeString::EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName)
1358 {
1359     SString::Iterator itr = ssTypeName->Begin();
1360     WCHAR c;
1361     while ((c = *itr++) != W('\0'))
1362     {
1363         if (IsTypeNameReservedChar(c))
1364             ssEscapedTypeName->Append(W("\\"));
1365     
1366         ssEscapedTypeName->Append(c);
1367     }
1368 }
1369
1370 /*static*/
1371 bool TypeString::ContainsReservedChar(LPCWSTR pTypeName)
1372 {
1373     CONTRACTL
1374     {
1375         GC_NOTRIGGER;
1376         MODE_ANY;
1377     }
1378     CONTRACTL_END;
1379
1380     WCHAR c;
1381     while ((c = * pTypeName++) != W('\0'))
1382     {
1383         if (IsTypeNameReservedChar(c))
1384         {
1385             return true;
1386         }
1387     }
1388
1389     return false;
1390 }