Revert "[cil-strip] Remove old private copy of Mono.Cecil"
[mono.git] / mcs / tools / cil-strip / Mono.Cecil / ReflectionWriter.cs
1 //
2 // ReflectionWriter.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 - 2007 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 namespace Mono.Cecil {
30
31         using System;
32         using System.Collections;
33         using System.Globalization;
34         using System.Text;
35
36         using Mono.Cecil.Binary;
37         using Mono.Cecil.Cil;
38         using Mono.Cecil.Metadata;
39         using Mono.Cecil.Signatures;
40
41         internal sealed class ReflectionWriter : BaseReflectionVisitor {
42
43                 StructureWriter m_structureWriter;
44                 ModuleDefinition m_mod;
45                 SignatureWriter m_sigWriter;
46                 CodeWriter m_codeWriter;
47                 MetadataWriter m_mdWriter;
48                 MetadataTableWriter m_tableWriter;
49                 MetadataRowWriter m_rowWriter;
50
51                 bool m_saveSymbols;
52                 string m_asmOutput;
53                 ISymbolWriter m_symbolWriter;
54
55                 ArrayList m_typeDefStack;
56                 ArrayList m_methodStack;
57                 ArrayList m_fieldStack;
58                 ArrayList m_genericParamStack;
59                 IDictionary m_typeSpecTokenCache;
60                 IDictionary m_memberRefTokenCache;
61
62                 uint m_methodIndex;
63                 uint m_fieldIndex;
64                 uint m_paramIndex;
65                 uint m_eventIndex;
66                 uint m_propertyIndex;
67
68                 MemoryBinaryWriter m_constWriter;
69
70                 public StructureWriter StructureWriter {
71                         get { return m_structureWriter; }
72                         set {
73                                  m_structureWriter = value;
74
75                                 Initialize ();
76                         }
77                 }
78
79                 public CodeWriter CodeWriter {
80                         get { return m_codeWriter; }
81                 }
82
83                 public bool SaveSymbols {
84                         get { return m_saveSymbols; }
85                         set { m_saveSymbols = value; }
86                 }
87
88                 public string OutputFile
89                 {
90                         get { return m_asmOutput; }
91                         set { m_asmOutput = value; }
92                 }
93
94                 public ISymbolWriter SymbolWriter {
95                         get { return m_symbolWriter; }
96                         set { m_symbolWriter = value; }
97                 }
98
99                 public SignatureWriter SignatureWriter {
100                         get { return m_sigWriter; }
101                 }
102
103                 public MetadataWriter MetadataWriter {
104                         get { return m_mdWriter; }
105                 }
106
107                 public MetadataTableWriter MetadataTableWriter {
108                         get { return m_tableWriter; }
109                 }
110
111                 public MetadataRowWriter MetadataRowWriter {
112                         get { return m_rowWriter; }
113                 }
114
115                 public ReflectionWriter (ModuleDefinition mod)
116                 {
117                         m_mod = mod;
118                 }
119
120                 void Initialize ()
121                 {
122                         m_mdWriter = new MetadataWriter (
123                                 m_mod.Assembly,
124                                 m_mod.Image.MetadataRoot,
125                                 m_structureWriter.Assembly.Kind,
126                                 m_mod.Assembly.Runtime,
127                                 m_structureWriter.GetWriter ());
128                         m_tableWriter = m_mdWriter.GetTableVisitor ();
129                         m_rowWriter = m_tableWriter.GetRowVisitor () as MetadataRowWriter;
130                         m_sigWriter = new SignatureWriter (m_mdWriter);
131                         m_codeWriter = new CodeWriter (this, m_mdWriter.CilWriter);
132
133                         m_typeDefStack = new ArrayList ();
134                         m_methodStack = new ArrayList ();
135                         m_fieldStack = new ArrayList ();
136                         m_genericParamStack = new ArrayList ();
137                         m_typeSpecTokenCache = new Hashtable ();
138                         m_memberRefTokenCache = new Hashtable ();
139
140                         m_methodIndex = 1;
141                         m_fieldIndex = 1;
142                         m_paramIndex = 1;
143                         m_eventIndex = 1;
144                         m_propertyIndex = 1;
145
146                         m_constWriter = new MemoryBinaryWriter ();
147                 }
148
149                 public TypeReference GetCoreType (string name)
150                 {
151                         return m_mod.Controller.Reader.SearchCoreType (name);
152                 }
153
154                 public static uint GetRidFor (IMetadataTokenProvider tp)
155                 {
156                         return tp.MetadataToken.RID;
157                 }
158
159                 public uint GetRidFor (AssemblyNameReference asmName)
160                 {
161                         return (uint) m_mod.AssemblyReferences.IndexOf (asmName) + 1;
162                 }
163
164                 public uint GetRidFor (ModuleDefinition mod)
165                 {
166                         return (uint) m_mod.Assembly.Modules.IndexOf (mod) + 1;
167                 }
168
169                 public uint GetRidFor (ModuleReference modRef)
170                 {
171                         return (uint) m_mod.ModuleReferences.IndexOf (modRef) + 1;
172                 }
173
174                 static bool IsTypeSpec (TypeReference type)
175                 {
176                         return type is TypeSpecification || type is GenericParameter;
177                 }
178
179                 public MetadataToken GetTypeDefOrRefToken (TypeReference type)
180                 {
181                         if (IsTypeSpec (type)) {
182                                 uint sig = m_sigWriter.AddTypeSpec (GetTypeSpecSig (type));
183                                 if (m_typeSpecTokenCache.Contains (sig))
184                                         return (MetadataToken) m_typeSpecTokenCache [sig];
185
186                                 TypeSpecTable tsTable = m_tableWriter.GetTypeSpecTable ();
187                                 TypeSpecRow tsRow = m_rowWriter.CreateTypeSpecRow (sig);
188                                 tsTable.Rows.Add (tsRow);
189
190                                 MetadataToken token = new MetadataToken (TokenType.TypeSpec, (uint) tsTable.Rows.Count);
191                                 if (! (type is GenericParameter))
192                                         type.MetadataToken = token;
193
194                                 m_typeSpecTokenCache [sig] = token;
195                                 return token;
196                         } else if (type != null)
197                                 return type.MetadataToken;
198                         else // <Module> and interfaces
199                                 return new MetadataToken (TokenType.TypeRef, 0);
200                 }
201
202                 public MetadataToken GetMemberRefToken (MemberReference member)
203                 {
204                         if (member is MethodSpecification)
205                                 return GetMemberRefToken (((MethodSpecification) member).ElementMethod);
206                         if (member is IMemberDefinition)
207                                 return member.MetadataToken;
208                         if (m_memberRefTokenCache.Contains (member))
209                                 return (MetadataToken) m_memberRefTokenCache [member];
210
211                         MemberRefTable mrTable = m_tableWriter.GetMemberRefTable ();
212
213                         uint sig = 0;
214                         if (member is FieldReference)
215                                 sig = m_sigWriter.AddFieldSig (GetFieldSig ((FieldReference) member));
216                         else if (member is MethodReference)
217                                 sig = m_sigWriter.AddMethodRefSig (GetMethodRefSig ((MethodReference) member));
218
219                         MetadataToken declaringType = GetTypeDefOrRefToken (member.DeclaringType);
220                         uint name = m_mdWriter.AddString (member.Name);
221
222                         for (int i = 0; i < mrTable.Rows.Count; i++) {
223                                 MemberRefRow row = mrTable [i];
224                                 if (row.Class == declaringType && row.Name == name && row.Signature == sig)
225                                         return MetadataToken.FromMetadataRow (TokenType.MemberRef, i);
226                         }
227
228                         MemberRefRow mrRow = m_rowWriter.CreateMemberRefRow (
229                                 declaringType,
230                                 name,
231                                 sig);
232
233                         mrTable.Rows.Add (mrRow);
234                         member.MetadataToken = new MetadataToken (
235                                 TokenType.MemberRef, (uint) mrTable.Rows.Count);
236                         m_memberRefTokenCache [member] = member.MetadataToken;
237                         return member.MetadataToken;
238                 }
239
240                 public MetadataToken GetMethodSpecToken (GenericInstanceMethod gim)
241                 {
242                         uint sig = m_sigWriter.AddMethodSpec (GetMethodSpecSig (gim));
243                         MethodSpecTable msTable = m_tableWriter.GetMethodSpecTable ();
244
245                         MetadataToken meth = GetMemberRefToken (gim.ElementMethod);
246
247                         for (int i = 0; i < msTable.Rows.Count; i++) {
248                                 MethodSpecRow row = msTable [i];
249                                 if (row.Method == meth && row.Instantiation == sig)
250                                         return MetadataToken.FromMetadataRow (TokenType.MethodSpec, i);
251                         }
252
253                         MethodSpecRow msRow = m_rowWriter.CreateMethodSpecRow (
254                                 meth,
255                                 sig);
256                         msTable.Rows.Add (msRow);
257                         gim.MetadataToken = new MetadataToken (TokenType.MethodSpec, (uint) msTable.Rows.Count);
258                         return gim.MetadataToken;
259                 }
260
261                 public override void VisitModuleDefinition (ModuleDefinition mod)
262                 {
263                         mod.FullLoad ();
264                 }
265
266                 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
267                 {
268                         TypeDefTable tdTable = m_tableWriter.GetTypeDefTable ();
269
270                         if (types [Constants.ModuleType] == null)
271                                 types.Add (new TypeDefinition (
272                                                 Constants.ModuleType, string.Empty, TypeAttributes.NotPublic));
273
274                         foreach (TypeDefinition t in types)
275                                 m_typeDefStack.Add (t);
276
277                         m_typeDefStack.Sort (TableComparers.TypeDef.Instance);
278
279                         for (int i = 0; i < m_typeDefStack.Count; i++) {
280                                 TypeDefinition t = (TypeDefinition) m_typeDefStack [i];
281                                 if (t.Module.Assembly != m_mod.Assembly)
282                                         throw new ReflectionException ("A type as not been correctly imported");
283
284                                 t.MetadataToken = new MetadataToken (TokenType.TypeDef, (uint) (i + 1));
285                         }
286
287                         foreach (TypeDefinition t in m_typeDefStack) {
288                                 TypeDefRow tdRow = m_rowWriter.CreateTypeDefRow (
289                                         t.Attributes,
290                                         m_mdWriter.AddString (t.Name),
291                                         m_mdWriter.AddString (t.Namespace),
292                                         GetTypeDefOrRefToken (t.BaseType),
293                                         0,
294                                         0);
295
296                                 tdTable.Rows.Add (tdRow);
297                         }
298                 }
299
300                 public void CompleteTypeDefinitions ()
301                 {
302                         TypeDefTable tdTable = m_tableWriter.GetTypeDefTable ();
303
304                         for (int i = 0; i < m_typeDefStack.Count; i++) {
305                                 TypeDefRow tdRow = tdTable [i];
306                                 TypeDefinition t = (TypeDefinition) m_typeDefStack [i];
307                                 tdRow.FieldList = m_fieldIndex;
308                                 tdRow.MethodList = m_methodIndex;
309                                 if (t.HasFields) {
310                                         foreach (FieldDefinition field in t.Fields)
311                                                 VisitFieldDefinition (field);
312                                 }
313                                 if (t.HasConstructors) {
314                                         foreach (MethodDefinition ctor in t.Constructors)
315                                                 VisitMethodDefinition (ctor);
316                                 }
317                                 if (t.HasMethods) {
318                                         foreach (MethodDefinition meth in t.Methods)
319                                                 VisitMethodDefinition (meth);
320                                 }
321
322                                 if (t.HasLayoutInfo)
323                                         WriteLayout (t);
324                         }
325
326                         foreach (FieldDefinition field in m_fieldStack) {
327                                 if (field.HasCustomAttributes)
328                                         VisitCustomAttributeCollection (field.CustomAttributes);
329                                 if (field.MarshalSpec != null)
330                                         VisitMarshalSpec (field.MarshalSpec);
331                         }
332
333                         foreach (MethodDefinition meth in m_methodStack) {
334                                 if (meth.ReturnType.HasCustomAttributes)
335                                         VisitCustomAttributeCollection (meth.ReturnType.CustomAttributes);
336                                 if (meth.HasParameters) {
337                                         foreach (ParameterDefinition param in meth.Parameters) {
338                                                 if (param.HasCustomAttributes)
339                                                         VisitCustomAttributeCollection (param.CustomAttributes);
340                                         }
341                                 }
342                                 if (meth.HasGenericParameters)
343                                         VisitGenericParameterCollection (meth.GenericParameters);
344                                 if (meth.HasOverrides)
345                                         VisitOverrideCollection (meth.Overrides);
346                                 if (meth.HasCustomAttributes)
347                                         VisitCustomAttributeCollection (meth.CustomAttributes);
348                                 if (meth.HasSecurityDeclarations)
349                                         VisitSecurityDeclarationCollection (meth.SecurityDeclarations);
350                                 if (meth.PInvokeInfo != null) {
351                                         meth.Attributes |= MethodAttributes.PInvokeImpl;
352                                         VisitPInvokeInfo (meth.PInvokeInfo);
353                                 }
354                         }
355
356                         foreach (TypeDefinition t in m_typeDefStack)
357                                 t.Accept (this);
358                 }
359
360                 public override void VisitTypeReferenceCollection (TypeReferenceCollection refs)
361                 {
362                         ArrayList orderedTypeRefs = new ArrayList (refs.Count);
363                         foreach (TypeReference tr in refs)
364                                 orderedTypeRefs.Add (tr);
365
366                         orderedTypeRefs.Sort (TableComparers.TypeRef.Instance);
367
368                         TypeRefTable trTable = m_tableWriter.GetTypeRefTable ();
369                         foreach (TypeReference t in orderedTypeRefs) {
370                                 MetadataToken scope;
371
372                                 if (t.Module.Assembly != m_mod.Assembly)
373                                         throw new ReflectionException ("A type as not been correctly imported");
374
375                                 if (t.Scope == null)
376                                         continue;
377
378                                 if (t.DeclaringType != null)
379                                         scope = new MetadataToken (TokenType.TypeRef, GetRidFor (t.DeclaringType));
380                                 else if (t.Scope is AssemblyNameReference)
381                                         scope = new MetadataToken (TokenType.AssemblyRef,
382                                                 GetRidFor ((AssemblyNameReference) t.Scope));
383                                 else if (t.Scope is ModuleDefinition)
384                                         scope = new MetadataToken (TokenType.Module,
385                                                 GetRidFor ((ModuleDefinition) t.Scope));
386                                 else if (t.Scope is ModuleReference)
387                                         scope = new MetadataToken (TokenType.ModuleRef,
388                                                 GetRidFor ((ModuleReference) t.Scope));
389                                 else
390                                         scope = new MetadataToken (TokenType.ExportedType, 0);
391
392                                 TypeRefRow trRow = m_rowWriter.CreateTypeRefRow (
393                                         scope,
394                                         m_mdWriter.AddString (t.Name),
395                                         m_mdWriter.AddString (t.Namespace));
396
397                                 trTable.Rows.Add (trRow);
398                                 t.MetadataToken = new MetadataToken (TokenType.TypeRef, (uint) trTable.Rows.Count);
399                         }
400                 }
401
402                 public override void VisitGenericParameterCollection (GenericParameterCollection parameters)
403                 {
404                         if (parameters.Count == 0)
405                                 return;
406
407                         foreach (GenericParameter gp in parameters)
408                                 m_genericParamStack.Add (gp);
409                 }
410
411                 public override void VisitInterfaceCollection (InterfaceCollection interfaces)
412                 {
413                         if (interfaces.Count == 0)
414                                 return;
415
416                         InterfaceImplTable iiTable = m_tableWriter.GetInterfaceImplTable ();
417                         foreach (TypeReference interf in interfaces) {
418                                 InterfaceImplRow iiRow = m_rowWriter.CreateInterfaceImplRow (
419                                         GetRidFor (interfaces.Container),
420                                         GetTypeDefOrRefToken (interf));
421
422                                 iiTable.Rows.Add (iiRow);
423                         }
424                 }
425
426                 public override void VisitExternTypeCollection (ExternTypeCollection externs)
427                 {
428                         if (externs.Count == 0)
429                                 return;
430
431                         ExportedTypeTable etTable = m_tableWriter.GetExportedTypeTable ();
432                         foreach (TypeReference ext in externs) {
433                                 TypeDefinition td = ext.Resolve ();
434                                 if (td == null)
435                                         continue;
436
437                                 MetadataToken scope = GetExportedTypeScope (td);
438
439                                 ExportedTypeRow etRow = m_rowWriter.CreateExportedTypeRow (
440                                         td.Attributes,
441                                         0,
442                                         m_mdWriter.AddString (td.Name),
443                                         m_mdWriter.AddString (td.Namespace),
444                                         scope);
445
446                                 etTable.Rows.Add (etRow);
447                                 ext.MetadataToken = new MetadataToken (TokenType.ExportedType, (uint) etTable.Rows.Count);
448                         }
449                 }
450
451                 MetadataToken GetExportedTypeScope (TypeDefinition t)
452                 {
453                         if (t.DeclaringType != null)
454                                 return t.DeclaringType.MetadataToken;
455
456                         if (t.Scope is AssemblyNameReference)
457                                 return new MetadataToken (TokenType.AssemblyRef, GetRidFor ((AssemblyNameReference) t.Scope));
458
459                         if (t.Scope is ModuleDefinition)
460                                 return new MetadataToken (TokenType.Module, GetRidFor ((ModuleDefinition) t.Scope));
461
462                         throw new NotImplementedException ();
463                 }
464
465                 public override void VisitOverrideCollection (OverrideCollection meths)
466                 {
467                         if (meths.Count == 0)
468                                 return;
469
470                         MethodImplTable miTable = m_tableWriter.GetMethodImplTable ();
471                         foreach (MethodReference ov in meths) {
472                                 MethodImplRow miRow = m_rowWriter.CreateMethodImplRow (
473                                         GetRidFor (meths.Container.DeclaringType as TypeDefinition),
474                                         new MetadataToken (TokenType.Method, GetRidFor (meths.Container)),
475                                         GetMemberRefToken (ov));
476
477                                 miTable.Rows.Add (miRow);
478                         }
479                 }
480
481                 public override void VisitNestedTypeCollection (NestedTypeCollection nestedTypes)
482                 {
483                         if (nestedTypes.Count == 0)
484                                 return;
485
486                         NestedClassTable ncTable = m_tableWriter.GetNestedClassTable ();
487                         foreach (TypeDefinition nested in nestedTypes) {
488                                 NestedClassRow ncRow = m_rowWriter.CreateNestedClassRow (
489                                         nested.MetadataToken.RID,
490                                         GetRidFor (nestedTypes.Container));
491
492                                 ncTable.Rows.Add (ncRow);
493                         }
494                 }
495
496                 public override void VisitParameterDefinitionCollection (ParameterDefinitionCollection parameters)
497                 {
498                         if (parameters.Count == 0)
499                                 return;
500
501                         ushort seq = 1;
502                         ParamTable pTable = m_tableWriter.GetParamTable ();
503                         foreach (ParameterDefinition param in parameters)
504                                 InsertParameter (pTable, param, seq++);
505                 }
506
507                 void InsertParameter (ParamTable pTable, ParameterDefinition param, ushort seq)
508                 {
509                         ParamRow pRow = m_rowWriter.CreateParamRow (
510                                 param.Attributes,
511                                 seq,
512                                 m_mdWriter.AddString (param.Name));
513
514                         pTable.Rows.Add (pRow);
515                         param.MetadataToken = new MetadataToken (TokenType.Param, (uint) pTable.Rows.Count);
516
517                         if (param.MarshalSpec != null)
518                                 param.MarshalSpec.Accept (this);
519
520                         if (param.HasConstant)
521                                 WriteConstant (param, param.ParameterType);
522
523                         m_paramIndex++;
524                 }
525
526                 static bool RequiresParameterRow (MethodReturnType mrt)
527                 {
528                         return mrt.HasConstant || mrt.MarshalSpec != null ||
529                                 mrt.CustomAttributes.Count > 0 || mrt.Parameter.Attributes != (ParameterAttributes) 0;
530                 }
531
532                 public override void VisitMethodDefinition (MethodDefinition method)
533                 {
534                         MethodTable mTable = m_tableWriter.GetMethodTable ();
535                         MethodRow mRow = m_rowWriter.CreateMethodRow (
536                                 RVA.Zero,
537                                 method.ImplAttributes,
538                                 method.Attributes,
539                                 m_mdWriter.AddString (method.Name),
540                                 m_sigWriter.AddMethodDefSig (GetMethodDefSig (method)),
541                                 m_paramIndex);
542
543                         mTable.Rows.Add (mRow);
544                         m_methodStack.Add (method);
545                         method.MetadataToken = new MetadataToken (TokenType.Method, (uint) mTable.Rows.Count);
546                         m_methodIndex++;
547
548                         if (RequiresParameterRow (method.ReturnType))
549                                 InsertParameter (m_tableWriter.GetParamTable (), method.ReturnType.Parameter, 0);
550
551                         VisitParameterDefinitionCollection (method.Parameters);
552                 }
553
554                 public override void VisitPInvokeInfo (PInvokeInfo pinvk)
555                 {
556                         ImplMapTable imTable = m_tableWriter.GetImplMapTable ();
557                         ImplMapRow imRow = m_rowWriter.CreateImplMapRow (
558                                 pinvk.Attributes,
559                                 new MetadataToken (TokenType.Method, GetRidFor (pinvk.Method)),
560                                 m_mdWriter.AddString (pinvk.EntryPoint),
561                                 GetRidFor (pinvk.Module));
562
563                         imTable.Rows.Add (imRow);
564                 }
565
566                 public override void VisitEventDefinitionCollection (EventDefinitionCollection events)
567                 {
568                         if (events.Count == 0)
569                                 return;
570
571                         EventMapTable emTable = m_tableWriter.GetEventMapTable ();
572                         EventMapRow emRow = m_rowWriter.CreateEventMapRow (
573                                 GetRidFor (events.Container),
574                                 m_eventIndex);
575
576                         emTable.Rows.Add (emRow);
577                         VisitCollection (events);
578                 }
579
580                 public override void VisitEventDefinition (EventDefinition evt)
581                 {
582                         EventTable eTable = m_tableWriter.GetEventTable ();
583                         EventRow eRow = m_rowWriter.CreateEventRow (
584                                 evt.Attributes,
585                                 m_mdWriter.AddString (evt.Name),
586                                 GetTypeDefOrRefToken (evt.EventType));
587
588                         eTable.Rows.Add (eRow);
589                         evt.MetadataToken = new MetadataToken (TokenType.Event, (uint) eTable.Rows.Count);
590
591                         if (evt.AddMethod != null)
592                                 WriteSemantic (MethodSemanticsAttributes.AddOn, evt, evt.AddMethod);
593
594                         if (evt.InvokeMethod != null)
595                                 WriteSemantic (MethodSemanticsAttributes.Fire, evt, evt.InvokeMethod);
596
597                         if (evt.RemoveMethod != null)
598                                 WriteSemantic (MethodSemanticsAttributes.RemoveOn, evt, evt.RemoveMethod);
599
600                         m_eventIndex++;
601                 }
602
603                 public override void VisitFieldDefinition (FieldDefinition field)
604                 {
605                         FieldTable fTable = m_tableWriter.GetFieldTable ();
606                         FieldRow fRow = m_rowWriter.CreateFieldRow (
607                                 field.Attributes,
608                                 m_mdWriter.AddString (field.Name),
609                                 m_sigWriter.AddFieldSig (GetFieldSig (field)));
610
611                         fTable.Rows.Add (fRow);
612                         field.MetadataToken = new MetadataToken (TokenType.Field, (uint) fTable.Rows.Count);
613                         m_fieldIndex++;
614
615                         if (field.HasConstant)
616                                 WriteConstant (field, field.FieldType);
617
618                         if (field.HasLayoutInfo)
619                                 WriteLayout (field);
620
621                         m_fieldStack.Add (field);
622                 }
623
624                 public override void VisitPropertyDefinitionCollection (PropertyDefinitionCollection properties)
625                 {
626                         if (properties.Count == 0)
627                                 return;
628
629                         PropertyMapTable pmTable = m_tableWriter.GetPropertyMapTable ();
630                         PropertyMapRow pmRow = m_rowWriter.CreatePropertyMapRow (
631                                 GetRidFor (properties.Container),
632                                 m_propertyIndex);
633
634                         pmTable.Rows.Add (pmRow);
635                         VisitCollection (properties);
636                 }
637
638                 public override void VisitPropertyDefinition (PropertyDefinition property)
639                 {
640                         PropertyTable pTable = m_tableWriter.GetPropertyTable ();
641                         PropertyRow pRow = m_rowWriter.CreatePropertyRow (
642                                 property.Attributes,
643                                 m_mdWriter.AddString (property.Name),
644                                 m_sigWriter.AddPropertySig (GetPropertySig (property)));
645
646                         pTable.Rows.Add (pRow);
647                         property.MetadataToken = new MetadataToken (TokenType.Property, (uint) pTable.Rows.Count);
648
649                         if (property.GetMethod != null)
650                                 WriteSemantic (MethodSemanticsAttributes.Getter, property, property.GetMethod);
651
652                         if (property.SetMethod != null)
653                                 WriteSemantic (MethodSemanticsAttributes.Setter, property, property.SetMethod);
654
655                         if (property.HasConstant)
656                                 WriteConstant (property, property.PropertyType);
657
658                         m_propertyIndex++;
659                 }
660
661                 public override void VisitSecurityDeclarationCollection (SecurityDeclarationCollection secDecls)
662                 {
663                         if (secDecls.Count == 0)
664                                 return;
665
666                         DeclSecurityTable dsTable = m_tableWriter.GetDeclSecurityTable ();
667                         foreach (SecurityDeclaration secDec in secDecls) {
668                                 DeclSecurityRow dsRow = m_rowWriter.CreateDeclSecurityRow (
669                                         secDec.Action,
670                                         secDecls.Container.MetadataToken,
671                                         m_mdWriter.AddBlob (secDec.Resolved ?
672                                                 m_mod.GetAsByteArray (secDec) : secDec.Blob));
673
674                                 dsTable.Rows.Add (dsRow);
675                         }
676                 }
677
678                 public override void VisitCustomAttributeCollection (CustomAttributeCollection customAttrs)
679                 {
680                         if (customAttrs.Count == 0)
681                                 return;
682
683                         CustomAttributeTable caTable = m_tableWriter.GetCustomAttributeTable ();
684                         foreach (CustomAttribute ca in customAttrs) {
685                                 MetadataToken parent;
686                                 if (customAttrs.Container is AssemblyDefinition)
687                                         parent = new MetadataToken (TokenType.Assembly, 1);
688                                 else if (customAttrs.Container is ModuleDefinition)
689                                         parent = new MetadataToken (TokenType.Module, 1);
690                                 else if (customAttrs.Container is IMetadataTokenProvider)
691                                         parent = ((IMetadataTokenProvider) customAttrs.Container).MetadataToken;
692                                 else
693                                         throw new ReflectionException ("Unknown Custom Attribute parent");
694
695                                 uint value = ca.Resolved ?
696                                         m_sigWriter.AddCustomAttribute (GetCustomAttributeSig (ca), ca.Constructor) :
697                                         m_mdWriter.AddBlob (m_mod.GetAsByteArray (ca));
698                                 CustomAttributeRow caRow = m_rowWriter.CreateCustomAttributeRow (
699                                         parent,
700                                         GetMemberRefToken (ca.Constructor),
701                                         value);
702
703                                 caTable.Rows.Add (caRow);
704                         }
705                 }
706
707                 public override void VisitMarshalSpec (MarshalSpec marshalSpec)
708                 {
709                         FieldMarshalTable fmTable = m_tableWriter.GetFieldMarshalTable ();
710                         FieldMarshalRow fmRow = m_rowWriter.CreateFieldMarshalRow (
711                                 marshalSpec.Container.MetadataToken,
712                                 m_sigWriter.AddMarshalSig (GetMarshalSig (marshalSpec)));
713
714                         fmTable.Rows.Add (fmRow);
715                 }
716
717                 void WriteConstant (IHasConstant hc, TypeReference type)
718                 {
719                         ConstantTable cTable = m_tableWriter.GetConstantTable ();
720                         ElementType et;
721                         if (type is TypeDefinition && (type as TypeDefinition).IsEnum) {
722                                 Type t = hc.Constant.GetType ();
723                                 if (t.IsEnum)
724                                         t = Enum.GetUnderlyingType (t);
725
726                                 et = GetCorrespondingType (string.Concat (t.Namespace, '.', t.Name));
727                         } else
728                                 et = GetCorrespondingType (type.FullName);
729
730                         if (et == ElementType.Object || et == ElementType.Type || et == ElementType.String)
731                                 et = hc.Constant == null ?
732                                         ElementType.Class :
733                                         GetCorrespondingType (hc.Constant.GetType ().FullName);
734
735                         ConstantRow cRow = m_rowWriter.CreateConstantRow (
736                                 et,
737                                 hc.MetadataToken,
738                                 m_mdWriter.AddBlob (EncodeConstant (et, hc.Constant)));
739
740                         cTable.Rows.Add (cRow);
741                 }
742
743                 void WriteLayout (FieldDefinition field)
744                 {
745                         FieldLayoutTable flTable = m_tableWriter.GetFieldLayoutTable ();
746                         FieldLayoutRow flRow = m_rowWriter.CreateFieldLayoutRow (
747                                 field.Offset,
748                                 GetRidFor (field));
749
750                         flTable.Rows.Add (flRow);
751                 }
752
753                 void WriteLayout (TypeDefinition type)
754                 {
755                         ClassLayoutTable clTable = m_tableWriter.GetClassLayoutTable ();
756                         ClassLayoutRow clRow = m_rowWriter.CreateClassLayoutRow (
757                                 type.PackingSize,
758                                 type.ClassSize,
759                                 GetRidFor (type));
760
761                         clTable.Rows.Add (clRow);
762                 }
763
764                 void WriteSemantic (MethodSemanticsAttributes attrs,
765                         IMetadataTokenProvider member, MethodDefinition meth)
766                 {
767                         MethodSemanticsTable msTable = m_tableWriter.GetMethodSemanticsTable ();
768                         MethodSemanticsRow msRow = m_rowWriter.CreateMethodSemanticsRow (
769                                 attrs,
770                                 GetRidFor (meth),
771                                 member.MetadataToken);
772
773                         msTable.Rows.Add (msRow);
774                 }
775
776                 void SortTables ()
777                 {
778                         TablesHeap th = m_mdWriter.GetMetadataRoot ().Streams.TablesHeap;
779                         th.Sorted = 0;
780
781                         if (th.HasTable (NestedClassTable.RId))
782                                 m_tableWriter.GetNestedClassTable ().Rows.Sort (
783                                         TableComparers.NestedClass.Instance);
784                         th.Sorted |= ((long) 1 << NestedClassTable.RId);
785
786                         if (th.HasTable (InterfaceImplTable.RId))
787                                 m_tableWriter.GetInterfaceImplTable ().Rows.Sort (
788                                         TableComparers.InterfaceImpl.Instance);
789                         th.Sorted |= ((long) 1 << InterfaceImplTable.RId);
790
791                         if (th.HasTable (ConstantTable.RId))
792                                 m_tableWriter.GetConstantTable ().Rows.Sort (
793                                         TableComparers.Constant.Instance);
794                         th.Sorted |= ((long) 1 << ConstantTable.RId);
795
796                         if (th.HasTable (MethodSemanticsTable.RId))
797                                 m_tableWriter.GetMethodSemanticsTable ().Rows.Sort (
798                                         TableComparers.MethodSem.Instance);
799                         th.Sorted |= ((long) 1 << MethodSemanticsTable.RId);
800
801                         if (th.HasTable (FieldMarshalTable.RId))
802                                 m_tableWriter.GetFieldMarshalTable ().Rows.Sort (
803                                         TableComparers.FieldMarshal.Instance);
804                         th.Sorted |= ((long) 1 << FieldMarshalTable.RId);
805
806                         if (th.HasTable (ClassLayoutTable.RId))
807                                 m_tableWriter.GetClassLayoutTable ().Rows.Sort (
808                                         TableComparers.TypeLayout.Instance);
809                         th.Sorted |= ((long) 1 << ClassLayoutTable.RId);
810
811                         if (th.HasTable (FieldLayoutTable.RId))
812                                 m_tableWriter.GetFieldLayoutTable ().Rows.Sort (
813                                         TableComparers.FieldLayout.Instance);
814                         th.Sorted |= ((long) 1 << FieldLayoutTable.RId);
815
816                         if (th.HasTable (ImplMapTable.RId))
817                                 m_tableWriter.GetImplMapTable ().Rows.Sort (
818                                         TableComparers.PInvoke.Instance);
819                         th.Sorted |= ((long) 1 << ImplMapTable.RId);
820
821                         if (th.HasTable (FieldRVATable.RId))
822                                 m_tableWriter.GetFieldRVATable ().Rows.Sort (
823                                         TableComparers.FieldRVA.Instance);
824                         th.Sorted |= ((long) 1 << FieldRVATable.RId);
825
826                         if (th.HasTable (MethodImplTable.RId))
827                                 m_tableWriter.GetMethodImplTable ().Rows.Sort (
828                                         TableComparers.Override.Instance);
829                         th.Sorted |= ((long) 1 << MethodImplTable.RId);
830
831                         if (th.HasTable (CustomAttributeTable.RId))
832                                 m_tableWriter.GetCustomAttributeTable ().Rows.Sort (
833                                         TableComparers.CustomAttribute.Instance);
834                         th.Sorted |= ((long) 1 << CustomAttributeTable.RId);
835
836                         if (th.HasTable (DeclSecurityTable.RId))
837                                 m_tableWriter.GetDeclSecurityTable ().Rows.Sort (
838                                         TableComparers.SecurityDeclaration.Instance);
839                         th.Sorted |= ((long) 1 << DeclSecurityTable.RId);
840                 }
841
842                 void CompleteGenericTables ()
843                 {
844                         if (m_genericParamStack.Count == 0)
845                                 return;
846
847                         TablesHeap th = m_mdWriter.GetMetadataRoot ().Streams.TablesHeap;
848                         GenericParamTable gpTable = m_tableWriter.GetGenericParamTable ();
849
850                         m_genericParamStack.Sort (TableComparers.GenericParam.Instance);
851
852                         foreach (GenericParameter gp in m_genericParamStack) {
853                                 GenericParamRow gpRow = m_rowWriter.CreateGenericParamRow (
854                                         (ushort) gp.Owner.GenericParameters.IndexOf (gp),
855                                         gp.Attributes,
856                                         gp.Owner.MetadataToken,
857                                         m_mdWriter.AddString (gp.Name));
858
859                                 gpTable.Rows.Add (gpRow);
860                                 gp.MetadataToken = new MetadataToken (TokenType.GenericParam, (uint) gpTable.Rows.Count);
861
862                                 if (gp.HasCustomAttributes)
863                                         VisitCustomAttributeCollection (gp.CustomAttributes);
864
865                                 if (!gp.HasConstraints)
866                                         continue;
867
868                                 GenericParamConstraintTable gpcTable = m_tableWriter.GetGenericParamConstraintTable ();
869
870                                 foreach (TypeReference constraint in gp.Constraints) {
871                                         GenericParamConstraintRow gpcRow = m_rowWriter.CreateGenericParamConstraintRow (
872                                                 (uint) gpTable.Rows.Count,
873                                                 GetTypeDefOrRefToken (constraint));
874
875                                         gpcTable.Rows.Add (gpcRow);
876                                 }
877                         }
878
879                         th.Sorted |= ((long) 1 << GenericParamTable.RId);
880                         th.Sorted |= ((long) 1 << GenericParamConstraintTable.RId);
881                 }
882
883                 public override void TerminateModuleDefinition (ModuleDefinition module)
884                 {
885                         if (module.Assembly.HasCustomAttributes)
886                                 VisitCustomAttributeCollection (module.Assembly.CustomAttributes);
887                         if (module.Assembly.HasSecurityDeclarations)
888                                 VisitSecurityDeclarationCollection (module.Assembly.SecurityDeclarations);
889                         if (module.HasCustomAttributes)
890                                 VisitCustomAttributeCollection (module.CustomAttributes);
891
892                         if (module.ExternTypes.Count > 0)
893                                 VisitExternTypeCollection (module.ExternTypes);
894
895                         CompleteGenericTables ();
896                         SortTables ();
897
898                         MethodTable mTable = m_tableWriter.GetMethodTable ();
899                         for (int i = 0; i < m_methodStack.Count; i++) {
900                                 MethodDefinition meth = (MethodDefinition) m_methodStack [i];
901                                 if (meth.HasBody)
902                                         mTable [i].RVA = m_codeWriter.WriteMethodBody (meth);
903                         }
904
905                         if (m_fieldStack.Count > 0) {
906                                 FieldRVATable frTable = null;
907                                 foreach (FieldDefinition field in m_fieldStack) {
908                                         if (field.InitialValue != null && field.InitialValue.Length > 0) {
909                                                 if (frTable == null)
910                                                         frTable = m_tableWriter.GetFieldRVATable ();
911
912                                                 FieldRVARow frRow = m_rowWriter.CreateFieldRVARow (
913                                                         m_mdWriter.GetDataCursor (),
914                                                         field.MetadataToken.RID);
915
916                                                 m_mdWriter.AddData (field.InitialValue.Length + 3 & (~3));
917                                                 m_mdWriter.AddFieldInitData (field.InitialValue);
918
919                                                 frTable.Rows.Add (frRow);
920                                         }
921                                 }
922                         }
923
924                         if (m_symbolWriter != null)
925                                 m_symbolWriter.Dispose ();
926
927                         if (m_mod.Assembly.EntryPoint != null)
928                                 m_mdWriter.EntryPointToken =
929                                         ((uint) TokenType.Method) | GetRidFor (m_mod.Assembly.EntryPoint);
930
931                         m_mod.Image.MetadataRoot.Accept (m_mdWriter);
932                 }
933
934                 public static ElementType GetCorrespondingType (string fullName)
935                 {
936                         switch (fullName) {
937                         case Constants.Boolean :
938                                 return ElementType.Boolean;
939                         case Constants.Char :
940                                 return ElementType.Char;
941                         case Constants.SByte :
942                                 return ElementType.I1;
943                         case Constants.Int16 :
944                                 return ElementType.I2;
945                         case Constants.Int32 :
946                                 return ElementType.I4;
947                         case Constants.Int64 :
948                                 return ElementType.I8;
949                         case Constants.Byte :
950                                 return ElementType.U1;
951                         case Constants.UInt16 :
952                                 return ElementType.U2;
953                         case Constants.UInt32 :
954                                 return ElementType.U4;
955                         case Constants.UInt64 :
956                                 return ElementType.U8;
957                         case Constants.Single :
958                                 return ElementType.R4;
959                         case Constants.Double :
960                                 return ElementType.R8;
961                         case Constants.String :
962                                 return ElementType.String;
963                         case Constants.Type :
964                                 return ElementType.Type;
965                         case Constants.Object :
966                                 return ElementType.Object;
967                         default:
968                                 return ElementType.Class;
969                         }
970                 }
971
972                 byte [] EncodeConstant (ElementType et, object value)
973                 {
974                         m_constWriter.Empty ();
975
976                         if (value == null)
977                                 et = ElementType.Class;
978
979                         IConvertible ic = value as IConvertible;
980                         IFormatProvider fp = CultureInfo.CurrentCulture.NumberFormat;
981
982                         switch (et) {
983                         case ElementType.Boolean :
984                                 m_constWriter.Write ((byte) (ic.ToBoolean (fp) ? 1 : 0));
985                                 break;
986                         case ElementType.Char :
987                                 m_constWriter.Write ((ushort) ic.ToChar (fp));
988                                 break;
989                         case ElementType.I1 :
990                                 m_constWriter.Write (ic.ToSByte (fp));
991                                 break;
992                         case ElementType.I2 :
993                                 m_constWriter.Write (ic.ToInt16 (fp));
994                                 break;
995                         case ElementType.I4 :
996                                 m_constWriter.Write (ic.ToInt32 (fp));
997                                 break;
998                         case ElementType.I8 :
999                                 m_constWriter.Write (ic.ToInt64 (fp));
1000                                 break;
1001                         case ElementType.U1 :
1002                                 m_constWriter.Write (ic.ToByte (fp));
1003                                 break;
1004                         case ElementType.U2 :
1005                                 m_constWriter.Write (ic.ToUInt16 (fp));
1006                                 break;
1007                         case ElementType.U4 :
1008                                 m_constWriter.Write (ic.ToUInt32 (fp));
1009                                 break;
1010                         case ElementType.U8 :
1011                                 m_constWriter.Write (ic.ToUInt64 (fp));
1012                                 break;
1013                         case ElementType.R4 :
1014                                 m_constWriter.Write (ic.ToSingle (fp));
1015                                 break;
1016                         case ElementType.R8 :
1017                                 m_constWriter.Write (ic.ToDouble (fp));
1018                                 break;
1019                         case ElementType.String :
1020                                 m_constWriter.Write (Encoding.Unicode.GetBytes ((string) value));
1021                                 break;
1022                         case ElementType.Class :
1023                                 m_constWriter.Write (new byte [4]);
1024                                 break;
1025                         default :
1026                                 throw new ArgumentException ("Non valid element for a constant");
1027                         }
1028
1029                         return m_constWriter.ToArray ();
1030                 }
1031
1032                 public SigType GetSigType (TypeReference type)
1033                 {
1034                         string name = type.FullName;
1035
1036                         switch (name) {
1037                         case Constants.Void :
1038                                 return new SigType (ElementType.Void);
1039                         case Constants.Object :
1040                                 return new SigType (ElementType.Object);
1041                         case Constants.Boolean :
1042                                 return new SigType (ElementType.Boolean);
1043                         case Constants.String :
1044                                 return new SigType (ElementType.String);
1045                         case Constants.Char :
1046                                 return new SigType (ElementType.Char);
1047                         case Constants.SByte :
1048                                 return new SigType (ElementType.I1);
1049                         case Constants.Byte :
1050                                 return new SigType (ElementType.U1);
1051                         case Constants.Int16 :
1052                                 return new SigType (ElementType.I2);
1053                         case Constants.UInt16 :
1054                                 return new SigType (ElementType.U2);
1055                         case Constants.Int32 :
1056                                 return new SigType (ElementType.I4);
1057                         case Constants.UInt32 :
1058                                 return new SigType (ElementType.U4);
1059                         case Constants.Int64 :
1060                                 return new SigType (ElementType.I8);
1061                         case Constants.UInt64 :
1062                                 return new SigType (ElementType.U8);
1063                         case Constants.Single :
1064                                 return new SigType (ElementType.R4);
1065                         case Constants.Double :
1066                                 return new SigType (ElementType.R8);
1067                         case Constants.IntPtr :
1068                                 return new SigType (ElementType.I);
1069                         case Constants.UIntPtr :
1070                                 return new SigType (ElementType.U);
1071                         case Constants.TypedReference :
1072                                 return new SigType (ElementType.TypedByRef);
1073                         }
1074
1075                         if (type is GenericParameter) {
1076                                 GenericParameter gp = type as GenericParameter;
1077                                 int pos = gp.Owner.GenericParameters.IndexOf (gp);
1078                                 if (gp.Owner is TypeReference)
1079                                         return new VAR (pos);
1080                                 else if (gp.Owner is MethodReference)
1081                                         return new MVAR (pos);
1082                                 else
1083                                         throw new ReflectionException ("Unkown generic parameter type");
1084                         } else if (type is GenericInstanceType) {
1085                                 GenericInstanceType git = type as GenericInstanceType;
1086                                 GENERICINST gi = new GENERICINST ();
1087                                 gi.ValueType = git.IsValueType;
1088                                 gi.Type = GetTypeDefOrRefToken (git.ElementType);
1089                                 gi.Signature = new GenericInstSignature ();
1090                                 gi.Signature.Arity = git.GenericArguments.Count;
1091                                 gi.Signature.Types = new GenericArg [gi.Signature.Arity];
1092                                 for (int i = 0; i < git.GenericArguments.Count; i++)
1093                                         gi.Signature.Types [i] = GetGenericArgSig (git.GenericArguments [i]);
1094
1095                                 return gi;
1096                         } else if (type is ArrayType) {
1097                                 ArrayType aryType = type as ArrayType;
1098                                 if (aryType.IsSizedArray) {
1099                                         SZARRAY szary = new SZARRAY ();
1100                                         szary.CustomMods = GetCustomMods (aryType.ElementType);
1101                                         szary.Type = GetSigType (aryType.ElementType);
1102                                         return szary;
1103                                 }
1104
1105                                 // not optimized
1106                                 ArrayShape shape = new ArrayShape ();
1107                                 shape.Rank = aryType.Dimensions.Count;
1108                                 shape.NumSizes = 0;
1109
1110                                 for (int i = 0; i < shape.Rank; i++) {
1111                                         ArrayDimension dim = aryType.Dimensions [i];
1112                                         if (dim.UpperBound > 0)
1113                                                 shape.NumSizes++;
1114                                 }
1115
1116                                 shape.Sizes = new int [shape.NumSizes];
1117                                 shape.NumLoBounds = shape.Rank;
1118                                 shape.LoBounds = new int [shape.NumLoBounds];
1119
1120                                 for (int i = 0; i < shape.Rank; i++) {
1121                                         ArrayDimension dim = aryType.Dimensions [i];
1122                                         shape.LoBounds [i] = dim.LowerBound;
1123                                         if (dim.UpperBound > 0)
1124                                                 shape.Sizes [i] = dim.UpperBound - dim.LowerBound + 1;
1125                                 }
1126
1127                                 ARRAY ary = new ARRAY ();
1128                                 ary.Shape = shape;
1129                                 ary.CustomMods = GetCustomMods (aryType.ElementType);
1130                                 ary.Type = GetSigType (aryType.ElementType);
1131                                 return ary;
1132                         } else if (type is PointerType) {
1133                                 PTR p = new PTR ();
1134                                 TypeReference elementType = (type as PointerType).ElementType;
1135                                 p.Void = elementType.FullName == Constants.Void;
1136                                 if (!p.Void) {
1137                                         p.CustomMods = GetCustomMods (elementType);
1138                                         p.PtrType = GetSigType (elementType);
1139                                 }
1140                                 return p;
1141                         } else if (type is FunctionPointerType) {
1142                                 FNPTR fp = new FNPTR ();
1143                                 FunctionPointerType fptr = type as FunctionPointerType;
1144
1145                                 int sentinel = fptr.GetSentinel ();
1146                                 if (sentinel < 0)
1147                                         fp.Method = GetMethodDefSig (fptr);
1148                                 else
1149                                         fp.Method = GetMethodRefSig (fptr);
1150
1151                                 return fp;
1152                         } else if (type is TypeSpecification) {
1153                                 return GetSigType ((type as TypeSpecification).ElementType);
1154                         } else if (type.IsValueType) {
1155                                 VALUETYPE vt = new VALUETYPE ();
1156                                 vt.Type = GetTypeDefOrRefToken (type);
1157                                 return vt;
1158                         } else {
1159                                 CLASS c = new CLASS ();
1160                                 c.Type = GetTypeDefOrRefToken (type);
1161                                 return c;
1162                         }
1163                 }
1164
1165                 public GenericArg GetGenericArgSig (TypeReference type)
1166                 {
1167                         GenericArg arg = new GenericArg (GetSigType (type));
1168                         arg.CustomMods = GetCustomMods (type);
1169                         return arg;
1170                 }
1171
1172                 public CustomMod [] GetCustomMods (TypeReference type)
1173                 {
1174                         ModType modifier = type as ModType;
1175                         if (modifier == null)
1176                                 return CustomMod.EmptyCustomMod;
1177
1178                         ArrayList cmods = new ArrayList ();
1179                         do {
1180                                 CustomMod cmod = new CustomMod ();
1181                                 cmod.TypeDefOrRef = GetTypeDefOrRefToken (modifier.ModifierType);
1182
1183                                 if (modifier is ModifierOptional)
1184                                         cmod.CMOD = CustomMod.CMODType.OPT;
1185                                 else if (modifier is ModifierRequired)
1186                                         cmod.CMOD = CustomMod.CMODType.REQD;
1187
1188                                 cmods.Add (cmod);
1189                                 modifier = modifier.ElementType as ModType;
1190                         } while (modifier != null);
1191
1192                         return cmods.ToArray (typeof (CustomMod)) as CustomMod [];
1193                 }
1194
1195                 public Signature GetMemberRefSig (MemberReference member)
1196                 {
1197                         if (member is FieldReference)
1198                                 return GetFieldSig (member as FieldReference);
1199                         else
1200                                 return GetMemberRefSig (member as MethodReference);
1201                 }
1202
1203                 public FieldSig GetFieldSig (FieldReference field)
1204                 {
1205                         FieldSig sig = new FieldSig ();
1206                         sig.CallingConvention |= 0x6;
1207                         sig.Field = true;
1208                         sig.CustomMods = GetCustomMods (field.FieldType);
1209                         sig.Type = GetSigType (field.FieldType);
1210                         return sig;
1211                 }
1212
1213                 Param [] GetParametersSig (ParameterDefinitionCollection parameters)
1214                 {
1215                         Param [] ret = new Param [parameters.Count];
1216                         for (int i = 0; i < ret.Length; i++) {
1217                                 ParameterDefinition pDef = parameters [i];
1218                                 Param p = new Param ();
1219                                 p.CustomMods = GetCustomMods (pDef.ParameterType);
1220                                 if (pDef.ParameterType.FullName == Constants.TypedReference)
1221                                         p.TypedByRef = true;
1222                                 else if (IsByReferenceType (pDef.ParameterType)) {
1223                                         p.ByRef = true;
1224                                         p.Type = GetSigType (pDef.ParameterType);
1225                                 } else
1226                                         p.Type = GetSigType (pDef.ParameterType);
1227                                 ret [i] = p;
1228                         }
1229                         return ret;
1230                 }
1231
1232                 void CompleteMethodSig (IMethodSignature meth, MethodSig sig)
1233                 {
1234                         sig.HasThis = meth.HasThis;
1235                         sig.ExplicitThis = meth.ExplicitThis;
1236                         if (sig.HasThis)
1237                                 sig.CallingConvention |= 0x20;
1238                         if (sig.ExplicitThis)
1239                                 sig.CallingConvention |= 0x40;
1240
1241                         if ((meth.CallingConvention & MethodCallingConvention.VarArg) != 0)
1242                                 sig.CallingConvention |= 0x5;
1243
1244                         sig.ParamCount = meth.Parameters.Count;
1245                         sig.Parameters = GetParametersSig (meth.Parameters);
1246
1247                         RetType rtSig = new RetType ();
1248                         rtSig.CustomMods = GetCustomMods (meth.ReturnType.ReturnType);
1249
1250                         if (meth.ReturnType.ReturnType.FullName == Constants.Void)
1251                                 rtSig.Void = true;
1252                         else if (meth.ReturnType.ReturnType.FullName == Constants.TypedReference)
1253                                 rtSig.TypedByRef = true;
1254                         else if (IsByReferenceType (meth.ReturnType.ReturnType)) {
1255                                 rtSig.ByRef = true;
1256                                 rtSig.Type = GetSigType (meth.ReturnType.ReturnType);
1257                         } else
1258                                 rtSig.Type = GetSigType (meth.ReturnType.ReturnType);
1259
1260                         sig.RetType = rtSig;
1261                 }
1262
1263                 static bool IsByReferenceType (TypeReference type)
1264                 {
1265                         TypeSpecification ts = type as TypeSpecification;
1266                         while (ts != null) {
1267                                 if (ts is ReferenceType)
1268                                         return true;
1269                                 ts = ts.ElementType as TypeSpecification;
1270                         }
1271                         return false;
1272                 }
1273
1274                 public MethodRefSig GetMethodRefSig (IMethodSignature meth)
1275                 {
1276                         MethodReference methodRef = meth as MethodReference;
1277                         if (methodRef != null && methodRef.GenericParameters.Count > 0)
1278                                 return GetMethodDefSig (meth);
1279
1280                         MethodRefSig methSig = new MethodRefSig ();
1281
1282                         CompleteMethodSig (meth, methSig);
1283
1284                         int sentinel = meth.GetSentinel ();
1285                         if (sentinel >= 0)
1286                                 methSig.Sentinel = sentinel;
1287
1288                         if ((meth.CallingConvention & MethodCallingConvention.C) != 0)
1289                                 methSig.CallingConvention |= 0x1;
1290                         else if ((meth.CallingConvention & MethodCallingConvention.StdCall) != 0)
1291                                 methSig.CallingConvention |= 0x2;
1292                         else if ((meth.CallingConvention & MethodCallingConvention.ThisCall) != 0)
1293                                 methSig.CallingConvention |= 0x3;
1294                         else if ((meth.CallingConvention & MethodCallingConvention.FastCall) != 0)
1295                                 methSig.CallingConvention |= 0x4;
1296
1297                         return methSig;
1298                 }
1299
1300                 public MethodDefSig GetMethodDefSig (IMethodSignature meth)
1301                 {
1302                         MethodDefSig sig = new MethodDefSig ();
1303
1304                         CompleteMethodSig (meth, sig);
1305
1306                         MethodReference methodRef = meth as MethodReference;
1307                         if (methodRef != null && methodRef.GenericParameters.Count > 0) {
1308                                 sig.CallingConvention |= 0x10;
1309                                 sig.GenericParameterCount = methodRef.GenericParameters.Count;
1310                         }
1311
1312                         return sig;
1313                 }
1314
1315                 public PropertySig GetPropertySig (PropertyDefinition prop)
1316                 {
1317                         PropertySig ps = new PropertySig ();
1318                         ps.CallingConvention |= 0x8;
1319
1320                         bool hasThis;
1321                         bool explicitThis;
1322                         MethodCallingConvention mcc;
1323                         ParameterDefinitionCollection parameters = prop.Parameters;
1324
1325                         MethodDefinition meth;
1326                         if (prop.GetMethod != null)
1327                                 meth = prop.GetMethod;
1328                         else if (prop.SetMethod != null)
1329                                 meth = prop.SetMethod;
1330                         else
1331                                 meth = null;
1332
1333                         if (meth != null) {
1334                                 hasThis = meth.HasThis;
1335                                 explicitThis = meth.ExplicitThis;
1336                                 mcc = meth.CallingConvention;
1337                         } else {
1338                                 hasThis = explicitThis = false;
1339                                 mcc = MethodCallingConvention.Default;
1340                         }
1341
1342                         if (hasThis)
1343                                 ps.CallingConvention |= 0x20;
1344                         if (explicitThis)
1345                                 ps.CallingConvention |= 0x40;
1346
1347                         if ((mcc & MethodCallingConvention.VarArg) != 0)
1348                                 ps.CallingConvention |= 0x5;
1349
1350                         int paramCount = parameters != null ? parameters.Count : 0;
1351
1352                         ps.ParamCount = paramCount;
1353                         ps.Parameters = GetParametersSig (parameters);
1354                         ps.CustomMods = GetCustomMods (prop.PropertyType);
1355                         ps.Type = GetSigType (prop.PropertyType);
1356
1357                         return ps;
1358                 }
1359
1360                 public TypeSpec GetTypeSpecSig (TypeReference type)
1361                 {
1362                         TypeSpec ts = new TypeSpec ();
1363                         ts.CustomMods = GetCustomMods (type);
1364                         ts.Type = GetSigType (type);
1365                         return ts;
1366                 }
1367
1368                 public MethodSpec GetMethodSpecSig (GenericInstanceMethod gim)
1369                 {
1370                         GenericInstSignature gis = new GenericInstSignature ();
1371                         gis.Arity = gim.GenericArguments.Count;
1372                         gis.Types = new GenericArg [gis.Arity];
1373                         for (int i = 0; i < gis.Arity; i++)
1374                                 gis.Types [i] = GetGenericArgSig (gim.GenericArguments [i]);
1375
1376                         return new MethodSpec (gis);
1377                 }
1378
1379                 static string GetObjectTypeName (object o)
1380                 {
1381                         Type t = o.GetType ();
1382                         return string.Concat (t.Namespace, ".", t.Name);
1383                 }
1384
1385                 static CustomAttrib.Elem CreateElem (TypeReference type, object value)
1386                 {
1387                         CustomAttrib.Elem elem = new CustomAttrib.Elem ();
1388                         elem.Value = value;
1389                         elem.ElemType = type;
1390                         elem.FieldOrPropType = GetCorrespondingType (type.FullName);
1391
1392                         switch (elem.FieldOrPropType) {
1393                         case ElementType.Boolean :
1394                         case ElementType.Char :
1395                         case ElementType.R4 :
1396                         case ElementType.R8 :
1397                         case ElementType.I1 :
1398                         case ElementType.I2 :
1399                         case ElementType.I4 :
1400                         case ElementType.I8 :
1401                         case ElementType.U1 :
1402                         case ElementType.U2 :
1403                         case ElementType.U4 :
1404                         case ElementType.U8 :
1405                                 elem.Simple = true;
1406                                 break;
1407                         case ElementType.String:
1408                                 elem.String = true;
1409                                 break;
1410                         case ElementType.Type:
1411                                 elem.Type = true;
1412                                 break;
1413                         case ElementType.Object:
1414                                 elem.BoxedValueType = true;
1415                                 if (value == null)
1416                                         elem.FieldOrPropType = ElementType.String;
1417                                 else
1418                                         elem.FieldOrPropType = GetCorrespondingType (
1419                                                 GetObjectTypeName (value));
1420                                 break;
1421                         }
1422
1423                         return elem;
1424                 }
1425
1426                 static CustomAttrib.FixedArg CreateFixedArg (TypeReference type, object value)
1427                 {
1428                         CustomAttrib.FixedArg fa = new CustomAttrib.FixedArg ();
1429                         if (value is object []) {
1430                                 fa.SzArray = true;
1431                                 object [] values = value as object [];
1432                                 TypeReference obj = ((ArrayType) type).ElementType;
1433                                 fa.NumElem = (uint) values.Length;
1434                                 fa.Elems = new CustomAttrib.Elem [values.Length];
1435                                 for (int i = 0; i < values.Length; i++)
1436                                         fa.Elems [i] = CreateElem (obj, values [i]);
1437                         } else {
1438                                 fa.Elems = new CustomAttrib.Elem [1];
1439                                 fa.Elems [0] = CreateElem (type, value);
1440                         }
1441
1442                         return fa;
1443                 }
1444
1445                 static CustomAttrib.NamedArg CreateNamedArg (TypeReference type, string name,
1446                         object value, bool field)
1447                 {
1448                         CustomAttrib.NamedArg na = new CustomAttrib.NamedArg ();
1449                         na.Field = field;
1450                         na.Property = !field;
1451
1452                         na.FieldOrPropName = name;
1453                         na.FieldOrPropType = GetCorrespondingType (type.FullName);
1454                         na.FixedArg = CreateFixedArg (type, value);
1455
1456                         return na;
1457                 }
1458
1459                 public static CustomAttrib GetCustomAttributeSig (CustomAttribute ca)
1460                 {
1461                         CustomAttrib cas = new CustomAttrib (ca.Constructor);
1462                         cas.Prolog = CustomAttrib.StdProlog;
1463
1464                         cas.FixedArgs = new CustomAttrib.FixedArg [ca.Constructor.Parameters.Count];
1465
1466                         for (int i = 0; i < cas.FixedArgs.Length; i++)
1467                                 cas.FixedArgs [i] = CreateFixedArg (
1468                                         ca.Constructor.Parameters [i].ParameterType, ca.ConstructorParameters [i]);
1469
1470                         int nn = ca.Fields.Count + ca.Properties.Count;
1471                         cas.NumNamed = (ushort) nn;
1472                         cas.NamedArgs = new CustomAttrib.NamedArg [nn];
1473
1474                         if (cas.NamedArgs.Length > 0) {
1475                                 int curs = 0;
1476                                 foreach (DictionaryEntry entry in ca.Fields) {
1477                                         string field = (string) entry.Key;
1478                                         cas.NamedArgs [curs++] = CreateNamedArg (
1479                                                 ca.GetFieldType (field), field, entry.Value, true);
1480                                 }
1481
1482                                 foreach (DictionaryEntry entry in ca.Properties) {
1483                                         string property = (string) entry.Key;
1484                                         cas.NamedArgs [curs++] = CreateNamedArg (
1485                                                 ca.GetPropertyType (property), property, entry.Value, false);
1486                                 }
1487                         }
1488
1489                         return cas;
1490                 }
1491
1492                 static MarshalSig GetMarshalSig (MarshalSpec mSpec)
1493                 {
1494                         MarshalSig ms = new MarshalSig (mSpec.NativeIntrinsic);
1495
1496                         if (mSpec is ArrayMarshalSpec) {
1497                                 ArrayMarshalSpec amd = mSpec as ArrayMarshalSpec;
1498                                 MarshalSig.Array ar = new MarshalSig.Array ();
1499                                 ar.ArrayElemType = amd.ElemType;
1500                                 ar.NumElem = amd.NumElem;
1501                                 ar.ParamNum = amd.ParamNum;
1502                                 ar.ElemMult = amd.ElemMult;
1503                                 ms.Spec = ar;
1504                         } else if (mSpec is CustomMarshalerSpec) {
1505                                 CustomMarshalerSpec cmd = mSpec as CustomMarshalerSpec;
1506                                 MarshalSig.CustomMarshaler cm = new MarshalSig.CustomMarshaler ();
1507                                 cm.Guid = cmd.Guid.ToString ();
1508                                 cm.UnmanagedType = cmd.UnmanagedType;
1509                                 cm.ManagedType = cmd.ManagedType;
1510                                 cm.Cookie = cmd.Cookie;
1511                                 ms.Spec = cm;
1512                         } else if (mSpec is FixedArraySpec) {
1513                                 FixedArraySpec fad = mSpec as FixedArraySpec;
1514                                 MarshalSig.FixedArray fa = new MarshalSig.FixedArray ();
1515                                 fa.ArrayElemType  = fad.ElemType;
1516                                 fa.NumElem = fad.NumElem;
1517                                 ms.Spec = fa;
1518                         } else if (mSpec is FixedSysStringSpec) {
1519                                 MarshalSig.FixedSysString fss = new MarshalSig.FixedSysString ();
1520                                 fss.Size = (mSpec as FixedSysStringSpec).Size;
1521                                 ms.Spec = fss;
1522                         } else if (mSpec is SafeArraySpec) {
1523                                 MarshalSig.SafeArray sa = new MarshalSig.SafeArray ();
1524                                 sa.ArrayElemType = (mSpec as SafeArraySpec).ElemType;
1525                                 ms.Spec = sa;
1526                         }
1527
1528                         return ms;
1529                 }
1530
1531                 public void WriteSymbols (ModuleDefinition module)
1532                 {
1533                         if (!m_saveSymbols)
1534                                 return;
1535
1536                         if (m_asmOutput == null)
1537                                 m_asmOutput = module.Assembly.Name.Name + "." + (module.Assembly.Kind == AssemblyKind.Dll ? "dll" : "exe");
1538
1539                         if (m_symbolWriter == null)
1540                                 m_symbolWriter = SymbolStoreHelper.GetWriter (module, m_asmOutput);
1541
1542                         foreach (TypeDefinition type in module.Types) {
1543                                 if (type.HasMethods) {
1544                                         foreach (MethodDefinition method in type.Methods)
1545                                                 WriteSymbols (method);
1546                                 }
1547                                 if (type.HasConstructors) {
1548                                         foreach (MethodDefinition ctor in type.Constructors)
1549                                                 WriteSymbols (ctor);
1550                                 }
1551                         }
1552
1553                         m_symbolWriter.Dispose ();
1554                 }
1555
1556                 void WriteSymbols (MethodDefinition meth)
1557                 {
1558                         if (!meth.HasBody)
1559                                 return;
1560
1561                         m_symbolWriter.Write (meth.Body);
1562                 }
1563         }
1564 }