[ilasm] Adds AggressiveInlining support
[mono.git] / mcs / class / PEAPI / Metadata.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5 using System.Reflection;
6
7 namespace PEAPI {
8
9         #region Enums
10
11         /// <summary>
12         /// flags for the assembly (.corflags)
13         /// </summary>
14         public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15                 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
16
17         /// <summary>
18         /// subsystem for the assembly (.subsystem)
19         /// </summary>
20         public enum SubSystem { Native = 1, Windows_GUI = 2, 
21                 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8, 
22                 Windows_CE_GUI = 9}
23
24         /// <summary>
25         /// Hash algorithms for the assembly
26         /// </summary>
27         public enum HashAlgorithm { None, SHA1 }
28
29         /// <summary>
30         /// Attributes for this assembly
31         /// </summary>
32         public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000, 
33                 DisableJITCompileOptimizer = 0x4000}
34
35         /// <summary>
36         /// Method call conventions
37         /// </summary>
38         [Flags]
39         public enum CallConv { Default, Cdecl, Stdcall, Thiscall, 
40                 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
41
42         /// <summary>
43         /// Type custom modifier
44         /// </summary>
45         public enum CustomModifier { modreq = 0x1F, modopt };
46
47         /// <summary>
48         /// Attibutes for a class
49         /// </summary>
50         [Flags]
51         public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, 
52                 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, 
53                 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, 
54                 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, 
55                 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, 
56                 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57                 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
58                 Forwarder = 0x200000,
59                 VisibilityMask = 0x07 }
60
61         /// <summary>
62         /// Attributes for a field
63         /// </summary>
64         public enum FieldAttr {Default, Private, FamAndAssem, Assembly, 
65                 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16, 
66                 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80, 
67                 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
68
69         /// <summary>
70         /// Attributes for a method
71         /// </summary>
72         public enum MethAttr { Default, Private, FamAndAssem, Assembly,
73                 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, 
74                 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, 
75                 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, 
76                 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
77                 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, 
78                 HasSecurity = 0x4000, RequireSecObject = 0x8000}
79
80         /// <summary>
81         /// Attributes for .pinvokeimpl method declarations
82         /// </summary>
83         public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
84                 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
85                 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
86                 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
87                 charmaperror_on = 0x1000, charmaperror_off = 0x2000
88         }
89
90         /// <summary>
91         /// Implementation attributes for a method
92         /// </summary>
93         public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
94                 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000, 
95                 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, NoOptimization = 0x0040, Optil = 0x0002,
96                 AggressiveInlining = 0x0100
97         }
98
99         /// <summary>
100         /// Storage location for initial field data
101         /// </summary>
102         public enum DataSegment { Data, TLS, CIL }
103
104         /// <summary>
105         /// Modes for a parameter
106         /// </summary>
107         public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
108
109         /// <summary>
110         /// CIL instructions
111         /// </summary>
112         public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
113                 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3, 
114                 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3, 
115                 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop, 
116                 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4, 
117                 ldind_u4, ldind_i8, ldind_i,  ldind_r4, ldind_r8, ldind_ref, stind_ref, 
118                 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
119                 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not, 
120                 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8, 
121                 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
122                 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un, 
123                 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un, 
124                 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2, 
125                 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8, 
126                 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
127                 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2, 
128                 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3, 
129                 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf, 
130                 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, 
131                 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, 
132                 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, 
133                 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
134
135         /// <summary>
136         /// CIL instructions requiring an integer parameter
137         /// </summary>
138         public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s, 
139                 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
140                 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
141
142         /// <summary>
143         /// CIL instructions requiring a field parameter
144         /// </summary>
145         public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
146                 stsfld, ldtoken = 0xD0 }
147
148         /// <summary>
149         /// CIL instructions requiring a method parameter
150         /// </summary>
151         public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73, 
152                 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
153
154         /// <summary>
155         /// CIL instructions requiring a type parameter
156         /// </summary>
157         public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, 
158                 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, 
159                 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, 
160                 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16, 
161                 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
162
163         /// <summary>
164         /// CIL branch instructions
165         /// </summary>
166         public enum BranchOp {
167                 // short branches
168                 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
169                 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
170                 // long branches
171                 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
172                 bne_un, bge_un, bgt_un, ble_un, blt_un,
173
174                 leave = 0xDD, leave_s }
175
176         /// <summary>
177         /// Index for all the tables in the meta data
178         /// </summary>
179         public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
180                 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute, 
181                 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig, 
182                 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics, 
183                 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20, 
184                 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor, 
185                 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
186                 GenericParam, MethodSpec, GenericParamConstraint  }
187
188         public enum SafeArrayType { int16 = 2, int32, float32, float64,
189                 currency, date, bstr, dispatch, error, boolean, variant, unknown,
190                 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
191
192         internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
193                 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, 
194                 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
195                 TypeOrMethodDef, MaxCIx }
196
197         internal enum MapType { eventMap, propertyMap, nestedClass }
198
199         public enum ValueClass { ValueType, Enum }
200
201         public enum GenParamType : byte { 
202                 Var = 0x13, MVar = 0x1E 
203         }
204
205         [Flags]
206         public enum GenericParamAttributes : ushort {
207                 VarianceMask  = 0x0003,
208                 NonVariant    = 0x0000,
209                 Covariant     = 0x0001,
210                 Contravariant = 0x0002,
211
212                 SpecialConstraintMask = 0x001c,
213                 ReferenceTypeConstraint = 0x0004,
214                 NotNullableValueTypeConstraint = 0x0008,
215                 DefaultConstructorConstrait = 0x0010
216         }
217
218         /* Taken from Mono.Cecil */
219         public enum SecurityAction : short {
220                 Request = 1,
221                 Demand = 2,
222                 Assert = 3,
223                 Deny = 4,
224                 PermitOnly = 5,
225                 LinkDemand = 6,
226                 InheritDemand = 7,
227                 RequestMinimum = 8,
228                 RequestOptional = 9,
229                 RequestRefuse = 10,
230                 PreJitGrant = 11,
231                 PreJitDeny = 12,
232                 NonCasDemand = 13,
233                 NonCasLinkDemand = 14,
234                 NonCasInheritance = 15,
235                 LinkDemandChoice = 16,
236                 InheritDemandChoice = 17,
237                 DemandChoice = 18
238         }
239
240         #endregion
241
242         /**************************************************************************/  
243         /// <summary>
244         /// Base class for all Meta Data table elements
245         /// </summary>
246
247         public abstract class MetaDataElement: IComparable {
248                 protected ArrayList customAttributes;
249                 private uint row = 0;
250                 protected bool done = false;
251                 protected MDTable tabIx;
252                 protected bool sortTable = false;
253                 //Temporary hack.. 
254                 private bool has_custom_attrs = false;
255
256                 internal MetaDataElement() { }
257
258                 public uint Row {
259                         get {
260                                 return row;
261                         }
262                         set {
263                                 row = value;
264                         }
265                 }
266
267                 public bool HasCustomAttr {
268                         get { return has_custom_attrs; }
269                         set { has_custom_attrs = value; }
270                 }
271
272                 internal virtual uint GetCodedIx(CIx code) { return 0; }
273
274                 /// <summary>
275                 /// Add a custom attribute to this item
276                 /// </summary>
277                 /// <param name="ctorMeth">the constructor method for this attribute</param>
278                 /// <param name="val">the byte value of the parameters</param>
279                 public void AddCustomAttribute(Method ctorMeth, byte[] val) 
280                 {
281                         if (customAttributes == null) {
282                                 customAttributes = new ArrayList();
283                         } 
284                         customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
285                 }
286
287                 /// <summary>
288                 /// Add a custom attribute to this item
289                 /// </summary>
290                 /// <param name="ctorMeth">the constructor method for this attribute</param>
291                 /// <param name="val">the constant values of the parameters</param>
292                 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) 
293                 {
294                         if (customAttributes == null) {
295                                 customAttributes = new ArrayList();
296                         } 
297                         //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
298                 }
299
300                 internal uint Token() 
301                 {
302                         return (((uint)tabIx << 24) | row);
303                 }
304
305                 internal virtual void BuildTables(MetaData md) 
306                 {
307                         done = true;
308                 }
309
310                 internal virtual uint Size(MetaData md) 
311                 {
312                         return 0;
313                 }
314
315                 internal virtual void Write(FileImage output) {   }
316
317                 internal virtual uint SortKey() 
318                 { 
319                         throw new PEFileException("Trying to sort table of " + this);
320                         //return 0; 
321                 }
322
323                 internal virtual uint SortKey2()
324                 {
325                         return 0;
326                 }
327
328                 public int CompareTo(object obj) 
329                 {
330                         uint otherKey = ((MetaDataElement)obj).SortKey();
331                         uint thisKey = SortKey();
332
333                         if (thisKey == otherKey)  {
334
335                                 otherKey = ((MetaDataElement)obj).SortKey2();
336                                 thisKey = SortKey2();
337                                 if (thisKey == otherKey)
338                                         return 0;
339                                 if (thisKey < otherKey)
340                                         return -1;
341                                 return 1;
342                         }
343                         if (thisKey < otherKey) return -1;
344
345                         return 1;
346                 }
347
348         }
349
350         /**************************************************************************/  
351         /// <summary>
352         /// Layout information for a class (.class [sequential | explicit])
353         /// </summary>
354         internal class ClassLayout : MetaDataElement {
355
356                 ClassDef parent;
357                 ushort packSize = 0;
358                 uint classSize = 0;
359
360                 internal ClassLayout(int pack, int cSize, ClassDef par) 
361                 {
362                         packSize = (ushort)pack;
363                         classSize = (uint)cSize;
364                         parent = par;
365                         tabIx = MDTable.ClassLayout;
366                 }
367
368                 internal sealed override uint Size(MetaData md) 
369                 {
370                         return 6 + md.TableIndexSize(MDTable.TypeDef);
371                 }
372
373                 internal sealed override void Write(FileImage output) 
374                 {
375                         output.Write(packSize);
376                         output.Write(classSize);
377                         output.WriteIndex(MDTable.TypeDef,parent.Row);
378                 }
379
380         }
381
382         /**************************************************************************/  
383         /// <summary>
384         /// Summary description for ConstantElem.
385         /// </summary>
386         internal class ConstantElem : MetaDataElement {
387
388                 MetaDataElement parent;
389                 Constant cValue;
390                 uint valIx = 0;
391
392                 internal ConstantElem(MetaDataElement parent, Constant val) 
393                 {
394                         this.parent = parent;
395                         cValue = val;
396                         tabIx = MDTable.Constant;
397                         sortTable = true;
398                 }
399
400                 internal override uint SortKey() 
401                 {  
402                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst]) 
403                                 | parent.GetCodedIx(CIx.HasConst);
404                 }
405
406                 internal sealed override void BuildTables(MetaData md) 
407                 {
408                         if (done) return;
409                         valIx = cValue.GetBlobIndex(md);
410                         done = true;
411                 }
412
413                 internal void AddToBlob(BinaryWriter bw) 
414                 {
415                         cValue.Write(bw);
416                 }
417
418                 internal sealed override uint Size(MetaData md) 
419                 {
420                         return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
421                 }
422
423                 internal sealed override void Write(FileImage output) 
424                 {
425                         output.Write(cValue.GetTypeIndex());
426                         output.Write((byte)0);
427                         output.WriteCodedIndex(CIx.HasConst,parent);
428                         output.BlobIndex(valIx);
429                 }
430
431         }
432         /**************************************************************************/  
433         /// <summary>
434         /// Descriptor for a Custom Attribute (.custom) 
435         /// </summary>
436
437         public class CustomAttribute : MetaDataElement {
438
439                 MetaDataElement parent;
440                 Method type;
441                 uint valIx;
442                 Constant cVal;
443                 byte[] byteVal;
444                 ushort numNamed = 0;
445                 ArrayList names, vals;
446
447                 internal CustomAttribute(MetaDataElement paren, Method constrType, 
448                                 Constant val) {
449                         parent = paren;
450                         type = constrType;
451                         cVal = val;
452                         tabIx = MDTable.CustomAttribute;
453
454                         byteVal = ConstantToByteArray (val);
455                 }
456
457                 static byte[] ConstantToByteArray (Constant c)
458                 {
459                         var bac = c as ByteArrConst;
460                         if (bac != null)
461                                 return bac.val;
462
463                         var ms = new MemoryStream ();
464                         // Version info
465                         ms.WriteByte (1);
466                         ms.WriteByte (0);
467
468                         if (c == null) {
469                                 ms.WriteByte (0);
470                                 ms.WriteByte (0);
471                                 return ms.ToArray ();
472                         }
473
474                         var sc = c as StringConst;
475                         if (sc != null) {
476                                 string value = sc.val;
477                                 if (value == null)
478                                         throw new NotImplementedException ();
479
480                                 var buf = Encoding.UTF8.GetBytes (value);
481                                 MetaData.CompressNum ((uint) buf.Length, ms);
482                                 var byteVal = ms.ToArray ();
483                                 System.Array.Resize (ref byteVal, (int) ms.Length + buf.Length + 2);
484                                 System.Array.Copy (buf, 0, byteVal, ms.Length, buf.Length);
485                                 return byteVal;
486                         }
487
488                         var ac = c as ArrayConstant;
489                         if (ac != null) {
490                                 var bw = new BinaryWriter (ms);
491                                 if (ac.ExplicitSize != null)
492                                         bw.Write (ac.ExplicitSize.Value);
493                                 ac.Write (bw);
494                                 bw.Write ((short)0);
495                                 return ms.ToArray ();
496                         }
497
498                         var bc = c as DataConstant;
499                         if (bc != null) {
500                                 var bw = new BinaryWriter (ms);
501                                 bc.Write (bw);
502                                 bw.Write ((short)0);
503                                 return ms.ToArray ();
504                         }
505
506                         throw new NotImplementedException (c.GetType ().ToString ());
507                 }
508
509                 internal CustomAttribute(MetaDataElement paren, Method constrType,
510                                 byte[] val) {
511                         parent = paren;
512                         type = constrType;
513                         tabIx = MDTable.CustomAttribute;
514                         byteVal = val;
515                 }
516
517                 internal override uint SortKey() 
518                 {
519                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
520                                 | parent.GetCodedIx(CIx.HasCustomAttr);
521                 }
522
523                 public void AddFieldOrProp(string name, Constant val) 
524                 {
525                         if (numNamed == 0) {
526                                 names = new ArrayList();
527                                 vals = new ArrayList();
528                         }
529                         names.Add(name);
530                         vals.Add(val);
531                 }
532
533                 internal sealed override void BuildTables(MetaData md) 
534                 {
535                         md.AddToTable(MDTable.CustomAttribute, this);
536                         if (byteVal == null) {
537                                 valIx = 0;
538                                 return;
539                         }
540
541                         BinaryWriter bw = new BinaryWriter(new MemoryStream());
542                         bw.Write(byteVal);
543                         MemoryStream str = (MemoryStream)bw.BaseStream;
544                         valIx = md.AddToBlobHeap(str.ToArray());
545                 }
546
547                 internal sealed override uint Size(MetaData md) 
548                 {
549                         return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
550                 }
551
552                 internal sealed override void Write(FileImage output) 
553                 {
554                         output.WriteCodedIndex(CIx.HasCustomAttr,parent);
555                         output.WriteCodedIndex(CIx.CustomAttributeType,type);
556                         output.BlobIndex(valIx);
557                 }
558
559         }
560
561         /**************************************************************************/  
562         /// <summary>
563         /// Descriptor for security permissions for a class or a method
564         /// </summary>
565
566         public abstract class BaseDeclSecurity : MetaDataElement {
567
568                 ushort action;
569                 MetaDataElement parent;
570                 uint permissionIx;
571
572                 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
573                 {
574                         parent = paren;
575                         action = act;
576                         tabIx = MDTable.DeclSecurity;
577                 }
578
579                 internal override uint SortKey() 
580                 {
581                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
582                                 | parent.GetCodedIx(CIx.HasDeclSecurity);
583                 }
584
585                 internal sealed override uint Size(MetaData md) 
586                 {
587                         return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
588                 }
589
590                 internal sealed override void BuildTables(MetaData md) 
591                 {
592                         if (done) return;
593
594                         BinaryWriter bw = new BinaryWriter (new MemoryStream ());
595                         md.AddToTable (MDTable.DeclSecurity, this);
596                         MemoryStream str = (MemoryStream)bw.BaseStream;
597                         WriteSig (bw);
598                         permissionIx = md.AddToBlobHeap(str.ToArray());
599
600                         done = true;
601                 }
602
603                 internal abstract void WriteSig (BinaryWriter bw);
604
605                 internal sealed override void Write(FileImage output) 
606                 {
607                         output.Write(action);
608                         output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
609                         output.BlobIndex(permissionIx);
610                 }
611
612         }
613
614         public class DeclSecurity : BaseDeclSecurity {
615
616                 byte [] byteVal;
617
618                 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)        
619                         : base (paren, act)
620                 {
621                         byteVal = val;
622                 }
623
624                 internal override void WriteSig (BinaryWriter bw)
625                 {
626                         bw.Write (byteVal);
627                 }
628
629         }
630
631         public class DeclSecurity_20 : BaseDeclSecurity {
632
633                 PermissionSet ps;
634
635                 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
636                         : base (paren, act)
637                 {
638                         this.ps = ps;
639                 }
640
641                 internal override void WriteSig (BinaryWriter bw)
642                 {
643                         ps.Write (bw);
644                 }
645         }
646
647         public class PermissionMember {
648
649                 MemberTypes member_type;
650                 PEAPI.Type type;
651                 string name;
652                 object value;
653
654                 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
655                 {
656                         this.member_type = member_type;
657                         this.type = type;
658                         this.name = name;
659                         this.value = value;
660                 }
661
662                 public void Write (BinaryWriter bw)
663                 {
664                         byte [] b;
665
666                         if (member_type == MemberTypes.Field)
667                                 bw.Write ((byte) 0x53);
668                         else
669                                 //Property
670                                 bw.Write ((byte) 0x54);
671
672                         if (type is PrimitiveType) {
673                                 bw.Write (type.GetTypeIndex ());
674                         } else {
675                                 //must be enum
676                                 bw.Write ((byte) 0x55); //ENUM
677
678                                 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
679                                 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
680                                 bw.Write (b);
681                         }
682                         
683                         b = Encoding.UTF8.GetBytes (name);
684                         MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
685                         bw.Write (b);
686
687                         ((Constant) value).Write (bw);
688                 }
689
690         }
691
692         public class Permission
693         {
694                 PEAPI.Type type;
695
696                 //PermissionMembers
697                 ArrayList members;
698                 string name;
699
700                 public Permission (PEAPI.Type type, string name)
701                 {
702                         this.type = type;
703                         this.name = name;
704                 }
705
706                 public void AddMember (PEAPI.PermissionMember member)
707                 {
708                         if (members == null)
709                                 members = new ArrayList ();
710
711                         members.Add (member);
712                 }
713
714                 public void Write (BinaryWriter bw)
715                 {
716                         byte [] b = Encoding.UTF8.GetBytes (name);
717                         MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
718                         bw.Write (b);
719
720                         BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
721                         MemoryStream str = (MemoryStream) perm_writer.BaseStream;
722
723                         MetaData.CompressNum ((uint) members.Count, str);//number of params
724                         foreach (PermissionMember member in members)
725                                 member.Write (perm_writer);
726
727                         bw.Write ((byte) str.Length); //(optional) parameters length
728                         bw.Write (str.ToArray ());
729                 }
730         }
731
732         public class PermissionSet 
733         {
734                 PEAPI.SecurityAction sec_action;
735                 ArrayList permissions;
736
737                 public PermissionSet (PEAPI.SecurityAction sec_action)
738                 {
739                         this.sec_action = sec_action;
740                 }
741
742                 public void AddPermission (PEAPI.Permission perm)
743                 {
744                         if (permissions == null)
745                                 permissions = new ArrayList ();
746
747                         permissions.Add (perm);
748                 }
749
750                 public void Write (BinaryWriter bw)
751                 {
752                         bw.Write ((byte) 0x2e);
753                         MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
754
755                         foreach (Permission perm in permissions)
756                                 perm.Write (bw);
757                 }
758
759         }
760
761         /**************************************************************************/  
762         /// <summary>
763         /// Descriptor for layout information for a field
764         /// </summary>
765
766         public class FieldLayout : MetaDataElement {
767
768                 Field field;
769                 uint offset;
770
771                 internal FieldLayout(Field field, uint offset)      
772                 {
773                         this.field = field;
774                         this.offset = offset;
775                         tabIx = MDTable.FieldLayout;
776                 }
777
778                 internal sealed override uint Size(MetaData md) 
779                 {
780                         return 4 + md.TableIndexSize(MDTable.Field);
781                 }
782
783                 internal sealed override void Write(FileImage output) 
784                 {
785                         output.Write(offset);
786                         output.WriteIndex(MDTable.Field,field.Row);
787                 }
788
789         }
790
791         /*****************************************************************************/  
792         /// <summary>
793         /// Marshalling information for a field or param
794         /// </summary>
795         public class FieldMarshal : MetaDataElement {
796
797                 MetaDataElement field;
798                 NativeType nt;
799                 uint ntIx;
800
801                 internal FieldMarshal(MetaDataElement field, NativeType nType)      
802                 {
803                         this.field = field;
804                         this.nt = nType;
805                         tabIx = MDTable.FieldMarshal;
806                 }
807
808                 internal override uint SortKey() 
809                 {
810                         return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
811                                 | field.GetCodedIx(CIx.HasFieldMarshal);
812                 }
813
814                 internal sealed override void BuildTables(MetaData md) 
815                 {
816                         if (done) return;
817                         ntIx = md.AddToBlobHeap(nt.ToBlob());
818                         done = true;
819                 }
820
821                 internal sealed override uint Size(MetaData md) 
822                 {
823                         return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
824                 }
825
826                 internal sealed override void Write(FileImage output) 
827                 {
828                         output.WriteCodedIndex(CIx.HasFieldMarshal,field);
829                         output.BlobIndex(ntIx);
830                 }
831
832         }
833
834         /**************************************************************************/  
835         /// <summary>
836         /// Descriptor for the address of a field's value in the PE file
837         /// </summary>
838         public class FieldRVA : MetaDataElement {
839
840                 Field field;
841                 DataConstant data;
842
843                 internal FieldRVA(Field field, DataConstant data)   
844                 {
845                         this.field = field;
846                         this.data = data;
847                         tabIx = MDTable.FieldRVA;
848                 }
849
850                 internal sealed override void BuildTables(MetaData md) 
851                 {
852                         if (done) return;
853                         md.AddData(data);
854                         done = true;
855                 }
856
857                 internal sealed override uint Size(MetaData md) 
858                 {
859                         return 4 + md.TableIndexSize(MDTable.Field);
860                 }
861
862                 internal sealed override void Write(FileImage output) 
863                 {
864                         output.WriteDataRVA(data.DataOffset);
865                         output.WriteIndex(MDTable.Field,field.Row);
866                 }
867
868         }
869
870         /**************************************************************************/  
871         /// <summary>
872         /// Descriptor for a file referenced in THIS assembly/module (.file)
873         /// </summary>
874         public class FileRef : MetaDataElement {
875
876                 private static readonly uint NoMetaData = 0x1;
877                 uint nameIx = 0, hashIx = 0;
878                 uint flags = 0;
879                 protected string name;
880
881                 internal FileRef(string name, byte[] hashBytes, bool metaData,
882                                 bool entryPoint, MetaData md) {
883                         if (!metaData) flags = NoMetaData;
884                         if (entryPoint) md.SetEntryPoint(this);
885                         this.name = name;
886                         nameIx = md.AddToStringsHeap(name);
887                         hashIx = md.AddToBlobHeap(hashBytes);
888                         tabIx = MDTable.File;
889                 }
890
891                 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
892                                 bool entryPoint, MetaData md) {
893                         if (!metaData) flags = NoMetaData;
894                         if (entryPoint) md.SetEntryPoint(this);
895                         this.nameIx = nameIx;
896                         hashIx = md.AddToBlobHeap(hashBytes);
897                         tabIx = MDTable.File;
898                 }
899
900                 internal sealed override uint Size(MetaData md) 
901                 {
902                         return 4 + md.StringsIndexSize() + md.BlobIndexSize();
903                 }
904
905                 internal sealed override void BuildTables(MetaData md) 
906                 {
907                         md.AddToTable(MDTable.File,this);
908                 }
909
910                 internal sealed override void Write(FileImage output) 
911                 {
912                         output.Write(flags);
913                         output.StringsIndex(nameIx);
914                         output.BlobIndex(hashIx);
915                 }
916
917                 internal sealed override uint GetCodedIx(CIx code) 
918                 {
919                         switch (code) {
920                                 case (CIx.HasCustomAttr) : return 16; 
921                                 case (CIx.Implementation) : return 0;
922                         }
923                         return 0;
924                 }
925
926         }
927         /**************************************************************************/  
928         /// <summary>
929         /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
930         /// </summary>
931         public class ImplMap : MetaDataElement {
932
933                 private static readonly ushort NoMangle = 0x01;
934                 ushort flags;
935                 Method meth;
936                 string importName;
937                 uint iNameIx;
938                 ModuleRef importScope;
939
940                 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) 
941                 {
942                         flags = flag;
943                         meth = implMeth;
944                         importName = iName;
945                         importScope = mScope;
946                         tabIx = MDTable.ImplMap;
947                         if (iName == null) flags |= NoMangle;
948                         //throw(new NotYetImplementedException("PInvoke "));
949                 }
950
951                 internal override uint SortKey() 
952                 {
953                         return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded]) 
954                                 | meth.GetCodedIx(CIx.MemberForwarded);
955                 }
956
957                 internal sealed override void BuildTables(MetaData md) 
958                 {
959                         if (done) return;
960                         iNameIx = md.AddToStringsHeap(importName);
961                         done = true;
962                 }
963
964                 internal sealed override uint Size(MetaData md) 
965                 {
966                         return 2+ md.CodedIndexSize(CIx.MemberForwarded) + 
967                                 md.StringsIndexSize() +  md.TableIndexSize(MDTable.ModuleRef);
968                 }
969
970                 internal sealed override void Write(FileImage output) 
971                 {
972                         output.Write(flags);
973                         output.WriteCodedIndex(CIx.MemberForwarded,meth);
974                         output.StringsIndex(iNameIx);
975                         output.WriteIndex(MDTable.ModuleRef,importScope.Row);
976                 }
977
978         }
979
980         /**************************************************************************/  
981
982         public class GenericParameter : MetaDataElement {
983
984                 MetaDataElement owner;
985                 MetaData metadata;
986                 public string name;
987                 uint nameIx;
988                 short index;
989                 GenericParamAttributes attr;
990
991                 internal GenericParameter (ClassDef owner, MetaData metadata,
992                                 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
993                 {
994                 }
995
996                 internal GenericParameter (MethodDef owner, MetaData metadata,
997                                 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
998                 {
999                 }
1000
1001                 private GenericParameter (MetaDataElement owner, MetaData metadata,
1002                                 short index, string name, GenericParamAttributes attr, bool nadda) {
1003                         this.owner = owner;
1004                         this.metadata = metadata;
1005                         this.index = index;
1006                         tabIx = MDTable.GenericParam;
1007                         this.name = name;
1008                         this.attr = attr;
1009                 }
1010
1011                 internal override uint SortKey() 
1012                 {
1013                         return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
1014                                 | owner.GetCodedIx(CIx.TypeOrMethodDef);
1015                 }
1016
1017                 internal override uint SortKey2 ()
1018                 {
1019                         return (uint) index;
1020                 }
1021
1022                 public void AddConstraint  (Type constraint) 
1023                 {
1024                         metadata.AddToTable (MDTable.GenericParamConstraint,
1025                                         new GenericParamConstraint (this, constraint));
1026                 }
1027
1028                 internal sealed override uint Size(MetaData md) 
1029                 {
1030                         return (uint) (4 +
1031                                         md.CodedIndexSize(CIx.TypeOrMethodDef) + 
1032                                         md.StringsIndexSize ());
1033                 }
1034
1035                 internal sealed override void BuildTables(MetaData md) 
1036                 {
1037                         if (done) return;
1038                         nameIx = md.AddToStringsHeap(name);
1039                         done = true;
1040                 }
1041
1042                 internal sealed override void Write(FileImage output) 
1043                 {
1044                         output.Write ((short) index);
1045                         output.Write ((short) attr);
1046                         output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
1047                         output.StringsIndex (nameIx);
1048                 }
1049
1050                 internal sealed override uint GetCodedIx(CIx code) 
1051                 {
1052                         switch (code) {
1053                                 case (CIx.HasCustomAttr) : return 19; 
1054                         }
1055                         return 0;
1056                 }
1057
1058         }
1059
1060         internal class GenericParamConstraint : MetaDataElement {
1061
1062                 GenericParameter param;
1063                 Type type;
1064
1065                 public GenericParamConstraint (GenericParameter param, Type type) 
1066                 {
1067                         this.param = param;
1068                         this.type = type;
1069                         tabIx = MDTable.GenericParamConstraint;
1070                 }
1071
1072                 internal override uint SortKey() 
1073                 {
1074                         return param.Row;
1075                 }
1076
1077                 internal sealed override uint Size(MetaData md) 
1078                 {
1079                         return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1080                                         md.CodedIndexSize(CIx.TypeDefOrRef));
1081                 }
1082
1083                 internal sealed override void Write(FileImage output) 
1084                 {
1085                         output.WriteIndex(MDTable.GenericParam, param.Row);
1086                         output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1087                 }
1088
1089         }
1090
1091         internal class MethodSpec : Method {
1092
1093                 Method meth;
1094                 GenericMethodSig g_sig;
1095                 uint sidx;
1096
1097                 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1098                 {
1099                         this.meth = meth;
1100                         this.g_sig = g_sig;
1101                         tabIx = MDTable.MethodSpec;
1102                 }
1103
1104                 internal override uint GetSigIx (MetaData md)
1105                 {
1106                         throw new Exception ("Should not be used.");
1107                 }
1108
1109                 public override void AddCallConv (CallConv cconv)
1110                 {
1111                         throw new Exception ("Should not be used.");
1112                 }
1113                 
1114                 internal sealed override void BuildTables (MetaData md) 
1115                 {
1116                         if (done) return;
1117                         sidx = g_sig.GetSigIx (md);
1118                         done = true;
1119                 }
1120
1121                 internal sealed override uint Size (MetaData md) 
1122                 {
1123                         return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1124                                         md.BlobIndexSize ());
1125                 }
1126
1127                 internal sealed override void Write (FileImage output) 
1128                 {
1129                         output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1130                         output.BlobIndex (sidx);
1131                 }
1132
1133                 internal sealed override void TypeSig (MemoryStream sig)
1134                 {
1135                         throw new Exception ("Should not be used.");
1136                 }
1137         }
1138
1139         /**************************************************************************/
1140         /// <summary>
1141         /// Descriptor for interface implemented by a class
1142         /// </summary>
1143         public class InterfaceImpl: MetaDataElement {
1144
1145                 ClassDef theClass;
1146                 Class theInterface;
1147
1148                 internal InterfaceImpl(ClassDef theClass, Class theInterface) 
1149                 {
1150                         this.theClass = theClass;
1151                         this.theInterface = theInterface;
1152                         tabIx = MDTable.InterfaceImpl;
1153                 }
1154
1155                 internal sealed override uint Size(MetaData md) 
1156                 {
1157                         return md.TableIndexSize(MDTable.TypeDef) + 
1158                                 md.CodedIndexSize(CIx.TypeDefOrRef);
1159                 }
1160
1161                 internal sealed override void Write(FileImage output) 
1162                 {
1163                         output.WriteIndex(MDTable.TypeDef,theClass.Row);
1164                         output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1165                 }
1166
1167                 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1168
1169                 internal override uint SortKey ()
1170                 {
1171                         return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1172                                 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1173                 }
1174
1175         }
1176
1177         /**************************************************************************/  
1178         /// <summary>
1179         /// Descriptor for resources used in this PE file 
1180         /// </summary>
1181
1182         public class ManifestResource : MetaDataElement {
1183
1184                 public static readonly uint PublicResource = 0x1;
1185                 public static readonly uint PrivateResource = 0x2;
1186
1187                 string mrName;
1188                 MetaDataElement rRef;
1189                 uint fileOffset;
1190                 uint nameIx = 0;
1191                 uint flags = 0;
1192                 byte [] resourceBytes;
1193
1194                 public ManifestResource (string name, byte[] resBytes, uint flags) 
1195                 {
1196                         InitResource (name, flags);
1197                         this.resourceBytes = resBytes;
1198                 }
1199
1200                 public ManifestResource(string name, uint flags, FileRef fileRef) 
1201                 {
1202                         InitResource (name, flags);
1203                         rRef = fileRef;
1204                 }
1205
1206                 public ManifestResource(string name, uint flags, FileRef fileRef, 
1207                                 uint fileIx) {
1208                         InitResource (name, flags);
1209                         rRef = fileRef;
1210                         fileOffset = fileIx;
1211                 }
1212
1213                 public ManifestResource(string name, uint flags, AssemblyRef assemRef) 
1214                 {
1215                         InitResource (name, flags);
1216                         rRef = assemRef;
1217                 }
1218
1219                 internal ManifestResource (ManifestResource mres) 
1220                 {
1221                         mrName = mres.mrName;
1222                         flags = mres.flags;
1223                         rRef = mres.rRef;
1224                         fileOffset = mres.fileOffset;
1225                         resourceBytes = mres.resourceBytes;
1226                 }
1227
1228                 private void InitResource (string name, uint flags) 
1229                 {
1230                         mrName = name;
1231                         this.flags = flags;
1232                         tabIx = MDTable.ManifestResource;
1233                 }
1234
1235                 internal sealed override void BuildTables(MetaData md) 
1236                 {
1237                         if (done) return;
1238                         md.AddToTable (MDTable.ManifestResource, this);
1239                         nameIx = md.AddToStringsHeap(mrName);
1240                         if (resourceBytes != null) {
1241                                 if (rRef != null)
1242                                         throw new PEFileException ("Manifest Resource has byte value and file reference");
1243                                 fileOffset = md.AddResource(resourceBytes);
1244                         } else {
1245                                 if (rRef == null)
1246                                         throw new PEFileException ("Manifest Resource has no implementation or value");
1247                                 rRef.BuildTables (md);
1248                         }
1249
1250                         done = true;
1251                 }
1252
1253                 internal sealed override uint Size(MetaData md) 
1254                 {
1255                         return 8 + md.StringsIndexSize() + 
1256                                 md.CodedIndexSize(CIx.Implementation);
1257                 }
1258
1259                 internal sealed override void Write(FileImage output) 
1260                 {
1261                         output.Write(fileOffset);
1262                         output.Write(flags);
1263                         output.StringsIndex(nameIx);
1264                         output.WriteCodedIndex(CIx.Implementation,rRef);
1265                 }
1266
1267                 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1268
1269                 public string Name {
1270                         get { return mrName; }
1271                         set { mrName = value; }
1272                 }
1273
1274         }
1275         /**************************************************************************/  
1276         /// <summary>
1277         /// Base class for elements in the PropertyMap, EventMap and 
1278         /// NestedClass MetaData tables
1279         /// </summary>
1280         public class MapElem : MetaDataElement {
1281
1282                 ClassDef parent;
1283                 uint elemIx;
1284                 MDTable elemTable;
1285
1286                 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) 
1287                 {
1288                         parent = par;
1289                         elemIx = elIx;
1290                         elemTable = elemTab;
1291                 }
1292
1293                 internal sealed override uint Size(MetaData md) 
1294                 {
1295                         return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1296                 }
1297
1298                 internal sealed override void Write(FileImage output) 
1299                 {
1300                         output.WriteIndex(MDTable.TypeDef,parent.Row);
1301                         output.WriteIndex(elemTable,elemIx);
1302                 }
1303         }
1304
1305         /**************************************************************************/  
1306         /// <summary>
1307         /// Descriptor for an overriding method (.override)
1308         /// </summary>
1309         public class MethodImpl : MetaDataElement {
1310
1311                 ClassDef parent;
1312                 Method header, body;
1313
1314                 internal MethodImpl(ClassDef par, Method decl, Method bod)      
1315                 {
1316                         parent = par;
1317                         header = decl;
1318                         body = bod;
1319                         tabIx = MDTable.MethodImpl;
1320                 }
1321
1322                 internal sealed override uint Size(MetaData md) 
1323                 {
1324                         return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1325                 }
1326
1327                 internal sealed override void Write(FileImage output) 
1328                 {
1329                         output.WriteIndex(MDTable.TypeDef,parent.Row);
1330                         output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1331                         output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1332                 }
1333
1334         }
1335
1336         /**************************************************************************/  
1337         /// <summary>
1338         /// Descriptor for Property and Event methods
1339         /// </summary>
1340         public class MethodSemantics : MetaDataElement {
1341
1342                 Feature.MethodType type;
1343                 MethodDef meth;
1344                 Feature eventOrProp;
1345
1346                 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) 
1347                 {
1348                         type = mType;
1349                         meth = method;
1350                         eventOrProp = feature;
1351                         tabIx = MDTable.MethodSemantics;
1352                 }
1353
1354                 internal override uint SortKey() 
1355                 {
1356                         return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1357                                 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1358                 }
1359
1360                 internal sealed override uint Size(MetaData md) 
1361                 {
1362                         return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1363                 }
1364
1365                 internal sealed override void Write(FileImage output) 
1366                 {
1367                         output.Write((ushort)type);
1368                         output.WriteIndex(MDTable.Method,meth.Row);
1369                         output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1370                 }
1371
1372         }
1373
1374         /**************************************************************************/  
1375         /// <summary>
1376         /// Descriptor for a parameter of a method defined in this assembly/module
1377         /// </summary>
1378         public class Param : MetaDataElement {
1379
1380
1381                 Type pType;
1382                 string pName;
1383                 internal ushort seqNo = 0;
1384                 ushort parMode;
1385                 ConstantElem defaultVal;
1386                 uint nameIx = 0;
1387                 FieldMarshal marshalInfo;
1388
1389                 /// <summary>
1390                 /// Create a new parameter for a method
1391                 /// </summary>
1392                 /// <param name="mode">param mode (in, out, opt)</param>
1393                 /// <param name="parName">parameter name</param>
1394                 /// <param name="parType">parameter type</param>
1395                 public Param(ParamAttr mode, string parName, Type parType) 
1396                 {
1397                         pName = parName;
1398                         pType = parType;
1399                         parMode = (ushort)mode;
1400                         tabIx = MDTable.Param;
1401                 }
1402
1403                 public bool HasMarshalInfo {
1404                         get { return marshalInfo != null; }
1405                 }
1406
1407                 /// <summary>
1408                 /// Add a default value to this parameter
1409                 /// </summary>
1410                 /// <param name="c">the default value for the parameter</param>
1411                 public void AddDefaultValue(Constant cVal) 
1412                 {
1413                         defaultVal = new ConstantElem(this,cVal);
1414                         parMode |= (ushort) ParamAttr.HasDefault;
1415                 }
1416
1417                 /// <summary>
1418                 /// Add marshalling information about this parameter
1419                 /// </summary>
1420                 public void AddMarshallInfo(NativeType marshallType) 
1421                 {
1422                         parMode |= (ushort) ParamAttr.HasFieldMarshal;
1423                         marshalInfo = new FieldMarshal(this,marshallType);
1424                 }
1425
1426                 internal Type GetParType() { return pType; }
1427
1428                 internal sealed override void BuildTables(MetaData md) 
1429                 {
1430                         if (done) return;
1431                         nameIx = md.AddToStringsHeap(pName);
1432                         if (defaultVal != null) {
1433                                 md.AddToTable(MDTable.Constant,defaultVal);
1434                                 defaultVal.BuildTables(md);
1435                         }
1436                         if (marshalInfo != null) {
1437                                 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1438                                 marshalInfo.BuildTables(md);
1439                         }
1440                         done = true;
1441                 }
1442
1443                 internal void TypeSig(MemoryStream str) 
1444                 {
1445                         pType.TypeSig(str);
1446                 }
1447
1448                 internal sealed override uint Size(MetaData md) 
1449                 {
1450                         return 4 + md.StringsIndexSize();
1451                 }
1452
1453                 internal sealed override void Write(FileImage output) 
1454                 {
1455                         output.Write(parMode);
1456                         output.Write(seqNo);
1457                         output.StringsIndex(nameIx);
1458                 }
1459
1460                 internal sealed override uint GetCodedIx(CIx code) 
1461                 {
1462                         switch (code) {
1463                                 case (CIx.HasCustomAttr) : return 4; 
1464                                 case (CIx.HasConst) : return 1; 
1465                                 case (CIx.HasFieldMarshal) : return 1; 
1466                         }
1467                         return 0;
1468                 }
1469
1470         }
1471
1472         /**************************************************************************/  
1473         public abstract class Signature : MetaDataElement  {
1474
1475                 protected uint sigIx;
1476
1477                 internal Signature() 
1478                 {
1479                         tabIx = MDTable.StandAloneSig;
1480                 }
1481
1482                 internal sealed override uint Size(MetaData md) 
1483                 {
1484                         return md.BlobIndexSize();
1485                 }
1486
1487                 internal sealed override void Write(FileImage output) 
1488                 {
1489                         output.BlobIndex(sigIx);
1490                 }
1491
1492                 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1493
1494         }
1495
1496         /**************************************************************************/  
1497         public class TypeSpec : MetaDataElement {
1498                 uint sigIx = 0;
1499
1500                 internal TypeSpec(Type aType, MetaData md) 
1501                 {
1502                         MemoryStream sig = new MemoryStream();
1503                         aType.TypeSig(sig);
1504                         sigIx = md.AddToBlobHeap(sig.ToArray());
1505                         tabIx = MDTable.TypeSpec;
1506                 }
1507
1508                 internal sealed override uint GetCodedIx(CIx code) 
1509                 {
1510                         switch (code) {
1511                                 case (CIx.TypeDefOrRef) : return 2; 
1512                                 case (CIx.HasCustomAttr) : return 13; 
1513                                 case (CIx.MemberRefParent) : return 4; 
1514                         }
1515                         return 0;
1516                 }
1517
1518                 internal override uint Size(MetaData md) 
1519                 {
1520                         return md.BlobIndexSize();
1521                 }
1522
1523                 internal sealed override void Write(FileImage output) 
1524                 {
1525                         //Console.WriteLine("Writing the blob index for a TypeSpec");
1526                         output.BlobIndex(sigIx);
1527                 }
1528         }
1529
1530
1531         /**************************************************************************/  
1532         /// <summary>
1533         /// Base class for all IL types
1534         /// </summary>
1535         public abstract class Type : MetaDataElement {
1536                 protected byte typeIndex;
1537                 protected TypeSpec typeSpec;
1538
1539                 internal Type(byte tyIx) { typeIndex = tyIx; }
1540
1541                 internal byte GetTypeIndex() { return typeIndex; }
1542                 internal void SetTypeIndex (byte b) { typeIndex = b; }
1543
1544                 internal virtual MetaDataElement GetTypeSpec(MetaData md) 
1545                 {
1546                         if (typeSpec == null) {
1547                                 typeSpec = new TypeSpec(this,md);
1548                                 md.AddToTable(MDTable.TypeSpec,typeSpec);
1549                         }
1550                         return typeSpec;
1551                 }
1552
1553                 internal virtual void TypeSig(MemoryStream str) 
1554                 {
1555                         throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1556                                                 " doesn't have a type signature!!"));   
1557                 }
1558         }
1559
1560         public class ClassRefInst : Type {
1561
1562                 private Type type;
1563                 private bool is_value;
1564
1565                 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ()) 
1566                 {
1567                         this.type = type;
1568                         this.is_value = is_value;
1569                         if (is_value)
1570                                 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1571                         tabIx = MDTable.TypeSpec;
1572                 }
1573
1574                 internal sealed override void TypeSig(MemoryStream str) 
1575                 {
1576                         type.TypeSig (str);
1577                 }
1578         }
1579
1580         /**************************************************************************/  
1581         /// <summary>
1582         /// The base descriptor for a class 
1583         /// </summary>
1584         public abstract class Class : Type {
1585
1586                 protected int row = 0;
1587                 public string name, nameSpace;
1588                 protected uint nameIx, nameSpaceIx;
1589                 protected MetaData _metaData;
1590                 internal Class(string nameSpaceName, string className, MetaData md)
1591                         : base(PrimitiveType.Class.GetTypeIndex ()) 
1592                 {
1593                                 nameSpace = nameSpaceName;
1594                                 name = className;
1595                                 nameIx = md.AddToStringsHeap(name);
1596                                 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1597                                 _metaData = md;
1598                 }
1599
1600                 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ()) 
1601                 {
1602                         nameSpaceIx = nsIx;
1603                         nameIx = nIx;
1604                 }
1605
1606                 internal Class (byte typeIndex) : base (typeIndex)
1607                 {
1608                         nameSpace = "Should not be used";
1609                         name = "Should not be used";
1610                 }
1611
1612                 internal virtual uint TypeDefOrRefToken() { return 0; }
1613
1614                 internal virtual void MakeValueClass(ValueClass vClass) 
1615                 {
1616                         typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1617                 }
1618
1619                 internal virtual string TypeName() 
1620                 {
1621                         return (nameSpace + "." + name);
1622                 }
1623
1624                 internal override MetaDataElement GetTypeSpec(MetaData md) 
1625                 {
1626                         return this;
1627                 }
1628         }
1629
1630         /**************************************************************************/  
1631         // This Class produces entries in the TypeDef table of the MetaData 
1632         // in the PE meta data.
1633
1634         // NOTE:  Entry 0 in TypeDef table is always the pseudo class <module> 
1635         // which is the parent for functions and variables declared a module level
1636
1637         /// <summary>
1638         /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1639         /// </summary>
1640         /// 
1641         public class ClassDef : Class {
1642
1643                 Class superType;
1644                 ArrayList fields = new ArrayList();
1645                 ArrayList methods = new ArrayList();
1646                 ArrayList events;
1647                 ArrayList properties;
1648                 bool typeIndexChecked = true;
1649                 uint fieldIx = 0, methodIx = 0;
1650                 uint flags;
1651                 ClassLayout layout;
1652                 ClassDef parentClass;
1653                 MetaData metaData;
1654
1655                 internal ClassDef(TypeAttr attrSet, string nsName, string name, 
1656                                 MetaData md) : base(nsName, name, md) 
1657                 {
1658                         metaData = md;
1659                         if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1660                                 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1661                         }
1662                         flags = (uint)attrSet;
1663                         tabIx = MDTable.TypeDef;
1664                 }
1665
1666                 internal void SetSuper(Class sClass) 
1667                 {
1668                         superType = sClass;
1669                         if (! (sClass is GenericTypeInst))
1670                                 typeIndexChecked = false;
1671                 }
1672
1673                 internal override void MakeValueClass(ValueClass vClass) 
1674                 {
1675                         if (vClass == ValueClass.Enum)  
1676                                 superType = metaData.mscorlib.EnumType();
1677                         else  
1678                                 superType = metaData.mscorlib.ValueType();
1679
1680                         typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1681                 }
1682
1683                 public void SpecialNoSuper() 
1684                 {
1685                         superType = null;
1686                 }
1687
1688                 /// <summary>
1689                 /// Add an attribute to this class
1690                 /// </summary>
1691                 /// <param name="ta">the attribute to be added</param>
1692                 public void AddAttribute(TypeAttr ta) 
1693                 {
1694                         flags |= (uint)ta;
1695                 }
1696
1697                 /// <summary>
1698                 /// Add an interface that is implemented by this class
1699                 /// </summary>
1700                 /// <param name="iFace">the interface that is implemented</param>
1701                 public void AddImplementedInterface(Class iFace) 
1702                 {
1703                         metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1704                 }
1705
1706                 /// <summary>
1707                 ///  Add a named generic type parameter
1708                 /// </summary>
1709                 public GenericParameter AddGenericParameter (short index, string name) 
1710                 {
1711                         return AddGenericParameter (index, name, 0);
1712                 }
1713
1714                 /// <summary>
1715                 ///  Add a named generic type parameter with attributes
1716                 /// </summary>
1717                 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1718                 {
1719                         GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1720                         metaData.AddToTable (MDTable.GenericParam, gp);
1721                         return gp;
1722                 }
1723
1724                 /// <summary>
1725                 /// Add a field to this class
1726                 /// </summary>
1727                 /// <param name="name">field name</param>
1728                 /// <param name="fType">field type</param>
1729                 /// <returns>a descriptor for this new field</returns>
1730                 public FieldDef AddField(string name, Type fType) 
1731                 {
1732                         FieldDef field = new FieldDef(name,fType);
1733                         fields.Add(field);
1734                         return field;
1735                 }
1736
1737                 /// <summary>
1738                 /// Add a field to this class
1739                 /// </summary>
1740                 /// <param name="fAtts">attributes for this field</param>
1741                 /// <param name="name">field name</param>
1742                 /// <param name="fType">field type</param>
1743                 /// <returns>a descriptor for this new field</returns>
1744                 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) 
1745                 {
1746                         FieldDef field = new FieldDef(fAtts,name,fType);
1747                         fields.Add(field);
1748                         return field;
1749                 }
1750
1751                 public void SetFieldOrder (ArrayList fields)
1752                 {
1753                         this.fields = fields;
1754                 }
1755
1756                 /// <summary>
1757                 /// Add a method to this class
1758                 /// </summary>
1759                 /// <param name="name">method name</param>
1760                 /// <param name="retType">return type</param>
1761                 /// <param name="pars">parameters</param>
1762                 /// <returns>a descriptor for this new method</returns>
1763                 public MethodDef AddMethod(string name, Type retType, Param[] pars) 
1764                 {
1765                         return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1766                 }
1767
1768                 public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 
1769                 {
1770                         // Console.WriteLine("Adding method " + name + " to class " + this.name);
1771                         MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1772                         methods.Add(meth);
1773                         return meth;
1774                 }
1775
1776                 /// <summary>
1777                 /// Add a method to this class
1778                 /// </summary>
1779                 /// <param name="mAtts">attributes for this method</param>
1780                 /// <param name="iAtts">implementation attributes for this method</param>
1781                 /// <param name="name">method name</param>
1782                 /// <param name="retType">return type</param>
1783                 /// <param name="pars">parameters</param>
1784                 /// <returns>a descriptor for this new method</returns>
1785                 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, 
1786                                 Param ret_param, Param [] pars) {
1787                         // Console.WriteLine("Adding method " + name + " to class " + this.name);
1788                         MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1789                         methods.Add(meth);
1790                         return meth;
1791                 }
1792
1793                 /// <summary>
1794                 /// Add an event to this class
1795                 /// </summary>
1796                 /// <param name="name">event name</param>
1797                 /// <param name="eType">event type</param>
1798                 /// <returns>a descriptor for this new event</returns>
1799                 public Event AddEvent(string name, Type eType) 
1800                 {
1801                         Event e = new Event(name,eType,this);
1802                         if (events == null) events = new ArrayList();
1803                         events.Add(e);
1804                         return e;
1805                 }
1806
1807                 /// <summary>
1808                 /// Add a property to this class
1809                 /// </summary>
1810                 /// <param name="name">property name</param>
1811                 /// <param name="propType">property type</param>
1812                 /// <returns>a descriptor for this new property</returns>
1813                 public Property AddProperty(string name, Type retType, Type[] pars) 
1814                 {
1815                         Property p = new Property(name, retType, pars, this);
1816                         if (properties == null) properties = new ArrayList();
1817                         properties.Add(p);
1818                         return p;
1819                 }
1820
1821                 /// <summary>
1822                 /// Add a nested class to this class
1823                 /// </summary>
1824                 /// <param name="attrSet">attributes for this nested class</param>
1825                 /// <param name="nsName">nested name space name</param>
1826                 /// <param name="name">nested class name</param>
1827                 /// <returns>a descriptor for this new nested class</returns>
1828                 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1829                                 string name) {
1830                         ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1831                         metaData.AddToTable(MDTable.TypeDef,nClass);
1832                         metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1833                         nClass.parentClass = this;
1834                         return (nClass);
1835                 }
1836
1837                 public static bool IsValueType (Class type)
1838                 {
1839                         return IsValueType (type.nameSpace, type.name);
1840                 }
1841
1842                 public static bool IsEnum (Class type)
1843                 {
1844                         return IsEnum (type.nameSpace, type.name);
1845                 }
1846
1847                 public static bool IsValueType (string nsName, string name)
1848                 {
1849                         return (nsName == "System" && name == "ValueType");
1850                 }
1851
1852                 public static bool IsEnum (string nsName, string name)
1853                 {
1854                         return (nsName == "System" && name == "Enum");
1855                 }
1856
1857                 /// <summary>
1858                 /// Add a nested class to this class
1859                 /// </summary>
1860                 /// <param name="attrSet">attributes for this nested class</param>
1861                 /// <param name="nsName">nested name space name</param>
1862                 /// <param name="name">nested class name</param>
1863                 /// <param name="sType">super type of this nested class</param>
1864                 /// <returns>a descriptor for this new nested class</returns>
1865                 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1866                                 string name, Class sType) {
1867                         ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1868                         nClass.SetSuper(sType);
1869                         if (ClassDef.IsValueType (sType))
1870                                 nClass.MakeValueClass (ValueClass.ValueType);
1871                         else
1872                                 if (ClassDef.IsEnum (sType))
1873                                         nClass.MakeValueClass (ValueClass.Enum);
1874
1875                         if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1876                                 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1877
1878                         nClass.typeIndexChecked = true;
1879                         return (nClass);
1880                 }
1881
1882                 /// <summary>
1883                 /// Add layout information for this class.  This class must have the
1884                 /// sequential or explicit attribute.
1885                 /// </summary>
1886                 /// <param name="packSize">packing size (.pack)</param>
1887                 /// <param name="classSize">class size (.size)</param>
1888                 public void AddLayoutInfo (int packSize, int classSize) 
1889                 {
1890                         layout = new ClassLayout(packSize,classSize,this);
1891                 }
1892
1893                 /// <summary>
1894                 /// Use a method as the implementation for another method (.override)
1895                 /// </summary>
1896                 /// <param name="decl">the method to be overridden</param>
1897                 /// <param name="body">the implementation to be used</param>
1898                 public void AddMethodOverride(Method decl, Method body) 
1899                 {
1900                         metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1901                 }
1902
1903                 /// <summary>
1904                 /// Add security to this class NOT YET IMPLEMENTED
1905                 /// </summary>
1906                 /// <param name="permissionSet"></param>
1907                 public void AddSecurity(byte[] permissionSet) 
1908                 {
1909                         throw(new NotYetImplementedException("Class security "));
1910                         //flags |= HasSecurity;
1911                         // securityActions = permissionSet;
1912                 }
1913
1914                 //public void AddLineInfo(int row, int col) { }
1915
1916                 internal void CheckTypeIndex() 
1917                 {
1918                         if (typeIndexChecked) return;
1919                         if (superType is ClassDef) 
1920                                 ((ClassDef)superType).CheckTypeIndex();
1921                         typeIndex = superType.GetTypeIndex();
1922                         typeIndexChecked = true;
1923                 }
1924
1925                 internal sealed override void BuildTables(MetaData md) 
1926                 {
1927                         if (done) return;
1928                         if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1929                         // Console.WriteLine("Building tables for " + name);
1930                         if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1931                         // Console.WriteLine("adding methods " + methods.Count);
1932                         methodIx = md.TableIndex(MDTable.Method);
1933                         for (int i=0; i < methods.Count; i++) {
1934                                 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1935                                 ((MethodDef)methods[i]).BuildTables(md);
1936                         }
1937                         // Console.WriteLine("adding fields");
1938                         fieldIx = md.TableIndex(MDTable.Field);
1939                         for (int i=0; i < fields.Count; i++) {
1940                                 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1941                                 ((FieldDef)fields[i]).BuildTables(md);
1942                         }
1943                         // Console.WriteLine("adding events and properties");
1944                         if (events != null) { 
1945                                 for (int i=0; i < events.Count; i++) {
1946                                         md.AddToTable(MDTable.Event,(Event)events[i]);
1947                                         ((Event)events[i]).BuildTables(md);
1948                                 }
1949                                 md.AddToTable(MDTable.EventMap,
1950                                                 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1951                         }
1952                         if (properties != null) { 
1953                                 for (int i=0; i < properties.Count; i++) {
1954                                         md.AddToTable(MDTable.Property,(Property)properties[i]);
1955                                         ((Property)properties[i]).BuildTables(md);
1956                                 }
1957                                 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1958                                                         ((Property)properties[0]).Row,MDTable.Property));
1959                         }
1960                         // Console.WriteLine("End of building tables");
1961                         done = true;
1962                 }
1963
1964                 internal sealed override uint Size(MetaData md) 
1965                 {
1966                         return 4 + 2 * md.StringsIndexSize() + 
1967                                 md.CodedIndexSize(CIx.TypeDefOrRef) +
1968                                 md.TableIndexSize(MDTable.Field) + 
1969                                 md.TableIndexSize(MDTable.Method);
1970                 }
1971
1972                 internal sealed override void Write(FileImage output) 
1973                 {
1974                         output.Write(flags);
1975                         output.StringsIndex(nameIx);
1976                         output.StringsIndex(nameSpaceIx);
1977                         //if (superType != null) 
1978                         // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1979                         output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1980                         output.WriteIndex(MDTable.Field,fieldIx);
1981                         output.WriteIndex(MDTable.Method,methodIx);
1982                 }
1983
1984                 internal sealed override uint TypeDefOrRefToken() 
1985                 {
1986                         uint cIx = Row;
1987                         cIx = cIx << 2;
1988                         return cIx;
1989                 }
1990
1991                 internal sealed override void TypeSig(MemoryStream sig) 
1992                 {
1993                         if (!typeIndexChecked) CheckTypeIndex();
1994                         sig.WriteByte(GetTypeIndex());
1995                         MetaData.CompressNum(TypeDefOrRefToken(),sig);
1996                 }
1997
1998                 internal sealed override uint GetCodedIx(CIx code) 
1999                 {
2000                         switch (code) {
2001                                 case (CIx.TypeDefOrRef) : return 0; 
2002                                 case (CIx.HasCustomAttr) : return 3; 
2003                                 case (CIx.HasDeclSecurity) : return 0; 
2004                                 case (CIx.TypeOrMethodDef) : return 0; 
2005                         }
2006                         return 0;
2007                 }
2008
2009         }
2010
2011         /**************************************************************************/  
2012         /// <summary>
2013         /// Descriptor for a class/interface declared in another module of THIS 
2014         /// assembly, or in another assembly.
2015         /// </summary>
2016         public class ClassRef : Class, IExternRef, IResolutionScope {
2017
2018                 protected IResolutionScope parent;
2019                 protected MetaData metaData;
2020
2021                 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) 
2022                 {
2023                         metaData = md;
2024                         tabIx = MDTable.TypeRef;
2025                 }
2026
2027                 /// <summary>
2028                 /// Add a method to this class
2029                 /// </summary>
2030                 /// <param name="name">method name</param>
2031                 /// <param name="retType">return type</param>
2032                 /// <param name="pars">parameter types</param>
2033                 /// <returns>a descriptor for this method</returns>
2034                 public MethodRef AddMethod(string name, Type retType, Type[] pars) 
2035                 {
2036                         return AddMethod (name, retType, pars, 0);
2037                 }
2038                 
2039                 /// <summary>
2040                 /// Add a method to this class
2041                 /// </summary>
2042                 /// <param name="name">method name</param>
2043                 /// <param name="retType">return type</param>
2044                 /// <param name="pars">parameter types</param>
2045                 /// <param name="gen_param_count">num of generic parameters</param>
2046                 /// <returns>a descriptor for this method</returns>
2047                 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count) 
2048                 {
2049                         MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
2050                         metaData.AddToTable(MDTable.MemberRef,meth);
2051                         return meth;
2052                 }
2053
2054                 /// <summary>
2055                 /// Add a method to this class
2056                 /// </summary>
2057                 /// <param name="name">method name</param>
2058                 /// <param name="retType">return type</param>
2059                 /// <param name="pars">parameter types</param>
2060                 /// <returns>a descriptor for this method</returns>
2061                 public MethodRef AddVarArgMethod(string name, Type retType, 
2062                                 Type[] pars, Type[] optPars) 
2063                 {
2064                         MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2065                         metaData.AddToTable(MDTable.MemberRef,meth);
2066                         return meth;
2067                 }
2068
2069                 /// <summary>
2070                 /// Add a field to this class
2071                 /// </summary>
2072                 /// <param name="name">field name</param>
2073                 /// <param name="fType">field type</param>
2074                 /// <returns>a descriptor for this field</returns>
2075                 public FieldRef AddField(string name, Type fType) 
2076                 {
2077                         FieldRef field = new FieldRef(this,name,fType);
2078                         metaData.AddToTable(MDTable.MemberRef,field);
2079                         return field;
2080                 }
2081
2082                 public ClassRef AddClass (string nsName, string name)
2083                 {
2084                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2085                         metaData.AddToTable(MDTable.TypeRef,aClass);
2086                         aClass.SetParent(this);
2087                         return aClass;
2088                 }
2089
2090                 public ClassRef AddValueClass (string nsName, string name)
2091                 {
2092                         ClassRef aClass = AddClass (nsName, name);
2093                         aClass.MakeValueClass (ValueClass.ValueType);
2094                         return aClass;
2095                 }
2096
2097                 internal void SetParent(IResolutionScope par) 
2098                 {
2099                         parent = par;
2100                 }
2101
2102                 internal override string TypeName() 
2103                 {
2104                         if ((parent != null) && (parent is AssemblyRef))
2105                                 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2106                         else 
2107                                 return (nameSpace + name);
2108                 }
2109
2110                 internal sealed override uint Size(MetaData md) 
2111                 {
2112                         return md.CodedIndexSize(CIx.ResolutionScope) + 2 * 
2113                                 md.StringsIndexSize();
2114                 }
2115
2116                 internal sealed override void Write(FileImage output) 
2117                 {
2118                         output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2119                         output.StringsIndex(nameIx);
2120                         output.StringsIndex(nameSpaceIx);
2121                 }
2122
2123                 internal override sealed uint TypeDefOrRefToken() 
2124                 {
2125                         uint cIx = Row;
2126                         cIx = (cIx << 2) | 0x1;
2127                         return cIx;
2128                 }
2129
2130                 internal override void TypeSig(MemoryStream sig) 
2131                 {
2132                         sig.WriteByte(GetTypeIndex());
2133                         MetaData.CompressNum(TypeDefOrRefToken(),sig);
2134                 }
2135
2136                 internal sealed override uint GetCodedIx(CIx code) 
2137                 {
2138                         switch (code) {
2139                                 case (CIx.TypeDefOrRef) : return 1; 
2140                                 case (CIx.HasCustomAttr) : return 2; 
2141                                 case (CIx.MemberRefParent) : return 1; 
2142                                 case (CIx.ResolutionScope) : return 3; 
2143                         }
2144                         return 0;
2145                 }
2146
2147         }
2148
2149         /**************************************************************************/  
2150         public class ExternClassRef : ClassRef {
2151
2152                 ExternClass externClass;
2153
2154                 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2155                                 MetaDataElement declRef, MetaData md) : base(nsName,name,md) 
2156                 {
2157                         externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2158                         metaData.AddToTable(MDTable.ExportedType,externClass);
2159                 }
2160
2161                 internal ExternClassRef(string name, MetaData md) : base(null,name,md) 
2162                 {
2163                 }
2164
2165                 public ClassRef AddNestedClass(TypeAttr attrs, string name) 
2166                 {
2167                         ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2168                         externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2169                         metaData.AddToTable(MDTable.ExportedType,externClass);
2170                         return nestedClass;
2171                 }
2172
2173         }
2174
2175         /**************************************************************************/  
2176         /// <summary>
2177         /// Descriptor for a class defined in another module of THIS assembly 
2178         /// and exported (.class extern)
2179         /// </summary>
2180
2181         internal class ExternClass : Class {
2182
2183                 MetaDataElement parent;
2184                 uint flags;
2185
2186                 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx, 
2187                                 MetaDataElement paren) : base(nsIx,nIx) 
2188                 {
2189                         flags = (uint)attr;
2190                         parent = paren;
2191                         tabIx = MDTable.ExportedType;
2192                 }
2193
2194                 internal sealed override uint Size(MetaData md) 
2195                 {
2196                         return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2197                 }
2198
2199                 internal sealed override void Write(FileImage output) 
2200                 {
2201                         output.Write(flags);
2202                         output.Write(0);
2203                         output.StringsIndex(nameIx);
2204                         output.StringsIndex(nameSpaceIx);
2205                         output.WriteCodedIndex(CIx.Implementation,parent);
2206                 }
2207
2208                 internal sealed override uint GetCodedIx(CIx code) 
2209                 {
2210                         switch (code) {
2211                                 case (CIx.HasCustomAttr) : return 17; 
2212                                 case (CIx.Implementation) : return 2; 
2213                         }
2214                         return 0;
2215                 }
2216
2217         }
2218
2219         public class GenParam : Class {
2220
2221                 private int index;
2222                 private string param_name;
2223                 private uint sigIx = 0;
2224
2225                 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype) 
2226                 {
2227                         this.index = index;
2228                         this.param_name = name;
2229                         tabIx = MDTable.TypeSpec;
2230                 }
2231
2232                 public int Index {
2233                         get { return index; }
2234                         set { index = value; }
2235                 }
2236
2237                 public string Name {
2238                         get { return param_name; }
2239                         set { param_name = value; }
2240                 }
2241
2242                 public GenParamType Type {
2243                         get { return (GenParamType) GetTypeIndex (); }
2244                 }
2245                 
2246                 internal sealed override void BuildTables (MetaData md)
2247                 {
2248                         if (done)
2249                                 return;
2250                         MemoryStream str = new MemoryStream ();
2251                         TypeSig (str);
2252                         sigIx = md.AddToBlobHeap (str.ToArray ());
2253
2254                         done = true;
2255                 }
2256
2257                 internal sealed override void TypeSig(MemoryStream str) 
2258                 {
2259                         if (index < 0)
2260                                 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2261                         str.WriteByte(typeIndex);
2262                         MetaData.CompressNum ((uint) index, str);
2263                 }
2264                 
2265                 internal override uint Size(MetaData md) 
2266                 {
2267                         return md.BlobIndexSize();
2268                 }
2269
2270                 internal sealed override void Write (FileImage output)
2271                 {
2272                         output.BlobIndex (sigIx);       
2273                 }
2274
2275                 internal sealed override uint GetCodedIx(CIx code) 
2276                 {
2277                         switch (code) {
2278                                 case (CIx.TypeDefOrRef) : return 2; 
2279                                 case (CIx.HasCustomAttr) : return 13; 
2280                                 case (CIx.MemberRefParent) : return 4; 
2281                         }
2282                         return 0;
2283                 }
2284         }
2285
2286         public class GenericTypeInst : Class {
2287
2288                 private Type gen_type;
2289                 private Type[] gen_param;
2290                 bool inTable = false;
2291                 uint sigIx = 0;
2292
2293                 public GenericTypeInst (Type gen_type, Type[] gen_param) 
2294                         : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2295                 {
2296                         this.gen_type = gen_type;
2297                         this.gen_param = gen_param;
2298                         tabIx = MDTable.TypeSpec;
2299                 }
2300
2301                 internal override MetaDataElement GetTypeSpec (MetaData md)
2302                 {
2303                         if (!inTable) {
2304                                 md.AddToTable (MDTable.TypeSpec, this);
2305                                 inTable = true;
2306                         }
2307
2308                         return this;
2309                 }
2310
2311                 internal sealed override void TypeSig(MemoryStream str) 
2312                 {
2313                         str.WriteByte(typeIndex);
2314                         gen_type.TypeSig (str);
2315                         MetaData.CompressNum ((uint) gen_param.Length, str);
2316                         foreach (Type param in gen_param)
2317                                 param.TypeSig (str);
2318                 }
2319
2320                 internal sealed override void BuildTables (MetaData md)
2321                 {
2322                         if (done)
2323                                 return;
2324                         MemoryStream str = new MemoryStream ();
2325                         TypeSig (str);
2326                         sigIx = md.AddToBlobHeap (str.ToArray ());
2327
2328                         done = true;
2329                 }
2330
2331                 internal sealed override uint Size (MetaData md)
2332                 {
2333                         return md.BlobIndexSize ();
2334                 }
2335
2336                 internal sealed override void Write (FileImage output)
2337                 {
2338                         output.BlobIndex (sigIx);       
2339                 }
2340
2341                 internal sealed override uint GetCodedIx (CIx code)
2342                 {
2343                         switch (code) {
2344                                 case (CIx.TypeDefOrRef): return 2;
2345                                 case (CIx.MemberRefParent): return 4;
2346                                 case (CIx.HasCustomAttr): return 13;
2347                         }
2348                         return 0;
2349                 }
2350         }
2351
2352         public class GenericMethodSig {
2353
2354                 private Type[] gen_param;
2355                 private bool done;
2356                 private uint sigIx = 0;
2357
2358                 public GenericMethodSig (Type[] gen_param)
2359                 {
2360                         this.gen_param = gen_param;
2361                         done = false;
2362                 }
2363
2364                 internal void TypeSig (MemoryStream str)
2365                 {
2366                         str.WriteByte (0x0A); /* GENERIC_INST */
2367                         MetaData.CompressNum ((uint) gen_param.Length, str);
2368                         foreach (Type param in gen_param)
2369                                 param.TypeSig (str);
2370                 }
2371
2372                 internal uint GetSigIx (MetaData md)
2373                 {
2374                         if (done)
2375                                 return sigIx;
2376
2377                         MemoryStream sig = new MemoryStream();
2378                         TypeSig (sig);
2379                         sigIx = md.AddToBlobHeap (sig.ToArray());
2380                         done = true;
2381                         return sigIx;
2382                 }
2383         }
2384
2385         public class Sentinel : Type {
2386
2387                 public Sentinel () : base (0x41) { }
2388
2389                 internal sealed override void TypeSig(MemoryStream str) 
2390                 {
2391                         str.WriteByte(typeIndex);
2392                 }
2393         }
2394
2395         /**************************************************************************/  
2396         /// <summary>
2397         /// Descriptor for a FunctionPointer type
2398         /// </summary>
2399         /// 
2400         public class MethPtrType : Type {
2401
2402                 bool varArgMeth;
2403                 Type retType;
2404                 Type [] parList;
2405                 Type [] optParList;
2406                 CallConv callConv;
2407                 uint numPars;
2408                 uint numOptPars;
2409                 uint sigIx = 0;
2410
2411                 /// <summary>
2412                 /// Create a new function pointer type
2413                 /// </summary>
2414                 /// <param name="meth">the function to be referenced</param>
2415                 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2416                                 bool varArgMeth, Type[] optPars) : base(0x1B) 
2417                 {
2418                         this.retType = retType;
2419                         callConv = callconv;
2420                         parList = pars;
2421                         this.varArgMeth = varArgMeth;
2422                         if (parList != null) numPars = (uint)parList.Length;
2423                         if (varArgMeth) {
2424                                 optParList = optPars;
2425                                 if (optParList != null) numOptPars = (uint)optParList.Length;
2426                                 callConv |= CallConv.Vararg;
2427                         }
2428                         tabIx = MDTable.TypeSpec;
2429                 }
2430
2431                 internal sealed override void TypeSig(MemoryStream sig) 
2432                 {
2433                         sig.WriteByte(typeIndex);
2434                         // Bootlegged from method ref
2435                         sig.WriteByte((byte)callConv);
2436                         MetaData.CompressNum (numPars + numOptPars, sig);
2437                         retType.TypeSig (sig);
2438                         for (int i=0; i < numPars; i++) {
2439                                 parList[i].TypeSig (sig);
2440                         }
2441                         if (varArgMeth) {
2442                                 sig.WriteByte (0x41); // Write the sentinel
2443                                 for (int i=0; i < numOptPars; i++) {
2444                                         optParList[i].TypeSig (sig);
2445                                 }
2446                         }
2447                 }
2448
2449                 internal sealed override void BuildTables(MetaData md) 
2450                 {
2451                         if (done) return;
2452                         MemoryStream sig = new MemoryStream();
2453                         TypeSig(sig);
2454                         sigIx = md.AddToBlobHeap(sig.ToArray());
2455                         done = true;
2456                 }
2457
2458                 internal sealed override uint Size(MetaData md) 
2459                 {
2460                         return md.BlobIndexSize();
2461                 }
2462
2463                 internal sealed override void Write(FileImage output) 
2464                 {
2465                         output.BlobIndex(sigIx);
2466                 }
2467
2468                 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2469
2470         }
2471
2472         #region Array Types
2473         /* Classes for Arrays */
2474
2475         /// <summary>
2476         /// The IL Array type
2477         /// </summary>
2478         public abstract class Array : Type {
2479
2480                 protected Type elemType;
2481                 protected MetaData metaData;
2482                 protected string cnameSpace, cname;
2483
2484                 internal Array(Type eType, byte TypeId) : base(TypeId) 
2485                 {
2486                         elemType = eType;
2487                         tabIx = MDTable.TypeSpec;
2488                 }
2489         }
2490
2491         /// <summary>
2492         /// Single dimensional array with zero lower bound
2493         /// </summary>
2494         public class ZeroBasedArray : Array {
2495
2496                 /// <summary>
2497                 /// Create a new array  -   elementType[]
2498                 /// </summary>
2499                 /// <param name="elementType">the type of the array elements</param>
2500                 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2501
2502                 internal sealed override void TypeSig(MemoryStream str) 
2503                 {
2504                         str.WriteByte(typeIndex);
2505                         elemType.TypeSig(str); 
2506                 }
2507
2508         }
2509
2510         /// <summary>
2511         /// Multi dimensional array with explicit bounds
2512         /// </summary>
2513         public class BoundArray : Array {
2514                 int[] lowerBounds;
2515                 int[] sizes;
2516                 uint numDims;
2517
2518                 /// <summary>
2519                 /// Create a new multi dimensional array type 
2520                 /// eg. elemType[1..5,3..10,5,,] would be 
2521                 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2522                 /// </summary>
2523                 /// <param name="elementType">the type of the elements</param>
2524                 /// <param name="dimensions">the number of dimensions</param>
2525                 /// <param name="loBounds">lower bounds of dimensions</param>
2526                 /// <param name="sizes">sizes for the dimensions</param>
2527                 public BoundArray(Type elementType, uint dimensions, int[] loBounds, 
2528                                 int[] sizes) : base (elementType,0x14) 
2529                 {
2530                         numDims = dimensions;
2531                         lowerBounds = loBounds;
2532                         this.sizes = sizes;
2533                 }
2534
2535                 /// <summary>
2536                 /// Create a new multi dimensional array type 
2537                 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2538                 /// </summary>
2539                 /// <param name="elementType">the type of the elements</param>
2540                 /// <param name="dimensions">the number of dimensions</param>
2541                 /// <param name="size">the sizes of the dimensions</param>
2542                 public BoundArray(Type elementType, uint dimensions, int[] size) 
2543                         : base (elementType,0x14) 
2544                 {
2545                         numDims = dimensions;
2546                         sizes = size;
2547                 }
2548
2549                 /// <summary>
2550                 /// Create a new multi dimensional array type 
2551                 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2552                 /// </summary>
2553                 /// <param name="elementType">the type of the elements</param>
2554                 /// <param name="dimensions">the number of dimensions</param>
2555                 public BoundArray(Type elementType, uint dimensions)
2556                         : base (elementType,0x14) 
2557                 {
2558                         numDims = dimensions;
2559                 }
2560
2561                 internal sealed override void TypeSig(MemoryStream str) 
2562                 {
2563                         str.WriteByte(typeIndex);
2564                         elemType.TypeSig(str);
2565                         MetaData.CompressNum(numDims,str);
2566                         if ((sizes != null) && (sizes.Length > 0))  {
2567
2568                                 MetaData.CompressNum((uint)sizes.Length,str);
2569                                 for (int i=0; i < sizes.Length; i++) {
2570                                         MetaData.CompressNum((uint)sizes[i],str);
2571                                 }
2572                         } else str.WriteByte(0);
2573                         if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2574                                 MetaData.CompressNum((uint)lowerBounds.Length,str);
2575                                 for (int i=0; i < lowerBounds.Length; i++) {
2576                                         CompressSignedNum (lowerBounds[i],str);
2577                                 }
2578                         } else str.WriteByte(0);
2579                 }
2580                 private void CompressSignedNum (int val, MemoryStream str)
2581                 {
2582                         uint uval = (uint) val;
2583                         byte sign = 0;
2584                         if (val < 0) {
2585                                 val = -val;
2586                                 sign = 1;
2587                         }
2588
2589                         /* Map the signed number to an unsigned number in two ways.
2590
2591                              fval: left-rotated 2's complement representation
2592                              sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2593                                    the mapping is: x -> 2*|x| - signbit(x)
2594                         */
2595                         uint fval = (uval << 1) | sign;
2596                         int sval = (val  << 1) - sign;
2597
2598                         /* An overly clever transformation: 
2599
2600                            a. sval is used to determine the number of bytes in the compressed representation.
2601                            b. fval is truncated to the appropriate number of bits and output using the 
2602                               normal unsigned-int compressor.
2603
2604                            However, or certain values, the truncated fval doesn't carry enough information to round trip.
2605
2606                                 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2607
2608                            So, we use full 4 bytes to encode such values.
2609
2610                            LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2611                                      e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2612                         */
2613                         if (sval <= 0x7F)
2614                                 MetaData.CompressNum (fval & 0x7F, str);
2615                         else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2616                                 MetaData.CompressNum (fval & 0x3FFF, str);
2617                         else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2618                                 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2619                         else
2620                                 /* FIXME: number cannot be represented.  Report a warning.  */
2621                                 // throw new Exception ("cannot represent signed value" + -val);
2622                                 MetaData.CompressNum (fval, str);
2623                 }
2624         }
2625
2626         #endregion
2627
2628
2629         /* Empty interface for grouping TypeRef's possible ResolutionScope
2630            namely : Module, ModuleRef, AssemblyRef and TypeRef */
2631         public interface IResolutionScope  {
2632         }
2633
2634         /**************************************************************************/  
2635         /// <summary>
2636         /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2637         /// </summary>
2638         public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2639
2640                 protected uint nameIx = 0;
2641                 protected MetaData metaData;
2642                 protected string name;
2643
2644                 internal ResolutionScope(string name, MetaData md)
2645                 {
2646                         metaData = md;
2647                         this.name = name;
2648                         nameIx = md.AddToStringsHeap(name);
2649                 }
2650
2651                 internal string GetName() { return name; }
2652
2653         }
2654
2655         /**************************************************************************/  
2656         /// <summary>
2657         /// Descriptor for THIS assembly (.assembly)
2658         /// </summary>
2659         public class Assembly : ResolutionScope  {
2660
2661                 ushort majorVer, minorVer, buildNo, revisionNo;
2662                 uint flags;
2663                 uint hashAlgId;
2664                 uint keyIx = 0, cultIx = 0;
2665                 bool hasPublicKey = false;
2666
2667                 internal Assembly(string name, MetaData md) : base(name,md) 
2668                 {
2669                         tabIx = MDTable.Assembly;
2670                 }
2671
2672                 /// <summary>
2673                 /// Add details about THIS assembly
2674                 /// </summary>
2675                 /// <param name="majVer">Major Version</param>
2676                 /// <param name="minVer">Minor Version</param>
2677                 /// <param name="bldNo">Build Number</param>
2678                 /// <param name="revNo">Revision Number</param>
2679                 /// <param name="key">Hash Key</param>
2680                 /// <param name="hash">Hash Algorithm</param>
2681                 /// <param name="cult">Culture</param>
2682                 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, 
2683                                 byte[] key, uint hash, string cult) 
2684                 {
2685                         majorVer = (ushort)majVer;
2686                         minorVer = (ushort)minVer;
2687                         buildNo = (ushort)bldNo;
2688                         revisionNo = (ushort)revNo;
2689                         hashAlgId = hash;
2690                         hasPublicKey = (key != null);
2691                         keyIx = metaData.AddToBlobHeap(key);
2692                         cultIx = metaData.AddToStringsHeap(cult);
2693                 }
2694
2695                 /// <summary>
2696                 /// Add an attribute to THIS assembly
2697                 /// </summary>
2698                 /// <param name="aa">assembly attribute</param>
2699                 public void AddAssemblyAttr(AssemAttr aa) 
2700                 {
2701                         flags |= (uint)aa;
2702                 }
2703
2704                 internal sealed override uint Size(MetaData md) 
2705                 {
2706                         return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2707                 }
2708
2709                 internal sealed override void Write(FileImage output) 
2710                 {
2711                         //      Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2712                         output.Write((uint)hashAlgId);
2713                         output.Write(majorVer);
2714                         output.Write(minorVer);
2715                         output.Write(buildNo);
2716                         output.Write(revisionNo);
2717                         output.Write(flags);
2718                         output.BlobIndex(keyIx);
2719                         output.StringsIndex(nameIx);
2720                         output.StringsIndex(cultIx);
2721                 }
2722
2723                 internal sealed override uint GetCodedIx(CIx code) 
2724                 {
2725                         switch (code) {
2726                                 case (CIx.HasCustomAttr) : return 14; 
2727                                 case (CIx.HasDeclSecurity) : return 2; 
2728                         }
2729                         return 0;
2730                 }
2731
2732                 internal bool HasPublicKey {
2733                         get { return hasPublicKey; }
2734                 }
2735         }
2736
2737         /**************************************************************************/  
2738         /// <summary>
2739         /// Descriptor for THIS module
2740         /// </summary>
2741         public class Module : ResolutionScope, IExternRef {
2742
2743                 Guid mvid;
2744                 uint mvidIx = 0;
2745
2746                 internal Module(string name, MetaData md) : base(name,md)       
2747                 {
2748                         mvid = Guid.NewGuid();
2749                         mvidIx = md.AddToGUIDHeap(mvid);
2750                         tabIx = MDTable.Module;
2751                 }
2752
2753                 public Guid Guid {
2754                         get { return mvid; }
2755                 }
2756
2757                 public ClassRef AddClass(string nsName, string name) 
2758                 {
2759                         ClassRef aClass = new ClassRef (nsName, name, metaData);
2760                         metaData.AddToTable (MDTable.TypeRef, aClass);
2761                         aClass.SetParent (this);
2762                         return aClass;
2763                 }
2764
2765                 public ClassRef AddValueClass(string nsName, string name) 
2766                 {
2767                         ClassRef aClass = AddClass (nsName, name);
2768                         aClass.MakeValueClass (ValueClass.ValueType);
2769                         return aClass;
2770                 }
2771
2772                 internal sealed override uint Size(MetaData md) 
2773                 {
2774                         return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2775                 }
2776
2777                 internal sealed override void Write(FileImage output) 
2778                 {
2779                         output.Write((short)0);
2780                         output.StringsIndex(nameIx);
2781                         output.GUIDIndex(mvidIx);
2782                         output.GUIDIndex(0);
2783                         output.GUIDIndex(0);
2784                 }
2785
2786                 internal sealed override uint GetCodedIx(CIx code) 
2787                 {
2788                         switch (code) {
2789                                 case (CIx.HasCustomAttr) : return 7; 
2790                                 case (CIx.ResolutionScope) : return 0;
2791                         }
2792                         return 0;
2793                 }
2794         }
2795         /**************************************************************************/  
2796         /// <summary>
2797         /// Descriptor for another module in THIS assembly
2798         /// </summary>
2799         public class ModuleRef : ResolutionScope, IExternRef {
2800
2801                 internal ModuleRef(MetaData md, string name) : base(name,md) 
2802                 {
2803                         tabIx = MDTable.ModuleRef;
2804                 }
2805
2806                 /// <summary>
2807                 /// Add a class to this external module.  This is a class declared in
2808                 /// another module of THIS assembly.
2809                 /// </summary>
2810                 /// <param name="nsName">name space name</param>
2811                 /// <param name="name">class name</param>
2812                 /// <returns>a descriptor for this class in another module</returns>
2813                 public ClassRef AddClass(string nsName, string name) 
2814                 {
2815                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2816                         metaData.AddToTable(MDTable.TypeRef,aClass);
2817                         aClass.SetParent(this);
2818                         return aClass;
2819                 }
2820
2821                 /// <summary>
2822                 /// Make a file descriptor to correspond to this module.  The file
2823                 /// descriptor will have the same name as the module descriptor
2824                 /// </summary>
2825                 /// <param name="hashBytes">the hash of the file</param>
2826                 /// <param name="hasMetaData">the file contains metadata</param>
2827                 /// <param name="entryPoint">the program entry point is in this file</param>
2828                 /// <returns>a descriptor for the file which contains this module</returns>
2829                 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) 
2830                 {
2831                         FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2832                         metaData.AddToTable(MDTable.File,file);
2833                         return file;
2834                 }
2835
2836                 /// <summary>
2837                 /// Add a value class to this module.  This is a class declared in
2838                 /// another module of THIS assembly.
2839                 /// </summary>
2840                 /// <param name="nsName">name space name</param>
2841                 /// <param name="name">class name</param>
2842                 /// <returns></returns>
2843                 public ClassRef AddValueClass(string nsName, string name) 
2844                 {
2845                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2846                         metaData.AddToTable(MDTable.TypeRef,aClass);
2847                         aClass.SetParent(this);
2848                         aClass.MakeValueClass(ValueClass.ValueType);
2849                         return aClass;
2850                 }
2851
2852                 /// <summary>
2853                 /// Add a class which is declared public in this external module of
2854                 /// THIS assembly.  This class will be exported from this assembly.
2855                 /// The ilasm syntax for this is .extern class
2856                 /// </summary>
2857                 /// <param name="attrSet">attributes of the class to be exported</param>
2858                 /// <param name="nsName">name space name</param>
2859                 /// <param name="name">external class name</param>
2860                 /// <param name="declFile">the file where the class is declared</param>
2861                 /// <param name="isValueClass">is this class a value type?</param>
2862                 /// <returns>a descriptor for this external class</returns>
2863                 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName, 
2864                                 string name, FileRef declFile, 
2865                                 bool isValueClass) {
2866                         ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2867                         metaData.AddToTable(MDTable.TypeRef,cRef);
2868                         cRef.SetParent(this);
2869                         if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2870                         return cRef;
2871                 }
2872
2873                 /// <summary>
2874                 /// Add a "global" method in another module
2875                 /// </summary>
2876                 /// <param name="name">method name</param>
2877                 /// <param name="retType">return type</param>
2878                 /// <param name="pars">method parameter types</param>
2879                 /// <returns>a descriptor for this method in anther module</returns>
2880                 public MethodRef AddMethod(string name, Type retType, Type[] pars) 
2881                 {
2882                         MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2883                         metaData.AddToTable(MDTable.MemberRef,meth);
2884                         return meth;
2885                 }
2886
2887                 /// <summary>
2888                 /// Add a vararg method to this class
2889                 /// </summary>
2890                 /// <param name="name">method name</param>
2891                 /// <param name="retType">return type</param>
2892                 /// <param name="pars">parameter types</param>
2893                 /// <param name="optPars">optional param types for this vararg method</param>
2894                 /// <returns>a descriptor for this method</returns>
2895                 public MethodRef AddVarArgMethod(string name, Type retType, 
2896                                 Type[] pars, Type[] optPars) {
2897                         MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2898                         metaData.AddToTable(MDTable.MemberRef,meth);
2899                         return meth;
2900                 }
2901
2902                 /// <summary>
2903                 /// Add a field in another module
2904                 /// </summary>
2905                 /// <param name="name">field name</param>
2906                 /// <param name="fType">field type</param>
2907                 /// <returns>a descriptor for this field in another module</returns>
2908                 public FieldRef AddField(string name, Type fType) 
2909                 {
2910                         FieldRef field = new FieldRef(this,name,fType);
2911                         metaData.AddToTable(MDTable.MemberRef,field);
2912                         return field;
2913                 }
2914
2915                 internal sealed override uint Size(MetaData md) 
2916                 {
2917                         return md.StringsIndexSize();
2918                 }
2919
2920                 internal sealed override void Write(FileImage output) 
2921                 {
2922                         output.StringsIndex(nameIx);
2923                 }
2924
2925                 internal sealed override uint GetCodedIx(CIx code) 
2926                 {
2927                         switch (code) {
2928                                 case (CIx.HasCustomAttr) : return 12; 
2929                                 case (CIx.MemberRefParent) : return 2; 
2930                                 case (CIx.ResolutionScope) : return 1; 
2931                         }
2932                         return 0;
2933                 }
2934
2935         }
2936
2937         #region Classes for Constants
2938         /// <summary>
2939         /// Descriptor for a constant value
2940         /// </summary>
2941         public abstract class Constant {
2942                 protected uint size = 0;
2943                 protected Type type;
2944                 protected uint blobIndex;
2945                 protected bool addedToBlobHeap = false;
2946
2947                 internal Constant() { }
2948
2949                 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2950
2951                 internal uint GetSize() { return size; }
2952
2953                 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2954
2955                 internal virtual void Write(BinaryWriter bw) {  }
2956
2957         }
2958         /// <summary>
2959         /// Descriptor for a constant value
2960         /// </summary>
2961         public abstract class DataConstant : Constant {
2962                 private uint dataOffset = 0;
2963
2964                 internal DataConstant() { }
2965
2966                 public uint DataOffset {
2967                         get { return dataOffset; }
2968                         set { dataOffset = value; }
2969                 }
2970
2971         }
2972
2973         /// <summary>
2974         /// Boolean constant
2975         /// </summary>
2976         public class BoolConst : DataConstant {
2977                 bool val;
2978
2979                 /// <summary>
2980                 /// Create a new boolean constant with the value "val"
2981                 /// </summary>
2982                 /// <param name="val">value of this boolean constant</param>
2983                 public BoolConst(bool val) 
2984                 {
2985                         this.val = val;
2986                         size = 1;
2987                         type = PrimitiveType.Boolean;
2988                 }
2989
2990                 internal sealed override uint GetBlobIndex(MetaData md) 
2991                 {
2992                         if (!addedToBlobHeap) {
2993                                 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2994                                 else blobIndex = md.AddToBlobHeap((sbyte)0);
2995                                 addedToBlobHeap = true;
2996                         }
2997                         return blobIndex;
2998                 }
2999
3000                 internal sealed override void Write(BinaryWriter bw) 
3001                 {
3002                         if (val) bw.Write((sbyte)1);
3003                         else bw.Write((sbyte)0);
3004                 }
3005
3006         }
3007
3008         public class ByteArrConst : DataConstant {
3009                 internal byte[] val;
3010
3011                 public ByteArrConst(byte[] val) 
3012                 {
3013                         type = PrimitiveType.String;
3014                         this.val = val;
3015                         size = (uint)val.Length;
3016                 }
3017
3018                 public Type Type {
3019                         get { return type; }
3020                         set { type = value; }
3021                 }
3022
3023                 internal sealed override uint GetBlobIndex(MetaData md) 
3024                 {
3025                         if (!addedToBlobHeap) {
3026                                 blobIndex = md.AddToBlobHeap(val);
3027                                 addedToBlobHeap = true;
3028                         }
3029                         return blobIndex;
3030                 }
3031
3032                 internal sealed override void Write(BinaryWriter bw) 
3033                 {
3034                         bw.Write(val);
3035                 }
3036
3037         }
3038
3039         public class CharConst : Constant {
3040                 char val;
3041
3042                 public CharConst(char val) 
3043                 {
3044                         this.val = val;
3045                         size = 2;
3046                         type = PrimitiveType.Char;
3047                 }
3048
3049                 internal sealed override uint GetBlobIndex(MetaData md) 
3050                 {
3051                         if (!addedToBlobHeap) {
3052                                 blobIndex = md.AddToBlobHeap(val);
3053                                 addedToBlobHeap = true;
3054                         }
3055                         return blobIndex;
3056                 }
3057
3058                 internal sealed override void Write(BinaryWriter bw) 
3059                 {
3060                         bw.Write(val);
3061                 }
3062
3063         }
3064
3065         public class FloatConst : DataConstant {
3066                 float val;
3067
3068                 public FloatConst(float val) 
3069                 {
3070                         this.val = val;
3071                         size = 4;
3072                         type = PrimitiveType.Float32;
3073                 }
3074
3075                 internal sealed override uint GetBlobIndex(MetaData md) 
3076                 {
3077                         if (!addedToBlobHeap) {
3078                                 blobIndex = md.AddToBlobHeap(val);
3079                                 addedToBlobHeap = true;
3080                         }
3081                         return blobIndex;
3082                 }
3083
3084                 internal sealed override void Write(BinaryWriter bw) 
3085                 {
3086                         bw.Write(val);
3087                 }
3088
3089         }
3090
3091         public class DoubleConst : DataConstant {
3092                 double val;
3093
3094                 public DoubleConst(double val) 
3095                 {
3096                         this.val = val;
3097                         size = 8;
3098                         type = PrimitiveType.Float64;
3099                 }
3100
3101                 internal sealed override uint GetBlobIndex(MetaData md) 
3102                 {
3103                         if (!addedToBlobHeap) {
3104                                 blobIndex = md.AddToBlobHeap(val);
3105                                 addedToBlobHeap = true;
3106                         }
3107                         return blobIndex;
3108                 }
3109
3110                 internal sealed override void Write(BinaryWriter bw) 
3111                 {
3112                         bw.Write(val);
3113                 }
3114
3115         }
3116
3117         public class IntConst : DataConstant {
3118                 long val;
3119
3120                 public IntConst(sbyte val) 
3121                 {
3122                         this.val = val;
3123                         size = 1;
3124                         type = PrimitiveType.Int8;
3125                 }
3126
3127                 public IntConst(short val) 
3128                 {
3129                         this.val = val;
3130                         size = 2;
3131                         type = PrimitiveType.Int16;
3132                 }
3133
3134                 public IntConst(int val) 
3135                 {
3136                         this.val = val;
3137                         size = 4;
3138                         type = PrimitiveType.Int32;
3139                 }
3140
3141                 public IntConst(long val) 
3142                 {
3143                         this.val = val;
3144                         size = 8;
3145                         type = PrimitiveType.Int64;
3146                 }
3147
3148                 internal sealed override uint GetBlobIndex(MetaData md) 
3149                 {
3150                         if (!addedToBlobHeap) {
3151                                 switch (size) {
3152                                         case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3153                                         case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3154                                         case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3155                                         default : blobIndex = md.AddToBlobHeap(val); break; 
3156                                 }
3157                                 addedToBlobHeap = true;
3158                         }
3159                         return blobIndex;
3160                 }
3161
3162                 internal sealed override void Write(BinaryWriter bw) 
3163                 {
3164                         switch (size) {
3165                                 case (1) : bw.Write((sbyte)val); break;
3166                                 case (2) : bw.Write((short)val); break;
3167                                 case (4) : bw.Write((int)val); break;
3168                                 default : bw.Write(val); break; 
3169                         }
3170                 }
3171
3172         }
3173
3174         public class UIntConst : DataConstant {
3175                 ulong val;
3176
3177                 public UIntConst(byte val) 
3178                 {
3179                         this.val = val;
3180                         size = 1;
3181                         type = PrimitiveType.UInt8;
3182                 }
3183                 public UIntConst(ushort val) 
3184                 {
3185                         this.val = val;
3186                         size = 2;
3187                         type = PrimitiveType.UInt16;
3188                 }
3189                 public UIntConst(uint val) 
3190                 {
3191                         this.val = val;
3192                         size = 4;
3193                         type = PrimitiveType.UInt32;
3194                 }
3195                 public UIntConst(ulong val) 
3196                 {
3197                         this.val = val;
3198                         size = 8;
3199                         type = PrimitiveType.UInt64;
3200                 }
3201
3202                 internal sealed override uint GetBlobIndex(MetaData md) 
3203                 {
3204                         if (!addedToBlobHeap) {
3205                                 switch (size) {
3206                                         case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3207                                         case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3208                                         case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3209                                         default : blobIndex = md.AddToBlobHeap(val); break;
3210                                 }
3211                                 addedToBlobHeap = true;
3212                         }
3213                         return blobIndex;
3214                 }
3215
3216                 internal sealed override void Write(BinaryWriter bw) 
3217                 {
3218                         switch (size) {
3219                                 case (1) : bw.Write((byte)val); break;
3220                                 case (2) : bw.Write((ushort)val); break;
3221                                 case (4) : bw.Write((uint)val); break;
3222                                 default : bw.Write(val); break;
3223                         }
3224                 }
3225
3226         }
3227
3228         public class StringConst : DataConstant {
3229                 internal string val;
3230
3231                 public StringConst(string val) 
3232                 {
3233                         this.val = val;
3234                         size = (uint)val.Length;  // need to add null ??
3235                         type = PrimitiveType.String;
3236                 }
3237
3238                 internal sealed override uint GetBlobIndex(MetaData md) 
3239                 {
3240                         if (!addedToBlobHeap) {
3241                                 byte [] b = Encoding.Unicode.GetBytes (val);
3242                                 blobIndex = md.AddToBlobHeap(b);
3243                                 addedToBlobHeap = true;
3244                         }
3245                         return blobIndex;
3246                 }
3247
3248                 internal sealed override void Write(BinaryWriter bw) 
3249                 {
3250                         bw.Write(val);
3251                 }
3252
3253         }
3254
3255         public class NullConst : Constant {
3256
3257                 public NullConst() 
3258                 {
3259                         size = 4;
3260                         type = PrimitiveType.Class;
3261                 }
3262
3263                 internal sealed override uint GetBlobIndex(MetaData md) 
3264                 {
3265                         if (!addedToBlobHeap) {
3266                                 blobIndex = md.AddToBlobHeap((int)0);
3267                                 addedToBlobHeap = true;
3268                         }
3269                         return blobIndex;
3270                 }
3271
3272                 internal sealed override void Write(BinaryWriter bw) 
3273                 {
3274                         bw.Write((int)0); 
3275                 }
3276
3277         }
3278
3279         public class AddressConstant : DataConstant {
3280                 DataConstant data;
3281
3282                 public AddressConstant(DataConstant dConst) 
3283                 {
3284                         data = dConst;
3285                         size = 4;
3286                         type = PrimitiveType.TypedRef;
3287                 }
3288
3289                 internal sealed override void Write(BinaryWriter bw) 
3290                 {
3291                         ((FileImage)bw).WriteDataRVA(data.DataOffset);
3292                 }
3293
3294         }
3295
3296         public class RepeatedConstant : DataConstant {
3297                 DataConstant data;
3298                 uint repCount;
3299
3300                 public RepeatedConstant(DataConstant dConst, int repeatCount) 
3301                 {
3302                         data = dConst;
3303                         repCount = (uint)repeatCount;
3304                         int[] sizes = new int[1];
3305                         sizes[0] = repeatCount;
3306                         type = new BoundArray(type,1,sizes);
3307                         size = data.GetSize() * repCount;
3308                 }
3309
3310                 internal sealed override void Write(BinaryWriter bw) 
3311                 {
3312                         for (int i=0; i < repCount; i++) {
3313                                 data.Write(bw);
3314                         }
3315                 }
3316
3317         }
3318
3319         public class ArrayConstant : DataConstant {
3320                 DataConstant[] dataVals;
3321
3322                 public ArrayConstant(DataConstant[] dVals) 
3323                 {
3324                         dataVals = dVals;
3325                         for (int i=0; i < dataVals.Length; i++) {
3326                                 size += dataVals[i].GetSize();
3327                         }
3328                 }
3329
3330                 public int? ExplicitSize { get; set; }
3331
3332                 internal sealed override void Write(BinaryWriter bw) 
3333                 {
3334                         for (int i=0; i < dataVals.Length; i++) {
3335                                 dataVals[i].Write(bw);
3336                         }
3337                 }
3338
3339         }
3340
3341         public class ClassType : Constant {
3342                 string name;
3343                 Class desc;
3344
3345                 public ClassType(string className) 
3346                 {
3347                         name = className;
3348                         type = PrimitiveType.ClassType;
3349                 }
3350
3351                 public ClassType(Class classDesc) 
3352                 {
3353                         desc = classDesc;
3354                         type = PrimitiveType.ClassType;
3355                 }
3356
3357                 internal override void Write(BinaryWriter bw) 
3358                 {
3359                         if (name == null)  name = desc.TypeName();
3360                         bw.Write(name);
3361                 }
3362
3363         }
3364
3365         #endregion
3366
3367         /**************************************************************************/  
3368         /// <summary>
3369         /// Descriptor for a custom modifier of a type (modopt or modreq)
3370         /// </summary>
3371
3372         public class CustomModifiedType : Type {
3373
3374                 Type type;
3375                 Class cmodType;
3376                 PrimitiveTypeRef cmodPrimType;
3377
3378                 /// <summary>
3379                 /// Create a new custom modifier for a type
3380                 /// </summary>
3381                 /// <param name="type">the type to be modified</param>
3382                 /// <param name="cmod">the modifier</param>
3383                 /// <param name="cmodType">the type reference to be associated with the type</param>
3384                 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3385                         : base((byte)cmod) 
3386                 {
3387                         this.type = type;
3388                         this.cmodType = cmodType;
3389                 }
3390
3391                 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3392                         : base((byte)cmod)
3393                 {
3394                         this.type = type;
3395                         this.cmodPrimType = cmodType;
3396                 }
3397
3398                 internal sealed override void TypeSig(MemoryStream str) 
3399                 {
3400                         str.WriteByte(typeIndex);
3401
3402                         if (cmodType != null) {
3403                                 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3404                         } else {
3405                                 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3406                         }
3407
3408                         type.TypeSig(str);
3409                 }
3410
3411         }
3412
3413         /**************************************************************************/  
3414         /// <summary>
3415         /// Base class for Event and Property descriptors
3416         /// </summary>
3417
3418         public class Feature : MetaDataElement {
3419
3420                 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08, 
3421                         RemoveOn = 0x10, Fire = 0x20 }
3422
3423                 private static readonly int INITSIZE = 5;
3424                 private static readonly ushort specialName = 0x200;
3425                 private static readonly ushort rtSpecialName = 0x400;
3426
3427                 protected ClassDef parent;
3428                 protected ushort flags = 0;
3429                 protected string name;
3430                 protected int tide = 0;
3431                 protected uint nameIx;
3432                 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3433
3434                 internal Feature(string name, ClassDef par) 
3435                 {
3436                         parent = par;
3437                         this.name = name;
3438                 }
3439
3440                 internal void AddMethod(MethodDef meth, MethodType mType) 
3441                 {
3442                         if (tide >= methods.Length) { 
3443                                 int len = methods.Length;
3444                                 MethodSemantics[] mTmp = methods;
3445                                 methods = new MethodSemantics[len * 2];
3446                                 for (int i=0; i < len; i++) {
3447                                         methods[i] = mTmp[i];
3448                                 }
3449                         }
3450                         methods[tide++] = new MethodSemantics(mType,meth,this);
3451                 }
3452
3453                 /// <summary>
3454                 /// Set the specialName attribute for this Event or Property
3455                 /// </summary>
3456                 public void SetSpecialName() 
3457                 {
3458                         flags |= specialName;
3459                 }
3460
3461                 /// <summary>
3462                 /// Set the RTSpecialName attribute for this Event or Property
3463                 /// </summary>
3464                 public void SetRTSpecialName() 
3465                 {
3466                         flags |= rtSpecialName;
3467                 }
3468
3469         }
3470
3471         /**************************************************************************/  
3472         /// <summary>
3473         /// Descriptor for an event
3474         /// </summary>
3475         public class Event : Feature {
3476
3477                 Type eventType;
3478
3479                 internal Event(string name, Type eType, ClassDef parent) 
3480                         : base(name, parent) 
3481                 {
3482                         eventType = eType;
3483                         tabIx = MDTable.Event;
3484                 }
3485
3486                 /// <summary>
3487                 /// Add the addon method to this event
3488                 /// </summary>
3489                 /// <param name="addon">the addon method</param>
3490                 public void AddAddon(MethodDef addon) 
3491                 {
3492                         AddMethod(addon,MethodType.AddOn);
3493                 }
3494
3495                 /// <summary>
3496                 /// Add the removeon method to this event
3497                 /// </summary>
3498                 /// <param name="removeOn">the removeon method</param>
3499                 public void AddRemoveOn(MethodDef removeOn) 
3500                 {
3501                         AddMethod(removeOn,MethodType.RemoveOn);
3502                 }
3503
3504                 /// <summary>
3505                 /// Add the fire method to this event
3506                 /// </summary>
3507                 /// <param name="fire">the fire method</param>
3508                 public void AddFire(MethodDef fire) 
3509                 {
3510                         AddMethod(fire,MethodType.Fire);
3511                 }
3512
3513                 /// <summary>
3514                 /// Add another method to this event
3515                 /// </summary>
3516                 /// <param name="other">the method to be added</param>
3517                 public void AddOther(MethodDef other) 
3518                 {
3519                         AddMethod(other,MethodType.Other);
3520                 }
3521
3522                 internal sealed override void BuildTables(MetaData md) 
3523                 {
3524                         if (done) return;
3525                         nameIx = md.AddToStringsHeap(name);
3526                         for (int i=0; i < tide; i++) {
3527                                 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3528                         }
3529                         done = true;
3530                 }
3531
3532                 internal sealed override uint Size(MetaData md) 
3533                 {
3534                         return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3535                 }
3536
3537                 internal sealed override void Write(FileImage output) 
3538                 {
3539                         output.Write(flags);
3540                         output.StringsIndex(nameIx);
3541                         output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3542                 }
3543
3544                 internal sealed override uint GetCodedIx(CIx code) 
3545                 {
3546                         switch (code) {
3547                                 case (CIx.HasCustomAttr) : return 10; 
3548                                 case (CIx.HasSemantics) : return 0; 
3549                         }
3550                         return 0;
3551                 }
3552
3553         }
3554
3555         /**************************************************************************/  
3556         /// <summary>
3557         /// Descriptor for the Property of a class
3558         /// </summary>
3559         public class Property : Feature {
3560
3561                 private static readonly byte PropertyTag = 0x8;
3562                 private bool instance;
3563                 MethodDef getterMeth;
3564                 ConstantElem constVal;
3565                 uint typeBlobIx = 0;
3566                 Type[] parList;
3567                 Type returnType;
3568                 uint numPars = 0;
3569
3570                 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) 
3571                 {
3572                         returnType = retType;
3573                         parList = pars;
3574                         if (pars != null) numPars = (uint)pars.Length;
3575                         tabIx = MDTable.Property;
3576                 }
3577
3578                 /// <summary>
3579                 /// Add a set method to this property
3580                 /// </summary>
3581                 /// <param name="setter">the set method</param>
3582                 public void AddSetter(MethodDef setter) 
3583                 {
3584                         AddMethod(setter,MethodType.Setter);
3585                 }
3586
3587                 /// <summary>
3588                 /// Add a get method to this property
3589                 /// </summary>
3590                 /// <param name="getter">the get method</param>
3591                 public void AddGetter(MethodDef getter) 
3592                 {
3593                         AddMethod(getter,MethodType.Getter);
3594                         getterMeth = getter;
3595                 }
3596
3597                 /// <summary>
3598                 /// Add another method to this property
3599                 /// </summary>
3600                 /// <param name="other">the method</param>
3601                 public void AddOther(MethodDef other) 
3602                 {
3603                         AddMethod(other,MethodType.Other);
3604                 }
3605
3606                 /// <summary>
3607                 /// Add an initial value for this property
3608                 /// </summary>
3609                 /// <param name="constVal">the initial value for this property</param>
3610                 public void AddInitValue(Constant constVal) 
3611                 {
3612                         this.constVal = new ConstantElem(this,constVal);
3613                 }
3614
3615                 public void SetInstance (bool isInstance)
3616                 {
3617                         this.instance = isInstance;
3618                 }
3619
3620                 internal sealed override void BuildTables(MetaData md) 
3621                 {
3622                         if (done) return;
3623                         nameIx = md.AddToStringsHeap(name);
3624                         MemoryStream sig = new MemoryStream();
3625                         byte tag = PropertyTag;
3626                         if (instance)
3627                                 tag |= 0x20;
3628                         sig.WriteByte(tag);
3629                         MetaData.CompressNum(numPars,sig);
3630                         returnType.TypeSig(sig);
3631                         for (int i=0; i < numPars; i++) {
3632                                 parList[i].TypeSig(sig);
3633                         }
3634                         typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3635                         for (int i=0; i < tide; i++) {
3636                                 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3637                         }
3638                         if (constVal != null) {
3639                                 md.AddToTable(MDTable.Constant,constVal);
3640                                 constVal.BuildTables(md);
3641                         }
3642                         done = true;
3643                 }
3644
3645                 internal sealed override uint Size(MetaData md) 
3646                 {
3647                         return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3648                 }
3649
3650                 internal sealed override void Write(FileImage output) 
3651                 {
3652                         output.Write(flags);
3653                         output.StringsIndex(nameIx);
3654                         output.BlobIndex(typeBlobIx);
3655                 }
3656
3657                 internal sealed override uint GetCodedIx(CIx code) 
3658                 {
3659                         switch (code) {
3660                                 case (CIx.HasCustomAttr) : return 9; 
3661                                 case (CIx.HasConst) : return 2; 
3662                                 case (CIx.HasSemantics) : return 1; 
3663                         }
3664                         return 0;
3665                 }
3666
3667         }
3668
3669         /**************************************************************************/  
3670         /// <summary>
3671         /// Base class for field/methods (member of a class)
3672         /// </summary>
3673         public abstract class Member : MetaDataElement {
3674
3675                 protected string name;
3676                 protected uint nameIx = 0, sigIx = 0;
3677
3678                 internal Member(string memName)
3679                 {
3680                         name = memName;
3681                         tabIx = MDTable.MemberRef;
3682                 }
3683
3684         }
3685
3686         /*****************************************************************************/  
3687         /// <summary>
3688         /// Descriptor for a field of a class
3689         /// </summary>
3690
3691         public abstract class Field : Member {
3692
3693                 protected static readonly byte FieldSig = 0x6;
3694
3695                 protected Type type;
3696
3697                 internal Field(string pfName, Type pfType) : base(pfName)
3698                 {
3699                         type = pfType;
3700                 }
3701
3702         }
3703         /**************************************************************************/  
3704         /// <summary>
3705         /// Descriptor for a field defined in a class of THIS assembly/module
3706         /// </summary>
3707         public class FieldDef : Field {
3708
3709                 //private static readonly uint PInvokeImpl = 0x2000;
3710                 private static readonly ushort HasFieldRVA = 0x100;
3711                 private static readonly ushort HasDefault = 0x8000;
3712
3713                 FieldRVA rva;
3714                 ConstantElem constVal;
3715                 FieldLayout layout;
3716                 FieldMarshal marshalInfo;
3717                 ushort flags;
3718
3719                 internal FieldDef(string name, Type fType) : base(name,fType) 
3720                 {
3721                         tabIx = MDTable.Field;
3722                 }
3723
3724                 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) 
3725                 {
3726                         flags = (ushort)attrSet;
3727                         tabIx = MDTable.Field;
3728                 }
3729
3730                 /// <summary>
3731                 /// Add an attribute(s) to this field
3732                 /// </summary>
3733                 /// <param name="fa">the attribute(s) to be added</param>
3734                 public void AddFieldAttr(FieldAttr fa) 
3735                 {
3736                         flags |= (ushort)fa;
3737                 }
3738
3739                 /// <summary>
3740                 /// Add a value for this field
3741                 /// </summary>
3742                 /// <param name="val">the value for the field</param>
3743                 public void AddValue(Constant val) 
3744                 {
3745                         constVal = new ConstantElem(this,val);
3746                         flags |= HasDefault;
3747                 }
3748
3749                 /// <summary>
3750                 /// Add an initial value for this field (at dataLabel) (.data)
3751                 /// </summary>
3752                 /// <param name="val">the value for the field</param>
3753                 /// <param name="repeatVal">the number of repetitions of this value</param>
3754                 public void AddDataValue(DataConstant val) 
3755                 {
3756                         flags |= HasFieldRVA;
3757                         rva = new FieldRVA(this,val);
3758                 }
3759
3760                 /// <summary>
3761                 /// Set the offset of the field.  Used for sequential or explicit classes.
3762                 /// (.field [offs])
3763                 /// </summary>
3764                 /// <param name="offs">field offset</param>
3765                 public void SetOffset(uint offs) 
3766                 {
3767                         layout = new FieldLayout(this,offs);
3768                 }
3769
3770                 /// <summary>
3771                 /// Set the marshalling info for a field
3772                 /// </summary>
3773                 /// <param name="mInf"></param>
3774                 public void SetMarshalInfo(NativeType marshallType) 
3775                 {
3776                         flags |= (ushort) FieldAttr.HasFieldMarshal;
3777                         marshalInfo = new FieldMarshal(this,marshallType);
3778                 }
3779
3780                 internal sealed override void BuildTables(MetaData md) 
3781                 {
3782                         if (done) return;
3783                         nameIx = md.AddToStringsHeap(name);
3784                         MemoryStream sig = new MemoryStream();
3785                         sig.WriteByte(FieldSig);
3786                         type.TypeSig(sig);
3787                         sigIx = md.AddToBlobHeap(sig.ToArray());
3788                         if (rva != null) {
3789                                 md.AddToTable(MDTable.FieldRVA,rva);
3790                                 rva.BuildTables(md);
3791                         } else if (constVal != null) {
3792                                 md.AddToTable(MDTable.Constant,constVal);
3793                                 constVal.BuildTables(md);
3794                         }
3795                         if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3796                         if (marshalInfo != null) {
3797                                 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3798                                 marshalInfo.BuildTables(md);
3799                         }
3800                         done = true;
3801                 }
3802
3803                 internal sealed override uint Size(MetaData md) 
3804                 {
3805                         return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3806                 }
3807
3808                 internal sealed override void Write(FileImage output) 
3809                 {
3810                         output.Write(flags);
3811                         output.StringsIndex(nameIx);
3812                         output.BlobIndex(sigIx);
3813                 }
3814
3815                 internal sealed override uint GetCodedIx(CIx code) 
3816                 {
3817                         switch (code) {
3818                                 case (CIx.HasConst) : return 0; 
3819                                 case (CIx.HasCustomAttr) : return 1; 
3820                                 case (CIx.HasFieldMarshal) : return 0; 
3821                                 case (CIx.MemberForwarded) : return 0; 
3822                         }
3823                         return 0;
3824                 }
3825
3826         }
3827
3828         /**************************************************************************/  
3829         /// <summary>
3830         /// Descriptor for a field of a class defined in another assembly/module
3831         /// </summary>
3832         public class FieldRef : Field {
3833
3834                 MetaDataElement parent;
3835
3836                 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)   
3837                 {
3838                         parent = paren;
3839                 }
3840
3841                 internal sealed override void BuildTables(MetaData md) 
3842                 {
3843                         if (done) return;
3844                         nameIx = md.AddToStringsHeap(name);
3845                         MemoryStream sig = new MemoryStream();
3846                         sig.WriteByte(FieldSig);
3847                         type.TypeSig(sig);
3848                         sigIx = md.AddToBlobHeap(sig.ToArray());
3849                         done = true;
3850                 }
3851
3852                 internal sealed override uint Size(MetaData md) 
3853                 {
3854                         return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3855                 }
3856
3857                 internal sealed override void Write(FileImage output) 
3858                 {
3859                         output.WriteCodedIndex(CIx.MemberRefParent,parent);
3860                         output.StringsIndex(nameIx);
3861                         output.BlobIndex(sigIx);
3862                 }
3863
3864                 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3865
3866         }
3867
3868         /**************************************************************************/  
3869         /// <summary>
3870         /// Base class for Method Descriptors
3871         /// </summary>
3872
3873         public abstract class Method : Member {
3874
3875                 internal Method (string methName) : base (methName)
3876                 {}
3877
3878                 public abstract void AddCallConv(CallConv cconv);
3879                 internal abstract void TypeSig(MemoryStream sig);
3880                 internal abstract uint GetSigIx(MetaData md);
3881         }
3882
3883         /**************************************************************************/  
3884         /// <summary>
3885         /// Descriptor for a method defined in THIS assembly/module
3886         /// IL     .method
3887         /// </summary>
3888
3889         public class MethodDef : Method {
3890
3891                 private static readonly ushort PInvokeImpl = 0x2000;
3892                 //private static readonly uint UnmanagedExport = 0x0008;
3893                 // private static readonly byte LocalSigByte = 0x7;
3894                 uint parIx = 0, textOffset = 0;
3895                 private CallConv callConv = CallConv.Default;
3896                 private int gen_param_count;
3897
3898                 MetaData metaData;
3899                 CILInstructions code;
3900                 Param[] parList;
3901                 Local[] locals;
3902                 bool initLocals;
3903                 ushort methFlags = 0, implFlags = 0;
3904                 int maxStack = 0, numPars = 0;
3905                 bool entryPoint = false;
3906                 LocalSig localSig;
3907                 ArrayList varArgSigList;
3908                 ImplMap pinvokeImpl;
3909                 Param ret_param;
3910
3911                 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3912                         : this (md, 0, 0, name, ret_param, pars)
3913                 {
3914                 }
3915
3916                 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, 
3917                                 Param ret_param, Param [] pars) 
3918                         : base (name)
3919                 {
3920                         methFlags = (ushort)mAttrSet;
3921                         implFlags = (ushort)iAttrSet;
3922                         this.ret_param = ret_param;
3923                         metaData = md;
3924                         parList = pars;
3925                         if (parList != null) 
3926                                 numPars = parList.Length;
3927                         tabIx = MDTable.Method;
3928                 }
3929
3930                 internal Param[] GetPars() 
3931                 {
3932                         return parList;
3933                 }
3934
3935                 internal override uint GetSigIx(MetaData md)
3936                 {
3937                         MemoryStream sig = new MemoryStream();
3938                         TypeSig(sig);
3939                         return md.AddToBlobHeap(sig.ToArray());
3940                 }
3941
3942                 public override void AddCallConv(CallConv cconv)
3943                 {
3944                         callConv |= cconv;
3945                 }
3946                 
3947                 /// <summary>
3948                 /// Add some attributes to this method descriptor
3949                 /// </summary>
3950                 /// <param name="ma">the attributes to be added</param>
3951                 public void AddMethAttribute(MethAttr ma) 
3952                 {
3953                         methFlags |= (ushort)ma;
3954                 }
3955
3956                 /// <summary>
3957                 /// Add some implementation attributes to this method descriptor
3958                 /// </summary>
3959                 /// <param name="ia">the attributes to be added</param>
3960                 public void AddImplAttribute(ImplAttr ia) 
3961                 {
3962                         implFlags |= (ushort)ia;
3963                 }
3964
3965                 public void AddPInvokeInfo(ModuleRef scope, string methName,
3966                                 PInvokeAttr callAttr) {
3967                         pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3968                         methFlags |= PInvokeImpl;
3969                 }
3970
3971                 /// <summary>
3972                 ///  Add a named generic type parameter
3973                 /// </summary>
3974                 public GenericParameter AddGenericParameter (short index, string name) 
3975                 {
3976                         return AddGenericParameter (index, name, 0);
3977                 }
3978
3979                 /// <summary>
3980                 ///  Add a named generic type parameter with attributes
3981                 /// </summary>
3982                 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr) 
3983                 {
3984                         GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3985                         metaData.AddToTable (MDTable.GenericParam, gp);
3986                         gen_param_count ++;
3987                         return gp;
3988                 }
3989
3990                 /// <summary>
3991                 /// Set the maximum stack height for this method
3992                 /// </summary>
3993                 /// <param name="maxStack">the maximum height of the stack</param>
3994                 public void SetMaxStack(int maxStack) 
3995                 {
3996                         this.maxStack = maxStack; 
3997                 }
3998
3999                 /// <summary>
4000                 /// Add local variables to this method
4001                 /// </summary>
4002                 /// <param name="locals">the locals to be added</param>
4003                 /// <param name="initLocals">are locals initialised to default values</param>
4004                 public void AddLocals(Local[] locals, bool initLocals) 
4005                 {
4006                         this.locals = locals;
4007                         this.initLocals = initLocals;
4008                 }
4009
4010                 /* Add Marshal info for return type */
4011                 public void AddRetTypeMarshallInfo (NativeType marshallType) 
4012                 {
4013                         ret_param.AddMarshallInfo (marshallType);
4014                 }
4015
4016                 /// <summary>
4017                 /// Mark this method as having an entry point
4018                 /// </summary>
4019                 public void DeclareEntryPoint() 
4020                 {
4021                         entryPoint = true;
4022                 }
4023
4024                 /// <summary>
4025                 /// Create a code buffer for this method to add the IL instructions to
4026                 /// </summary>
4027                 /// <returns>a buffer for this method's IL instructions</returns>
4028                 public CILInstructions CreateCodeBuffer() 
4029                 {
4030                         code = new CILInstructions(metaData);
4031                         return code;
4032                 }
4033
4034                 /// <summary>
4035                 /// Make a method reference descriptor for this method to be used 
4036                 /// as a callsite signature for this vararg method
4037                 /// </summary>
4038                 /// <param name="optPars">the optional pars for the vararg method call</param>
4039                 /// <returns></returns>
4040                 public MethodRef MakeVarArgSignature(Type[] optPars) 
4041                 {
4042                         Type[] pars = new Type[numPars];
4043                         MethodRef varArgSig;
4044                         for (int i=0; i < numPars; i++) {
4045                                 pars[i] = parList[i].GetParType();
4046                         }
4047                         varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
4048
4049                         if (varArgSigList == null)
4050                                 varArgSigList = new ArrayList ();
4051                         varArgSigList.Add (varArgSig);
4052                         return varArgSig;
4053                 }
4054
4055                 internal sealed override void TypeSig(MemoryStream sig) 
4056                 {
4057                         sig.WriteByte((byte)callConv);
4058                         if ((callConv & CallConv.Generic) == CallConv.Generic)
4059                                 MetaData.CompressNum ((uint) gen_param_count, sig);
4060                         MetaData.CompressNum((uint)numPars,sig);
4061
4062                         ret_param.seqNo = 0;
4063                         ret_param.TypeSig (sig);
4064                         for (ushort i=0; i < numPars; i++) {
4065                                 parList[i].seqNo = (ushort)(i+1);
4066                                 parList[i].TypeSig(sig);
4067                         }
4068                 }
4069
4070                 internal sealed override void BuildTables(MetaData md) 
4071                 {
4072                         if (done) return;
4073                         if (pinvokeImpl != null) {
4074                                 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4075                                 pinvokeImpl.BuildTables(md);
4076                         }
4077                         if (entryPoint) md.SetEntryPoint(this);
4078                         uint locToken = 0;
4079                         if (locals != null) {
4080                                 localSig = new LocalSig(locals);
4081                                 md.AddToTable(MDTable.StandAloneSig,localSig);
4082                                 localSig.BuildTables(md);
4083                                 locToken = localSig.Token();
4084                         }
4085                         if (code != null) {
4086                                 code.CheckCode(locToken,initLocals,maxStack);
4087                                 textOffset = md.AddCode(code);
4088                         }
4089                         nameIx = md.AddToStringsHeap(name);
4090                         sigIx = GetSigIx(md);
4091                         parIx = md.TableIndex(MDTable.Param);
4092                         if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4093                                 md.AddToTable(MDTable.Param, ret_param);
4094                                 ret_param.BuildTables(md);
4095                         }
4096                         for (int i=0; i < numPars; i++) {
4097                                 md.AddToTable(MDTable.Param,parList[i]);
4098                                 parList[i].BuildTables(md);
4099                         }
4100                         if (varArgSigList != null) {
4101                                 foreach (MethodRef varArgSig in varArgSigList) {
4102                                         md.AddToTable(MDTable.MemberRef,varArgSig);
4103                                         varArgSig.BuildTables(md);
4104                                 }
4105                         }
4106                         // Console.WriteLine("method has " + numPars + " parameters");
4107                         done = true;
4108                 }
4109
4110                 internal sealed override uint Size(MetaData md) 
4111                 {
4112                         return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4113                 }
4114
4115                 internal sealed override void Write(FileImage output) 
4116                 {
4117                         if (ZeroRva ()) output.Write(0);
4118                         else output.WriteCodeRVA(textOffset);
4119                         output.Write(implFlags);
4120                         output.Write(methFlags);
4121                         output.StringsIndex(nameIx);
4122                         output.BlobIndex(sigIx);
4123                         output.WriteIndex(MDTable.Param,parIx);
4124                 }
4125
4126                 internal bool ZeroRva () 
4127                 {
4128                         return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4129                                         ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4130                                         ((implFlags & (ushort)ImplAttr.InternalCall) != 0) || 
4131                                         (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4132                 }
4133
4134                 internal sealed override uint GetCodedIx(CIx code) 
4135                 {
4136                         switch (code) {
4137                                 case (CIx.HasCustomAttr) : return 0; 
4138                                 case (CIx.HasDeclSecurity) : return 1; 
4139                                 case (CIx.MemberRefParent) : return 3; 
4140                                 case (CIx.MethodDefOrRef) : return 0; 
4141                                 case (CIx.MemberForwarded) : return 1; 
4142                                 case (CIx.CustomAttributeType) : return 2; 
4143                                 case (CIx.TypeOrMethodDef) : return 1; 
4144                         }
4145                         return 0;
4146                 }
4147
4148         }
4149         /**************************************************************************/  
4150         /// <summary>
4151         /// Descriptor for a method defined in another assembly/module
4152         /// </summary>
4153         public class MethodRef : Method {
4154
4155                 private static readonly byte Sentinel = 0x41;
4156                 Type[] parList, optParList;
4157                 MetaDataElement parent;
4158                 uint numPars = 0, numOptPars = 0;
4159                 CallConv callConv = CallConv.Default;
4160                 Type retType;
4161                 int gen_param_count;
4162
4163                 internal MethodRef(MetaDataElement paren, string name, Type retType,
4164                                 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4165                 {
4166                         parent = paren;
4167                         parList = pars;
4168                         this.retType = retType;
4169                         if (parList != null) numPars = (uint)parList.Length;
4170                         if (varArgMeth) {
4171                                 optParList = optPars;
4172                                 if (optParList != null) numOptPars = (uint)optParList.Length;
4173                                 callConv = CallConv.Vararg;
4174                         }
4175                         this.gen_param_count = gen_param_count;
4176                 }
4177
4178                 internal override uint GetSigIx(MetaData md)
4179                 {
4180                         MemoryStream sig = new MemoryStream();
4181                         TypeSig(sig);
4182                         return md.AddToBlobHeap(sig.ToArray());
4183                 }
4184
4185                 public override void AddCallConv(CallConv cconv)
4186                 {
4187                         callConv |= cconv;
4188                 }
4189                 
4190                 internal sealed override void TypeSig(MemoryStream sig) 
4191                 {
4192                         sig.WriteByte((byte)callConv);
4193                         if ((callConv & CallConv.Generic) == CallConv.Generic)
4194                                 MetaData.CompressNum ((uint) gen_param_count, sig);
4195                         MetaData.CompressNum(numPars+numOptPars,sig);
4196                         retType.TypeSig(sig);
4197                         for (int i=0; i < numPars; i++) {
4198                                 parList[i].TypeSig(sig);
4199                         }
4200                         if (numOptPars > 0) {
4201                                 sig.WriteByte(Sentinel);
4202                                 for (int i=0; i < numOptPars; i++) {
4203                                         optParList[i].TypeSig(sig);
4204                                 }
4205                         }
4206                 }
4207
4208                 internal sealed override void BuildTables(MetaData md) 
4209                 {
4210                         if (done) return;
4211                         nameIx = md.AddToStringsHeap(name);
4212                         sigIx = GetSigIx(md);
4213                         done = true;
4214                 }
4215
4216                 internal sealed override uint Size(MetaData md) 
4217                 {
4218                         return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4219                 }
4220
4221                 internal sealed override void Write(FileImage output) 
4222                 {
4223                         output.WriteCodedIndex(CIx.MemberRefParent,parent);
4224                         output.StringsIndex(nameIx);
4225                         output.BlobIndex(sigIx);
4226                 }
4227
4228                 internal sealed override uint GetCodedIx(CIx code) 
4229                 {
4230                         switch (code) {
4231                                 case (CIx.HasCustomAttr) : return 6; 
4232                                 case (CIx.MethodDefOrRef) : return 1; 
4233                                 case (CIx.CustomAttributeType) : return 3; 
4234                         }
4235                         return 0;
4236                 }
4237
4238         }
4239
4240
4241         /**************************************************************************/  
4242         /// <summary>
4243         /// Descriptors for native types used for marshalling
4244         /// </summary>
4245         public class NativeType {
4246                 public static readonly NativeType Void = new NativeType(0x01);
4247                 public static readonly NativeType Boolean = new NativeType(0x02);
4248                 public static readonly NativeType Int8 = new NativeType(0x03);
4249                 public static readonly NativeType UInt8 = new NativeType(0x04);
4250                 public static readonly NativeType Int16 = new NativeType(0x05);
4251                 public static readonly NativeType UInt16 = new NativeType(0x06);
4252                 public static readonly NativeType Int32 = new NativeType(0x07);
4253                 public static readonly NativeType UInt32 = new NativeType(0x08);
4254                 public static readonly NativeType Int64 = new NativeType(0x09);
4255                 public static readonly NativeType UInt64 = new NativeType(0x0A);
4256                 public static readonly NativeType Float32 = new NativeType(0x0B);
4257                 public static readonly NativeType Float64 = new NativeType(0x0C);
4258                 public static readonly NativeType Currency = new NativeType(0x0F);
4259                 public static readonly NativeType BStr = new NativeType(0x13);
4260                 public static readonly NativeType LPStr = new NativeType(0x14);
4261                 public static readonly NativeType LPWStr = new NativeType(0x15);
4262                 public static readonly NativeType LPTStr = new NativeType(0x16);
4263                 public static readonly NativeType FixedSysString = new NativeType(0x17);
4264                 public static readonly NativeType IUnknown = new NativeType(0x19);
4265                 public static readonly NativeType IDispatch = new NativeType(0x1A);
4266                 public static readonly NativeType Struct = new NativeType(0x1B);
4267                 public static readonly NativeType Interface = new NativeType(0x1C);
4268                 public static readonly NativeType Int = new NativeType(0x1F);
4269                 public static readonly NativeType UInt = new NativeType(0x20);
4270                 public static readonly NativeType ByValStr = new NativeType(0x22);
4271                 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4272                 public static readonly NativeType TBstr = new NativeType(0x24);
4273                 public static readonly NativeType VariantBool = new NativeType(0x25);
4274                 public static readonly NativeType FuncPtr = new NativeType(0x26);
4275                 public static readonly NativeType AsAny = new NativeType(0x28);
4276                 public static readonly NativeType LPStruct = new NativeType(0x2b);
4277                 public static readonly NativeType Error = new NativeType(0x2d);
4278
4279                 protected byte typeIndex;
4280
4281                 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4282                 internal byte GetTypeIndex() { return typeIndex; }
4283
4284                 internal virtual byte[] ToBlob() 
4285                 {
4286                         byte[] bytes = new byte[1];
4287                         bytes[0] = GetTypeIndex();
4288                         return bytes;
4289                 }
4290
4291         }
4292
4293         public class FixedSysString : NativeType  {
4294
4295                 uint size;
4296
4297                 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4298                 {
4299                         this.size = size;
4300                 }
4301
4302                 internal override byte [] ToBlob () 
4303                 {
4304                         MemoryStream str = new MemoryStream ();
4305                         str.WriteByte (GetTypeIndex ());
4306                         MetaData.CompressNum (size, str);
4307                         return str.ToArray ();
4308                 }
4309
4310         }  
4311
4312         public class NativeArray : NativeType  {
4313
4314                 NativeType elemType;
4315                 int numElem = -1, parNum = -1, elemMult = -1;
4316
4317                 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1) 
4318                 {
4319                         this.elemType = elemType;
4320                 }
4321
4322                 /*    public NativeArray(NativeType elemType, int len) : base(0x2A) {
4323                       this.elemType = elemType;
4324                       this.len = len;
4325                       }
4326                  */
4327
4328                 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A) 
4329                 {
4330                         this.elemType = elemType;
4331                         this.numElem = numElem;
4332                         parNum = parNumForLen;
4333                         this.elemMult = elemMult;
4334                 }
4335
4336                 public NativeArray(NativeType elemType, int numElem, int parNumForLen) 
4337                         : this (elemType, numElem, parNumForLen, -1) 
4338                 {
4339                 }
4340
4341                 internal override byte[] ToBlob() 
4342                 {
4343                         MemoryStream str = new MemoryStream();
4344                         str.WriteByte(GetTypeIndex());
4345                         if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
4346                         else str.WriteByte(elemType.GetTypeIndex());
4347
4348                         /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4349                          * LAMESPEC: Older spec versions say elemMult comes before
4350                          * len. Newer spec versions don't talk about elemMult at
4351                          * all, but csc still emits it, and it is used to distinguish
4352                          * between parNum being 0, and parNum being omitted.
4353                          */
4354
4355                         if (parNum == -1)
4356                                 // <native_type> []
4357                                 return str.ToArray ();
4358
4359                         MetaData.CompressNum((uint) parNum,str);
4360                         if (numElem != -1) {
4361                                 MetaData.CompressNum ((uint) numElem, str);
4362                                 if (elemMult != -1)
4363                                         // <native_type> [ int32 ]
4364                                         MetaData.CompressNum((uint) elemMult,str);
4365                                 //else <native_type> [ int32 + int32 ]
4366                         } else if (elemMult != -1) {
4367                                 // When can this occur ?
4368                                 MetaData.CompressNum (0, str);
4369                                 MetaData.CompressNum((uint) elemMult,str);
4370                         }
4371                         //else <native_type> [ + int32 ]
4372
4373                         return str.ToArray();
4374                 }
4375
4376         }
4377
4378         public class SafeArray : NativeType  {
4379
4380                 SafeArrayType elemType;
4381                 bool hasElemType;
4382
4383                 public SafeArray() : base(0x1D) 
4384                 {
4385                 }
4386
4387                 public SafeArray(SafeArrayType elemType) : base(0x1D) 
4388                 {
4389                         this.elemType = elemType;
4390                         hasElemType = true;
4391                 }
4392
4393                 internal override byte[] ToBlob() 
4394                 {
4395                         byte[] bytes = new byte[hasElemType ? 2 : 1];
4396                         bytes[0] = GetTypeIndex();
4397                         if (hasElemType)
4398                                 bytes[1] = (byte)elemType;
4399                         return bytes;
4400                 }
4401
4402         }
4403
4404         public class FixedArray : NativeType  {
4405
4406                 uint numElem;
4407
4408                 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4409                 public FixedArray(int numElems) : base(0x1E) 
4410                 {
4411                         //this.elemType = elemType;
4412                         numElem = (uint)numElems;
4413                 }
4414
4415                 internal override byte[] ToBlob() 
4416                 {
4417                         MemoryStream str = new MemoryStream();
4418                         str.WriteByte(GetTypeIndex());
4419                         MetaData.CompressNum(numElem,str);
4420                         /* FIXME: 
4421                            fixed array [5] lpstr [2]
4422                            This format is not supported by ilasm 1.1.4322.2032, 
4423                            but is supported by 2.0.5125..
4424                            ilasm 1.1 only supports "fixed array [5]" 
4425                            if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
4426                            else str.WriteByte(elemType.GetTypeIndex());*/
4427
4428                         return str.ToArray();
4429                 }
4430
4431         }
4432
4433         public class CustomMarshaller : NativeType  {
4434
4435                 string typeName;
4436                 string marshallerName;
4437                 string cookie;
4438
4439                 public CustomMarshaller(string typeNameOrGUID, string marshallerName, 
4440                                 string optCookie) : base(0x2C) 
4441                 {
4442                         typeName = typeNameOrGUID;
4443                         this.marshallerName = marshallerName;
4444                         cookie = optCookie;
4445                 }
4446
4447                 public CustomMarshaller(string marshallerName, string optCookie)
4448                         :this (null, marshallerName, optCookie) 
4449                 {
4450                 }
4451
4452                 internal override byte[] ToBlob() 
4453                 {
4454                         MemoryStream str = new MemoryStream();
4455                         BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4456                         bw.Write(GetTypeIndex());
4457                         //Native type name & unmanaged type - unused
4458                         //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4459                         bw.Write ((byte) 0); // Native Type name, unused 
4460                         bw.Write ((byte) 0); // Unmanaged type, unused 
4461                         if (marshallerName != null) {
4462                                 MetaData.CompressNum ((uint)marshallerName.Length, str);
4463                                 bw.Write(marshallerName.ToCharArray());
4464                         } else { 
4465                                 bw.Write ((byte) 0);
4466                         }
4467                         if (cookie != null) {
4468                                 MetaData.CompressNum ((uint)cookie.Length, str);
4469                                 bw.Write(cookie.ToCharArray());
4470                         } else {
4471                                 bw.Write ((byte) 0);
4472                         }
4473                         bw.Flush();
4474                         return str.ToArray();
4475                 }
4476         }
4477
4478         /**************************************************************************/  
4479         /// <summary>
4480         /// Descriptor for the Primitive types defined in IL
4481         /// </summary>
4482         public class PrimitiveType : Type {
4483
4484                 private string name;
4485                 private int systemTypeIndex;
4486                 public static int NumSystemTypes = 18;
4487
4488                 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4489                 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4490                 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4491                 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4492                 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4493                 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4494                 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4495                 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4496                 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4497                 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4498                 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4499                 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4500                 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4501                 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4502                 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4503                 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4504                 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4505                 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4506                 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4507                 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4508                 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4509                 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4510                 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4511                 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4512                 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4513                 public static readonly PrimitiveType NativeInt = IntPtr;
4514                 public static readonly PrimitiveType NativeUInt = UIntPtr;
4515
4516                 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4517
4518                 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) 
4519                 {
4520                         this.name = name;
4521                         this.systemTypeIndex = STIx;
4522                 }
4523
4524                 internal string GetName() { return name; }
4525
4526                 internal int GetSystemTypeIx() { return systemTypeIndex; }
4527
4528                 internal sealed override void TypeSig(MemoryStream str) 
4529                 {
4530                         str.WriteByte(typeIndex);
4531                 }
4532
4533                 internal override MetaDataElement GetTypeSpec(MetaData md) 
4534                 {
4535                         TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4536                         if (tS == null) {
4537                                 tS = new TypeSpec(this,md);
4538                                 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4539                                 md.AddToTable(MDTable.TypeSpec,tS);
4540                         }
4541                         return tS;
4542                 }
4543
4544         }
4545
4546         public class PrimitiveTypeRef : Type
4547         {
4548                 PrimitiveType type;
4549                 MetaData metaData;
4550
4551                 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4552                         : base (0)
4553                 {
4554                         this.type = type;
4555                         this.metaData = md;
4556                 }
4557
4558                 internal uint TypeDefOrRefToken()
4559                 {
4560                         uint cIx = type.GetTypeSpec (metaData).Row;
4561                         cIx = (cIx << 2) | 0x2;
4562                         return cIx;
4563                 }
4564         }
4565
4566         /**************************************************************************/  
4567         /// <summary>
4568         /// Descriptor for an pointer (type * or type &)
4569         /// </summary>
4570         public abstract class PtrType : Type {
4571
4572                 Type baseType;
4573
4574                 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4575                 {
4576                         baseType = bType;
4577                         tabIx = MDTable.TypeSpec;
4578                 }
4579
4580                 internal sealed override void TypeSig(MemoryStream str) 
4581                 {
4582                         str.WriteByte(typeIndex);
4583                         baseType.TypeSig(str);
4584                 }
4585
4586         }
4587         /**************************************************************************/  
4588         /// <summary>
4589         /// Descriptor for a managed pointer (type &  or byref)
4590         /// </summary>
4591
4592         public class ManagedPointer : PtrType {
4593
4594                 /// <summary>
4595                 /// Create new managed pointer to baseType
4596                 /// </summary>
4597                 /// <param name="bType">the base type of the pointer</param>
4598                 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4599
4600         }
4601         /**************************************************************************/  
4602         /// <summary>
4603         /// Descriptor for an unmanaged pointer (type *)
4604         /// </summary>
4605         public class UnmanagedPointer : PtrType {
4606
4607                 /// <summary>
4608                 /// Create a new unmanaged pointer to baseType
4609                 /// </summary>
4610                 /// <param name="baseType">the base type of the pointer</param>
4611                 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4612
4613         }
4614
4615         /**************************************************************************/  
4616
4617         public interface IExternRef  {
4618                 ClassRef AddClass(string nsName, string name);
4619                 ClassRef AddValueClass(string nsName, string name);
4620         }
4621
4622         /// <summary>
4623         /// A reference to an external assembly (.assembly extern)
4624         /// </summary>
4625         public class AssemblyRef : ResolutionScope, IExternRef {
4626
4627                 private ushort major, minor, build, revision;
4628                 uint flags, keyIx, hashIx, cultIx;
4629                 bool hasVersion = false, isKeyToken = false;
4630                 byte[] keyBytes;
4631                 string culture;
4632
4633                 internal AssemblyRef(MetaData md, string name) : base(name,md) 
4634                 {
4635                         tabIx = MDTable.AssemblyRef;
4636                 }
4637
4638                 public void AddAssemblyAttr (AssemAttr aa)
4639                 {
4640                         flags |= (uint)aa;
4641                 }
4642
4643                 /// <summary>
4644                 /// Add version information about this external assembly
4645                 /// </summary>
4646                 /// <param name="majVer">Major Version</param>
4647                 /// <param name="minVer">Minor Version</param>
4648                 /// <param name="bldNo">Build Number</param>
4649                 /// <param name="revNo">Revision Number</param>
4650                 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) 
4651                 {
4652                         major = (ushort)majVer;
4653                         minor = (ushort)minVer;
4654                         build = (ushort)bldNo;
4655                         revision = (ushort)revNo;
4656                         hasVersion = true;
4657                 }
4658
4659                 /// <summary>
4660                 /// Add the hash value for this external assembly
4661                 /// </summary>
4662                 /// <param name="hash">bytes of the hash value</param>
4663                 public void AddHash(byte[] hash) 
4664                 {
4665                         hashIx = metaData.AddToBlobHeap(hash); 
4666                 }
4667
4668                 /// <summary>
4669                 /// Set the culture for this external assembly
4670                 /// </summary>
4671                 /// <param name="cult">the culture string</param>
4672                 public void AddCulture(string cult) 
4673                 {
4674                         cultIx = metaData.AddToStringsHeap(cult);
4675                         culture = cult;
4676                 }
4677
4678                 /// <summary>
4679                 /// Add the full public key for this external assembly
4680                 /// </summary>
4681                 /// <param name="key">bytes of the public key</param>
4682                 public void AddKey(byte[] key) 
4683                 {
4684                         flags |= 0x0001;   // full public key
4685                         keyBytes = key;
4686                         keyIx = metaData.AddToBlobHeap(key); 
4687                 }
4688
4689                 /// <summary>
4690                 /// Add the public key token (low 8 bytes of the public key)
4691                 /// </summary>
4692                 /// <param name="key">low 8 bytes of public key</param>
4693                 public void AddKeyToken(byte[] key) 
4694                 {
4695                         keyIx = metaData.AddToBlobHeap(key); 
4696                         keyBytes = key;
4697                         isKeyToken = true;
4698                 }
4699
4700                 /// <summary>
4701                 /// Add a class to this external assembly
4702                 /// </summary>
4703                 /// <param name="nsName">name space name</param>
4704                 /// <param name="name">class name</param>
4705                 /// <returns></returns>
4706                 public virtual ClassRef AddClass(string nsName, string name) 
4707                 {
4708                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4709                         metaData.AddToTable(MDTable.TypeRef,aClass);
4710                         aClass.SetParent(this);
4711                         return aClass;
4712                 }
4713
4714                 /// <summary>
4715                 /// Add a value class to this external assembly
4716                 /// </summary>
4717                 /// <param name="nsName">name space name</param>
4718                 /// <param name="name">class name</param>
4719                 /// <returns></returns>
4720                 public virtual ClassRef AddValueClass(string nsName, string name) 
4721                 {
4722                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4723                         metaData.AddToTable(MDTable.TypeRef,aClass);
4724                         aClass.SetParent(this);
4725                         aClass.MakeValueClass(ValueClass.ValueType);
4726                         return aClass;
4727                 }
4728
4729                 internal string TypeName() 
4730                 {
4731                         string result = name;
4732                         if (hasVersion) 
4733                                 result = result + ", Version=" + major + "." + minor + "." + 
4734                                         build + "." + revision;
4735                         if (keyBytes != null) {
4736                                 string tokenStr = "=";
4737                                 if (isKeyToken) tokenStr = "Token=";
4738                                 result = result + ", PublicKey" + tokenStr;
4739                                 for (int i=0; i < keyBytes.Length; i++) {
4740                                         result = result + Hex.Byte(keyBytes[i]);
4741                                 }
4742                         }
4743                         if (culture != null) 
4744                                 result = result + ", Culture=" + culture;
4745                         return result;
4746                 }
4747
4748                 internal sealed override uint Size(MetaData md) 
4749                 {
4750                         return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4751                 }
4752
4753                 internal sealed override void Write(FileImage output) 
4754                 {
4755                         output.Write(major);
4756                         output.Write(minor);
4757                         output.Write(build);
4758                         output.Write(revision);
4759                         output.Write(flags);
4760                         output.BlobIndex(keyIx);
4761                         output.StringsIndex(nameIx);
4762                         output.StringsIndex(cultIx);
4763                         output.BlobIndex(hashIx);
4764                 }
4765
4766                 internal sealed override uint GetCodedIx(CIx code) 
4767                 {
4768                         switch (code) {
4769                                 case (CIx.ResolutionScope) : return 2; 
4770                                 case (CIx.HasCustomAttr) : return 15; 
4771                                 case (CIx.Implementation) : return 1; 
4772                         }
4773                         return 0;
4774                 }
4775
4776         }
4777
4778         /**************************************************************************/  
4779         /// <summary>
4780         /// Descriptor for a class defined in System (mscorlib)
4781         /// </summary>
4782         internal class SystemClass : ClassRef {
4783
4784                 PrimitiveType elemType; 
4785
4786                 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4787                         : base("System",eType.GetName(),md) {
4788                                 elemType = eType;
4789                                 parent = paren;
4790                         }
4791
4792                 internal override sealed MetaDataElement GetTypeSpec(MetaData md) 
4793                 {
4794                         if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4795                         return typeSpec;
4796                 }
4797
4798
4799                 internal sealed override void TypeSig(MemoryStream str) 
4800                 {
4801                         str.WriteByte(elemType.GetTypeIndex());
4802                 }
4803
4804         }
4805
4806         /**************************************************************************/  
4807         /// <summary>
4808         /// The assembly for mscorlib.  
4809         /// </summary>
4810         public sealed class MSCorLib : AssemblyRef {
4811
4812                 private static readonly int valueTypeIx = 18;
4813                 private readonly string systemName = "System";
4814                 private Class[] systemClasses = new Class[valueTypeIx+2];
4815                 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4816
4817                 private static int[] specialNames = {
4818                         PrimitiveType.Void.GetName().GetHashCode(),
4819                         PrimitiveType.Boolean.GetName().GetHashCode(),
4820                         PrimitiveType.Char.GetName().GetHashCode(),
4821                         PrimitiveType.Int8.GetName().GetHashCode(),
4822                         PrimitiveType.UInt8.GetName().GetHashCode(),
4823                         PrimitiveType.Int16.GetName().GetHashCode(),
4824                         PrimitiveType.UInt16.GetName().GetHashCode(),
4825                         PrimitiveType.Int32.GetName().GetHashCode(),
4826                         PrimitiveType.UInt32.GetName().GetHashCode(),
4827                         PrimitiveType.Int64.GetName().GetHashCode(),
4828                         PrimitiveType.UInt64.GetName().GetHashCode(),
4829                         PrimitiveType.Float32.GetName().GetHashCode(),
4830                         PrimitiveType.Float64.GetName().GetHashCode(),
4831                         PrimitiveType.String.GetName().GetHashCode(),
4832                         PrimitiveType.TypedRef.GetName().GetHashCode(),
4833                         PrimitiveType.IntPtr.GetName().GetHashCode(),
4834                         PrimitiveType.UIntPtr.GetName().GetHashCode(),
4835                         PrimitiveType.Object.GetName().GetHashCode(),
4836                         PrimitiveType.ValueType.GetName ().GetHashCode(),
4837                         "Enum".GetHashCode()
4838                 };
4839
4840                 internal MSCorLib(MetaData md) : base(md,"mscorlib") 
4841                 {
4842                         if (!PEFile.IsMSCorlib)
4843                                 md.AddToTable(MDTable.AssemblyRef,this);
4844                         systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4845                         systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4846                         systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4847                         systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4848                         systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4849                         systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4850                         systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4851                         systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4852                         systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4853                         systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4854                         systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4855                         systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4856                         systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4857                         systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4858                         systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4859                         systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4860                         systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4861                         systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4862                 }
4863
4864                 /// <summary>
4865                 /// Add a class to the mscorlib assembly
4866                 /// </summary>
4867                 /// <param name="nsName">name space name</param>
4868                 /// <param name="name">class name</param>
4869                 /// <returns></returns>
4870                 public override ClassRef AddClass(string nsName, string name) 
4871                 {
4872                         /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4873                            it should be returning ClassRef ..*/
4874                         Class aClass = GetSpecialClass(nsName,name);
4875                         if (aClass == null) {
4876                                 aClass = new ClassRef(nsName,name,metaData);
4877                                 metaData.AddToTable(MDTable.TypeRef,aClass);
4878                                 if (aClass is ClassRef)
4879                                         ((ClassRef) aClass).SetParent(this);
4880                         }
4881                         //FIXME: Check for !ClassRef here?
4882                         return (ClassRef) aClass;
4883                 }
4884
4885                 private Class GetSpecialClass(string nsName,string name) 
4886                 {
4887                         if (nsName.CompareTo(systemName) != 0) return null;
4888                         int hash = name.GetHashCode();
4889                         for (int i=0; i < specialNames.Length; i++) {
4890                                 if (hash != specialNames[i])
4891                                         continue;
4892                                 if (systemClasses[i] == null) {
4893                                         if (i < valueTypeIx) {
4894                                                 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4895                                                 if ((systemTypes[i] != PrimitiveType.Object) &&
4896                                                                 (systemTypes[i] != PrimitiveType.String)) {
4897                                                         systemClasses[i].MakeValueClass(ValueClass.ValueType);
4898                                                 }
4899                                         } else {
4900                                                 systemClasses[i] = new ClassRef(nsName,name,metaData);
4901                                                 ((ClassRef) systemClasses[i]).SetParent(this);
4902                                                 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4903                                                         systemClasses[i].MakeValueClass(ValueClass.ValueType);
4904                                         }
4905                                         metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4906                                 }
4907                                 return systemClasses[i];
4908                         }
4909                         return null;
4910                 }
4911
4912                 internal void SetSpecialSystemClass (string nsName, string name, Class aClass) 
4913                 {
4914                         if (nsName != systemName) return;
4915                         int hash = name.GetHashCode ();
4916                         for (int i = 0; i < specialNames.Length; i++) {
4917                                 if (hash != specialNames [i])
4918                                         continue;
4919                                 if (systemClasses [i] == null) {
4920                                         systemClasses [i] = aClass;
4921                                 }
4922                         }
4923                 }
4924
4925                 internal Class GetSpecialSystemClass(PrimitiveType pType) 
4926                 {
4927                         int ix = pType.GetSystemTypeIx();
4928                         if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4929                                 systemClasses[ix] = new SystemClass(pType,this,metaData);
4930                                 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4931                         }
4932                         return systemClasses[ix];
4933                 }
4934
4935                 private ClassRef GetValueClass(string name, int hash) 
4936                 {
4937                         /* Called by MSCorLib.AddValueClass, which is called by
4938                            !mscorlib, for adding ref to value class INTO mscorlib,
4939                            so this should be classref */
4940                         int ix = valueTypeIx;
4941                         if (hash != specialNames[valueTypeIx]) ix++;
4942                         if (systemClasses[ix] == null) {
4943                                 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4944                                 ((ClassRef) systemClasses[ix]).SetParent(this);
4945                                 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4946                                 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4947                         }
4948                         return (ClassRef) systemClasses[ix];
4949                 }
4950
4951                 internal Class ValueType() 
4952                 {
4953                         if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4954                                 ClassRef valType = new ClassRef("System","ValueType",metaData);
4955                                 valType.SetParent(this);
4956                                 valType.MakeValueClass(ValueClass.ValueType);
4957                                 metaData.AddToTable(MDTable.TypeRef,valType);
4958                                 systemClasses[valueTypeIx] = valType;
4959                         }
4960                         return systemClasses[valueTypeIx];
4961                 }
4962
4963                 internal Class EnumType() 
4964                 {
4965                         /* Called by both mscorlib & !mscorlib, so can be
4966                            either ClassRef or ClassDef */
4967                         //systemClasses [ valueTypeIx + 1] -> System.Enum
4968                         if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4969                                 ClassRef valType = new ClassRef("System","Enum",metaData);
4970                                 valType.SetParent(this);
4971                                 valType.MakeValueClass(ValueClass.Enum);
4972                                 metaData.AddToTable(MDTable.TypeRef,valType);
4973                                 systemClasses[valueTypeIx + 1] = valType;
4974                         }
4975                         return systemClasses[valueTypeIx + 1];
4976                 }
4977
4978                 /// <summary>
4979                 /// Add a value class to this external assembly
4980                 /// </summary>
4981                 /// <param name="nsName">name space name</param>
4982                 /// <param name="name">class name</param>
4983                 /// <returns></returns>
4984                 public override ClassRef AddValueClass(string nsName, string name) 
4985                 {
4986                         if (nsName.CompareTo(systemName) == 0) {
4987                                 int hash = name.GetHashCode();
4988                                 if ((hash == specialNames[valueTypeIx]) ||
4989                                                 (hash == specialNames[valueTypeIx+1])) {
4990                                         return GetValueClass(name,hash);
4991                                 }
4992                         }
4993                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4994                         metaData.AddToTable(MDTable.TypeRef,aClass);
4995                         aClass.SetParent(this);
4996                         aClass.MakeValueClass(ValueClass.ValueType);
4997                         return aClass;
4998                 }
4999
5000         }
5001
5002         /**************************************************************************/  
5003         /// <summary>
5004         /// MetaData 
5005         ///   Root (20 bytes + UTF-8 Version String + quad align padding)
5006         ///   StreamHeaders (8 bytes + null terminated name string + quad align padding)
5007         ///   Streams 
5008         ///     #~        (always present - holds metadata tables)
5009         ///     #Strings  (always present - holds identifier strings)
5010         ///     #US       (Userstring heap)
5011         ///     #Blob     (signature blobs)
5012         ///     #GUID     (guids for assemblies or Modules)
5013         /// </summary>
5014         public class MetaData  {
5015
5016                 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
5017                 private static readonly byte StringsHeapMask = 0x1;
5018                 private static readonly byte GUIDHeapMask = 0x2;
5019                 private static readonly byte BlobHeapMask = 0x4;
5020                 private static readonly uint MetaDataSignature = 0x424A5342;
5021                 private static readonly uint maxSmlIxSize = 0xFFFF;
5022                 private static readonly uint max1BitSmlIx = 0x7FFF;
5023                 private static readonly uint max2BitSmlIx = 0x3FFF;
5024                 private static readonly uint max3BitSmlIx = 0x1FFF;
5025                 private static readonly uint max5BitSmlIx = 0x7FF;
5026                 // NOTE: version and stream name strings MUST always be quad padded
5027                 private static readonly string version = "v4.0.30319\0\0";
5028                 private static readonly char[] tildeName = {'#','~','\0','\0'};
5029                 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
5030                 private static readonly char[] usName = {'#','U','S','\0'};
5031                 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
5032                 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
5033                 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
5034                 private static readonly uint TildeHeaderSize = 24;
5035                 private static readonly uint StreamHeaderSize = 8;
5036                 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
5037
5038                 MetaDataStream strings, us, guid, blob;
5039
5040                 MetaDataStream[] streams = new MetaDataStream[5];
5041                 uint numStreams = 5;
5042                 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
5043                 uint numTables = 0, resourcesSize = 0;
5044                 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
5045                 ArrayList byteCodes = new ArrayList();
5046                 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
5047                 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
5048                 bool[] largeIx = new bool[numMetaDataTables];
5049                 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
5050                 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
5051                 private FileImage file;
5052                 private byte heapSizes = 0;
5053                 MetaDataElement entryPoint;
5054                 BinaryWriter output;
5055                 public MSCorLib mscorlib;
5056                 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
5057                 long mdStart;
5058                 private ArrayList cattr_list;
5059                 private ArrayList declsec_list;
5060                 ArrayList resources;            
5061
5062                 internal MetaData(FileImage file) 
5063                 {
5064                         // tilde = new MetaDataStream(tildeName,false,0);
5065                         this.file = file;
5066                         strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5067                         us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5068                         guid = new MetaDataStream(guidName,false);
5069                         blob = new MetaDataStream(blobName,true);
5070                         streams[1] = strings;
5071                         streams[2] = us;
5072                         streams[3] = guid;
5073                         streams[4] = blob;
5074                         for (int i=0; i < numMetaDataTables; i++) {
5075                                 largeIx[i] = false;
5076                         }
5077                         for (int i=0; i < lgeCIx.Length; i++) {
5078                                 lgeCIx[i] = false;
5079                         }
5080                         mscorlib = new MSCorLib(this);
5081                 }
5082
5083                 internal TypeSpec GetPrimitiveTypeSpec(int ix) 
5084                 {
5085                         return systemTypeSpecs[ix];
5086                 }
5087
5088                 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) 
5089                 {
5090                         systemTypeSpecs[ix] = typeSpec;
5091                 }
5092
5093                 internal uint Size() 
5094                 {
5095                         return metaDataSize;
5096                 }
5097
5098                 private void CalcHeapSizes ()
5099                 {
5100                         if (strings.LargeIx()) {
5101                                 largeStrings = true;
5102                                 heapSizes |= StringsHeapMask;
5103                         }
5104                         if (guid.LargeIx()) {
5105                                 largeGUID = true;
5106                                 heapSizes |= GUIDHeapMask;
5107                         }
5108                         if (blob.LargeIx()) {
5109                                 largeBlob = true;
5110                                 heapSizes |= BlobHeapMask;
5111                         }
5112
5113                         largeUS = us.LargeIx();
5114                 }
5115
5116                 internal void StreamSize(byte mask) 
5117                 {
5118                         heapSizes |= mask;
5119                 }
5120
5121                 internal uint AddToUSHeap(string str) 
5122                 {
5123                         if (str == null) return 0;
5124                         return us.Add(str,true);
5125                 }
5126
5127                 internal uint AddToUSHeap(byte[] str) 
5128                 {
5129                         if (str == null) return 0;
5130                         return us.Add (str, true);
5131                 }
5132
5133                 internal uint AddToStringsHeap(string str) 
5134                 {
5135                         if ((str == null) || (str.CompareTo("") == 0)) return 0;
5136                         return strings.Add(str,false);
5137                 }
5138
5139                 internal uint AddToGUIDHeap(Guid guidNum) 
5140                 {
5141                         return guid.Add(guidNum, false);
5142                 }
5143
5144                 internal uint AddToBlobHeap(byte[] blobBytes) 
5145                 {
5146                         if (blobBytes == null) return 0;
5147                         return blob.Add(blobBytes, true);
5148                 }
5149
5150                 internal uint AddToBlobHeap(byte val) 
5151                 {
5152                         return blob.Add(val, true);
5153                 }
5154
5155                 internal uint AddToBlobHeap(sbyte val) 
5156                 {
5157                         return blob.Add(val, true);
5158                 }
5159
5160                 internal uint AddToBlobHeap(ushort val) 
5161                 {
5162                         return blob.Add(val, true);
5163                 }
5164
5165                 internal uint AddToBlobHeap(short val) 
5166                 {
5167                         return blob.Add(val, true);
5168                 }
5169
5170                 internal uint AddToBlobHeap(uint val) 
5171                 {
5172                         return blob.Add(val, true);
5173                 }
5174
5175                 internal uint AddToBlobHeap(int val) 
5176                 {
5177                         return blob.Add(val, true);
5178                 }
5179
5180                 internal uint AddToBlobHeap(ulong val) 
5181                 {
5182                         return blob.Add(val, true);
5183                 }
5184
5185                 internal uint AddToBlobHeap(long val) 
5186                 {
5187                         return blob.Add(val, true);
5188                 }
5189
5190                 internal uint AddToBlobHeap(float val) 
5191                 {
5192                         return blob.Add(val, true);
5193                 }
5194
5195                 internal uint AddToBlobHeap(double val) 
5196                 {
5197                         return blob.Add(val, true);
5198                 }
5199
5200                 internal uint AddToBlobHeap(string val) 
5201                 {
5202                         return blob.Add(val,true);
5203                 }
5204
5205                 internal void AddCustomAttribute (CustomAttribute cattr)
5206                 {
5207                         if (cattr_list == null)
5208                                 cattr_list = new ArrayList ();
5209                         cattr_list.Add (cattr);
5210                 }
5211
5212                 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5213                 {
5214                         if (declsec_list == null)
5215                                 declsec_list = new ArrayList ();
5216                         declsec_list.Add (decl_sec);
5217                 }
5218
5219                 private ArrayList GetTable(MDTable tableIx) 
5220                 {
5221                         int tabIx = (int)tableIx;
5222                         if (metaDataTables[tabIx] == null) {
5223                                 metaDataTables[tabIx] = new ArrayList();
5224                                 valid |= ((ulong)0x1 << tabIx);
5225                                 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5226                                 numTables++;
5227                         }
5228                         return metaDataTables[tabIx];
5229                 }
5230
5231                 internal void AddToTable(MDTable tableIx, MetaDataElement elem) 
5232                 {
5233                         if (elem.Row > 0) {
5234                                 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5235                                 return;
5236                         }
5237                         // updates Row field of the element
5238                         // Console.WriteLine("Adding element to table " + (uint)tableIx);
5239                         ArrayList table = GetTable(tableIx);
5240                         elem.Row = (uint)table.Count + 1;
5241                         table.Add(elem);
5242                 }
5243
5244                 internal uint TableIndex(MDTable tableIx) 
5245                 {
5246                         if (metaDataTables[(int)tableIx] == null) return 1;
5247                         return (uint)metaDataTables[(int)tableIx].Count+1;
5248                 }
5249
5250                 internal uint AddCode(CILInstructions byteCode) 
5251                 {
5252                         byteCodes.Add(byteCode);
5253                         uint offset = codeSize + codeStart;
5254                         codeSize += byteCode.GetCodeSize();
5255                         return offset;
5256                 }
5257
5258                 internal void SetEntryPoint(MetaDataElement ep) 
5259                 {
5260                         entryPoint = ep;
5261                 }
5262
5263                 internal uint AddResource(byte[] resBytes) 
5264                 {
5265                         if (resources == null) resources = new ArrayList ();
5266                         resources.Add (resBytes);
5267                         uint offset = resourcesSize;
5268                         resourcesSize += (uint)resBytes.Length + 4;
5269                         return offset;
5270                 }
5271
5272                 internal void AddData(DataConstant cVal) 
5273                 {
5274                         file.AddInitData(cVal);
5275                 }
5276
5277                 internal static void CompressNum(uint val, MemoryStream sig) 
5278                 {
5279                         if (val <= 0x7F) {
5280                                 sig.WriteByte((byte)val);
5281                         } else if (val <= 0x3FFF) {
5282                                 byte b1 = (byte)((val >> 8) | 0x80);
5283                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5284                                 sig.WriteByte(b1);
5285                                 sig.WriteByte(b2);
5286                         } else {
5287                                 byte b1 = (byte)((val >> 24) | 0xC0);
5288                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5289                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5290                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5291                                 sig.WriteByte(b1);
5292                                 sig.WriteByte(b2);
5293                                 sig.WriteByte(b3);
5294                                 sig.WriteByte(b4);
5295                         }
5296                 }
5297
5298                 internal uint CodeSize() 
5299                 {
5300                         return codeSize + byteCodePadding;
5301                 }
5302
5303                 internal uint GetResourcesSize() 
5304                 { 
5305                         return resourcesSize; 
5306                 }
5307
5308                 internal uint StringsIndexSize() 
5309                 {
5310                         if (largeStrings) return 4;
5311                         return 2;
5312                 }
5313
5314                 internal uint GUIDIndexSize() 
5315                 {
5316                         if (largeGUID) return 4;
5317                         return 2;
5318                 }
5319
5320                 internal uint USIndexSize() 
5321                 {
5322                         if (largeUS) return 4;
5323                         return 2;
5324                 }
5325
5326                 internal uint BlobIndexSize() 
5327                 {
5328                         if (largeBlob) return 4;
5329                         return 2;
5330                 }
5331
5332                 internal uint CodedIndexSize(CIx code) 
5333                 {
5334                         if (lgeCIx[(uint)code]) return 4;
5335                         return 2;
5336                 }
5337
5338                 internal uint TableIndexSize(MDTable tabIx) 
5339                 {
5340                         if (largeIx[(uint)tabIx]) return 4;
5341                         return 2;
5342                 }
5343
5344                 private void SetIndexSizes() 
5345                 {
5346                         for (int i=0; i < numMetaDataTables; i++) {
5347                                 if (metaDataTables[i] == null)
5348                                         continue;
5349
5350                                 uint count = (uint)metaDataTables[i].Count;
5351                                 if (count > maxSmlIxSize)
5352                                         largeIx[i] = true;
5353
5354                                 MDTable tabIx = (MDTable)i;
5355                                 if (count > max5BitSmlIx) {
5356                                         if (tabIx == MDTable.Method || tabIx == MDTable.Field || tabIx == MDTable.TypeRef ||
5357                                                 tabIx == MDTable.TypeDef || tabIx == MDTable.Param || tabIx == MDTable.InterfaceImpl ||
5358                                                 tabIx == MDTable.MemberRef || tabIx == MDTable.Module || tabIx == MDTable.DeclSecurity ||
5359                                                 tabIx == MDTable.Property || tabIx == MDTable.Event || tabIx == MDTable.StandAloneSig ||
5360                                                 tabIx == MDTable.ModuleRef || tabIx == MDTable.TypeSpec || tabIx == MDTable.Assembly ||
5361                                                 tabIx == MDTable.AssemblyRef || tabIx == MDTable.File || tabIx == MDTable.ExportedType ||
5362                                                 tabIx == MDTable.ManifestResource || tabIx == MDTable.GenericParam)
5363                                         lgeCIx[(int)CIx.HasCustomAttr] = true;
5364                                 }
5365                                 if (count > max3BitSmlIx) {
5366                                         if (tabIx == MDTable.Method || tabIx == MDTable.MemberRef)
5367                                                 lgeCIx[(int)CIx.CustomAttributeType] = true;
5368                                         if (tabIx == MDTable.TypeDef || tabIx == MDTable.TypeRef || tabIx == MDTable.ModuleRef ||
5369                                                 tabIx == MDTable.Method || tabIx == MDTable.TypeSpec)
5370                                                 lgeCIx[(int)CIx.MemberRefParent] = true;
5371                                 }
5372                                 if (count > max2BitSmlIx) {
5373                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property)) 
5374                                                 lgeCIx[(int)CIx.HasConst] = true;
5375                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5376                                                 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5377                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5378                                                 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5379                                         if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5380                                                 lgeCIx[(int)CIx.Implementation] = true;
5381                                         if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5382                                                 lgeCIx[(int)CIx.ResolutionScope] = true;
5383                                 }
5384                                 if (count > max1BitSmlIx) {
5385                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param)) 
5386                                                 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5387                                         if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property)) 
5388                                                 lgeCIx[(int)CIx.HasSemantics] = true;
5389                                         if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) 
5390                                                 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5391                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method)) 
5392                                                 lgeCIx[(int)CIx.MemberForwarded] = true; 
5393                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method)) 
5394                                                 lgeCIx[(int)CIx.TypeOrMethodDef] = true; 
5395                                 }
5396                         }
5397                 }
5398
5399                 private void SetStreamOffsets() 
5400                 {
5401                         uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5402                         for (int i=1; i < numStreams; i++) {
5403                                 sizeOfHeaders += streams[i].headerSize();
5404                         }
5405                         metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5406                         tildeStart = metaDataSize;
5407                         metaDataSize += tildeTide + tildePadding;
5408                         for (int i=1; i < numStreams; i++) {
5409                                 streams[i].Start = metaDataSize;
5410                                 metaDataSize += streams[i].Size();
5411                                 streams[i].WriteDetails();
5412                         }
5413                 }
5414
5415                 internal void CalcTildeStreamSize() 
5416                 {
5417                         CalcHeapSizes ();
5418                         //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5419                         tildeTide = TildeHeaderSize;
5420                         tildeTide += 4 * numTables;
5421                         //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5422                         for (int i=0; i < numMetaDataTables; i++) {
5423                                 if (metaDataTables[i] != null) {
5424                                         ArrayList table = metaDataTables[i];
5425                                         // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5426                                         tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5427                                         // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5428                                         // Console.WriteLine("tildeTide = " + tildeTide);
5429                                 }
5430                         }
5431                         if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5432                         //Console.WriteLine("tildePadding = " + tildePadding);
5433                 }
5434
5435                 internal void WriteTildeStream(FileImage output) 
5436                 {
5437                         output.Seek(0,SeekOrigin.Current);
5438                         output.Write((uint)0); // Reserved
5439                         output.Write((byte)2); // MajorVersion
5440                         output.Write((byte)0); // MinorVersion
5441                         output.Write(heapSizes);
5442                         output.Write((byte)1); // Reserved
5443                         output.Write(valid);
5444                         output.Write(sorted);
5445                         
5446                         for (int i=0; i < numMetaDataTables; i++) {
5447                                 if (metaDataTables[i] != null) {
5448                                         uint count = (uint)metaDataTables[i].Count;
5449                                         output.Write(count);
5450                                 }
5451                         }
5452                         
5453                         output.Seek(0,SeekOrigin.Current);
5454                         // Console.WriteLine("Starting metaData tables at " + tabStart);
5455                         for (int i=0; i < numMetaDataTables; i++) {
5456                                 if (metaDataTables[i] != null) {
5457                                         // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5458                                         ArrayList table = metaDataTables[i];
5459                                         for (int j=0; j < table.Count; j++) {
5460                                                 ((MetaDataElement)table[j]).Write(output);
5461                                         }
5462                                 }
5463                         }
5464                         // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5465                         for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5466                 }
5467
5468                 private void BuildTable(ArrayList table) 
5469                 {
5470                         if (table == null) return;
5471                         for (int j=0; j < table.Count; j++) {
5472                                 ((MetaDataElement)table[j]).BuildTables(this);
5473                         }
5474                 }
5475
5476                 private void SortTable (ArrayList mTable) 
5477                 {
5478                         if (mTable == null) return;
5479                         mTable.Sort();
5480                         for (int i=0; i < mTable.Count; i++) {
5481                                 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5482                         }
5483                 }
5484
5485                 internal void BuildMetaData(uint codeStartOffset) 
5486                 {
5487                         codeStart = codeStartOffset;
5488                         BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5489                         BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5490                         BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5491                         BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5492                         BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5493                         BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5494                         BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5495
5496                         if (cattr_list != null) {
5497                                 foreach (CustomAttribute cattr in cattr_list)
5498                                         cattr.BuildTables (this);
5499                         }
5500
5501                         if (declsec_list != null) {
5502                                 foreach (BaseDeclSecurity decl_sec in declsec_list)
5503                                         decl_sec.BuildTables (this);
5504                         }
5505
5506                         /*      for (int i=0; i < metaDataTables.Length; i++) {
5507                                 ArrayList table = metaDataTables[i];
5508                                 if (table != null) {
5509                                 for (int j=0; j < table.Count; j++) {
5510                                 ((MetaDataElement)table[j]).BuildTables(this);
5511                                 }
5512                                 }
5513                                 }
5514                          */
5515
5516                         SetIndexSizes();
5517                         for (int i=1; i < numStreams; i++) {
5518                                 streams[i].EndStream();
5519                         }
5520                         CalcTildeStreamSize();
5521                         SetStreamOffsets();
5522                         byteCodePadding = NumToAlign(codeSize,4);
5523                         if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5524
5525                         // Check ordering of specific tables
5526                         // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5527                         // ImplMap, GenericParam
5528                         // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5529                         // The tables:
5530                         //   InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5531                         // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5532
5533                         SortTable(metaDataTables[(int)MDTable.Constant]);
5534                         SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5535                         SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5536                         SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5537                         SortTable(metaDataTables[(int)MDTable.ImplMap]);
5538                         if (metaDataTables[(int)MDTable.GenericParam] != null) {
5539                                 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5540                                 // Now add GenericParamConstraints
5541                                 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5542                                   ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5543                                   }*/
5544                         }
5545                         SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5546                         SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5547                         SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5548
5549                 }
5550
5551                 internal void WriteByteCodes(FileImage output) 
5552                 {
5553                         for (int i=0; i < byteCodes.Count; i++) {
5554                                 ((CILInstructions)byteCodes[i]).Write(output);
5555                         }
5556                         for (int i=0; i < byteCodePadding; i++) {
5557                                 output.Write((byte)0);
5558                         }
5559                 }
5560
5561                 internal void WriteResources (FileImage output) 
5562                 {
5563                         if (resources == null) return;
5564                         for (int i = 0; i < resources.Count; i ++) {
5565                                 byte [] resBytes = (byte []) resources [i];
5566                                 output.Write ((uint) resBytes.Length);
5567                                 output.Write (resBytes);
5568                         } 
5569                 }
5570
5571                 internal void WriteMetaData(FileImage output) 
5572                 {
5573                         this.output = output;
5574                         mdStart = output.Seek(0,SeekOrigin.Current);
5575                         // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5576                         output.Write(MetaDataSignature);
5577                         output.Write((short)1);  // Major Version
5578                         output.Write((short)1);  // Minor Version  ECMA = 0, PEFiles = 1
5579                         output.Write(0);         // Reserved
5580                         output.Write(version.Length);
5581                         output.Write(version.ToCharArray());   // version string is already zero padded
5582                         output.Write((short)0);
5583                         output.Write((ushort)numStreams);
5584                         // write tilde header
5585                         output.Write(tildeStart);
5586                         output.Write(tildeTide + tildePadding);
5587                         output.Write(tildeName);
5588                         for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5589                         // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5590                         WriteTildeStream(output);
5591                         for (int i=1; i < numStreams; i++) streams[i].Write(output);
5592                         // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5593                 }
5594
5595                 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5596                 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5597                 internal bool LargeUSIndex() { return us.LargeIx(); }
5598                 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5599
5600                 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5601
5602
5603                 private uint NumToAlign(uint val, uint alignVal) 
5604                 {
5605                         if ((val % alignVal) == 0) return 0;
5606                         return alignVal - (val % alignVal);
5607                 }
5608
5609                 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) 
5610                 {
5611                         uint ix = 0;
5612                         if (elem != null) { 
5613                                 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5614                                 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5615                                 //} else {
5616                                 // Console.WriteLine("elem for coded index is null");
5617                         }
5618                         if (lgeCIx[(uint)code]) 
5619                                 output.Write(ix);
5620                         else
5621                                 output.Write((ushort)ix);
5622                 }
5623
5624         }
5625
5626         /**************************************************************************/  
5627         /// <summary>
5628         /// Stream in the Meta Data  (#Strings, #US, #Blob and #GUID)
5629         /// </summary>
5630
5631         internal class MetaDataStream : BinaryWriter  {
5632
5633                 private static readonly uint StreamHeaderSize = 8;
5634                 private static uint maxSmlIxSize = 0xFFFF;
5635
5636                 private uint start = 0; 
5637                 uint size = 0, tide = 1;
5638                 bool largeIx = false;
5639                 uint sizeOfHeader;
5640                 char[] name;
5641                 Hashtable htable = new Hashtable();
5642                 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5643
5644                 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) 
5645                 {
5646                         if (addInitByte) { Write((byte)0); size = 1; }
5647                         this.name = name;
5648                         sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5649                 }
5650
5651                 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) 
5652                 {
5653                         if (addInitByte) { Write((byte)0); size = 1; }
5654                         this.name = name;
5655                         sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5656                 }
5657
5658                 public uint Start {
5659                         get { return start; }
5660                         set { start = value; }
5661                 }
5662
5663                 internal uint headerSize() 
5664                 {
5665                         // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5666                         return sizeOfHeader;
5667                 }
5668
5669                 internal void SetSize(uint siz) 
5670                 {
5671                         size = siz;
5672                 }
5673
5674                 internal uint Size() 
5675                 {
5676                         return size;
5677                 }
5678
5679                 internal bool LargeIx() 
5680                 {
5681                         return largeIx;
5682                 }
5683
5684                 internal void WriteDetails() 
5685                 {
5686                         // Console.WriteLine(name + " - size = " + size);
5687                 }
5688
5689                 internal uint Add(string str, bool prependSize) 
5690                 {
5691                         Object val = htable[str];
5692                         uint index = 0;
5693                         if (val == null) { 
5694                                 index = size;
5695                                 htable[str] = index;
5696                                 char[] arr = str.ToCharArray();
5697                                 if (prependSize) CompressNum((uint)arr.Length*2+1);
5698                                 Write(arr);
5699                                 Write((byte)0);
5700                                 size = (uint)Seek(0,SeekOrigin.Current);
5701                         } else {
5702                                 index = (uint)val;
5703                         }
5704                         return index;
5705                 }
5706                 internal uint Add (byte[] str, bool prependSize) 
5707                 {
5708                         Object val = btable [str];
5709                         uint index = 0;
5710                         if (val == null) {
5711                                 index = size;
5712                                 btable [str] = index;
5713                                 if (prependSize) CompressNum ((uint) str.Length);
5714                                 Write (str);
5715                                 size = (uint) Seek (0, SeekOrigin.Current);
5716                         } else {
5717                                 index = (uint) val;
5718                         }
5719                         return index;
5720                 }
5721
5722
5723                 internal uint Add(Guid guid, bool prependSize) 
5724                 {
5725                         byte [] b = guid.ToByteArray ();
5726                         if (prependSize) CompressNum ((uint) b.Length);
5727                         Write(guid.ToByteArray());
5728                         size =(uint)Seek(0,SeekOrigin.Current);
5729                         return tide++;
5730                 }
5731
5732                 internal uint Add(byte[] blob) 
5733                 {
5734                         uint ix = size;
5735                         CompressNum((uint)blob.Length);
5736                         Write(blob);
5737                         size = (uint)Seek(0,SeekOrigin.Current);
5738                         return ix;
5739                 }
5740
5741                 internal uint Add(byte val, bool prependSize) 
5742                 {
5743                         uint ix = size;
5744                         if (prependSize) CompressNum (1);
5745                         Write(val);
5746                         size = (uint)Seek(0,SeekOrigin.Current);
5747                         return ix;
5748                 }
5749
5750                 internal uint Add(sbyte val, bool prependSize) 
5751                 {
5752                         uint ix = size;
5753                         if (prependSize) CompressNum (1);
5754                         Write(val);
5755                         size = (uint)Seek(0,SeekOrigin.Current);
5756                         return ix;
5757                 }
5758
5759                 internal uint Add(ushort val, bool prependSize) 
5760                 {
5761                         uint ix = size;
5762                         if (prependSize) CompressNum (2);
5763                         Write(val);
5764                         size = (uint)Seek(0,SeekOrigin.Current);
5765                         return ix;
5766                 }
5767
5768                 internal uint Add(short val, bool prependSize) 
5769                 {
5770                         uint ix = size;
5771                         if (prependSize) CompressNum (2);
5772                         Write(val);
5773                         size = (uint)Seek(0,SeekOrigin.Current);
5774                         return ix;
5775                 }
5776
5777                 internal uint Add(uint val, bool prependSize) 
5778                 {
5779                         uint ix = size;
5780                         if (prependSize) CompressNum (4);
5781                         Write(val);
5782                         size = (uint)Seek(0,SeekOrigin.Current);
5783                         return ix;
5784                 }
5785
5786                 internal uint Add(int val, bool prependSize) 
5787                 {
5788                         uint ix = size;
5789                         if (prependSize) CompressNum (4);
5790                         Write (val);
5791                         size = (uint)Seek(0,SeekOrigin.Current);
5792                         return ix;
5793                 }
5794
5795                 internal uint Add(ulong val, bool prependSize) 
5796                 {
5797                         uint ix = size;
5798                         if (prependSize) CompressNum (8);
5799                         Write(val);
5800                         size = (uint)Seek(0,SeekOrigin.Current);
5801                         return ix;
5802                 }
5803
5804                 internal uint Add(long val, bool prependSize) 
5805                 {
5806                         uint ix = size;
5807                         if (prependSize) CompressNum (8);
5808                         Write(val);
5809                         size = (uint)Seek(0,SeekOrigin.Current);
5810                         return ix;
5811                 }
5812
5813                 internal uint Add(float val, bool prependSize) 
5814                 {
5815                         uint ix = size;
5816                         if (prependSize) CompressNum (4);
5817                         Write(val);
5818                         size = (uint)Seek(0,SeekOrigin.Current);
5819                         return ix;
5820                 }
5821
5822                 internal uint Add(double val, bool prependSize) 
5823                 {
5824                         uint ix = size;
5825                         if (prependSize) CompressNum (8);
5826                         Write(val);
5827                         size = (uint)Seek(0,SeekOrigin.Current);
5828                         return ix;
5829                 }
5830
5831                 private void CompressNum(uint val) 
5832                 {
5833                         if (val < 0x7F) {
5834                                 Write((byte)val);
5835                         } else if (val < 0x3FFF) {
5836                                 byte b1 = (byte)((val >> 8) | 0x80);
5837                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5838                                 Write(b1);
5839                                 Write(b2);
5840                         } else {
5841                                 byte b1 = (byte)((val >> 24) | 0xC0);
5842                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5843                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5844                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5845                                 Write(b1);
5846                                 Write(b2);
5847                                 Write(b3);
5848                                 Write(b4);
5849                         }
5850                 }
5851
5852                 private void QuadAlign() 
5853                 {
5854                         if ((size % 4) != 0) {
5855                                 uint pad = 4 - (size % 4);
5856                                 size += pad;
5857                                 for (int i=0; i < pad; i++) {
5858                                         Write((byte)0);
5859                                 }
5860                         }
5861                 }
5862
5863                 internal void EndStream() 
5864                 {
5865                         QuadAlign();
5866                         if (size > maxSmlIxSize) {
5867                                 largeIx = true;
5868                         }
5869                 }
5870
5871                 internal void WriteHeader(BinaryWriter output) 
5872                 {
5873                         output.Write(start);
5874                         output.Write(size);
5875                         output.Write(name);
5876                 }
5877
5878                 internal virtual void Write(BinaryWriter output) 
5879                 {
5880                         // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5881                         MemoryStream str = (MemoryStream)BaseStream;
5882                         output.Write(str.ToArray());
5883                 }
5884
5885         }
5886
5887         /**************************************************************************/  
5888         class ByteArrayComparer : IComparer {
5889
5890                 public int Compare (object x, object y)
5891                 {
5892                         byte [] a = (byte []) x;
5893                         byte [] b = (byte []) y;
5894                         int len = a.Length;
5895
5896                         if (b.Length != len)
5897                                 return 1;
5898
5899                         for (int i = 0; i < len; ++i)
5900                                 if (a [i] != b [i])
5901                                         return 1;
5902                         return 0;
5903                 }
5904         }
5905
5906         class ByteArrayHashCodeProvider : IHashCodeProvider {
5907
5908                 public int GetHashCode (Object key)
5909                 {
5910                         byte [] arr = (byte []) key;
5911                         int len = arr.Length;
5912                         int h = 0;
5913
5914                         for (int i = 0; i < len; ++i)
5915                                 h = (h << 5) - h + arr [i];
5916
5917                         return h;
5918                 }
5919
5920         }
5921
5922
5923 }