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