update Mono.Cecil
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / AssemblyWriter.cs
1 //
2 // AssemblyWriter.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2011 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 using System;
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Text;
33
34 using Mono.Collections.Generic;
35 using Mono.Cecil.Cil;
36 using Mono.Cecil.Metadata;
37 using Mono.Cecil.PE;
38
39 using RVA = System.UInt32;
40 using RID = System.UInt32;
41 using CodedRID = System.UInt32;
42 using StringIndex = System.UInt32;
43 using BlobIndex = System.UInt32;
44
45 namespace Mono.Cecil {
46
47 #if !READ_ONLY
48
49         using TypeRefRow     = Row<CodedRID, StringIndex, StringIndex>;
50         using TypeDefRow     = Row<TypeAttributes, StringIndex, StringIndex, CodedRID, RID, RID>;
51         using FieldRow       = Row<FieldAttributes, StringIndex, BlobIndex>;
52         using MethodRow      = Row<RVA, MethodImplAttributes, MethodAttributes, StringIndex, BlobIndex, RID>;
53         using ParamRow       = Row<ParameterAttributes, ushort, StringIndex>;
54         using InterfaceImplRow = Row<uint, CodedRID>;
55         using MemberRefRow   = Row<CodedRID, StringIndex, BlobIndex>;
56         using ConstantRow    = Row<ElementType, CodedRID, BlobIndex>;
57         using CustomAttributeRow = Row<CodedRID, CodedRID, BlobIndex>;
58         using FieldMarshalRow = Row<CodedRID, BlobIndex>;
59         using DeclSecurityRow = Row<SecurityAction, CodedRID, BlobIndex>;
60         using ClassLayoutRow = Row<ushort, uint, RID>;
61         using FieldLayoutRow = Row<uint, RID>;
62         using EventMapRow    = Row<RID, RID>;
63         using EventRow       = Row<EventAttributes, StringIndex, CodedRID>;
64         using PropertyMapRow = Row<RID, RID>;
65         using PropertyRow    = Row<PropertyAttributes, StringIndex, BlobIndex>;
66         using MethodSemanticsRow = Row<MethodSemanticsAttributes, RID, CodedRID>;
67         using MethodImplRow  = Row<RID, CodedRID, CodedRID>;
68         using ImplMapRow     = Row<PInvokeAttributes, CodedRID, StringIndex, RID>;
69         using FieldRVARow    = Row<RVA, RID>;
70         using AssemblyRow    = Row<AssemblyHashAlgorithm, ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint>;
71         using AssemblyRefRow = Row<ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint, uint>;
72         using FileRow        = Row<FileAttributes, StringIndex, BlobIndex>;
73         using ExportedTypeRow = Row<TypeAttributes, uint, StringIndex, StringIndex, CodedRID>;
74         using ManifestResourceRow = Row<uint, ManifestResourceAttributes, StringIndex, CodedRID>;
75         using NestedClassRow = Row<RID, RID>;
76         using GenericParamRow = Row<ushort, GenericParameterAttributes, CodedRID, StringIndex>;
77         using MethodSpecRow = Row<CodedRID, BlobIndex>;
78         using GenericParamConstraintRow = Row<RID, CodedRID>;
79
80         static class ModuleWriter {
81
82                 public static void WriteModuleTo (ModuleDefinition module, Stream stream, WriterParameters parameters)
83                 {
84                         if ((module.Attributes & ModuleAttributes.ILOnly) == 0)
85                                 throw new ArgumentException ();
86
87                         if (module.HasImage && module.ReadingMode == ReadingMode.Deferred)
88                                 ImmediateModuleReader.ReadModule (module);
89
90                         module.MetadataSystem.Clear ();
91
92                         var name = module.assembly != null ? module.assembly.Name : null;
93                         var fq_name = stream.GetFullyQualifiedName ();
94                         var symbol_writer_provider = parameters.SymbolWriterProvider;
95                         if (symbol_writer_provider == null && parameters.WriteSymbols)
96                                 symbol_writer_provider = SymbolProvider.GetPlatformWriterProvider ();
97                         var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider);
98
99 #if !SILVERLIGHT && !CF
100                         if (parameters.StrongNameKeyPair != null && name != null)
101                                 name.PublicKey = parameters.StrongNameKeyPair.PublicKey;
102 #endif
103
104                         if (name != null && name.HasPublicKey)
105                                 module.Attributes |= ModuleAttributes.StrongNameSigned;
106
107                         var metadata = new MetadataBuilder (module, fq_name,
108                                 symbol_writer_provider, symbol_writer);
109
110                         BuildMetadata (module, metadata);
111
112                         if (module.SymbolReader != null)
113                                 module.SymbolReader.Dispose ();
114
115                         var writer = ImageWriter.CreateWriter (module, metadata, stream);
116
117                         writer.WriteImage ();
118
119 #if !SILVERLIGHT && !CF
120                         if (parameters.StrongNameKeyPair != null)
121                                 CryptoService.StrongName (stream, writer, parameters.StrongNameKeyPair);
122 #endif
123                         if (symbol_writer != null)
124                                 symbol_writer.Dispose ();
125                 }
126
127                 static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata)
128                 {
129                         if (!module.HasImage) {
130                                 metadata.BuildMetadata ();
131                                 return;
132                         }
133
134                         module.Read (metadata, (builder, _) => {
135                                 builder.BuildMetadata ();
136                                 return builder;
137                         });
138                 }
139
140                 static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider)
141                 {
142                         if (symbol_writer_provider == null)
143                                 return null;
144
145                         return symbol_writer_provider.GetSymbolWriter (module, fq_name);
146                 }
147         }
148
149         abstract class MetadataTable {
150
151                 public abstract int Length { get; }
152
153                 public bool IsLarge {
154                         get { return Length > 65535; }
155                 }
156
157                 public abstract void Write (TableHeapBuffer buffer);
158                 public abstract void Sort ();
159         }
160
161         abstract class OneRowTable<TRow> : MetadataTable where TRow : struct {
162
163                 internal TRow row;
164
165                 public sealed override int Length {
166                         get { return 1; }
167                 }
168
169                 public sealed override void Sort ()
170                 {
171                 }
172         }
173
174         abstract class MetadataTable<TRow> : MetadataTable where TRow : struct {
175
176                 internal TRow [] rows = new TRow [2];
177                 internal int length;
178
179                 public sealed override int Length {
180                         get { return length; }
181                 }
182
183                 public int AddRow (TRow row)
184                 {
185                         if (rows.Length == length)
186                                 Grow ();
187
188                         rows [length++] = row;
189                         return length;
190                 }
191
192                 void Grow ()
193                 {
194                         var rows = new TRow [this.rows.Length * 2];
195                         Array.Copy (this.rows, rows, this.rows.Length);
196                         this.rows = rows;
197                 }
198
199                 public override void Sort ()
200                 {
201                 }
202         }
203
204         abstract class SortedTable<TRow> : MetadataTable<TRow>, IComparer<TRow> where TRow : struct {
205
206                 public sealed override void Sort ()
207                 {
208                         Array.Sort (rows, 0, length, this);
209                 }
210
211                 protected int Compare (uint x, uint y)
212                 {
213                         return x == y ? 0 : x > y ? 1 : -1;
214                 }
215
216                 public abstract int Compare (TRow x, TRow y);
217         }
218
219         sealed class ModuleTable : OneRowTable<uint> {
220
221                 public override void Write (TableHeapBuffer buffer)
222                 {
223                         buffer.WriteUInt16 (0);         // Generation
224                         buffer.WriteString (row);       // Name
225                         buffer.WriteUInt16 (1);         // Mvid
226                         buffer.WriteUInt16 (0);         // EncId
227                         buffer.WriteUInt16 (0);         // EncBaseId
228                 }
229         }
230
231         sealed class TypeRefTable : MetadataTable<TypeRefRow> {
232
233                 public override void Write (TableHeapBuffer buffer)
234                 {
235                         for (int i = 0; i < length; i++) {
236                                 buffer.WriteCodedRID (
237                                         rows [i].Col1, CodedIndex.ResolutionScope);     // Scope
238                                 buffer.WriteString (rows [i].Col2);                     // Name
239                                 buffer.WriteString (rows [i].Col3);                     // Namespace
240                         }
241                 }
242         }
243
244         sealed class TypeDefTable : MetadataTable<TypeDefRow> {
245
246                 public override void Write (TableHeapBuffer buffer)
247                 {
248                         for (int i = 0; i < length; i++) {
249                                 buffer.WriteUInt32 ((uint) rows [i].Col1);      // Attributes
250                                 buffer.WriteString (rows [i].Col2);                     // Name
251                                 buffer.WriteString (rows [i].Col3);                     // Namespace
252                                 buffer.WriteCodedRID (
253                                         rows [i].Col4, CodedIndex.TypeDefOrRef);        // Extends
254                                 buffer.WriteRID (rows [i].Col5, Table.Field);   // FieldList
255                                 buffer.WriteRID (rows [i].Col6, Table.Method);  // MethodList
256                         }
257                 }
258         }
259
260         sealed class FieldTable : MetadataTable<FieldRow> {
261
262                 public override void Write (TableHeapBuffer buffer)
263                 {
264                         for (int i = 0; i < length; i++) {
265                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Attributes
266                                 buffer.WriteString (rows [i].Col2);                     // Name
267                                 buffer.WriteBlob (rows [i].Col3);                       // Signature
268                         }
269                 }
270         }
271
272         sealed class MethodTable : MetadataTable<MethodRow> {
273
274                 public override void Write (TableHeapBuffer buffer)
275                 {
276                         for (int i = 0; i < length; i++) {
277                                 buffer.WriteUInt32 (rows [i].Col1);             // RVA
278                                 buffer.WriteUInt16 ((ushort) rows [i].Col2);    // ImplFlags
279                                 buffer.WriteUInt16 ((ushort) rows [i].Col3);    // Flags
280                                 buffer.WriteString (rows [i].Col4);             // Name
281                                 buffer.WriteBlob (rows [i].Col5);               // Signature
282                                 buffer.WriteRID (rows [i].Col6, Table.Param);   // ParamList
283                         }
284                 }
285         }
286
287         sealed class ParamTable : MetadataTable<ParamRow> {
288
289                 public override void Write (TableHeapBuffer buffer)
290                 {
291                         for (int i = 0; i < length; i++) {
292                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Attributes
293                                 buffer.WriteUInt16 (rows [i].Col2);             // Sequence
294                                 buffer.WriteString (rows [i].Col3);             // Name
295                         }
296                 }
297         }
298
299         sealed class InterfaceImplTable : MetadataTable<InterfaceImplRow> {
300
301                 public override void Write (TableHeapBuffer buffer)
302                 {
303                         for (int i = 0; i < length; i++) {
304                                 buffer.WriteRID (rows [i].Col1, Table.TypeDef);         // Class
305                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef);  // Interface
306                         }
307                 }
308
309                 /*public override int Compare (InterfaceImplRow x, InterfaceImplRow y)
310                 {
311                         return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1);
312                 }*/
313         }
314
315         sealed class MemberRefTable : MetadataTable<MemberRefRow> {
316
317                 public override void Write (TableHeapBuffer buffer)
318                 {
319                         for (int i = 0; i < length; i++) {
320                                 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent);
321                                 buffer.WriteString (rows [i].Col2);
322                                 buffer.WriteBlob (rows [i].Col3);
323                         }
324                 }
325         }
326
327         sealed class ConstantTable : SortedTable<ConstantRow> {
328
329                 public override void Write (TableHeapBuffer buffer)
330                 {
331                         for (int i = 0; i < length; i++) {
332                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);
333                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant);
334                                 buffer.WriteBlob (rows [i].Col3);
335                         }
336                 }
337
338                 public override int Compare (ConstantRow x, ConstantRow y)
339                 {
340                         return Compare (x.Col2, y.Col2);
341                 }
342         }
343
344         sealed class CustomAttributeTable : SortedTable<CustomAttributeRow> {
345
346                 public override void Write (TableHeapBuffer buffer)
347                 {
348                         for (int i = 0; i < length; i++) {
349                                 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute);    // Parent
350                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType);   // Type
351                                 buffer.WriteBlob (rows [i].Col3);
352                         }
353                 }
354
355                 public override int Compare (CustomAttributeRow x, CustomAttributeRow y)
356                 {
357                         return Compare (x.Col1, y.Col1);
358                 }
359         }
360
361         sealed class FieldMarshalTable : SortedTable<FieldMarshalRow> {
362
363                 public override void Write (TableHeapBuffer buffer)
364                 {
365                         for (int i = 0; i < length; i++) {
366                                 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal);
367                                 buffer.WriteBlob (rows [i].Col2);
368                         }
369                 }
370
371                 public override int Compare (FieldMarshalRow x, FieldMarshalRow y)
372                 {
373                         return Compare (x.Col1, y.Col1);
374                 }
375         }
376
377         sealed class DeclSecurityTable : SortedTable<DeclSecurityRow> {
378
379                 public override void Write (TableHeapBuffer buffer)
380                 {
381                         for (int i = 0; i < length; i++) {
382                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);
383                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity);
384                                 buffer.WriteBlob (rows [i].Col3);
385                         }
386                 }
387
388                 public override int Compare (DeclSecurityRow x, DeclSecurityRow y)
389                 {
390                         return Compare (x.Col2, y.Col2);
391                 }
392         }
393
394         sealed class ClassLayoutTable : SortedTable<ClassLayoutRow> {
395
396                 public override void Write (TableHeapBuffer buffer)
397                 {
398                         for (int i = 0; i < length; i++) {
399                                 buffer.WriteUInt16 (rows [i].Col1);             // PackingSize
400                                 buffer.WriteUInt32 (rows [i].Col2);             // ClassSize
401                                 buffer.WriteRID (rows [i].Col3, Table.TypeDef); // Parent
402                         }
403                 }
404
405                 public override int Compare (ClassLayoutRow x, ClassLayoutRow y)
406                 {
407                         return Compare (x.Col3, y.Col3);
408                 }
409         }
410
411         sealed class FieldLayoutTable : SortedTable<FieldLayoutRow> {
412
413                 public override void Write (TableHeapBuffer buffer)
414                 {
415                         for (int i = 0; i < length; i++) {
416                                 buffer.WriteUInt32 (rows [i].Col1);             // Offset
417                                 buffer.WriteRID (rows [i].Col2, Table.Field);   // Parent
418                         }
419                 }
420
421                 public override int Compare (FieldLayoutRow x, FieldLayoutRow y)
422                 {
423                         return Compare (x.Col2, y.Col2);
424                 }
425         }
426
427         sealed class StandAloneSigTable : MetadataTable<uint> {
428
429                 public override void Write (TableHeapBuffer buffer)
430                 {
431                         for (int i = 0; i < length; i++)
432                                 buffer.WriteBlob (rows [i]);
433                 }
434         }
435
436         sealed class EventMapTable : MetadataTable<EventMapRow> {
437
438                 public override void Write (TableHeapBuffer buffer)
439                 {
440                         for (int i = 0; i < length; i++) {
441                                 buffer.WriteRID (rows [i].Col1, Table.TypeDef);         // Parent
442                                 buffer.WriteRID (rows [i].Col2, Table.Event);           // EventList
443                         }
444                 }
445         }
446
447         sealed class EventTable : MetadataTable<EventRow> {
448
449                 public override void Write (TableHeapBuffer buffer)
450                 {
451                         for (int i = 0; i < length; i++) {
452                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Flags
453                                 buffer.WriteString (rows [i].Col2);             // Name
454                                 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef);  // EventType
455                         }
456                 }
457         }
458
459         sealed class PropertyMapTable : MetadataTable<PropertyMapRow> {
460
461                 public override void Write (TableHeapBuffer buffer)
462                 {
463                         for (int i = 0; i < length; i++) {
464                                 buffer.WriteRID (rows [i].Col1, Table.TypeDef);         // Parent
465                                 buffer.WriteRID (rows [i].Col2, Table.Property);        // PropertyList
466                         }
467                 }
468         }
469
470         sealed class PropertyTable : MetadataTable<PropertyRow> {
471
472                 public override void Write (TableHeapBuffer buffer)
473                 {
474                         for (int i = 0; i < length; i++) {
475                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Flags
476                                 buffer.WriteString (rows [i].Col2);             // Name
477                                 buffer.WriteBlob (rows [i].Col3);               // Type
478                         }
479                 }
480         }
481
482         sealed class MethodSemanticsTable : SortedTable<MethodSemanticsRow> {
483
484                 public override void Write (TableHeapBuffer buffer)
485                 {
486                         for (int i = 0; i < length; i++) {
487                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Flags
488                                 buffer.WriteRID (rows [i].Col2, Table.Method);  // Method
489                                 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics);  // Association
490                         }
491                 }
492
493                 public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y)
494                 {
495                         return Compare (x.Col3, y.Col3);
496                 }
497         }
498
499         sealed class MethodImplTable : MetadataTable<MethodImplRow> {
500
501                 public override void Write (TableHeapBuffer buffer)
502                 {
503                         for (int i = 0; i < length; i++) {
504                                 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class
505                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef);        // MethodBody
506                                 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef);        // MethodDeclaration
507                         }
508                 }
509         }
510
511         sealed class ModuleRefTable : MetadataTable<uint> {
512
513                 public override void Write (TableHeapBuffer buffer)
514                 {
515                         for (int i = 0; i < length; i++)
516                                 buffer.WriteString (rows [i]);  // Name
517                 }
518         }
519
520         sealed class TypeSpecTable : MetadataTable<uint> {
521
522                 public override void Write (TableHeapBuffer buffer)
523                 {
524                         for (int i = 0; i < length; i++)
525                                 buffer.WriteBlob (rows [i]);    // Signature
526                 }
527         }
528
529         sealed class ImplMapTable : SortedTable<ImplMapRow> {
530
531                 public override void Write (TableHeapBuffer buffer)
532                 {
533                         for (int i = 0; i < length; i++) {
534                                 buffer.WriteUInt16 ((ushort) rows [i].Col1);    // Flags
535                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded);       // MemberForwarded
536                                 buffer.WriteString (rows [i].Col3);             // ImportName
537                                 buffer.WriteRID (rows [i].Col4, Table.ModuleRef);       // ImportScope
538                         }
539                 }
540
541                 public override int Compare (ImplMapRow x, ImplMapRow y)
542                 {
543                         return Compare (x.Col2, y.Col2);
544                 }
545         }
546
547         sealed class FieldRVATable : SortedTable<FieldRVARow> {
548
549                 internal int position;
550
551                 public override void Write (TableHeapBuffer buffer)
552                 {
553                         position = buffer.position;
554                         for (int i = 0; i < length; i++) {
555                                 buffer.WriteUInt32 (rows [i].Col1);             // RVA
556                                 buffer.WriteRID (rows [i].Col2, Table.Field);   // Field
557                         }
558                 }
559
560                 public override int Compare (FieldRVARow x, FieldRVARow y)
561                 {
562                         return Compare (x.Col2, y.Col2);
563                 }
564         }
565
566         sealed class AssemblyTable : OneRowTable<AssemblyRow> {
567
568                 public override void Write (TableHeapBuffer buffer)
569                 {
570                         buffer.WriteUInt32 ((uint) row.Col1);   // AssemblyHashAlgorithm
571                         buffer.WriteUInt16 (row.Col2);                  // MajorVersion
572                         buffer.WriteUInt16 (row.Col3);                  // MinorVersion
573                         buffer.WriteUInt16 (row.Col4);                  // Build
574                         buffer.WriteUInt16 (row.Col5);                  // Revision
575                         buffer.WriteUInt32 ((uint) row.Col6);   // Flags
576                         buffer.WriteBlob (row.Col7);                    // PublicKey
577                         buffer.WriteString (row.Col8);                  // Name
578                         buffer.WriteString (row.Col9);                  // Culture
579                 }
580         }
581
582         sealed class AssemblyRefTable : MetadataTable<AssemblyRefRow> {
583
584                 public override void Write (TableHeapBuffer buffer)
585                 {
586                         for (int i = 0; i < length; i++) {
587                                 buffer.WriteUInt16 (rows [i].Col1);             // MajorVersion
588                                 buffer.WriteUInt16 (rows [i].Col2);             // MinorVersion
589                                 buffer.WriteUInt16 (rows [i].Col3);             // Build
590                                 buffer.WriteUInt16 (rows [i].Col4);             // Revision
591                                 buffer.WriteUInt32 ((uint) rows [i].Col5);      // Flags
592                                 buffer.WriteBlob (rows [i].Col6);               // PublicKeyOrToken
593                                 buffer.WriteString (rows [i].Col7);             // Name
594                                 buffer.WriteString (rows [i].Col8);             // Culture
595                                 buffer.WriteBlob (rows [i].Col9);               // Hash
596                         }
597                 }
598         }
599
600         sealed class FileTable : MetadataTable<FileRow> {
601
602                 public override void Write (TableHeapBuffer buffer)
603                 {
604                         for (int i = 0; i < length; i++) {
605                                 buffer.WriteUInt32 ((uint) rows [i].Col1);
606                                 buffer.WriteString (rows [i].Col2);
607                                 buffer.WriteBlob (rows [i].Col3);
608                         }
609                 }
610         }
611
612         sealed class ExportedTypeTable : MetadataTable<ExportedTypeRow> {
613
614                 public override void Write (TableHeapBuffer buffer)
615                 {
616                         for (int i = 0; i < length; i++) {
617                                 buffer.WriteUInt32 ((uint) rows [i].Col1);
618                                 buffer.WriteUInt32 (rows [i].Col2);
619                                 buffer.WriteString (rows [i].Col3);
620                                 buffer.WriteString (rows [i].Col4);
621                                 buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation);
622                         }
623                 }
624         }
625
626         sealed class ManifestResourceTable : MetadataTable<ManifestResourceRow> {
627
628                 public override void Write (TableHeapBuffer buffer)
629                 {
630                         for (int i = 0; i < length; i++) {
631                                 buffer.WriteUInt32 (rows [i].Col1);
632                                 buffer.WriteUInt32 ((uint) rows [i].Col2);
633                                 buffer.WriteString (rows [i].Col3);
634                                 buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation);
635                         }
636                 }
637         }
638
639         sealed class NestedClassTable : SortedTable<NestedClassRow> {
640
641                 public override void Write (TableHeapBuffer buffer)
642                 {
643                         for (int i = 0; i < length; i++) {
644                                 buffer.WriteRID (rows [i].Col1, Table.TypeDef);         // NestedClass
645                                 buffer.WriteRID (rows [i].Col2, Table.TypeDef);         // EnclosingClass
646                         }
647                 }
648
649                 public override int Compare (NestedClassRow x, NestedClassRow y)
650                 {
651                         return Compare (x.Col1, y.Col1);
652                 }
653         }
654
655         sealed class GenericParamTable : MetadataTable<GenericParamRow> {
656
657                 public override void Write (TableHeapBuffer buffer)
658                 {
659                         for (int i = 0; i < length; i++) {
660                                 buffer.WriteUInt16 (rows [i].Col1);             // Number
661                                 buffer.WriteUInt16 ((ushort) rows [i].Col2);    // Flags
662                                 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef);       // Owner
663                                 buffer.WriteString (rows [i].Col4);             // Name
664                         }
665                 }
666         }
667
668         sealed class MethodSpecTable : MetadataTable<MethodSpecRow> {
669
670                 public override void Write (TableHeapBuffer buffer)
671                 {
672                         for (int i = 0; i < length; i++) {
673                                 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef);        // Method
674                                 buffer.WriteBlob (rows [i].Col2);       // Instantiation
675                         }
676                 }
677         }
678
679         sealed class GenericParamConstraintTable : MetadataTable<GenericParamConstraintRow> {
680
681                 public override void Write (TableHeapBuffer buffer)
682                 {
683                         for (int i = 0; i < length; i++) {
684                                 buffer.WriteRID (rows [i].Col1, Table.GenericParam);    // Owner
685                                 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef);  // Constraint
686                         }
687                 }
688         }
689
690         sealed class MetadataBuilder {
691
692                 readonly internal ModuleDefinition module;
693                 readonly internal ISymbolWriterProvider symbol_writer_provider;
694                 readonly internal ISymbolWriter symbol_writer;
695                 readonly internal TextMap text_map;
696                 readonly internal string fq_name;
697
698                 readonly Dictionary<TypeRefRow, MetadataToken> type_ref_map;
699                 readonly Dictionary<uint, MetadataToken> type_spec_map;
700                 readonly Dictionary<MemberRefRow, MetadataToken> member_ref_map;
701                 readonly Dictionary<MethodSpecRow, MetadataToken> method_spec_map;
702                 readonly Collection<GenericParameter> generic_parameters;
703                 readonly Dictionary<MetadataToken, MetadataToken> method_def_map;
704
705                 readonly internal CodeWriter code;
706                 readonly internal DataBuffer data;
707                 readonly internal ResourceBuffer resources;
708                 readonly internal StringHeapBuffer string_heap;
709                 readonly internal UserStringHeapBuffer user_string_heap;
710                 readonly internal BlobHeapBuffer blob_heap;
711                 readonly internal TableHeapBuffer table_heap;
712
713                 internal MetadataToken entry_point;
714
715                 RID type_rid = 1;
716                 RID field_rid = 1;
717                 RID method_rid = 1;
718                 RID param_rid = 1;
719                 RID property_rid = 1;
720                 RID event_rid = 1;
721
722                 readonly TypeRefTable type_ref_table;
723                 readonly TypeDefTable type_def_table;
724                 readonly FieldTable field_table;
725                 readonly MethodTable method_table;
726                 readonly ParamTable param_table;
727                 readonly InterfaceImplTable iface_impl_table;
728                 readonly MemberRefTable member_ref_table;
729                 readonly ConstantTable constant_table;
730                 readonly CustomAttributeTable custom_attribute_table;
731                 readonly DeclSecurityTable declsec_table;
732                 readonly StandAloneSigTable standalone_sig_table;
733                 readonly EventMapTable event_map_table;
734                 readonly EventTable event_table;
735                 readonly PropertyMapTable property_map_table;
736                 readonly PropertyTable property_table;
737                 readonly TypeSpecTable typespec_table;
738                 readonly MethodSpecTable method_spec_table;
739
740                 readonly internal bool write_symbols;
741
742                 public MetadataBuilder (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, ISymbolWriter symbol_writer)
743                 {
744                         this.module = module;
745                         this.text_map = CreateTextMap ();
746                         this.fq_name = fq_name;
747                         this.symbol_writer_provider = symbol_writer_provider;
748                         this.symbol_writer = symbol_writer;
749                         this.write_symbols = symbol_writer != null;
750                         this.code = new CodeWriter (this);
751                         this.data = new DataBuffer ();
752                         this.resources = new ResourceBuffer ();
753                         this.string_heap = new StringHeapBuffer ();
754                         this.user_string_heap = new UserStringHeapBuffer ();
755                         this.blob_heap = new BlobHeapBuffer ();
756                         this.table_heap = new TableHeapBuffer (module, this);
757
758                         this.type_ref_table = GetTable<TypeRefTable> (Table.TypeRef);
759                         this.type_def_table = GetTable<TypeDefTable> (Table.TypeDef);
760                         this.field_table = GetTable<FieldTable> (Table.Field);
761                         this.method_table = GetTable<MethodTable> (Table.Method);
762                         this.param_table = GetTable<ParamTable> (Table.Param);
763                         this.iface_impl_table = GetTable<InterfaceImplTable> (Table.InterfaceImpl);
764                         this.member_ref_table = GetTable<MemberRefTable> (Table.MemberRef);
765                         this.constant_table = GetTable<ConstantTable> (Table.Constant);
766                         this.custom_attribute_table = GetTable<CustomAttributeTable> (Table.CustomAttribute);
767                         this.declsec_table = GetTable<DeclSecurityTable> (Table.DeclSecurity);
768                         this.standalone_sig_table = GetTable<StandAloneSigTable> (Table.StandAloneSig);
769                         this.event_map_table = GetTable<EventMapTable> (Table.EventMap);
770                         this.event_table = GetTable<EventTable> (Table.Event);
771                         this.property_map_table = GetTable<PropertyMapTable> (Table.PropertyMap);
772                         this.property_table = GetTable<PropertyTable> (Table.Property);
773                         this.typespec_table = GetTable<TypeSpecTable> (Table.TypeSpec);
774                         this.method_spec_table = GetTable<MethodSpecTable> (Table.MethodSpec);
775
776                         var row_equality_comparer = new RowEqualityComparer ();
777                         type_ref_map = new Dictionary<TypeRefRow, MetadataToken> (row_equality_comparer);
778                         type_spec_map = new Dictionary<uint, MetadataToken> ();
779                         member_ref_map = new Dictionary<MemberRefRow, MetadataToken> (row_equality_comparer);
780                         method_spec_map = new Dictionary<MethodSpecRow, MetadataToken> (row_equality_comparer);
781                         generic_parameters = new Collection<GenericParameter> ();
782                         if (write_symbols)
783                                 method_def_map = new Dictionary<MetadataToken, MetadataToken> ();
784                 }
785
786                 TextMap CreateTextMap ()
787                 {
788                         var map = new TextMap ();
789                         map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 16);
790                         map.AddMap (TextSegment.CLIHeader, 0x48, 8);
791                         return map;
792                 }
793
794                 TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
795                 {
796                         return table_heap.GetTable<TTable> (table);
797                 }
798
799                 uint GetStringIndex (string @string)
800                 {
801                         if (string.IsNullOrEmpty (@string))
802                                 return 0;
803
804                         return string_heap.GetStringIndex (@string);
805                 }
806
807                 uint GetBlobIndex (ByteBuffer blob)
808                 {
809                         if (blob.length == 0)
810                                 return 0;
811
812                         return blob_heap.GetBlobIndex (blob);
813                 }
814
815                 uint GetBlobIndex (byte [] blob)
816                 {
817                         if (blob.IsNullOrEmpty ())
818                                 return 0;
819
820                         return GetBlobIndex (new ByteBuffer (blob));
821                 }
822
823                 public void BuildMetadata ()
824                 {
825                         BuildModule ();
826
827                         table_heap.WriteTableHeap ();
828                 }
829
830                 void BuildModule ()
831                 {
832                         var table = GetTable<ModuleTable> (Table.Module);
833                         table.row = GetStringIndex (module.Name);
834
835                         var assembly = module.Assembly;
836
837                         if (assembly != null)
838                                 BuildAssembly ();
839
840                         if (module.HasAssemblyReferences)
841                                 AddAssemblyReferences ();
842
843                         if (module.HasModuleReferences)
844                                 AddModuleReferences ();
845
846                         if (module.HasResources)
847                                 AddResources ();
848
849                         if (module.HasExportedTypes)
850                                 AddExportedTypes ();
851
852                         BuildTypes ();
853
854                         if (assembly != null) {
855                                 if (assembly.HasCustomAttributes)
856                                         AddCustomAttributes (assembly);
857
858                                 if (assembly.HasSecurityDeclarations)
859                                         AddSecurityDeclarations (assembly);
860                         }
861
862                         if (module.HasCustomAttributes)
863                                 AddCustomAttributes (module);
864
865                         if (module.EntryPoint != null)
866                                 entry_point = LookupToken (module.EntryPoint);
867                 }
868
869                 void BuildAssembly ()
870                 {
871                         var assembly = module.Assembly;
872                         var name = assembly.Name;
873
874                         var table = GetTable<AssemblyTable> (Table.Assembly);
875
876                         table.row = new AssemblyRow (
877                                 name.HashAlgorithm,
878                                 (ushort) name.Version.Major,
879                                 (ushort) name.Version.Minor,
880                                 (ushort) name.Version.Build,
881                                 (ushort) name.Version.Revision,
882                                 name.Attributes,
883                                 GetBlobIndex (name.PublicKey),
884                                 GetStringIndex (name.Name),
885                                 GetStringIndex (name.Culture));
886
887                         if (assembly.Modules.Count > 1)
888                                 BuildModules ();
889                 }
890
891                 void BuildModules ()
892                 {
893                         var modules = this.module.Assembly.Modules;
894                         var table = GetTable<FileTable> (Table.File);
895
896                         for (int i = 0; i < modules.Count; i++) {
897                                 var module = modules [i];
898                                 if (module.IsMain)
899                                         continue;
900
901                                 var parameters = new WriterParameters {
902                                         SymbolWriterProvider = symbol_writer_provider,
903                                 };
904
905                                 var file_name = GetModuleFileName (module.Name);
906                                 module.Write (file_name, parameters);
907
908                                 var hash = CryptoService.ComputeHash (file_name);
909
910                                 table.AddRow (new FileRow (
911                                         FileAttributes.ContainsMetaData,
912                                         GetStringIndex (module.Name),
913                                         GetBlobIndex (hash)));
914                         }
915                 }
916
917                 string GetModuleFileName (string name)
918                 {
919                         if (string.IsNullOrEmpty (name))
920                                 throw new NotSupportedException ();
921
922                         var path = Path.GetDirectoryName (fq_name);
923                         return Path.Combine (path, name);
924                 }
925
926                 void AddAssemblyReferences ()
927                 {
928                         var references = module.AssemblyReferences;
929                         var table = GetTable<AssemblyRefTable> (Table.AssemblyRef);
930
931                         for (int i = 0; i < references.Count; i++) {
932                                 var reference = references [i];
933
934                                 var key_or_token = reference.PublicKey.IsNullOrEmpty ()
935                                         ? reference.PublicKeyToken
936                                         : reference.PublicKey;
937
938                                 var rid = table.AddRow (new AssemblyRefRow (
939                                         (ushort) reference.Version.Major,
940                                         (ushort) reference.Version.Minor,
941                                         (ushort) reference.Version.Build,
942                                         (ushort) reference.Version.Revision,
943                                         reference.Attributes,
944                                         GetBlobIndex (key_or_token),
945                                         GetStringIndex (reference.Name),
946                                         GetStringIndex (reference.Culture),
947                                         GetBlobIndex (reference.Hash)));
948
949                                 reference.token = new MetadataToken (TokenType.AssemblyRef, rid);
950                         }
951                 }
952
953                 void AddModuleReferences ()
954                 {
955                         var references = module.ModuleReferences;
956                         var table = GetTable<ModuleRefTable> (Table.ModuleRef);
957
958                         for (int i = 0; i < references.Count; i++) {
959                                 var reference = references [i];
960
961                                 reference.token = new MetadataToken (
962                                         TokenType.ModuleRef,
963                                         table.AddRow (GetStringIndex (reference.Name)));
964                         }
965                 }
966
967                 void AddResources ()
968                 {
969                         var resources = module.Resources;
970                         var table = GetTable<ManifestResourceTable> (Table.ManifestResource);
971
972                         for (int i = 0; i < resources.Count; i++) {
973                                 var resource = resources [i];
974
975                                 var row = new ManifestResourceRow (
976                                         0,
977                                         resource.Attributes,
978                                         GetStringIndex (resource.Name),
979                                         0);
980
981                                 switch (resource.ResourceType) {
982                                 case ResourceType.Embedded:
983                                         row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource);
984                                         break;
985                                 case ResourceType.Linked:
986                                         row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
987                                                 new MetadataToken (
988                                                         TokenType.File,
989                                                         AddLinkedResource ((LinkedResource) resource)));
990                                         break;
991                                 case ResourceType.AssemblyLinked:
992                                         row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
993                                                 ((AssemblyLinkedResource) resource).Assembly.MetadataToken);
994                                         break;
995                                 default:
996                                         throw new NotSupportedException ();
997                                 }
998
999                                 table.AddRow (row);
1000                         }
1001                 }
1002
1003                 uint AddLinkedResource (LinkedResource resource)
1004                 {
1005                         var table = GetTable<FileTable> (Table.File);
1006
1007                         var hash = resource.Hash.IsNullOrEmpty ()
1008                                 ? CryptoService.ComputeHash (resource.File)
1009                                 : resource.Hash;
1010
1011                         return (uint) table.AddRow (new FileRow (
1012                                 FileAttributes.ContainsNoMetaData,
1013                                 GetStringIndex (resource.File),
1014                                 GetBlobIndex (hash)));
1015                 }
1016
1017                 uint AddEmbeddedResource (EmbeddedResource resource)
1018                 {
1019                         return resources.AddResource (resource.GetResourceData ());
1020                 }
1021
1022                 void AddExportedTypes ()
1023                 {
1024                         var exported_types = module.ExportedTypes;
1025                         var table = GetTable<ExportedTypeTable> (Table.ExportedType);
1026
1027                         for (int i = 0; i < exported_types.Count; i++) {
1028                                 var exported_type = exported_types [i];
1029
1030                                 var rid = table.AddRow (new ExportedTypeRow (
1031                                         exported_type.Attributes,
1032                                         (uint) exported_type.Identifier,
1033                                         GetStringIndex (exported_type.Name),
1034                                         GetStringIndex (exported_type.Namespace),
1035                                         MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation)));
1036
1037                                 exported_type.token = new MetadataToken (TokenType.ExportedType, rid);
1038                         }
1039                 }
1040
1041                 MetadataToken GetExportedTypeScope (ExportedType exported_type)
1042                 {
1043                         if (exported_type.DeclaringType != null)
1044                                 return exported_type.DeclaringType.MetadataToken;
1045
1046                         var scope = exported_type.Scope;
1047                         switch (scope.MetadataToken.TokenType) {
1048                         case TokenType.AssemblyRef:
1049                                 return scope.MetadataToken;
1050                         case TokenType.ModuleRef:
1051                                 var file_table = GetTable<FileTable> (Table.File);
1052                                 for (int i = 0; i < file_table.length; i++)
1053                                         if (file_table.rows [i].Col2 == GetStringIndex (scope.Name))
1054                                                 return new MetadataToken (TokenType.File, i + 1);
1055
1056                                 break;
1057                         }
1058
1059                         throw new NotSupportedException ();
1060                 }
1061
1062                 void BuildTypes ()
1063                 {
1064                         if (!module.HasTypes)
1065                                 return;
1066
1067                         AttachTokens ();
1068                         AddTypeDefs ();
1069                         AddGenericParameters ();
1070                 }
1071
1072                 void AttachTokens ()
1073                 {
1074                         var types = module.Types;
1075
1076                         for (int i = 0; i < types.Count; i++)
1077                                 AttachTypeDefToken (types [i]);
1078                 }
1079
1080                 void AttachTypeDefToken (TypeDefinition type)
1081                 {
1082                         type.token = new MetadataToken (TokenType.TypeDef, type_rid++);
1083                         type.fields_range.Start = field_rid;
1084                         type.methods_range.Start = method_rid;
1085
1086                         if (type.HasFields)
1087                                 AttachFieldsDefToken (type);
1088
1089                         if (type.HasMethods)
1090                                 AttachMethodsDefToken (type);
1091
1092                         if (type.HasNestedTypes)
1093                                 AttachNestedTypesDefToken (type);
1094                 }
1095
1096                 void AttachNestedTypesDefToken (TypeDefinition type)
1097                 {
1098                         var nested_types = type.NestedTypes;
1099                         for (int i = 0; i < nested_types.Count; i++)
1100                                 AttachTypeDefToken (nested_types [i]);
1101                 }
1102
1103                 void AttachFieldsDefToken (TypeDefinition type)
1104                 {
1105                         var fields = type.Fields;
1106                         type.fields_range.Length = (uint) fields.Count;
1107                         for (int i = 0; i < fields.Count; i++)
1108                                 fields [i].token = new MetadataToken (TokenType.Field, field_rid++);
1109                 }
1110
1111                 void AttachMethodsDefToken (TypeDefinition type)
1112                 {
1113                         var methods = type.Methods;
1114                         type.methods_range.Length = (uint) methods.Count;
1115                         for (int i = 0; i < methods.Count; i++) {
1116                                 var method = methods [i];
1117                                 var new_token = new MetadataToken (TokenType.Method, method_rid++);
1118
1119                                 if (write_symbols && method.token != MetadataToken.Zero)
1120                                         method_def_map.Add (new_token, method.token);
1121
1122                                 method.token = new_token;
1123                         }
1124                 }
1125
1126                 public bool TryGetOriginalMethodToken (MetadataToken new_token, out MetadataToken original)
1127                 {
1128                         return method_def_map.TryGetValue (new_token, out original);
1129                 }
1130
1131                 MetadataToken GetTypeToken (TypeReference type)
1132                 {
1133                         if (type == null)
1134                                 return MetadataToken.Zero;
1135
1136                         if (type.IsDefinition)
1137                                 return type.token;
1138
1139                         if (type.IsTypeSpecification ())
1140                                 return GetTypeSpecToken (type);
1141
1142                         return GetTypeRefToken (type);
1143                 }
1144
1145                 MetadataToken GetTypeSpecToken (TypeReference type)
1146                 {
1147                         var row = GetBlobIndex (GetTypeSpecSignature (type));
1148
1149                         MetadataToken token;
1150                         if (type_spec_map.TryGetValue (row, out token))
1151                                 return token;
1152
1153                         return AddTypeSpecification (type, row);
1154                 }
1155
1156                 MetadataToken AddTypeSpecification (TypeReference type, uint row)
1157                 {
1158                         type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row));
1159
1160                         var token = type.token;
1161                         type_spec_map.Add (row, token);
1162                         return token;
1163                 }
1164
1165                 MetadataToken GetTypeRefToken (TypeReference type)
1166                 {
1167                         var row = CreateTypeRefRow (type);
1168
1169                         MetadataToken token;
1170                         if (type_ref_map.TryGetValue (row, out token))
1171                                 return token;
1172
1173                         return AddTypeReference (type, row);
1174                 }
1175
1176                 TypeRefRow CreateTypeRefRow (TypeReference type)
1177                 {
1178                         var scope_token = type.IsNested
1179                                 ? GetTypeRefToken (type.DeclaringType)
1180                                 : type.Scope.MetadataToken;
1181
1182                         return new TypeRefRow (
1183                                 MakeCodedRID (scope_token, CodedIndex.ResolutionScope),
1184                                 GetStringIndex (type.Name),
1185                                 GetStringIndex (type.Namespace));
1186                 }
1187
1188                 static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index)
1189                 {
1190                         return MakeCodedRID (provider.MetadataToken, index);
1191                 }
1192
1193                 static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index)
1194                 {
1195                         return index.CompressMetadataToken (token);
1196                 }
1197
1198                 MetadataToken AddTypeReference (TypeReference type, TypeRefRow row)
1199                 {
1200                         type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row));
1201
1202                         var token = type.token;
1203                         type_ref_map.Add (row, token);
1204                         return token;
1205                 }
1206
1207                 void AddTypeDefs ()
1208                 {
1209                         var types = module.Types;
1210
1211                         for (int i = 0; i < types.Count; i++)
1212                                 AddType (types [i]);
1213                 }
1214
1215                 void AddType (TypeDefinition type)
1216                 {
1217                         type_def_table.AddRow (new TypeDefRow (
1218                                 type.Attributes,
1219                                 GetStringIndex (type.Name),
1220                                 GetStringIndex (type.Namespace),
1221                                 MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef),
1222                                 type.fields_range.Start,
1223                                 type.methods_range.Start));
1224
1225                         if (type.HasGenericParameters)
1226                                 AddGenericParameters (type);
1227
1228                         if (type.HasInterfaces)
1229                                 AddInterfaces (type);
1230
1231                         if (type.HasLayoutInfo)
1232                                 AddLayoutInfo (type);
1233
1234                         if (type.HasFields)
1235                                 AddFields (type);
1236
1237                         if (type.HasMethods)
1238                                 AddMethods (type);
1239
1240                         if (type.HasProperties)
1241                                 AddProperties (type);
1242
1243                         if (type.HasEvents)
1244                                 AddEvents (type);
1245
1246                         if (type.HasCustomAttributes)
1247                                 AddCustomAttributes (type);
1248
1249                         if (type.HasSecurityDeclarations)
1250                                 AddSecurityDeclarations (type);
1251
1252                         if (type.HasNestedTypes)
1253                                 AddNestedTypes (type);
1254                 }
1255
1256                 void AddGenericParameters (IGenericParameterProvider owner)
1257                 {
1258                         var parameters = owner.GenericParameters;
1259
1260                         for (int i = 0; i < parameters.Count; i++)
1261                                 generic_parameters.Add (parameters [i]);
1262                 }
1263
1264                 sealed class GenericParameterComparer : IComparer<GenericParameter> {
1265
1266                         public int Compare (GenericParameter a, GenericParameter b)
1267                         {
1268                                 var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef);
1269                                 var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef);
1270                                 if (a_owner == b_owner) {
1271                                         var a_pos = a.Position;
1272                                         var b_pos = b.Position;
1273                                         return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1;
1274                                 }
1275
1276                                 return a_owner > b_owner ? 1 : -1;
1277                         }
1278                 }
1279
1280                 void AddGenericParameters ()
1281                 {
1282                         var items = this.generic_parameters.items;
1283                         var size = this.generic_parameters.size;
1284                         Array.Sort (items, 0, size, new GenericParameterComparer ());
1285
1286                         var generic_param_table = GetTable<GenericParamTable> (Table.GenericParam);
1287                         var generic_param_constraint_table = GetTable<GenericParamConstraintTable> (Table.GenericParamConstraint);
1288
1289                         for (int i = 0; i < size; i++) {
1290                                 var generic_parameter = items [i];
1291
1292                                 var rid = generic_param_table.AddRow (new GenericParamRow (
1293                                         (ushort) generic_parameter.Position,
1294                                         generic_parameter.Attributes,
1295                                         MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef),
1296                                         GetStringIndex (generic_parameter.Name)));
1297
1298                                 generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid);
1299
1300                                 if (generic_parameter.HasConstraints)
1301                                         AddConstraints (generic_parameter, generic_param_constraint_table);
1302
1303                                 if (generic_parameter.HasCustomAttributes)
1304                                         AddCustomAttributes (generic_parameter);
1305                         }
1306                 }
1307
1308                 void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table)
1309                 {
1310                         var constraints = generic_parameter.Constraints;
1311
1312                         var rid = generic_parameter.token.RID;
1313
1314                         for (int i = 0; i < constraints.Count; i++)
1315                                 table.AddRow (new GenericParamConstraintRow (
1316                                         rid,
1317                                         MakeCodedRID (GetTypeToken (constraints [i]), CodedIndex.TypeDefOrRef)));
1318                 }
1319
1320                 void AddInterfaces (TypeDefinition type)
1321                 {
1322                         var interfaces = type.Interfaces;
1323                         var type_rid = type.token.RID;
1324
1325                         for (int i = 0; i < interfaces.Count; i++)
1326                                 iface_impl_table.AddRow (new InterfaceImplRow (
1327                                         type_rid,
1328                                         MakeCodedRID (GetTypeToken (interfaces [i]), CodedIndex.TypeDefOrRef)));
1329                 }
1330
1331                 void AddLayoutInfo (TypeDefinition type)
1332                 {
1333                         var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
1334
1335                         table.AddRow (new ClassLayoutRow (
1336                                 (ushort) type.PackingSize,
1337                                 (uint) type.ClassSize,
1338                                 type.token.RID));
1339                 }
1340
1341                 void AddNestedTypes (TypeDefinition type)
1342                 {
1343                         var nested_types = type.NestedTypes;
1344                         var nested_table = GetTable<NestedClassTable> (Table.NestedClass);
1345
1346                         for (int i = 0; i < nested_types.Count; i++) {
1347                                 var nested = nested_types [i];
1348                                 AddType (nested);
1349                                 nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID));
1350                         }
1351                 }
1352
1353                 void AddFields (TypeDefinition type)
1354                 {
1355                         var fields = type.Fields;
1356
1357                         for (int i = 0; i < fields.Count; i++)
1358                                 AddField (fields [i]);
1359                 }
1360
1361                 void AddField (FieldDefinition field)
1362                 {
1363                         field_table.AddRow (new FieldRow (
1364                                 field.Attributes,
1365                                 GetStringIndex (field.Name),
1366                                 GetBlobIndex (GetFieldSignature (field))));
1367
1368                         if (!field.InitialValue.IsNullOrEmpty ())
1369                                 AddFieldRVA (field);
1370
1371                         if (field.HasLayoutInfo)
1372                                 AddFieldLayout (field);
1373
1374                         if (field.HasCustomAttributes)
1375                                 AddCustomAttributes (field);
1376
1377                         if (field.HasConstant)
1378                                 AddConstant (field, field.FieldType);
1379
1380                         if (field.HasMarshalInfo)
1381                                 AddMarshalInfo (field);
1382                 }
1383
1384                 void AddFieldRVA (FieldDefinition field)
1385                 {
1386                         var table = GetTable<FieldRVATable> (Table.FieldRVA);
1387                         table.AddRow (new FieldRVARow (
1388                                 data.AddData (field.InitialValue),
1389                                 field.token.RID));
1390                 }
1391
1392                 void AddFieldLayout (FieldDefinition field)
1393                 {
1394                         var table = GetTable<FieldLayoutTable> (Table.FieldLayout);
1395                         table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID));
1396                 }
1397
1398                 void AddMethods (TypeDefinition type)
1399                 {
1400                         var methods = type.Methods;
1401
1402                         for (int i = 0; i < methods.Count; i++)
1403                                 AddMethod (methods [i]);
1404                 }
1405
1406                 void AddMethod (MethodDefinition method)
1407                 {
1408                         method_table.AddRow (new MethodRow (
1409                                 method.HasBody ? code.WriteMethodBody (method) : 0,
1410                                 method.ImplAttributes,
1411                                 method.Attributes,
1412                                 GetStringIndex (method.Name),
1413                                 GetBlobIndex (GetMethodSignature (method)),
1414                                 param_rid));
1415
1416                         AddParameters (method);
1417
1418                         if (method.HasGenericParameters)
1419                                 AddGenericParameters (method);
1420
1421                         if (method.IsPInvokeImpl)
1422                                 AddPInvokeInfo (method);
1423
1424                         if (method.HasCustomAttributes)
1425                                 AddCustomAttributes (method);
1426
1427                         if (method.HasSecurityDeclarations)
1428                                 AddSecurityDeclarations (method);
1429
1430                         if (method.HasOverrides)
1431                                 AddOverrides (method);
1432                 }
1433
1434                 void AddParameters (MethodDefinition method)
1435                 {
1436                         var return_parameter = method.MethodReturnType.parameter;
1437
1438                         if (return_parameter != null && RequiresParameterRow (return_parameter))
1439                                 AddParameter (0, return_parameter, param_table);
1440
1441                         if (!method.HasParameters)
1442                                 return;
1443
1444                         var parameters = method.Parameters;
1445
1446                         for (int i = 0; i < parameters.Count; i++) {
1447                                 var parameter = parameters [i];
1448                                 if (!RequiresParameterRow (parameter))
1449                                         continue;
1450
1451                                 AddParameter ((ushort) (i + 1), parameter, param_table);
1452                         }
1453                 }
1454
1455                 void AddPInvokeInfo (MethodDefinition method)
1456                 {
1457                         var pinvoke = method.PInvokeInfo;
1458                         if (pinvoke == null)
1459                                 throw new ArgumentException ();
1460
1461                         var table = GetTable<ImplMapTable> (Table.ImplMap);
1462                         table.AddRow (new ImplMapRow (
1463                                 pinvoke.Attributes,
1464                                 MakeCodedRID (method, CodedIndex.MemberForwarded),
1465                                 GetStringIndex (pinvoke.EntryPoint),
1466                                 pinvoke.Module.MetadataToken.RID));
1467                 }
1468
1469                 void AddOverrides (MethodDefinition method)
1470                 {
1471                         var overrides = method.Overrides;
1472                         var table = GetTable<MethodImplTable> (Table.MethodImpl);
1473
1474                         for (int i = 0; i < overrides.Count; i++) {
1475                                 table.AddRow (new MethodImplRow (
1476                                         method.DeclaringType.token.RID,
1477                                         MakeCodedRID (method, CodedIndex.MethodDefOrRef),
1478                                         MakeCodedRID (LookupToken (overrides [i]), CodedIndex.MethodDefOrRef)));
1479                         }
1480                 }
1481
1482                 static bool RequiresParameterRow (ParameterDefinition parameter)
1483                 {
1484                         return !string.IsNullOrEmpty (parameter.Name)
1485                                 || parameter.Attributes != ParameterAttributes.None
1486                                 || parameter.HasMarshalInfo
1487                                 || parameter.HasConstant
1488                                 || parameter.HasCustomAttributes;
1489                 }
1490
1491                 void AddParameter (ushort sequence, ParameterDefinition parameter, ParamTable table)
1492                 {
1493                         table.AddRow (new ParamRow (
1494                                 parameter.Attributes,
1495                                 sequence,
1496                                 GetStringIndex (parameter.Name)));
1497
1498                         parameter.token = new MetadataToken (TokenType.Param, param_rid++);
1499
1500                         if (parameter.HasCustomAttributes)
1501                                 AddCustomAttributes (parameter);
1502
1503                         if (parameter.HasConstant)
1504                                 AddConstant (parameter, parameter.ParameterType);
1505
1506                         if (parameter.HasMarshalInfo)
1507                                 AddMarshalInfo (parameter);
1508                 }
1509
1510                 void AddMarshalInfo (IMarshalInfoProvider owner)
1511                 {
1512                         var table = GetTable<FieldMarshalTable> (Table.FieldMarshal);
1513
1514                         table.AddRow (new FieldMarshalRow (
1515                                 MakeCodedRID (owner, CodedIndex.HasFieldMarshal),
1516                                 GetBlobIndex (GetMarshalInfoSignature (owner))));
1517                 }
1518
1519                 void AddProperties (TypeDefinition type)
1520                 {
1521                         var properties = type.Properties;
1522
1523                         property_map_table.AddRow (new PropertyMapRow (type.token.RID, property_rid));
1524
1525                         for (int i = 0; i < properties.Count; i++)
1526                                 AddProperty (properties [i]);
1527                 }
1528
1529                 void AddProperty (PropertyDefinition property)
1530                 {
1531                         property_table.AddRow (new PropertyRow (
1532                                 property.Attributes,
1533                                 GetStringIndex (property.Name),
1534                                 GetBlobIndex (GetPropertySignature (property))));
1535                         property.token = new MetadataToken (TokenType.Property, property_rid++);
1536
1537                         var method = property.GetMethod;
1538                         if (method != null)
1539                                 AddSemantic (MethodSemanticsAttributes.Getter, property, method);
1540
1541                         method = property.SetMethod;
1542                         if (method != null)
1543                                 AddSemantic (MethodSemanticsAttributes.Setter, property, method);
1544
1545                         if (property.HasOtherMethods)
1546                                 AddOtherSemantic (property, property.OtherMethods);
1547
1548                         if (property.HasCustomAttributes)
1549                                 AddCustomAttributes (property);
1550
1551                         if (property.HasConstant)
1552                                 AddConstant (property, property.PropertyType);
1553                 }
1554
1555                 void AddOtherSemantic (IMetadataTokenProvider owner, Collection<MethodDefinition> others)
1556                 {
1557                         for (int i = 0; i < others.Count; i++)
1558                                 AddSemantic (MethodSemanticsAttributes.Other, owner, others [i]);
1559                 }
1560
1561                 void AddEvents (TypeDefinition type)
1562                 {
1563                         var events = type.Events;
1564
1565                         event_map_table.AddRow (new EventMapRow (type.token.RID, event_rid));
1566
1567                         for (int i = 0; i < events.Count; i++)
1568                                 AddEvent (events [i]);
1569                 }
1570
1571                 void AddEvent (EventDefinition @event)
1572                 {
1573                         event_table.AddRow (new EventRow (
1574                                 @event.Attributes,
1575                                 GetStringIndex (@event.Name),
1576                                 MakeCodedRID (GetTypeToken (@event.EventType), CodedIndex.TypeDefOrRef)));
1577                         @event.token = new MetadataToken (TokenType.Event, event_rid++);
1578
1579                         var method = @event.AddMethod;
1580                         if (method != null)
1581                                 AddSemantic (MethodSemanticsAttributes.AddOn, @event, method);
1582
1583                         method = @event.InvokeMethod;
1584                         if (method != null)
1585                                 AddSemantic (MethodSemanticsAttributes.Fire, @event, method);
1586
1587                         method = @event.RemoveMethod;
1588                         if (method != null)
1589                                 AddSemantic (MethodSemanticsAttributes.RemoveOn, @event, method);
1590
1591                         if (@event.HasOtherMethods)
1592                                 AddOtherSemantic (@event, @event.OtherMethods);
1593
1594                         if (@event.HasCustomAttributes)
1595                                 AddCustomAttributes (@event);
1596                 }
1597
1598                 void AddSemantic (MethodSemanticsAttributes semantics, IMetadataTokenProvider provider, MethodDefinition method)
1599                 {
1600                         method.SemanticsAttributes = semantics;
1601                         var table = GetTable<MethodSemanticsTable> (Table.MethodSemantics);
1602
1603                         table.AddRow (new MethodSemanticsRow (
1604                                 semantics,
1605                                 method.token.RID,
1606                                 MakeCodedRID (provider, CodedIndex.HasSemantics)));
1607                 }
1608
1609                 void AddConstant (IConstantProvider owner, TypeReference type)
1610                 {
1611                         var constant = owner.Constant;
1612                         var etype = GetConstantType (type, constant);
1613
1614                         constant_table.AddRow (new ConstantRow (
1615                                 etype,
1616                                 MakeCodedRID (owner.MetadataToken, CodedIndex.HasConstant),
1617                                 GetBlobIndex (GetConstantSignature (etype, constant))));
1618                 }
1619
1620                 static ElementType GetConstantType (TypeReference constant_type, object constant)
1621                 {
1622                         if (constant == null)
1623                                 return ElementType.Class;
1624
1625                         var etype = constant_type.etype;
1626                         switch (etype) {
1627                         case ElementType.None:
1628                                 var type = constant_type.CheckedResolve ();
1629                                 if (type.IsEnum)
1630                                         return GetConstantType (type.GetEnumUnderlyingType (), constant);
1631
1632                                 return ElementType.Class;
1633                         case ElementType.String:
1634                                 return ElementType.String;
1635                         case ElementType.Object:
1636                                 return GetConstantType (constant.GetType ());
1637                         case ElementType.Array:
1638                         case ElementType.SzArray:
1639                         case ElementType.MVar:
1640                         case ElementType.Var:
1641                                 return ElementType.Class;
1642                         case ElementType.GenericInst:
1643                         case ElementType.CModOpt:
1644                         case ElementType.CModReqD:
1645                         case ElementType.ByRef:
1646                         case ElementType.Sentinel:
1647                                 return GetConstantType (((TypeSpecification) constant_type).ElementType, constant);
1648                         case ElementType.Boolean:
1649                         case ElementType.Char:
1650                         case ElementType.I:
1651                         case ElementType.I1:
1652                         case ElementType.I2:
1653                         case ElementType.I4:
1654                         case ElementType.I8:
1655                         case ElementType.U:
1656                         case ElementType.U1:
1657                         case ElementType.U2:
1658                         case ElementType.U4:
1659                         case ElementType.U8:
1660                         case ElementType.R4:
1661                         case ElementType.R8:
1662                                 return GetConstantType (constant.GetType ());
1663                         default:
1664                                 return etype;
1665                         }
1666                 }
1667
1668                 static ElementType GetConstantType (Type type)
1669                 {
1670                         switch (Type.GetTypeCode (type)) {
1671                         case TypeCode.Boolean:
1672                                 return ElementType.Boolean;
1673                         case TypeCode.Byte:
1674                                 return ElementType.U1;
1675                         case TypeCode.SByte:
1676                                 return ElementType.I1;
1677                         case TypeCode.Char:
1678                                 return ElementType.Char;
1679                         case TypeCode.Int16:
1680                                 return ElementType.I2;
1681                         case TypeCode.UInt16:
1682                                 return ElementType.U2;
1683                         case TypeCode.Int32:
1684                                 return ElementType.I4;
1685                         case TypeCode.UInt32:
1686                                 return ElementType.U4;
1687                         case TypeCode.Int64:
1688                                 return ElementType.I8;
1689                         case TypeCode.UInt64:
1690                                 return ElementType.U8;
1691                         case TypeCode.Single:
1692                                 return ElementType.R4;
1693                         case TypeCode.Double:
1694                                 return ElementType.R8;
1695                         case TypeCode.String:
1696                                 return ElementType.String;
1697                         default:
1698                                 throw new NotSupportedException (type.FullName);
1699                         }
1700                 }
1701
1702                 void AddCustomAttributes (ICustomAttributeProvider owner)
1703                 {
1704                         var custom_attributes = owner.CustomAttributes;
1705
1706                         for (int i = 0; i < custom_attributes.Count; i++) {
1707                                 var attribute = custom_attributes [i];
1708
1709                                 custom_attribute_table.AddRow (new CustomAttributeRow (
1710                                         MakeCodedRID (owner, CodedIndex.HasCustomAttribute),
1711                                         MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType),
1712                                         GetBlobIndex (GetCustomAttributeSignature (attribute))));
1713                         }
1714                 }
1715
1716                 void AddSecurityDeclarations (ISecurityDeclarationProvider owner)
1717                 {
1718                         var declarations = owner.SecurityDeclarations;
1719
1720                         for (int i = 0; i < declarations.Count; i++) {
1721                                 var declaration = declarations [i];
1722
1723                                 declsec_table.AddRow (new DeclSecurityRow (
1724                                         declaration.Action,
1725                                         MakeCodedRID (owner, CodedIndex.HasDeclSecurity),
1726                                         GetBlobIndex (GetSecurityDeclarationSignature (declaration))));
1727                         }
1728                 }
1729
1730                 MetadataToken GetMemberRefToken (MemberReference member)
1731                 {
1732                         var row = CreateMemberRefRow (member);
1733
1734                         MetadataToken token;
1735                         if (member_ref_map.TryGetValue (row, out token))
1736                                 return token;
1737
1738                         AddMemberReference (member, row);
1739
1740                         return member.token;
1741                 }
1742
1743                 MemberRefRow CreateMemberRefRow (MemberReference member)
1744                 {
1745                         return new MemberRefRow (
1746                                 MakeCodedRID (GetTypeToken (member.DeclaringType), CodedIndex.MemberRefParent),
1747                                 GetStringIndex (member.Name),
1748                                 GetBlobIndex (GetMemberRefSignature (member)));
1749                 }
1750
1751                 void AddMemberReference (MemberReference member, MemberRefRow row)
1752                 {
1753                         member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row));
1754                         member_ref_map.Add (row, member.token);
1755                 }
1756
1757                 MetadataToken GetMethodSpecToken (MethodSpecification method_spec)
1758                 {
1759                         var row = CreateMethodSpecRow (method_spec);
1760
1761                         MetadataToken token;
1762                         if (method_spec_map.TryGetValue (row, out token))
1763                                 return token;
1764
1765                         AddMethodSpecification (method_spec, row);
1766
1767                         return method_spec.token;
1768                 }
1769
1770                 void AddMethodSpecification (MethodSpecification method_spec, MethodSpecRow row)
1771                 {
1772                         method_spec.token = new MetadataToken (TokenType.MethodSpec, method_spec_table.AddRow (row));
1773                         method_spec_map.Add (row, method_spec.token);
1774                 }
1775
1776                 MethodSpecRow CreateMethodSpecRow (MethodSpecification method_spec)
1777                 {
1778                         return new MethodSpecRow (
1779                                 MakeCodedRID (LookupToken (method_spec.ElementMethod), CodedIndex.MethodDefOrRef),
1780                                 GetBlobIndex (GetMethodSpecSignature (method_spec)));
1781                 }
1782
1783                 SignatureWriter CreateSignatureWriter ()
1784                 {
1785                         return new SignatureWriter (this);
1786                 }
1787
1788                 SignatureWriter GetMethodSpecSignature (MethodSpecification method_spec)
1789                 {
1790                         if (!method_spec.IsGenericInstance)
1791                                 throw new NotSupportedException ();
1792
1793                         var generic_instance = (GenericInstanceMethod) method_spec;
1794
1795                         var signature = CreateSignatureWriter ();
1796                         signature.WriteByte (0x0a);
1797
1798                         signature.WriteGenericInstanceSignature (generic_instance);
1799
1800                         return signature;
1801                 }
1802
1803                 public uint AddStandAloneSignature (uint signature)
1804                 {
1805                         return (uint) standalone_sig_table.AddRow (signature);
1806                 }
1807
1808                 public uint GetLocalVariableBlobIndex (Collection<VariableDefinition> variables)
1809                 {
1810                         return GetBlobIndex (GetVariablesSignature (variables));
1811                 }
1812
1813                 public uint GetCallSiteBlobIndex (CallSite call_site)
1814                 {
1815                         return GetBlobIndex (GetMethodSignature (call_site));
1816                 }
1817
1818                 SignatureWriter GetVariablesSignature (Collection<VariableDefinition> variables)
1819                 {
1820                         var signature = CreateSignatureWriter ();
1821                         signature.WriteByte (0x7);
1822                         signature.WriteCompressedUInt32 ((uint) variables.Count);
1823                         for (int i = 0; i < variables.Count; i++)
1824                                 signature.WriteTypeSignature (variables [i].VariableType);
1825                         return signature;
1826                 }
1827
1828                 SignatureWriter GetFieldSignature (FieldReference field)
1829                 {
1830                         var signature = CreateSignatureWriter ();
1831                         signature.WriteByte (0x6);
1832                         signature.WriteTypeSignature (field.FieldType);
1833                         return signature;
1834                 }
1835
1836                 SignatureWriter GetMethodSignature (IMethodSignature method)
1837                 {
1838                         var signature = CreateSignatureWriter ();
1839                         signature.WriteMethodSignature (method);
1840                         return signature;
1841                 }
1842
1843                 SignatureWriter GetMemberRefSignature (MemberReference member)
1844                 {
1845                         var field = member as FieldReference;
1846                         if (field != null)
1847                                 return GetFieldSignature (field);
1848
1849                         var method = member as MethodReference;
1850                         if (method != null)
1851                                 return GetMethodSignature (method);
1852
1853                         throw new NotSupportedException ();
1854                 }
1855
1856                 SignatureWriter GetPropertySignature (PropertyDefinition property)
1857                 {
1858                         var signature = CreateSignatureWriter ();
1859                         byte calling_convention = 0x8;
1860                         if (property.HasThis)
1861                                 calling_convention |= 0x20;
1862
1863                         uint param_count = 0;
1864                         Collection<ParameterDefinition> parameters = null;
1865
1866                         if (property.HasParameters) {
1867                                 parameters = property.Parameters;
1868                                 param_count = (uint) parameters.Count;
1869                         }
1870
1871                         signature.WriteByte (calling_convention);
1872                         signature.WriteCompressedUInt32 (param_count);
1873                         signature.WriteTypeSignature (property.PropertyType);
1874
1875                         if (param_count == 0)
1876                                 return signature;
1877
1878                         for (int i = 0; i < param_count; i++)
1879                                 signature.WriteTypeSignature (parameters [i].ParameterType);
1880
1881                         return signature;
1882                 }
1883
1884                 SignatureWriter GetTypeSpecSignature (TypeReference type)
1885                 {
1886                         var signature = CreateSignatureWriter ();
1887                         signature.WriteTypeSignature (type);
1888                         return signature;
1889                 }
1890
1891                 SignatureWriter GetConstantSignature (ElementType type, object value)
1892                 {
1893                         var signature = CreateSignatureWriter ();
1894
1895                         switch (type) {
1896                         case ElementType.Array:
1897                         case ElementType.SzArray:
1898                         case ElementType.Class:
1899                         case ElementType.Object:
1900                         case ElementType.Var:
1901                         case ElementType.MVar:
1902                                 signature.WriteInt32 (0);
1903                                 break;
1904                         case ElementType.String:
1905                                 signature.WriteConstantString ((string) value);
1906                                 break;
1907                         default:
1908                                 signature.WriteConstantPrimitive (value);
1909                                 break;
1910                         }
1911
1912                         return signature;
1913                 }
1914
1915                 SignatureWriter GetCustomAttributeSignature (CustomAttribute attribute)
1916                 {
1917                         var signature = CreateSignatureWriter ();
1918                         if (!attribute.resolved) {
1919                                 signature.WriteBytes (attribute.GetBlob ());
1920                                 return signature;
1921                         }
1922
1923                         signature.WriteUInt16 (0x0001);
1924
1925                         signature.WriteCustomAttributeConstructorArguments (attribute);
1926
1927                         signature.WriteCustomAttributeNamedArguments (attribute);
1928
1929                         return signature;
1930                 }
1931
1932                 SignatureWriter GetSecurityDeclarationSignature (SecurityDeclaration declaration)
1933                 {
1934                         var signature = CreateSignatureWriter ();
1935
1936                         if (!declaration.resolved)
1937                                 signature.WriteBytes (declaration.GetBlob ());
1938                         else if (module.Runtime < TargetRuntime.Net_2_0)
1939                                 signature.WriteXmlSecurityDeclaration (declaration);
1940                         else
1941                                 signature.WriteSecurityDeclaration (declaration);
1942
1943                         return signature;
1944                 }
1945
1946                 SignatureWriter GetMarshalInfoSignature (IMarshalInfoProvider owner)
1947                 {
1948                         var signature = CreateSignatureWriter ();
1949
1950                         signature.WriteMarshalInfo (owner.MarshalInfo);
1951
1952                         return signature;
1953                 }
1954
1955                 static Exception CreateForeignMemberException (MemberReference member)
1956                 {
1957                         return new ArgumentException (string.Format ("Member '{0}' is declared in another module and needs to be imported", member));
1958                 }
1959
1960                 public MetadataToken LookupToken (IMetadataTokenProvider provider)
1961                 {
1962                         if (provider == null)
1963                                 throw new ArgumentNullException ();
1964
1965                         var member = provider as MemberReference;
1966                         if (member == null || member.Module != module)
1967                                 throw CreateForeignMemberException (member);
1968
1969                         var token = provider.MetadataToken;
1970
1971                         switch (token.TokenType) {
1972                         case TokenType.TypeDef:
1973                         case TokenType.Method:
1974                         case TokenType.Field:
1975                         case TokenType.Event:
1976                         case TokenType.Property:
1977                                 return token;
1978                         case TokenType.TypeRef:
1979                         case TokenType.TypeSpec:
1980                         case TokenType.GenericParam:
1981                                 return GetTypeToken ((TypeReference) provider);
1982                         case TokenType.MethodSpec:
1983                                 return GetMethodSpecToken ((MethodSpecification) provider);
1984                         case TokenType.MemberRef:
1985                                 return GetMemberRefToken (member);
1986                         default:
1987                                 throw new NotSupportedException ();
1988                         }
1989                 }
1990         }
1991
1992         sealed class SignatureWriter : ByteBuffer {
1993
1994                 readonly MetadataBuilder metadata;
1995
1996                 public SignatureWriter (MetadataBuilder metadata)
1997                         : base (6)
1998                 {
1999                         this.metadata = metadata;
2000                 }
2001
2002                 public void WriteElementType (ElementType element_type)
2003                 {
2004                         WriteByte ((byte) element_type);
2005                 }
2006
2007                 public void WriteUTF8String (string @string)
2008                 {
2009                         if (@string == null) {
2010                                 WriteByte (0xff);
2011                                 return;
2012                         }
2013
2014                         var bytes = Encoding.UTF8.GetBytes (@string);
2015                         WriteCompressedUInt32 ((uint) bytes.Length);
2016                         WriteBytes (bytes);
2017                 }
2018
2019                 public void WriteMethodSignature (IMethodSignature method)
2020                 {
2021                         byte calling_convention = (byte) method.CallingConvention;
2022                         if (method.HasThis)
2023                                 calling_convention |= 0x20;
2024                         if (method.ExplicitThis)
2025                                 calling_convention |= 0x40;
2026
2027                         var generic_provider = method as IGenericParameterProvider;
2028                         var generic_arity = generic_provider != null && generic_provider.HasGenericParameters
2029                                 ? generic_provider.GenericParameters.Count
2030                                 : 0;
2031
2032                         if (generic_arity > 0)
2033                                 calling_convention |= 0x10;
2034
2035                         var param_count = method.HasParameters ? method.Parameters.Count : 0;
2036
2037                         WriteByte (calling_convention);
2038
2039                         if (generic_arity > 0)
2040                                 WriteCompressedUInt32 ((uint) generic_arity);
2041
2042                         WriteCompressedUInt32 ((uint) param_count);
2043                         WriteTypeSignature (method.ReturnType);
2044
2045                         if (param_count == 0)
2046                                 return;
2047
2048                         var parameters = method.Parameters;
2049
2050                         for (int i = 0; i < param_count; i++)
2051                                 WriteTypeSignature (parameters [i].ParameterType);
2052                 }
2053
2054                 uint MakeTypeDefOrRefCodedRID (TypeReference type)
2055                 {
2056                         return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type));
2057                 }
2058
2059                 public void WriteTypeSignature (TypeReference type)
2060                 {
2061                         if (type == null)
2062                                 throw new ArgumentNullException ();
2063
2064                         var etype = type.etype;
2065
2066                         switch (etype) {
2067                         case ElementType.MVar:
2068                         case ElementType.Var: {
2069                                 var generic_parameter = (GenericParameter) type;
2070
2071                                 WriteElementType (etype);
2072                                 var position = generic_parameter.Position;
2073                                 if (position == -1)
2074                                         throw new NotSupportedException ();
2075
2076                                 WriteCompressedUInt32 ((uint) position);
2077                                 break;
2078                         }
2079
2080                         case ElementType.GenericInst: {
2081                                 var generic_instance = (GenericInstanceType) type;
2082                                 WriteElementType (ElementType.GenericInst);
2083                                 WriteElementType (generic_instance.IsValueType ? ElementType.ValueType : ElementType.Class);
2084                                 WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (generic_instance.ElementType));
2085
2086                                 WriteGenericInstanceSignature (generic_instance);
2087                                 break;
2088                         }
2089
2090                         case ElementType.Ptr:
2091                         case ElementType.ByRef:
2092                         case ElementType.Pinned:
2093                         case ElementType.Sentinel: {
2094                                 var type_spec = (TypeSpecification) type;
2095                                 WriteElementType (etype);
2096                                 WriteTypeSignature (type_spec.ElementType);
2097                                 break;
2098                         }
2099
2100                         case ElementType.FnPtr: {
2101                                 var fptr = (FunctionPointerType) type;
2102                                 WriteElementType (ElementType.FnPtr);
2103                                 WriteMethodSignature (fptr);
2104                                 break;
2105                         }
2106
2107                         case ElementType.CModOpt:
2108                         case ElementType.CModReqD: {
2109                                 var modifier = (IModifierType) type;
2110                                 WriteModifierSignature (etype, modifier);
2111                                 break;
2112                         }
2113
2114                         case ElementType.Array: {
2115                                 var array = (ArrayType) type;
2116                                 if (!array.IsVector) {
2117                                         WriteArrayTypeSignature (array);
2118                                         break;
2119                                 }
2120
2121                                 WriteElementType (ElementType.SzArray);
2122                                 WriteTypeSignature (array.ElementType);
2123                                 break;
2124                         }
2125
2126                         case ElementType.None: {
2127                                 WriteElementType (type.IsValueType ? ElementType.ValueType : ElementType.Class);
2128                                 WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type));
2129                                 break;
2130                         }
2131
2132                         default:
2133                                 if (!TryWriteElementType (type))
2134                                         throw new NotSupportedException ();
2135
2136                                 break;
2137
2138                         }
2139                 }
2140
2141                 void WriteArrayTypeSignature (ArrayType array)
2142                 {
2143                         WriteElementType (ElementType.Array);
2144                         WriteTypeSignature (array.ElementType);
2145
2146                         var dimensions = array.Dimensions;
2147                         var rank = dimensions.Count;
2148
2149                         WriteCompressedUInt32 ((uint) rank);
2150
2151                         var sized = 0;
2152                         var lbounds = 0;
2153
2154                         for (int i = 0; i < rank; i++) {
2155                                 var dimension = dimensions [i];
2156
2157                                 if (dimension.UpperBound.HasValue) {
2158                                         sized++;
2159                                         lbounds++;
2160                                 } else if (dimension.LowerBound.HasValue)
2161                                         lbounds++;
2162                         }
2163
2164                         var sizes = new int [sized];
2165                         var low_bounds = new int [lbounds];
2166
2167                         for (int i = 0; i < lbounds; i++) {
2168                                 var dimension = dimensions [i];
2169                                 low_bounds [i] = dimension.LowerBound.GetValueOrDefault ();
2170                                 if (dimension.UpperBound.HasValue)
2171                                         sizes [i] = dimension.UpperBound.Value - low_bounds [i] + 1;
2172                         }
2173
2174                         WriteCompressedUInt32 ((uint) sized);
2175                         for (int i = 0; i < sized; i++)
2176                                 WriteCompressedUInt32 ((uint) sizes [i]);
2177
2178                         WriteCompressedUInt32 ((uint) lbounds);
2179                         for (int i = 0; i < lbounds; i++)
2180                                 WriteCompressedInt32 (low_bounds [i]);
2181                 }
2182
2183                 public void WriteGenericInstanceSignature (IGenericInstance instance)
2184                 {
2185                         var generic_arguments = instance.GenericArguments;
2186                         var arity = generic_arguments.Count;
2187
2188                         WriteCompressedUInt32 ((uint) arity);
2189                         for (int i = 0; i < arity; i++)
2190                                 WriteTypeSignature (generic_arguments [i]);
2191                 }
2192
2193                 void WriteModifierSignature (ElementType element_type, IModifierType type)
2194                 {
2195                         WriteElementType (element_type);
2196                         WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type.ModifierType));
2197                         WriteTypeSignature (type.ElementType);
2198                 }
2199
2200                 bool TryWriteElementType (TypeReference type)
2201                 {
2202                         var element = type.etype;
2203
2204                         if (element == ElementType.None)
2205                                 return false;
2206
2207                         WriteElementType (element);
2208                         return true;
2209                 }
2210
2211                 public void WriteConstantString (string value)
2212                 {
2213                         WriteBytes (Encoding.Unicode.GetBytes (value));
2214                 }
2215
2216                 public void WriteConstantPrimitive (object value)
2217                 {
2218                         WritePrimitiveValue (value);
2219                 }
2220
2221                 public void WriteCustomAttributeConstructorArguments (CustomAttribute attribute)
2222                 {
2223                         if (!attribute.HasConstructorArguments)
2224                                 return;
2225
2226                         var arguments = attribute.ConstructorArguments;
2227                         var parameters = attribute.Constructor.Parameters;
2228
2229                         if (parameters.Count != arguments.Count)
2230                                 throw new InvalidOperationException ();
2231
2232                         for (int i = 0; i < arguments.Count; i++)
2233                                 WriteCustomAttributeFixedArgument (parameters [i].ParameterType, arguments [i]);
2234                 }
2235
2236                 void WriteCustomAttributeFixedArgument (TypeReference type, CustomAttributeArgument argument)
2237                 {
2238                         if (type.IsArray) {
2239                                 WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
2240                                 return;
2241                         }
2242
2243                         WriteCustomAttributeElement (type, argument);
2244                 }
2245
2246                 void WriteCustomAttributeFixedArrayArgument (ArrayType type, CustomAttributeArgument argument)
2247                 {
2248                         var values = argument.Value as CustomAttributeArgument [];
2249
2250                         if (values == null) {
2251                                 WriteUInt32 (0xffffffff);
2252                                 return;
2253                         }
2254
2255                         WriteInt32 (values.Length);
2256
2257                         if (values.Length == 0)
2258                                 return;
2259
2260                         var element_type = type.ElementType;
2261
2262                         for (int i = 0; i < values.Length; i++)
2263                                 WriteCustomAttributeElement (element_type, values [i]);
2264                 }
2265
2266                 void WriteCustomAttributeElement (TypeReference type, CustomAttributeArgument argument)
2267                 {
2268                         if (type.IsArray) {
2269                                 WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
2270                                 return;
2271                         }
2272
2273                         if (type.etype == ElementType.Object) {
2274                                 argument = (CustomAttributeArgument) argument.Value;
2275                                 type = argument.Type;
2276
2277                                 WriteCustomAttributeFieldOrPropType (type);
2278                                 WriteCustomAttributeElement (type, argument);
2279                                 return;
2280                         }
2281
2282                         WriteCustomAttributeValue (type, argument.Value);
2283                 }
2284
2285                 void WriteCustomAttributeValue (TypeReference type, object value)
2286                 {
2287                         var etype = type.etype;
2288
2289                         switch (etype) {
2290                         case ElementType.String:
2291                                 var @string = (string) value;
2292                                 if (@string == null)
2293                                         WriteByte (0xff);
2294                                 else
2295                                         WriteUTF8String (@string);
2296                                 break;
2297                         case ElementType.None:
2298                                 if (type.IsTypeOf ("System", "Type"))
2299                                         WriteTypeReference ((TypeReference) value);
2300                                 else
2301                                         WriteCustomAttributeEnumValue (type, value);
2302                                 break;
2303                         default:
2304                                 WritePrimitiveValue (value);
2305                                 break;
2306                         }
2307                 }
2308
2309                 void WritePrimitiveValue (object value)
2310                 {
2311                         if (value == null)
2312                                 throw new ArgumentNullException ();
2313
2314                         switch (Type.GetTypeCode (value.GetType ())) {
2315                         case TypeCode.Boolean:
2316                                 WriteByte ((byte) (((bool) value) ? 1 : 0));
2317                                 break;
2318                         case TypeCode.Byte:
2319                                 WriteByte ((byte) value);
2320                                 break;
2321                         case TypeCode.SByte:
2322                                 WriteSByte ((sbyte) value);
2323                                 break;
2324                         case TypeCode.Int16:
2325                                 WriteInt16 ((short) value);
2326                                 break;
2327                         case TypeCode.UInt16:
2328                                 WriteUInt16 ((ushort) value);
2329                                 break;
2330                         case TypeCode.Char:
2331                                 WriteInt16 ((short) (char) value);
2332                                 break;
2333                         case TypeCode.Int32:
2334                                 WriteInt32 ((int) value);
2335                                 break;
2336                         case TypeCode.UInt32:
2337                                 WriteUInt32 ((uint) value);
2338                                 break;
2339                         case TypeCode.Single:
2340                                 WriteSingle ((float) value);
2341                                 break;
2342                         case TypeCode.Int64:
2343                                 WriteInt64 ((long) value);
2344                                 break;
2345                         case TypeCode.UInt64:
2346                                 WriteUInt64 ((ulong) value);
2347                                 break;
2348                         case TypeCode.Double:
2349                                 WriteDouble ((double) value);
2350                                 break;
2351                         default:
2352                                 throw new NotSupportedException (value.GetType ().FullName);
2353                         }
2354                 }
2355
2356                 void WriteCustomAttributeEnumValue (TypeReference enum_type, object value)
2357                 {
2358                         var type = enum_type.CheckedResolve ();
2359                         if (!type.IsEnum)
2360                                 throw new ArgumentException ();
2361
2362                         WriteCustomAttributeValue (type.GetEnumUnderlyingType (), value);
2363                 }
2364
2365                 void WriteCustomAttributeFieldOrPropType (TypeReference type)
2366                 {
2367                         if (type.IsArray) {
2368                                 var array = (ArrayType) type;
2369                                 WriteElementType (ElementType.SzArray);
2370                                 WriteCustomAttributeFieldOrPropType (array.ElementType);
2371                                 return;
2372                         }
2373
2374                         var etype = type.etype;
2375
2376                         switch (etype) {
2377                         case ElementType.Object:
2378                                 WriteElementType (ElementType.Boxed);
2379                                 return;
2380                         case ElementType.None:
2381                                 if (type.IsTypeOf ("System", "Type"))
2382                                         WriteElementType (ElementType.Type);
2383                                 else {
2384                                         WriteElementType (ElementType.Enum);
2385                                         WriteTypeReference (type);
2386                                 }
2387                                 return;
2388                         default:
2389                                 WriteElementType (etype);
2390                                 return;
2391                         }
2392                 }
2393
2394                 public void WriteCustomAttributeNamedArguments (CustomAttribute attribute)
2395                 {
2396                         var count = GetNamedArgumentCount (attribute);
2397
2398                         WriteUInt16 ((ushort) count);
2399
2400                         if (count == 0)
2401                                 return;
2402
2403                         WriteICustomAttributeNamedArguments (attribute);
2404                 }
2405
2406                 static int GetNamedArgumentCount (ICustomAttribute attribute)
2407                 {
2408                         int count = 0;
2409
2410                         if (attribute.HasFields)
2411                                 count += attribute.Fields.Count;
2412
2413                         if (attribute.HasProperties)
2414                                 count += attribute.Properties.Count;
2415
2416                         return count;
2417                 }
2418
2419                 void WriteICustomAttributeNamedArguments (ICustomAttribute attribute)
2420                 {
2421                         if (attribute.HasFields)
2422                                 WriteCustomAttributeNamedArguments (0x53, attribute.Fields);
2423
2424                         if (attribute.HasProperties)
2425                                 WriteCustomAttributeNamedArguments (0x54, attribute.Properties);
2426                 }
2427
2428                 void WriteCustomAttributeNamedArguments (byte kind, Collection<CustomAttributeNamedArgument> named_arguments)
2429                 {
2430                         for (int i = 0; i < named_arguments.Count; i++)
2431                                 WriteCustomAttributeNamedArgument (kind, named_arguments [i]);
2432                 }
2433
2434                 void WriteCustomAttributeNamedArgument (byte kind, CustomAttributeNamedArgument named_argument)
2435                 {
2436                         var argument = named_argument.Argument;
2437
2438                         WriteByte (kind);
2439                         WriteCustomAttributeFieldOrPropType (argument.Type);
2440                         WriteUTF8String (named_argument.Name);
2441                         WriteCustomAttributeFixedArgument (argument.Type, argument);
2442                 }
2443
2444                 void WriteSecurityAttribute (SecurityAttribute attribute)
2445                 {
2446                         WriteTypeReference (attribute.AttributeType);
2447
2448                         var count = GetNamedArgumentCount (attribute);
2449
2450                         if (count == 0) {
2451                                 WriteCompressedUInt32 (0); // length
2452                                 WriteCompressedUInt32 (0); // count
2453                                 return;
2454                         }
2455
2456             var buffer = new SignatureWriter (metadata);
2457                         buffer.WriteCompressedUInt32 ((uint) count);
2458                         buffer.WriteICustomAttributeNamedArguments (attribute);
2459
2460                         WriteCompressedUInt32 ((uint) buffer.length);
2461                         WriteBytes (buffer);
2462                 }
2463
2464                 public void WriteSecurityDeclaration (SecurityDeclaration declaration)
2465                 {
2466                         WriteByte ((byte) '.');
2467
2468                         var attributes = declaration.security_attributes;
2469                         if (attributes == null)
2470                                 throw new NotSupportedException ();
2471
2472                         WriteCompressedUInt32 ((uint) attributes.Count);
2473
2474                         for (int i = 0; i < attributes.Count; i++)
2475                                 WriteSecurityAttribute (attributes [i]);
2476                 }
2477
2478                 public void WriteXmlSecurityDeclaration (SecurityDeclaration declaration)
2479                 {
2480                         var xml = GetXmlSecurityDeclaration (declaration);
2481                         if (xml == null)
2482                                 throw new NotSupportedException ();
2483
2484                         WriteBytes (Encoding.Unicode.GetBytes (xml));
2485                 }
2486
2487                 static string GetXmlSecurityDeclaration (SecurityDeclaration declaration)
2488                 {
2489                         if (declaration.security_attributes == null || declaration.security_attributes.Count != 1)
2490                                 return null;
2491
2492                         var attribute = declaration.security_attributes [0];
2493
2494                         if (!attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute"))
2495                                 return null;
2496
2497                         if (attribute.properties == null || attribute.properties.Count != 1)
2498                                 return null;
2499
2500                         var property = attribute.properties [0];
2501                         if (property.Name != "XML")
2502                                 return null;
2503
2504                         return (string) property.Argument.Value;
2505                 }
2506
2507                 void WriteTypeReference (TypeReference type)
2508                 {
2509                         WriteUTF8String (TypeParser.ToParseable (type));
2510                 }
2511
2512                 public void WriteMarshalInfo (MarshalInfo marshal_info)
2513                 {
2514                         WriteNativeType (marshal_info.native);
2515
2516                         switch (marshal_info.native) {
2517                         case NativeType.Array: {
2518                                 var array = (ArrayMarshalInfo) marshal_info;
2519                                 if (array.element_type != NativeType.None)
2520                                         WriteNativeType (array.element_type);
2521                                 if (array.size_parameter_index > -1)
2522                                         WriteCompressedUInt32 ((uint) array.size_parameter_index);
2523                                 if (array.size > -1)
2524                                         WriteCompressedUInt32 ((uint) array.size);
2525                                 if (array.size_parameter_multiplier > -1)
2526                                         WriteCompressedUInt32 ((uint) array.size_parameter_multiplier);
2527                                 return;
2528                         }
2529                         case NativeType.SafeArray: {
2530                                 var array = (SafeArrayMarshalInfo) marshal_info;
2531                                 if (array.element_type != VariantType.None)
2532                                         WriteVariantType (array.element_type);
2533                                 return;
2534                         }
2535                         case NativeType.FixedArray: {
2536                                 var array = (FixedArrayMarshalInfo) marshal_info;
2537                                 if (array.size > -1)
2538                                         WriteCompressedUInt32 ((uint) array.size);
2539                                 if (array.element_type != NativeType.None)
2540                                         WriteNativeType (array.element_type);
2541                                 return;
2542                         }
2543                         case NativeType.FixedSysString:
2544                                 var sys_string = (FixedSysStringMarshalInfo) marshal_info;
2545                                 if (sys_string.size > -1)
2546                                         WriteCompressedUInt32 ((uint) sys_string.size);
2547                                 return;
2548                         case NativeType.CustomMarshaler:
2549                                 var marshaler = (CustomMarshalInfo) marshal_info;
2550                                 WriteUTF8String (marshaler.guid != Guid.Empty ? marshaler.guid.ToString () : string.Empty);
2551                                 WriteUTF8String (marshaler.unmanaged_type);
2552                                 WriteTypeReference (marshaler.managed_type);
2553                                 WriteUTF8String (marshaler.cookie);
2554                                 return;
2555                         }
2556                 }
2557
2558                 void WriteNativeType (NativeType native)
2559                 {
2560                         WriteByte ((byte) native);
2561                 }
2562
2563                 void WriteVariantType (VariantType variant)
2564                 {
2565                         WriteByte ((byte) variant);
2566                 }
2567         }
2568
2569 #endif
2570
2571 }