Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.Cecil/0.9.5/Mono.Cecil-0.9.5/Mono.Cecil/Mono.Cecil/AssemblyWriter.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 69.9 KB
Line 
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
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Text;
33
34using Mono.Collections.Generic;
35using Mono.Cecil.Cil;
36using Mono.Cecil.Metadata;
37using Mono.Cecil.PE;
38
39using RVA = System.UInt32;
40using RID = System.UInt32;
41using CodedRID = System.UInt32;
42using StringIndex = System.UInt32;
43using BlobIndex = System.UInt32;
44
45namespace 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 version = reference.Version;
939
940        var rid = table.AddRow (new AssemblyRefRow (
941          (ushort) version.Major,
942          (ushort) version.Minor,
943          (ushort) version.Build,
944          (ushort) version.Revision,
945          reference.Attributes,
946          GetBlobIndex (key_or_token),
947          GetStringIndex (reference.Name),
948          GetStringIndex (reference.Culture),
949          GetBlobIndex (reference.Hash)));
950
951        reference.token = new MetadataToken (TokenType.AssemblyRef, rid);
952      }
953    }
954
955    void AddModuleReferences ()
956    {
957      var references = module.ModuleReferences;
958      var table = GetTable<ModuleRefTable> (Table.ModuleRef);
959
960      for (int i = 0; i < references.Count; i++) {
961        var reference = references [i];
962
963        reference.token = new MetadataToken (
964          TokenType.ModuleRef,
965          table.AddRow (GetStringIndex (reference.Name)));
966      }
967    }
968
969    void AddResources ()
970    {
971      var resources = module.Resources;
972      var table = GetTable<ManifestResourceTable> (Table.ManifestResource);
973
974      for (int i = 0; i < resources.Count; i++) {
975        var resource = resources [i];
976
977        var row = new ManifestResourceRow (
978          0,
979          resource.Attributes,
980          GetStringIndex (resource.Name),
981          0);
982
983        switch (resource.ResourceType) {
984        case ResourceType.Embedded:
985          row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource);
986          break;
987        case ResourceType.Linked:
988          row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
989            new MetadataToken (
990              TokenType.File,
991              AddLinkedResource ((LinkedResource) resource)));
992          break;
993        case ResourceType.AssemblyLinked:
994          row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
995            ((AssemblyLinkedResource) resource).Assembly.MetadataToken);
996          break;
997        default:
998          throw new NotSupportedException ();
999        }
1000
1001        table.AddRow (row);
1002      }
1003    }
1004
1005    uint AddLinkedResource (LinkedResource resource)
1006    {
1007      var table = GetTable<FileTable> (Table.File);
1008
1009      var hash = resource.Hash.IsNullOrEmpty ()
1010        ? CryptoService.ComputeHash (resource.File)
1011        : resource.Hash;
1012
1013      return (uint) table.AddRow (new FileRow (
1014        FileAttributes.ContainsNoMetaData,
1015        GetStringIndex (resource.File),
1016        GetBlobIndex (hash)));
1017    }
1018
1019    uint AddEmbeddedResource (EmbeddedResource resource)
1020    {
1021      return resources.AddResource (resource.GetResourceData ());
1022    }
1023
1024    void AddExportedTypes ()
1025    {
1026      var exported_types = module.ExportedTypes;
1027      var table = GetTable<ExportedTypeTable> (Table.ExportedType);
1028
1029      for (int i = 0; i < exported_types.Count; i++) {
1030        var exported_type = exported_types [i];
1031
1032        var rid = table.AddRow (new ExportedTypeRow (
1033          exported_type.Attributes,
1034          (uint) exported_type.Identifier,
1035          GetStringIndex (exported_type.Name),
1036          GetStringIndex (exported_type.Namespace),
1037          MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation)));
1038
1039        exported_type.token = new MetadataToken (TokenType.ExportedType, rid);
1040      }
1041    }
1042
1043    MetadataToken GetExportedTypeScope (ExportedType exported_type)
1044    {
1045      if (exported_type.DeclaringType != null)
1046        return exported_type.DeclaringType.MetadataToken;
1047
1048      var scope = exported_type.Scope;
1049      switch (scope.MetadataToken.TokenType) {
1050      case TokenType.AssemblyRef:
1051        return scope.MetadataToken;
1052      case TokenType.ModuleRef:
1053        var file_table = GetTable<FileTable> (Table.File);
1054        for (int i = 0; i < file_table.length; i++)
1055          if (file_table.rows [i].Col2 == GetStringIndex (scope.Name))
1056            return new MetadataToken (TokenType.File, i + 1);
1057
1058        break;
1059      }
1060
1061      throw new NotSupportedException ();
1062    }
1063
1064    void BuildTypes ()
1065    {
1066      if (!module.HasTypes)
1067        return;
1068
1069      AttachTokens ();
1070      AddTypeDefs ();
1071      AddGenericParameters ();
1072    }
1073
1074    void AttachTokens ()
1075    {
1076      var types = module.Types;
1077
1078      for (int i = 0; i < types.Count; i++)
1079        AttachTypeDefToken (types [i]);
1080    }
1081
1082    void AttachTypeDefToken (TypeDefinition type)
1083    {
1084      type.token = new MetadataToken (TokenType.TypeDef, type_rid++);
1085      type.fields_range.Start = field_rid;
1086      type.methods_range.Start = method_rid;
1087
1088      if (type.HasFields)
1089        AttachFieldsDefToken (type);
1090
1091      if (type.HasMethods)
1092        AttachMethodsDefToken (type);
1093
1094      if (type.HasNestedTypes)
1095        AttachNestedTypesDefToken (type);
1096    }
1097
1098    void AttachNestedTypesDefToken (TypeDefinition type)
1099    {
1100      var nested_types = type.NestedTypes;
1101      for (int i = 0; i < nested_types.Count; i++)
1102        AttachTypeDefToken (nested_types [i]);
1103    }
1104
1105    void AttachFieldsDefToken (TypeDefinition type)
1106    {
1107      var fields = type.Fields;
1108      type.fields_range.Length = (uint) fields.Count;
1109      for (int i = 0; i < fields.Count; i++)
1110        fields [i].token = new MetadataToken (TokenType.Field, field_rid++);
1111    }
1112
1113    void AttachMethodsDefToken (TypeDefinition type)
1114    {
1115      var methods = type.Methods;
1116      type.methods_range.Length = (uint) methods.Count;
1117      for (int i = 0; i < methods.Count; i++) {
1118        var method = methods [i];
1119        var new_token = new MetadataToken (TokenType.Method, method_rid++);
1120
1121        if (write_symbols && method.token != MetadataToken.Zero)
1122          method_def_map.Add (new_token, method.token);
1123
1124        method.token = new_token;
1125      }
1126    }
1127
1128    public bool TryGetOriginalMethodToken (MetadataToken new_token, out MetadataToken original)
1129    {
1130      return method_def_map.TryGetValue (new_token, out original);
1131    }
1132
1133    MetadataToken GetTypeToken (TypeReference type)
1134    {
1135      if (type == null)
1136        return MetadataToken.Zero;
1137
1138      if (type.IsDefinition)
1139        return type.token;
1140
1141      if (type.IsTypeSpecification ())
1142        return GetTypeSpecToken (type);
1143
1144      return GetTypeRefToken (type);
1145    }
1146
1147    MetadataToken GetTypeSpecToken (TypeReference type)
1148    {
1149      var row = GetBlobIndex (GetTypeSpecSignature (type));
1150
1151      MetadataToken token;
1152      if (type_spec_map.TryGetValue (row, out token))
1153        return token;
1154
1155      return AddTypeSpecification (type, row);
1156    }
1157
1158    MetadataToken AddTypeSpecification (TypeReference type, uint row)
1159    {
1160      type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row));
1161
1162      var token = type.token;
1163      type_spec_map.Add (row, token);
1164      return token;
1165    }
1166
1167    MetadataToken GetTypeRefToken (TypeReference type)
1168    {
1169      var row = CreateTypeRefRow (type);
1170
1171      MetadataToken token;
1172      if (type_ref_map.TryGetValue (row, out token))
1173        return token;
1174
1175      return AddTypeReference (type, row);
1176    }
1177
1178    TypeRefRow CreateTypeRefRow (TypeReference type)
1179    {
1180      var scope_token = type.IsNested
1181        ? GetTypeRefToken (type.DeclaringType)
1182        : type.Scope.MetadataToken;
1183
1184      return new TypeRefRow (
1185        MakeCodedRID (scope_token, CodedIndex.ResolutionScope),
1186        GetStringIndex (type.Name),
1187        GetStringIndex (type.Namespace));
1188    }
1189
1190    static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index)
1191    {
1192      return MakeCodedRID (provider.MetadataToken, index);
1193    }
1194
1195    static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index)
1196    {
1197      return index.CompressMetadataToken (token);
1198    }
1199
1200    MetadataToken AddTypeReference (TypeReference type, TypeRefRow row)
1201    {
1202      type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row));
1203
1204      var token = type.token;
1205      type_ref_map.Add (row, token);
1206      return token;
1207    }
1208
1209    void AddTypeDefs ()
1210    {
1211      var types = module.Types;
1212
1213      for (int i = 0; i < types.Count; i++)
1214        AddType (types [i]);
1215    }
1216
1217    void AddType (TypeDefinition type)
1218    {
1219      type_def_table.AddRow (new TypeDefRow (
1220        type.Attributes,
1221        GetStringIndex (type.Name),
1222        GetStringIndex (type.Namespace),
1223        MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef),
1224        type.fields_range.Start,
1225        type.methods_range.Start));
1226
1227      if (type.HasGenericParameters)
1228        AddGenericParameters (type);
1229
1230      if (type.HasInterfaces)
1231        AddInterfaces (type);
1232
1233      if (type.HasLayoutInfo)
1234        AddLayoutInfo (type);
1235
1236      if (type.HasFields)
1237        AddFields (type);
1238
1239      if (type.HasMethods)
1240        AddMethods (type);
1241
1242      if (type.HasProperties)
1243        AddProperties (type);
1244
1245      if (type.HasEvents)
1246        AddEvents (type);
1247
1248      if (type.HasCustomAttributes)
1249        AddCustomAttributes (type);
1250
1251      if (type.HasSecurityDeclarations)
1252        AddSecurityDeclarations (type);
1253
1254      if (type.HasNestedTypes)
1255        AddNestedTypes (type);
1256    }
1257
1258    void AddGenericParameters (IGenericParameterProvider owner)
1259    {
1260      var parameters = owner.GenericParameters;
1261
1262      for (int i = 0; i < parameters.Count; i++)
1263        generic_parameters.Add (parameters [i]);
1264    }
1265
1266    sealed class GenericParameterComparer : IComparer<GenericParameter> {
1267
1268      public int Compare (GenericParameter a, GenericParameter b)
1269      {
1270        var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef);
1271        var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef);
1272        if (a_owner == b_owner) {
1273          var a_pos = a.Position;
1274          var b_pos = b.Position;
1275          return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1;
1276        }
1277
1278        return a_owner > b_owner ? 1 : -1;
1279      }
1280    }
1281
1282    void AddGenericParameters ()
1283    {
1284      var items = this.generic_parameters.items;
1285      var size = this.generic_parameters.size;
1286      Array.Sort (items, 0, size, new GenericParameterComparer ());
1287
1288      var generic_param_table = GetTable<GenericParamTable> (Table.GenericParam);
1289      var generic_param_constraint_table = GetTable<GenericParamConstraintTable> (Table.GenericParamConstraint);
1290
1291      for (int i = 0; i < size; i++) {
1292        var generic_parameter = items [i];
1293
1294        var rid = generic_param_table.AddRow (new GenericParamRow (
1295          (ushort) generic_parameter.Position,
1296          generic_parameter.Attributes,
1297          MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef),
1298          GetStringIndex (generic_parameter.Name)));
1299
1300        generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid);
1301
1302        if (generic_parameter.HasConstraints)
1303          AddConstraints (generic_parameter, generic_param_constraint_table);
1304
1305        if (generic_parameter.HasCustomAttributes)
1306          AddCustomAttributes (generic_parameter);
1307      }
1308    }
1309
1310    void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table)
1311    {
1312      var constraints = generic_parameter.Constraints;
1313
1314      var rid = generic_parameter.token.RID;
1315
1316      for (int i = 0; i < constraints.Count; i++)
1317        table.AddRow (new GenericParamConstraintRow (
1318          rid,
1319          MakeCodedRID (GetTypeToken (constraints [i]), CodedIndex.TypeDefOrRef)));
1320    }
1321
1322    void AddInterfaces (TypeDefinition type)
1323    {
1324      var interfaces = type.Interfaces;
1325      var type_rid = type.token.RID;
1326
1327      for (int i = 0; i < interfaces.Count; i++)
1328        iface_impl_table.AddRow (new InterfaceImplRow (
1329          type_rid,
1330          MakeCodedRID (GetTypeToken (interfaces [i]), CodedIndex.TypeDefOrRef)));
1331    }
1332
1333    void AddLayoutInfo (TypeDefinition type)
1334    {
1335      var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
1336
1337      table.AddRow (new ClassLayoutRow (
1338        (ushort) type.PackingSize,
1339        (uint) type.ClassSize,
1340        type.token.RID));
1341    }
1342
1343    void AddNestedTypes (TypeDefinition type)
1344    {
1345      var nested_types = type.NestedTypes;
1346      var nested_table = GetTable<NestedClassTable> (Table.NestedClass);
1347
1348      for (int i = 0; i < nested_types.Count; i++) {
1349        var nested = nested_types [i];
1350        AddType (nested);
1351        nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID));
1352      }
1353    }
1354
1355    void AddFields (TypeDefinition type)
1356    {
1357      var fields = type.Fields;
1358
1359      for (int i = 0; i < fields.Count; i++)
1360        AddField (fields [i]);
1361    }
1362
1363    void AddField (FieldDefinition field)
1364    {
1365      field_table.AddRow (new FieldRow (
1366        field.Attributes,
1367        GetStringIndex (field.Name),
1368        GetBlobIndex (GetFieldSignature (field))));
1369
1370      if (!field.InitialValue.IsNullOrEmpty ())
1371        AddFieldRVA (field);
1372
1373      if (field.HasLayoutInfo)
1374        AddFieldLayout (field);
1375
1376      if (field.HasCustomAttributes)
1377        AddCustomAttributes (field);
1378
1379      if (field.HasConstant)
1380        AddConstant (field, field.FieldType);
1381
1382      if (field.HasMarshalInfo)
1383        AddMarshalInfo (field);
1384    }
1385
1386    void AddFieldRVA (FieldDefinition field)
1387    {
1388      var table = GetTable<FieldRVATable> (Table.FieldRVA);
1389      table.AddRow (new FieldRVARow (
1390        data.AddData (field.InitialValue),
1391        field.token.RID));
1392    }
1393
1394    void AddFieldLayout (FieldDefinition field)
1395    {
1396      var table = GetTable<FieldLayoutTable> (Table.FieldLayout);
1397      table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID));
1398    }
1399
1400    void AddMethods (TypeDefinition type)
1401    {
1402      var methods = type.Methods;
1403
1404      for (int i = 0; i < methods.Count; i++)
1405        AddMethod (methods [i]);
1406    }
1407
1408    void AddMethod (MethodDefinition method)
1409    {
1410      method_table.AddRow (new MethodRow (
1411        method.HasBody ? code.WriteMethodBody (method) : 0,
1412        method.ImplAttributes,
1413        method.Attributes,
1414        GetStringIndex (method.Name),
1415        GetBlobIndex (GetMethodSignature (method)),
1416        param_rid));
1417
1418      AddParameters (method);
1419
1420      if (method.HasGenericParameters)
1421        AddGenericParameters (method);
1422
1423      if (method.IsPInvokeImpl)
1424        AddPInvokeInfo (method);
1425
1426      if (method.HasCustomAttributes)
1427        AddCustomAttributes (method);
1428
1429      if (method.HasSecurityDeclarations)
1430        AddSecurityDeclarations (method);
1431
1432      if (method.HasOverrides)
1433        AddOverrides (method);
1434    }
1435
1436    void AddParameters (MethodDefinition method)
1437    {
1438      var return_parameter = method.MethodReturnType.parameter;
1439
1440      if (return_parameter != null && RequiresParameterRow (return_parameter))
1441        AddParameter (0, return_parameter, param_table);
1442
1443      if (!method.HasParameters)
1444        return;
1445
1446      var parameters = method.Parameters;
1447
1448      for (int i = 0; i < parameters.Count; i++) {
1449        var parameter = parameters [i];
1450        if (!RequiresParameterRow (parameter))
1451          continue;
1452
1453        AddParameter ((ushort) (i + 1), parameter, param_table);
1454      }
1455    }
1456
1457    void AddPInvokeInfo (MethodDefinition method)
1458    {
1459      var pinvoke = method.PInvokeInfo;
1460      if (pinvoke == null)
1461        throw new ArgumentException ();
1462
1463      var table = GetTable<ImplMapTable> (Table.ImplMap);
1464      table.AddRow (new ImplMapRow (
1465        pinvoke.Attributes,
1466        MakeCodedRID (method, CodedIndex.MemberForwarded),
1467        GetStringIndex (pinvoke.EntryPoint),
1468        pinvoke.Module.MetadataToken.RID));
1469    }
1470
1471    void AddOverrides (MethodDefinition method)
1472    {
1473      var overrides = method.Overrides;
1474      var table = GetTable<MethodImplTable> (Table.MethodImpl);
1475
1476      for (int i = 0; i < overrides.Count; i++) {
1477        table.AddRow (new MethodImplRow (
1478          method.DeclaringType.token.RID,
1479          MakeCodedRID (method, CodedIndex.MethodDefOrRef),
1480          MakeCodedRID (LookupToken (overrides [i]), CodedIndex.MethodDefOrRef)));
1481      }
1482    }
1483
1484    static bool RequiresParameterRow (ParameterDefinition parameter)
1485    {
1486      return !string.IsNullOrEmpty (parameter.Name)
1487        || parameter.Attributes != ParameterAttributes.None
1488        || parameter.HasMarshalInfo
1489        || parameter.HasConstant
1490        || parameter.HasCustomAttributes;
1491    }
1492
1493    void AddParameter (ushort sequence, ParameterDefinition parameter, ParamTable table)
1494    {
1495      table.AddRow (new ParamRow (
1496        parameter.Attributes,
1497        sequence,
1498        GetStringIndex (parameter.Name)));
1499
1500      parameter.token = new MetadataToken (TokenType.Param, param_rid++);
1501
1502      if (parameter.HasCustomAttributes)
1503        AddCustomAttributes (parameter);
1504
1505      if (parameter.HasConstant)
1506        AddConstant (parameter, parameter.ParameterType);
1507
1508      if (parameter.HasMarshalInfo)
1509        AddMarshalInfo (parameter);
1510    }
1511
1512    void AddMarshalInfo (IMarshalInfoProvider owner)
1513    {
1514      var table = GetTable<FieldMarshalTable> (Table.FieldMarshal);
1515
1516      table.AddRow (new FieldMarshalRow (
1517        MakeCodedRID (owner, CodedIndex.HasFieldMarshal),
1518        GetBlobIndex (GetMarshalInfoSignature (owner))));
1519    }
1520
1521    void AddProperties (TypeDefinition type)
1522    {
1523      var properties = type.Properties;
1524
1525      property_map_table.AddRow (new PropertyMapRow (type.token.RID, property_rid));
1526
1527      for (int i = 0; i < properties.Count; i++)
1528        AddProperty (properties [i]);
1529    }
1530
1531    void AddProperty (PropertyDefinition property)
1532    {
1533      property_table.AddRow (new PropertyRow (
1534        property.Attributes,
1535        GetStringIndex (property.Name),
1536        GetBlobIndex (GetPropertySignature (property))));
1537      property.token = new MetadataToken (TokenType.Property, property_rid++);
1538
1539      var method = property.GetMethod;
1540      if (method != null)
1541        AddSemantic (MethodSemanticsAttributes.Getter, property, method);
1542
1543      method = property.SetMethod;
1544      if (method != null)
1545        AddSemantic (MethodSemanticsAttributes.Setter, property, method);
1546
1547      if (property.HasOtherMethods)
1548        AddOtherSemantic (property, property.OtherMethods);
1549
1550      if (property.HasCustomAttributes)
1551        AddCustomAttributes (property);
1552
1553      if (property.HasConstant)
1554        AddConstant (property, property.PropertyType);
1555    }
1556
1557    void AddOtherSemantic (IMetadataTokenProvider owner, Collection<MethodDefinition> others)
1558    {
1559      for (int i = 0; i < others.Count; i++)
1560        AddSemantic (MethodSemanticsAttributes.Other, owner, others [i]);
1561    }
1562
1563    void AddEvents (TypeDefinition type)
1564    {
1565      var events = type.Events;
1566
1567      event_map_table.AddRow (new EventMapRow (type.token.RID, event_rid));
1568
1569      for (int i = 0; i < events.Count; i++)
1570        AddEvent (events [i]);
1571    }
1572
1573    void AddEvent (EventDefinition @event)
1574    {
1575      event_table.AddRow (new EventRow (
1576        @event.Attributes,
1577        GetStringIndex (@event.Name),
1578        MakeCodedRID (GetTypeToken (@event.EventType), CodedIndex.TypeDefOrRef)));
1579      @event.token = new MetadataToken (TokenType.Event, event_rid++);
1580
1581      var method = @event.AddMethod;
1582      if (method != null)
1583        AddSemantic (MethodSemanticsAttributes.AddOn, @event, method);
1584
1585      method = @event.InvokeMethod;
1586      if (method != null)
1587        AddSemantic (MethodSemanticsAttributes.Fire, @event, method);
1588
1589      method = @event.RemoveMethod;
1590      if (method != null)
1591        AddSemantic (MethodSemanticsAttributes.RemoveOn, @event, method);
1592
1593      if (@event.HasOtherMethods)
1594        AddOtherSemantic (@event, @event.OtherMethods);
1595
1596      if (@event.HasCustomAttributes)
1597        AddCustomAttributes (@event);
1598    }
1599
1600    void AddSemantic (MethodSemanticsAttributes semantics, IMetadataTokenProvider provider, MethodDefinition method)
1601    {
1602      method.SemanticsAttributes = semantics;
1603      var table = GetTable<MethodSemanticsTable> (Table.MethodSemantics);
1604
1605      table.AddRow (new MethodSemanticsRow (
1606        semantics,
1607        method.token.RID,
1608        MakeCodedRID (provider, CodedIndex.HasSemantics)));
1609    }
1610
1611    void AddConstant (IConstantProvider owner, TypeReference type)
1612    {
1613      var constant = owner.Constant;
1614      var etype = GetConstantType (type, constant);
1615
1616      constant_table.AddRow (new ConstantRow (
1617        etype,
1618        MakeCodedRID (owner.MetadataToken, CodedIndex.HasConstant),
1619        GetBlobIndex (GetConstantSignature (etype, constant))));
1620    }
1621
1622    static ElementType GetConstantType (TypeReference constant_type, object constant)
1623    {
1624      if (constant == null)
1625        return ElementType.Class;
1626
1627      var etype = constant_type.etype;
1628      switch (etype) {
1629      case ElementType.None:
1630        var type = constant_type.CheckedResolve ();
1631        if (type.IsEnum)
1632          return GetConstantType (type.GetEnumUnderlyingType (), constant);
1633
1634        return ElementType.Class;
1635      case ElementType.String:
1636        return ElementType.String;
1637      case ElementType.Object:
1638        return GetConstantType (constant.GetType ());
1639      case ElementType.Array:
1640      case ElementType.SzArray:
1641      case ElementType.MVar:
1642      case ElementType.Var:
1643        return ElementType.Class;
1644      case ElementType.GenericInst:
1645      case ElementType.CModOpt:
1646      case ElementType.CModReqD:
1647      case ElementType.ByRef:
1648      case ElementType.Sentinel:
1649        return GetConstantType (((TypeSpecification) constant_type).ElementType, constant);
1650      case ElementType.Boolean:
1651      case ElementType.Char:
1652      case ElementType.I:
1653      case ElementType.I1:
1654      case ElementType.I2:
1655      case ElementType.I4:
1656      case ElementType.I8:
1657      case ElementType.U:
1658      case ElementType.U1:
1659      case ElementType.U2:
1660      case ElementType.U4:
1661      case ElementType.U8:
1662      case ElementType.R4:
1663      case ElementType.R8:
1664        return GetConstantType (constant.GetType ());
1665      default:
1666        return etype;
1667      }
1668    }
1669
1670    static ElementType GetConstantType (Type type)
1671    {
1672      switch (Type.GetTypeCode (type)) {
1673      case TypeCode.Boolean:
1674        return ElementType.Boolean;
1675      case TypeCode.Byte:
1676        return ElementType.U1;
1677      case TypeCode.SByte:
1678        return ElementType.I1;
1679      case TypeCode.Char:
1680        return ElementType.Char;
1681      case TypeCode.Int16:
1682        return ElementType.I2;
1683      case TypeCode.UInt16:
1684        return ElementType.U2;
1685      case TypeCode.Int32:
1686        return ElementType.I4;
1687      case TypeCode.UInt32:
1688        return ElementType.U4;
1689      case TypeCode.Int64:
1690        return ElementType.I8;
1691      case TypeCode.UInt64:
1692        return ElementType.U8;
1693      case TypeCode.Single:
1694        return ElementType.R4;
1695      case TypeCode.Double:
1696        return ElementType.R8;
1697      case TypeCode.String:
1698        return ElementType.String;
1699      default:
1700        throw new NotSupportedException (type.FullName);
1701      }
1702    }
1703
1704    void AddCustomAttributes (ICustomAttributeProvider owner)
1705    {
1706      var custom_attributes = owner.CustomAttributes;
1707
1708      for (int i = 0; i < custom_attributes.Count; i++) {
1709        var attribute = custom_attributes [i];
1710
1711        custom_attribute_table.AddRow (new CustomAttributeRow (
1712          MakeCodedRID (owner, CodedIndex.HasCustomAttribute),
1713          MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType),
1714          GetBlobIndex (GetCustomAttributeSignature (attribute))));
1715      }
1716    }
1717
1718    void AddSecurityDeclarations (ISecurityDeclarationProvider owner)
1719    {
1720      var declarations = owner.SecurityDeclarations;
1721
1722      for (int i = 0; i < declarations.Count; i++) {
1723        var declaration = declarations [i];
1724
1725        declsec_table.AddRow (new DeclSecurityRow (
1726          declaration.Action,
1727          MakeCodedRID (owner, CodedIndex.HasDeclSecurity),
1728          GetBlobIndex (GetSecurityDeclarationSignature (declaration))));
1729      }
1730    }
1731
1732    MetadataToken GetMemberRefToken (MemberReference member)
1733    {
1734      var row = CreateMemberRefRow (member);
1735
1736      MetadataToken token;
1737      if (member_ref_map.TryGetValue (row, out token))
1738        return token;
1739
1740      AddMemberReference (member, row);
1741
1742      return member.token;
1743    }
1744
1745    MemberRefRow CreateMemberRefRow (MemberReference member)
1746    {
1747      return new MemberRefRow (
1748        MakeCodedRID (GetTypeToken (member.DeclaringType), CodedIndex.MemberRefParent),
1749        GetStringIndex (member.Name),
1750        GetBlobIndex (GetMemberRefSignature (member)));
1751    }
1752
1753    void AddMemberReference (MemberReference member, MemberRefRow row)
1754    {
1755      member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row));
1756      member_ref_map.Add (row, member.token);
1757    }
1758
1759    MetadataToken GetMethodSpecToken (MethodSpecification method_spec)
1760    {
1761      var row = CreateMethodSpecRow (method_spec);
1762
1763      MetadataToken token;
1764      if (method_spec_map.TryGetValue (row, out token))
1765        return token;
1766
1767      AddMethodSpecification (method_spec, row);
1768
1769      return method_spec.token;
1770    }
1771
1772    void AddMethodSpecification (MethodSpecification method_spec, MethodSpecRow row)
1773    {
1774      method_spec.token = new MetadataToken (TokenType.MethodSpec, method_spec_table.AddRow (row));
1775      method_spec_map.Add (row, method_spec.token);
1776    }
1777
1778    MethodSpecRow CreateMethodSpecRow (MethodSpecification method_spec)
1779    {
1780      return new MethodSpecRow (
1781        MakeCodedRID (LookupToken (method_spec.ElementMethod), CodedIndex.MethodDefOrRef),
1782        GetBlobIndex (GetMethodSpecSignature (method_spec)));
1783    }
1784
1785    SignatureWriter CreateSignatureWriter ()
1786    {
1787      return new SignatureWriter (this);
1788    }
1789
1790    SignatureWriter GetMethodSpecSignature (MethodSpecification method_spec)
1791    {
1792      if (!method_spec.IsGenericInstance)
1793        throw new NotSupportedException ();
1794
1795      var generic_instance = (GenericInstanceMethod) method_spec;
1796
1797      var signature = CreateSignatureWriter ();
1798      signature.WriteByte (0x0a);
1799
1800      signature.WriteGenericInstanceSignature (generic_instance);
1801
1802      return signature;
1803    }
1804
1805    public uint AddStandAloneSignature (uint signature)
1806    {
1807      return (uint) standalone_sig_table.AddRow (signature);
1808    }
1809
1810    public uint GetLocalVariableBlobIndex (Collection<VariableDefinition> variables)
1811    {
1812      return GetBlobIndex (GetVariablesSignature (variables));
1813    }
1814
1815    public uint GetCallSiteBlobIndex (CallSite call_site)
1816    {
1817      return GetBlobIndex (GetMethodSignature (call_site));
1818    }
1819
1820    SignatureWriter GetVariablesSignature (Collection<VariableDefinition> variables)
1821    {
1822      var signature = CreateSignatureWriter ();
1823      signature.WriteByte (0x7);
1824      signature.WriteCompressedUInt32 ((uint) variables.Count);
1825      for (int i = 0; i < variables.Count; i++)
1826        signature.WriteTypeSignature (variables [i].VariableType);
1827      return signature;
1828    }
1829
1830    SignatureWriter GetFieldSignature (FieldReference field)
1831    {
1832      var signature = CreateSignatureWriter ();
1833      signature.WriteByte (0x6);
1834      signature.WriteTypeSignature (field.FieldType);
1835      return signature;
1836    }
1837
1838    SignatureWriter GetMethodSignature (IMethodSignature method)
1839    {
1840      var signature = CreateSignatureWriter ();
1841      signature.WriteMethodSignature (method);
1842      return signature;
1843    }
1844
1845    SignatureWriter GetMemberRefSignature (MemberReference member)
1846    {
1847      var field = member as FieldReference;
1848      if (field != null)
1849        return GetFieldSignature (field);
1850
1851      var method = member as MethodReference;
1852      if (method != null)
1853        return GetMethodSignature (method);
1854
1855      throw new NotSupportedException ();
1856    }
1857
1858    SignatureWriter GetPropertySignature (PropertyDefinition property)
1859    {
1860      var signature = CreateSignatureWriter ();
1861      byte calling_convention = 0x8;
1862      if (property.HasThis)
1863        calling_convention |= 0x20;
1864
1865      uint param_count = 0;
1866      Collection<ParameterDefinition> parameters = null;
1867
1868      if (property.HasParameters) {
1869        parameters = property.Parameters;
1870        param_count = (uint) parameters.Count;
1871      }
1872
1873      signature.WriteByte (calling_convention);
1874      signature.WriteCompressedUInt32 (param_count);
1875      signature.WriteTypeSignature (property.PropertyType);
1876
1877      if (param_count == 0)
1878        return signature;
1879
1880      for (int i = 0; i < param_count; i++)
1881        signature.WriteTypeSignature (parameters [i].ParameterType);
1882
1883      return signature;
1884    }
1885
1886    SignatureWriter GetTypeSpecSignature (TypeReference type)
1887    {
1888      var signature = CreateSignatureWriter ();
1889      signature.WriteTypeSignature (type);
1890      return signature;
1891    }
1892
1893    SignatureWriter GetConstantSignature (ElementType type, object value)
1894    {
1895      var signature = CreateSignatureWriter ();
1896
1897      switch (type) {
1898      case ElementType.Array:
1899      case ElementType.SzArray:
1900      case ElementType.Class:
1901      case ElementType.Object:
1902      case ElementType.Var:
1903      case ElementType.MVar:
1904        signature.WriteInt32 (0);
1905        break;
1906      case ElementType.String:
1907        signature.WriteConstantString ((string) value);
1908        break;
1909      default:
1910        signature.WriteConstantPrimitive (value);
1911        break;
1912      }
1913
1914      return signature;
1915    }
1916
1917    SignatureWriter GetCustomAttributeSignature (CustomAttribute attribute)
1918    {
1919      var signature = CreateSignatureWriter ();
1920      if (!attribute.resolved) {
1921        signature.WriteBytes (attribute.GetBlob ());
1922        return signature;
1923      }
1924
1925      signature.WriteUInt16 (0x0001);
1926
1927      signature.WriteCustomAttributeConstructorArguments (attribute);
1928
1929      signature.WriteCustomAttributeNamedArguments (attribute);
1930
1931      return signature;
1932    }
1933
1934    SignatureWriter GetSecurityDeclarationSignature (SecurityDeclaration declaration)
1935    {
1936      var signature = CreateSignatureWriter ();
1937
1938      if (!declaration.resolved)
1939        signature.WriteBytes (declaration.GetBlob ());
1940      else if (module.Runtime < TargetRuntime.Net_2_0)
1941        signature.WriteXmlSecurityDeclaration (declaration);
1942      else
1943        signature.WriteSecurityDeclaration (declaration);
1944
1945      return signature;
1946    }
1947
1948    SignatureWriter GetMarshalInfoSignature (IMarshalInfoProvider owner)
1949    {
1950      var signature = CreateSignatureWriter ();
1951
1952      signature.WriteMarshalInfo (owner.MarshalInfo);
1953
1954      return signature;
1955    }
1956
1957    static Exception CreateForeignMemberException (MemberReference member)
1958    {
1959      return new ArgumentException (string.Format ("Member '{0}' is declared in another module and needs to be imported", member));
1960    }
1961
1962    public MetadataToken LookupToken (IMetadataTokenProvider provider)
1963    {
1964      if (provider == null)
1965        throw new ArgumentNullException ();
1966
1967      var member = provider as MemberReference;
1968      if (member == null || member.Module != module)
1969        throw CreateForeignMemberException (member);
1970
1971      var token = provider.MetadataToken;
1972
1973      switch (token.TokenType) {
1974      case TokenType.TypeDef:
1975      case TokenType.Method:
1976      case TokenType.Field:
1977      case TokenType.Event:
1978      case TokenType.Property:
1979        return token;
1980      case TokenType.TypeRef:
1981      case TokenType.TypeSpec:
1982      case TokenType.GenericParam:
1983        return GetTypeToken ((TypeReference) provider);
1984      case TokenType.MethodSpec:
1985        return GetMethodSpecToken ((MethodSpecification) provider);
1986      case TokenType.MemberRef:
1987        return GetMemberRefToken (member);
1988      default:
1989        throw new NotSupportedException ();
1990      }
1991    }
1992  }
1993
1994  sealed class SignatureWriter : ByteBuffer {
1995
1996    readonly MetadataBuilder metadata;
1997
1998    public SignatureWriter (MetadataBuilder metadata)
1999      : base (6)
2000    {
2001      this.metadata = metadata;
2002    }
2003
2004    public void WriteElementType (ElementType element_type)
2005    {
2006      WriteByte ((byte) element_type);
2007    }
2008
2009    public void WriteUTF8String (string @string)
2010    {
2011      if (@string == null) {
2012        WriteByte (0xff);
2013        return;
2014      }
2015
2016      var bytes = Encoding.UTF8.GetBytes (@string);
2017      WriteCompressedUInt32 ((uint) bytes.Length);
2018      WriteBytes (bytes);
2019    }
2020
2021    public void WriteMethodSignature (IMethodSignature method)
2022    {
2023      byte calling_convention = (byte) method.CallingConvention;
2024      if (method.HasThis)
2025        calling_convention |= 0x20;
2026      if (method.ExplicitThis)
2027        calling_convention |= 0x40;
2028
2029      var generic_provider = method as IGenericParameterProvider;
2030      var generic_arity = generic_provider != null && generic_provider.HasGenericParameters
2031        ? generic_provider.GenericParameters.Count
2032        : 0;
2033
2034      if (generic_arity > 0)
2035        calling_convention |= 0x10;
2036
2037      var param_count = method.HasParameters ? method.Parameters.Count : 0;
2038
2039      WriteByte (calling_convention);
2040
2041      if (generic_arity > 0)
2042        WriteCompressedUInt32 ((uint) generic_arity);
2043
2044      WriteCompressedUInt32 ((uint) param_count);
2045      WriteTypeSignature (method.ReturnType);
2046
2047      if (param_count == 0)
2048        return;
2049
2050      var parameters = method.Parameters;
2051
2052      for (int i = 0; i < param_count; i++)
2053        WriteTypeSignature (parameters [i].ParameterType);
2054    }
2055
2056    uint MakeTypeDefOrRefCodedRID (TypeReference type)
2057    {
2058      return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type));
2059    }
2060
2061    public void WriteTypeSignature (TypeReference type)
2062    {
2063      if (type == null)
2064        throw new ArgumentNullException ();
2065
2066      var etype = type.etype;
2067
2068      switch (etype) {
2069      case ElementType.MVar:
2070      case ElementType.Var: {
2071        var generic_parameter = (GenericParameter) type;
2072
2073        WriteElementType (etype);
2074        var position = generic_parameter.Position;
2075        if (position == -1)
2076          throw new NotSupportedException ();
2077
2078        WriteCompressedUInt32 ((uint) position);
2079        break;
2080      }
2081
2082      case ElementType.GenericInst: {
2083        var generic_instance = (GenericInstanceType) type;
2084        WriteElementType (ElementType.GenericInst);
2085        WriteElementType (generic_instance.IsValueType ? ElementType.ValueType : ElementType.Class);
2086        WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (generic_instance.ElementType));
2087
2088        WriteGenericInstanceSignature (generic_instance);
2089        break;
2090      }
2091
2092      case ElementType.Ptr:
2093      case ElementType.ByRef:
2094      case ElementType.Pinned:
2095      case ElementType.Sentinel: {
2096        var type_spec = (TypeSpecification) type;
2097        WriteElementType (etype);
2098        WriteTypeSignature (type_spec.ElementType);
2099        break;
2100      }
2101
2102      case ElementType.FnPtr: {
2103        var fptr = (FunctionPointerType) type;
2104        WriteElementType (ElementType.FnPtr);
2105        WriteMethodSignature (fptr);
2106        break;
2107      }
2108
2109      case ElementType.CModOpt:
2110      case ElementType.CModReqD: {
2111        var modifier = (IModifierType) type;
2112        WriteModifierSignature (etype, modifier);
2113        break;
2114      }
2115
2116      case ElementType.Array: {
2117        var array = (ArrayType) type;
2118        if (!array.IsVector) {
2119          WriteArrayTypeSignature (array);
2120          break;
2121        }
2122
2123        WriteElementType (ElementType.SzArray);
2124        WriteTypeSignature (array.ElementType);
2125        break;
2126      }
2127
2128      case ElementType.None: {
2129        WriteElementType (type.IsValueType ? ElementType.ValueType : ElementType.Class);
2130        WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type));
2131        break;
2132      }
2133
2134      default:
2135        if (!TryWriteElementType (type))
2136          throw new NotSupportedException ();
2137
2138        break;
2139
2140      }
2141    }
2142
2143    void WriteArrayTypeSignature (ArrayType array)
2144    {
2145      WriteElementType (ElementType.Array);
2146      WriteTypeSignature (array.ElementType);
2147
2148      var dimensions = array.Dimensions;
2149      var rank = dimensions.Count;
2150
2151      WriteCompressedUInt32 ((uint) rank);
2152
2153      var sized = 0;
2154      var lbounds = 0;
2155
2156      for (int i = 0; i < rank; i++) {
2157        var dimension = dimensions [i];
2158
2159        if (dimension.UpperBound.HasValue) {
2160          sized++;
2161          lbounds++;
2162        } else if (dimension.LowerBound.HasValue)
2163          lbounds++;
2164      }
2165
2166      var sizes = new int [sized];
2167      var low_bounds = new int [lbounds];
2168
2169      for (int i = 0; i < lbounds; i++) {
2170        var dimension = dimensions [i];
2171        low_bounds [i] = dimension.LowerBound.GetValueOrDefault ();
2172        if (dimension.UpperBound.HasValue)
2173          sizes [i] = dimension.UpperBound.Value - low_bounds [i] + 1;
2174      }
2175
2176      WriteCompressedUInt32 ((uint) sized);
2177      for (int i = 0; i < sized; i++)
2178        WriteCompressedUInt32 ((uint) sizes [i]);
2179
2180      WriteCompressedUInt32 ((uint) lbounds);
2181      for (int i = 0; i < lbounds; i++)
2182        WriteCompressedInt32 (low_bounds [i]);
2183    }
2184
2185    public void WriteGenericInstanceSignature (IGenericInstance instance)
2186    {
2187      var generic_arguments = instance.GenericArguments;
2188      var arity = generic_arguments.Count;
2189
2190      WriteCompressedUInt32 ((uint) arity);
2191      for (int i = 0; i < arity; i++)
2192        WriteTypeSignature (generic_arguments [i]);
2193    }
2194
2195    void WriteModifierSignature (ElementType element_type, IModifierType type)
2196    {
2197      WriteElementType (element_type);
2198      WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type.ModifierType));
2199      WriteTypeSignature (type.ElementType);
2200    }
2201
2202    bool TryWriteElementType (TypeReference type)
2203    {
2204      var element = type.etype;
2205
2206      if (element == ElementType.None)
2207        return false;
2208
2209      WriteElementType (element);
2210      return true;
2211    }
2212
2213    public void WriteConstantString (string value)
2214    {
2215      WriteBytes (Encoding.Unicode.GetBytes (value));
2216    }
2217
2218    public void WriteConstantPrimitive (object value)
2219    {
2220      WritePrimitiveValue (value);
2221    }
2222
2223    public void WriteCustomAttributeConstructorArguments (CustomAttribute attribute)
2224    {
2225      if (!attribute.HasConstructorArguments)
2226        return;
2227
2228      var arguments = attribute.ConstructorArguments;
2229      var parameters = attribute.Constructor.Parameters;
2230
2231      if (parameters.Count != arguments.Count)
2232        throw new InvalidOperationException ();
2233
2234      for (int i = 0; i < arguments.Count; i++)
2235        WriteCustomAttributeFixedArgument (parameters [i].ParameterType, arguments [i]);
2236    }
2237
2238    void WriteCustomAttributeFixedArgument (TypeReference type, CustomAttributeArgument argument)
2239    {
2240      if (type.IsArray) {
2241        WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
2242        return;
2243      }
2244
2245      WriteCustomAttributeElement (type, argument);
2246    }
2247
2248    void WriteCustomAttributeFixedArrayArgument (ArrayType type, CustomAttributeArgument argument)
2249    {
2250      var values = argument.Value as CustomAttributeArgument [];
2251
2252      if (values == null) {
2253        WriteUInt32 (0xffffffff);
2254        return;
2255      }
2256
2257      WriteInt32 (values.Length);
2258
2259      if (values.Length == 0)
2260        return;
2261
2262      var element_type = type.ElementType;
2263
2264      for (int i = 0; i < values.Length; i++)
2265        WriteCustomAttributeElement (element_type, values [i]);
2266    }
2267
2268    void WriteCustomAttributeElement (TypeReference type, CustomAttributeArgument argument)
2269    {
2270      if (type.IsArray) {
2271        WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
2272        return;
2273      }
2274
2275      if (type.etype == ElementType.Object) {
2276        argument = (CustomAttributeArgument) argument.Value;
2277        type = argument.Type;
2278
2279        WriteCustomAttributeFieldOrPropType (type);
2280        WriteCustomAttributeElement (type, argument);
2281        return;
2282      }
2283
2284      WriteCustomAttributeValue (type, argument.Value);
2285    }
2286
2287    void WriteCustomAttributeValue (TypeReference type, object value)
2288    {
2289      var etype = type.etype;
2290
2291      switch (etype) {
2292      case ElementType.String:
2293        var @string = (string) value;
2294        if (@string == null)
2295          WriteByte (0xff);
2296        else
2297          WriteUTF8String (@string);
2298        break;
2299      case ElementType.None:
2300        if (type.IsTypeOf ("System", "Type"))
2301          WriteTypeReference ((TypeReference) value);
2302        else
2303          WriteCustomAttributeEnumValue (type, value);
2304        break;
2305      default:
2306        WritePrimitiveValue (value);
2307        break;
2308      }
2309    }
2310
2311    void WritePrimitiveValue (object value)
2312    {
2313      if (value == null)
2314        throw new ArgumentNullException ();
2315
2316      switch (Type.GetTypeCode (value.GetType ())) {
2317      case TypeCode.Boolean:
2318        WriteByte ((byte) (((bool) value) ? 1 : 0));
2319        break;
2320      case TypeCode.Byte:
2321        WriteByte ((byte) value);
2322        break;
2323      case TypeCode.SByte:
2324        WriteSByte ((sbyte) value);
2325        break;
2326      case TypeCode.Int16:
2327        WriteInt16 ((short) value);
2328        break;
2329      case TypeCode.UInt16:
2330        WriteUInt16 ((ushort) value);
2331        break;
2332      case TypeCode.Char:
2333        WriteInt16 ((short) (char) value);
2334        break;
2335      case TypeCode.Int32:
2336        WriteInt32 ((int) value);
2337        break;
2338      case TypeCode.UInt32:
2339        WriteUInt32 ((uint) value);
2340        break;
2341      case TypeCode.Single:
2342        WriteSingle ((float) value);
2343        break;
2344      case TypeCode.Int64:
2345        WriteInt64 ((long) value);
2346        break;
2347      case TypeCode.UInt64:
2348        WriteUInt64 ((ulong) value);
2349        break;
2350      case TypeCode.Double:
2351        WriteDouble ((double) value);
2352        break;
2353      default:
2354        throw new NotSupportedException (value.GetType ().FullName);
2355      }
2356    }
2357
2358    void WriteCustomAttributeEnumValue (TypeReference enum_type, object value)
2359    {
2360      var type = enum_type.CheckedResolve ();
2361      if (!type.IsEnum)
2362        throw new ArgumentException ();
2363
2364      WriteCustomAttributeValue (type.GetEnumUnderlyingType (), value);
2365    }
2366
2367    void WriteCustomAttributeFieldOrPropType (TypeReference type)
2368    {
2369      if (type.IsArray) {
2370        var array = (ArrayType) type;
2371        WriteElementType (ElementType.SzArray);
2372        WriteCustomAttributeFieldOrPropType (array.ElementType);
2373        return;
2374      }
2375
2376      var etype = type.etype;
2377
2378      switch (etype) {
2379      case ElementType.Object:
2380        WriteElementType (ElementType.Boxed);
2381        return;
2382      case ElementType.None:
2383        if (type.IsTypeOf ("System", "Type"))
2384          WriteElementType (ElementType.Type);
2385        else {
2386          WriteElementType (ElementType.Enum);
2387          WriteTypeReference (type);
2388        }
2389        return;
2390      default:
2391        WriteElementType (etype);
2392        return;
2393      }
2394    }
2395
2396    public void WriteCustomAttributeNamedArguments (CustomAttribute attribute)
2397    {
2398      var count = GetNamedArgumentCount (attribute);
2399
2400      WriteUInt16 ((ushort) count);
2401
2402      if (count == 0)
2403        return;
2404
2405      WriteICustomAttributeNamedArguments (attribute);
2406    }
2407
2408    static int GetNamedArgumentCount (ICustomAttribute attribute)
2409    {
2410      int count = 0;
2411
2412      if (attribute.HasFields)
2413        count += attribute.Fields.Count;
2414
2415      if (attribute.HasProperties)
2416        count += attribute.Properties.Count;
2417
2418      return count;
2419    }
2420
2421    void WriteICustomAttributeNamedArguments (ICustomAttribute attribute)
2422    {
2423      if (attribute.HasFields)
2424        WriteCustomAttributeNamedArguments (0x53, attribute.Fields);
2425
2426      if (attribute.HasProperties)
2427        WriteCustomAttributeNamedArguments (0x54, attribute.Properties);
2428    }
2429
2430    void WriteCustomAttributeNamedArguments (byte kind, Collection<CustomAttributeNamedArgument> named_arguments)
2431    {
2432      for (int i = 0; i < named_arguments.Count; i++)
2433        WriteCustomAttributeNamedArgument (kind, named_arguments [i]);
2434    }
2435
2436    void WriteCustomAttributeNamedArgument (byte kind, CustomAttributeNamedArgument named_argument)
2437    {
2438      var argument = named_argument.Argument;
2439
2440      WriteByte (kind);
2441      WriteCustomAttributeFieldOrPropType (argument.Type);
2442      WriteUTF8String (named_argument.Name);
2443      WriteCustomAttributeFixedArgument (argument.Type, argument);
2444    }
2445
2446    void WriteSecurityAttribute (SecurityAttribute attribute)
2447    {
2448      WriteTypeReference (attribute.AttributeType);
2449
2450      var count = GetNamedArgumentCount (attribute);
2451
2452      if (count == 0) {
2453        WriteCompressedUInt32 (0); // length
2454        WriteCompressedUInt32 (0); // count
2455        return;
2456      }
2457
2458            var buffer = new SignatureWriter (metadata);
2459      buffer.WriteCompressedUInt32 ((uint) count);
2460      buffer.WriteICustomAttributeNamedArguments (attribute);
2461
2462      WriteCompressedUInt32 ((uint) buffer.length);
2463      WriteBytes (buffer);
2464    }
2465
2466    public void WriteSecurityDeclaration (SecurityDeclaration declaration)
2467    {
2468      WriteByte ((byte) '.');
2469
2470      var attributes = declaration.security_attributes;
2471      if (attributes == null)
2472        throw new NotSupportedException ();
2473
2474      WriteCompressedUInt32 ((uint) attributes.Count);
2475
2476      for (int i = 0; i < attributes.Count; i++)
2477        WriteSecurityAttribute (attributes [i]);
2478    }
2479
2480    public void WriteXmlSecurityDeclaration (SecurityDeclaration declaration)
2481    {
2482      var xml = GetXmlSecurityDeclaration (declaration);
2483      if (xml == null)
2484        throw new NotSupportedException ();
2485
2486      WriteBytes (Encoding.Unicode.GetBytes (xml));
2487    }
2488
2489    static string GetXmlSecurityDeclaration (SecurityDeclaration declaration)
2490    {
2491      if (declaration.security_attributes == null || declaration.security_attributes.Count != 1)
2492        return null;
2493
2494      var attribute = declaration.security_attributes [0];
2495
2496      if (!attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute"))
2497        return null;
2498
2499      if (attribute.properties == null || attribute.properties.Count != 1)
2500        return null;
2501
2502      var property = attribute.properties [0];
2503      if (property.Name != "XML")
2504        return null;
2505
2506      return (string) property.Argument.Value;
2507    }
2508
2509    void WriteTypeReference (TypeReference type)
2510    {
2511      WriteUTF8String (TypeParser.ToParseable (type));
2512    }
2513
2514    public void WriteMarshalInfo (MarshalInfo marshal_info)
2515    {
2516      WriteNativeType (marshal_info.native);
2517
2518      switch (marshal_info.native) {
2519      case NativeType.Array: {
2520        var array = (ArrayMarshalInfo) marshal_info;
2521        if (array.element_type != NativeType.None)
2522          WriteNativeType (array.element_type);
2523        if (array.size_parameter_index > -1)
2524          WriteCompressedUInt32 ((uint) array.size_parameter_index);
2525        if (array.size > -1)
2526          WriteCompressedUInt32 ((uint) array.size);
2527        if (array.size_parameter_multiplier > -1)
2528          WriteCompressedUInt32 ((uint) array.size_parameter_multiplier);
2529        return;
2530      }
2531      case NativeType.SafeArray: {
2532        var array = (SafeArrayMarshalInfo) marshal_info;
2533        if (array.element_type != VariantType.None)
2534          WriteVariantType (array.element_type);
2535        return;
2536      }
2537      case NativeType.FixedArray: {
2538        var array = (FixedArrayMarshalInfo) marshal_info;
2539        if (array.size > -1)
2540          WriteCompressedUInt32 ((uint) array.size);
2541        if (array.element_type != NativeType.None)
2542          WriteNativeType (array.element_type);
2543        return;
2544      }
2545      case NativeType.FixedSysString:
2546        var sys_string = (FixedSysStringMarshalInfo) marshal_info;
2547        if (sys_string.size > -1)
2548          WriteCompressedUInt32 ((uint) sys_string.size);
2549        return;
2550      case NativeType.CustomMarshaler:
2551        var marshaler = (CustomMarshalInfo) marshal_info;
2552        WriteUTF8String (marshaler.guid != Guid.Empty ? marshaler.guid.ToString () : string.Empty);
2553        WriteUTF8String (marshaler.unmanaged_type);
2554        WriteTypeReference (marshaler.managed_type);
2555        WriteUTF8String (marshaler.cookie);
2556        return;
2557      }
2558    }
2559
2560    void WriteNativeType (NativeType native)
2561    {
2562      WriteByte ((byte) native);
2563    }
2564
2565    void WriteVariantType (VariantType variant)
2566    {
2567      WriteByte ((byte) variant);
2568    }
2569  }
2570
2571#endif
2572
2573}
Note: See TracBrowser for help on using the repository browser.