* PEAPI.cs: Don't build custom attributes twice.
[mono.git] / mcs / class / PEAPI / PEAPI.cs
index 9abf6fba3da0fbd646337a780498bf7e6160117e..9c28a49496c3d4c6d529453bd9b02420060fbe7d 100644 (file)
@@ -95,11 +95,30 @@ namespace PEAPI
     public TypeSignatureException(string msg) : base(msg) { }\r
   }\r
 \r
-    public class GenericTypeSpec : Type {\r
+                   public class ClassRefInst : Type {\r
+
+                          private Class type;
+                          private bool is_value;
+\r
+            public ClassRefInst (Class type, bool is_value) : base (0x12) {\r
+                    this.type = type;
+                    this.is_value = is_value;
+                    if (is_value)
+                            typeIndex = 0x11;
+                    tabIx = MDTable.TypeSpec;\r
+            }\r
+\r
+            internal sealed override void TypeSig(MemoryStream str) {\r
+                    str.WriteByte (GetTypeIndex());
+                    MetaData.CompressNum (type.TypeDefOrRefToken(), str);\r
+            }
+    }\r
+                  
+  public class MVar : Type {\r
 \r
             private int index;\r
 \r
-            public GenericTypeSpec (int index) : base (0x13) {\r
+            public MVar (int index) : base (0x1E) {\r
                     this.index = index;\r
                     tabIx = MDTable.TypeSpec;\r
             }\r
@@ -108,8 +127,22 @@ namespace PEAPI
                     str.WriteByte(typeIndex);\r
                     MetaData.CompressNum ((uint) index, str);\r
             }\r
+    }\r
+\r
+    public class GenericTypeSpec : Type {\r
+\r
+            private int index;\r
+\r
+            public GenericTypeSpec (int index) : base (0x13) {\r
+                    this.index = index;\r
+                    tabIx = MDTable.TypeSpec;\r
             }\r
 \r
+            internal sealed override void TypeSig(MemoryStream str) {\r
+                    str.WriteByte(typeIndex);\r
+                    MetaData.CompressNum ((uint) index, str);\r
+            }\r
+    }\r
 \r
   public class GenericTypeInst : Type {\r
 \r
@@ -132,7 +165,32 @@ namespace PEAPI
                           param.TypeSig (str);\r
             }\r
   }\r
-\r
+
+  public class GenericMethodSig {
+
+          private Type[] gen_param;
+
+          public GenericMethodSig (Type[] gen_param)
+          {
+                  this.gen_param = gen_param;
+          }
+
+          internal void TypeSig (MemoryStream str)
+          {
+                  MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
+                  MetaData.CompressNum ((uint) gen_param.Length, str);
+                  foreach (Type param in gen_param)
+                          param.TypeSig (str);
+          }
+
+          internal uint GetSigIx (MetaData md)
+          {
+                  MemoryStream sig = new MemoryStream();
+                  TypeSig (sig);
+                  return md.AddToBlobHeap (sig.ToArray());
+          }
+  }
+
         public class Sentinel : Type {
 
             public Sentinel () : base (0x41) { }
@@ -157,25 +215,6 @@ namespace PEAPI
                         tabIx = MDTable.TypeSpec;\r
     }\r
 \r
-    internal Array(Class eClass, MetaData md, string nameSpace, string name,\r
-                    byte TypeId) : base(TypeId) {\r
-            elemType = eClass;\r
-            tabIx = MDTable.TypeSpec;\r
-            metaData = md;\r
-            cnameSpace = nameSpace;\r
-            cname = name;\r
-    }\r
-\r
-      public Method AddMethod(string name, Type retType, Type[] pars) {\r
-\r
-              if (metaData == null || cnameSpace == null || cname == null)\r
-                      throw new Exception ("Methods cannot be added to arrays not created with the Class.GetArray* methods.");\r
-              Method meth = new MethodRef (GetTypeSpec (metaData), name, retType, pars, false, null);\r
-              metaData.AddToTable(MDTable.MemberRef,meth);\r
-\r
-              return meth;\r
-      }\r
\r
         }\r
 \r
   /**************************************************************************/  \r
@@ -191,9 +230,6 @@ namespace PEAPI
     /// <param name="elementType">the type of the array elements</param>\r
     public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }\r
 \r
-    public ZeroBasedArray(Class elementClass, MetaData md,\r
-                    string nameSpace, string name) : base (elementClass, md, nameSpace, name, 0x1D) { }\r
-\r
     internal sealed override void TypeSig(MemoryStream str) {\r
       str.WriteByte(typeIndex);\r
       elemType.TypeSig(str); \r
@@ -231,17 +267,6 @@ namespace PEAPI
       }\r
     }\r
 \r
-    internal BoundArray(Class elementClass, MetaData md, string nameSpace, string name,\r
-                    uint dimensions, int[] loBounds,\r
-                    int[] upBounds) : base (elementClass,md, nameSpace, name, 0x14) {\r
-      numDims = dimensions;\r
-      lowerBounds = loBounds;\r
-      sizes = new int[loBounds.Length];\r
-      for (int i=0; i < loBounds.Length; i++) {\r
-        sizes[i] = upBounds[i] - loBounds[i] + 1;\r
-      }\r
-    }\r
-\r
     /// <summary>\r
     /// Create a new multi dimensional array type \r
     /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])\r
@@ -293,7 +318,7 @@ namespace PEAPI
   {\r
     ushort majorVer, minorVer, buildNo, revisionNo;\r
     uint flags;\r
-    HashAlgorithm hashAlgId = HashAlgorithm.None;\r
+    uint hashAlgId;
     uint keyIx = 0, cultIx = 0;\r
     \r
     internal Assembly(string name, MetaData md) : base(name,md) {\r
@@ -311,7 +336,7 @@ namespace PEAPI
     /// <param name="hash">Hash Algorithm</param>\r
     /// <param name="cult">Culture</param>\r
     public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, \r
-                              byte[] key, HashAlgorithm hash, string cult) {\r
+                              byte[] key, uint hash, string cult) {\r
       majorVer = (ushort)majVer;\r
       minorVer = (ushort)minVer;\r
       buildNo = (ushort)bldNo;\r
@@ -356,10 +381,16 @@ namespace PEAPI
 \r
   }     \r
   /**************************************************************************/  \r
+
+        public interface IExternRef  {
+                ClassRef AddClass(string nsName, string name);
+                ClassRef AddValueClass(string nsName, string name);
+        }
+        
         /// <summary>\r
         /// A reference to an external assembly (.assembly extern)\r
         /// </summary>\r
-        public class AssemblyRef : ResolutionScope\r
+        public class AssemblyRef : ResolutionScope, IExternRef
         {\r
     private ushort major, minor, build, revision;\r
     uint flags, keyIx, hashIx, cultIx;\r
@@ -492,7 +523,7 @@ namespace PEAPI
       }\r
       return 0;\r
     }\r
\r
+
         }\r
   /**************************************************************************/  \r
 \r
@@ -524,7 +555,7 @@ namespace PEAPI
   /// Method call conventions\r
   /// </summary>\r
   public enum CallConv { Default, Cdecl, Stdcall, Thiscall, \r
-    Fastcall, Vararg, Instance = 0x20, InstanceExplicit = 0x60 }\r
+    Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }\r
 \r
   /// <summary>\r
   /// Type custom modifier\r
@@ -637,8 +668,15 @@ namespace PEAPI
   /// <summary>\r
   /// CIL branch instructions\r
   /// </summary>\r
-  public enum BranchOp {br = 0x2B, brfalse, brtrue, beq, bge, bgt, ble, blt,\r
-    bne_un, bge_un, bgt_un, ble_un, blt_un, leave = 0xDE }\r
+  public enum BranchOp {
+          // short branches
+          br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
+          ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
+          // long branches
+          br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,\r
+          bne_un, bge_un, bgt_un, ble_un, blt_un,
+
+          leave = 0xDD, leave_s }\r
 \r
   /// <summary>\r
   /// Index for all the tables in the meta data\r
@@ -987,8 +1025,15 @@ namespace PEAPI
     /// <param name="str">the string value</param>\r
     public void ldstr(string str) {\r
       AddToBuffer(new StringInstr(0x72,str));\r
-    }\r
-\r
+    }
+
+          /// <summary>
+          /// Add the load string instruction
+          /// </summary>
+          public void ldstr (byte[] str) {
+                  AddToBuffer (new StringInstr (0x72, str));
+          }
+          
     /// <summary>\r
     /// Add the calli instruction\r
     /// </summary>\r
@@ -1325,6 +1370,13 @@ namespace PEAPI
             numExceptClauses += (uint)tryBlock.NumHandlers();\r
             if (tryBlock.isFat()) fatExceptionFormat = true;\r
           }\r
+
+          uint data_size = ExHeaderSize + numExceptClauses *
+                 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
+
+          if (data_size > 256)
+                  fatExceptionFormat = true;
+                  
           // Console.WriteLine("numexceptclauses = " + numExceptClauses);\r
           if (fatExceptionFormat) {\r
             // Console.WriteLine("Fat exception format");\r
@@ -1652,19 +1704,6 @@ namespace PEAPI
       nameIx = nIx;\r
     }\r
 \r
-    public BoundArray GetBoundArray (uint dimensions, int[] loBounds,\r
-                    int[] upBounds) {\r
-            BoundArray bound_array = new BoundArray (this, _metaData, nameSpace,\r
-                            name, dimensions, loBounds, upBounds);\r
-            return bound_array;\r
-    }\r
-\r
-    public ZeroBasedArray GetZeroBasedArray () {\r
-            ZeroBasedArray array = new ZeroBasedArray (this, _metaData,\r
-                            nameSpace, name);\r
-            return array;\r
-    }\r
-\r
     internal virtual uint TypeDefOrRefToken() { return 0; }\r
 \r
     internal virtual void MakeValueClass() {\r
@@ -1749,15 +1788,6 @@ namespace PEAPI
       metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));\r
     }\r
 \r
-    /// <summary>\r
-    ///   Add a generic type parameter.\r
-    /// </summary>\r
-    public GenericParameter AddGenericParameter (short index) {\r
-            GenericParameter gp = new GenericParameter (this, metaData, index);
-            metaData.AddToTable (MDTable.GenericParam, gp);\r
-            return gp;
-    }\r
-\r
     /// <summary>\r
     ///  Add a named generic type parameter\r
     /// </summary>\r
@@ -1791,7 +1821,12 @@ namespace PEAPI
       fields.Add(field);\r
       return field;\r
     }\r
-\r
+
+    public void SetFieldOrder (ArrayList fields)
+    {
+            this.fields = fields;
+    }
+
     /// <summary>\r
     /// Add a method to this class\r
     /// </summary>\r
@@ -1958,7 +1993,6 @@ namespace PEAPI
         md.AddToTable(MDTable.PropertyMap,new MapElem(this,\r
                           ((Property)properties[0]).Row,MDTable.Property));\r
       }\r
-      DoCustomAttributes (md);\r
       // Console.WriteLine("End of building tables");\r
       done = true;\r
     }\r
@@ -2318,25 +2352,25 @@ namespace PEAPI
 \r
     public IntConst(sbyte val) {\r
       this.val = val;\r
-      size = 8;\r
+      size = 1;\r
       type = PrimitiveType.Int8;\r
     }\r
 \r
     public IntConst(short val) {\r
       this.val = val;\r
-      size = 16;\r
+      size = 2;\r
       type = PrimitiveType.Int16;\r
     }\r
 \r
     public IntConst(int val) {\r
       this.val = val;\r
-      size = 32;\r
+      size = 4;\r
       type = PrimitiveType.Int32;\r
     }\r
 \r
     public IntConst(long val) {\r
       this.val = val;\r
-      size = 64;\r
+      size = 8;\r
       type = PrimitiveType.Int64;\r
     }\r
 \r
@@ -2369,22 +2403,22 @@ namespace PEAPI
 \r
     public UIntConst(sbyte val) {\r
       this.val = val;\r
-      size = 8;\r
+      size = 1;\r
       type = PrimitiveType.UInt8;\r
     }\r
     public UIntConst(short val) {\r
       this.val = val;\r
-      size = 16;\r
+      size = 2;\r
       type = PrimitiveType.UInt16;\r
     }\r
     public UIntConst(int val) {\r
       this.val = val;\r
-      size = 32;\r
+      size = 4;\r
       type = PrimitiveType.UInt32;\r
     }\r
     public UIntConst(long val) {\r
       this.val = val;\r
-      size = 64;\r
+      size = 8;\r
       type = PrimitiveType.UInt64;\r
     }\r
 \r
@@ -2422,8 +2456,9 @@ namespace PEAPI
     }\r
 \r
     internal sealed override uint GetBlobIndex(MetaData md) {\r
-      if (!addedToBlobHeap) {\r
-        blobIndex = md.AddToBlobHeap(val);\r
+      if (!addedToBlobHeap) {
+        byte [] b = Encoding.Unicode.GetBytes (val);
+        blobIndex = md.AddToBlobHeap(b);\r
         addedToBlobHeap = true;\r
       }\r
       return blobIndex;\r
@@ -2615,7 +2650,7 @@ namespace PEAPI
 \r
     internal sealed override void BuildTables(MetaData md) {\r
       BinaryWriter bw = new BinaryWriter(new MemoryStream());\r
-      bw.Write((ushort)1);\r
+      bw.Write(byteVal);\r
       md.AddToTable(MDTable.CustomAttribute, this);\r
       MemoryStream str = (MemoryStream)bw.BaseStream;\r
       valIx = md.AddToBlobHeap(str.ToArray());\r
@@ -2888,6 +2923,7 @@ namespace PEAPI
     //private static readonly uint PInvokeImpl = 0x2000;\r
     private static readonly ushort HasFieldMarshal = 0x1000;\r
     private static readonly ushort HasFieldRVA = 0x100;\r
+    private static readonly ushort HasDefault = 0x8000;
 \r
     FieldRVA rva;\r
     ConstantElem constVal;\r
@@ -2918,6 +2954,7 @@ namespace PEAPI
     /// <param name="val">the value for the field</param>\r
     public void AddValue(Constant val) {\r
       constVal = new ConstantElem(this,val);\r
+      flags |= HasDefault;
     }\r
 \r
     /// <summary>\r
@@ -3342,12 +3379,12 @@ if (rsrc != null)
                                 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));\r
                                 sdata.SetOffset(offset);\r
         sdata.SetRVA(rva);\r
-        offset += sdata.Size();\r
+        offset += sdata.Size();
         rva = GetNextSectStart(rva,sdata.Tide());\r
                                 initDataSize += sdata.Size();\r
       }\r
       if (rsrc != null) { \r
-                                rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));\r
+                     rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));\r
                                 rsrc.SetOffset(offset);\r
         rsrc.SetRVA(rva);\r
         offset += rsrc.Size();\r
@@ -3449,9 +3486,13 @@ if (rsrc != null)
      }\r
 \r
     private void WriteSDataSection() {\r
+      long size = sdata.Size ();
+      long start = BaseStream.Position;
       for (int i=0; i < data.Count; i++) {\r
         ((DataConstant)data[i]).Write(this);\r
-      }\r
+      }
+      while (BaseStream.Position < (start + size))
+              Write ((byte) 0);
     }\r
 \r
                 private void WriteRsrcSection() {\r
@@ -3621,13 +3662,13 @@ if (rsrc != null)
         /// </summary>\r
         public class FileRef : MetaDataElement\r
         {\r
-    private static readonly uint HasMetaData = 0x1;\r
+    private static readonly uint NoMetaData = 0x1;\r
     uint nameIx = 0, hashIx = 0;\r
     uint flags = 0;\r
 \r
     internal FileRef(string name, byte[] hashBytes, bool metaData,\r
                       bool entryPoint, MetaData md) {\r
-      if (metaData) flags = HasMetaData;\r
+      if (!metaData) flags = NoMetaData;\r
       if (entryPoint) md.SetEntryPoint(this);\r
       nameIx = md.AddToStringsHeap(name);\r
       hashIx = md.AddToBlobHeap(hashBytes);\r
@@ -3636,7 +3677,7 @@ if (rsrc != null)
 \r
     internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,\r
                       bool entryPoint, MetaData md) {\r
-      if (metaData) flags = HasMetaData;\r
+      if (!metaData) flags = NoMetaData;\r
       if (entryPoint) md.SetEntryPoint(this);\r
       this.nameIx = nameIx;\r
       hashIx = md.AddToBlobHeap(hashBytes);\r
@@ -3852,16 +3893,25 @@ if (rsrc != null)
         }\r
 \r
   internal class StringInstr : Instr {\r
-    string val;\r
+    string val;
+          byte[] bval;                                                  
     uint strIndex;\r
 \r
     internal StringInstr(int inst, string str) : base(inst) {\r
       val = str;  \r
       size += 4;\r
-    }\r
-\r
-    internal sealed override bool Check(MetaData md) {\r
-      strIndex = md.AddToUSHeap(val);\r
+    }
+
+          internal StringInstr (int inst, byte[] str) : base (inst) {
+                  bval = str;
+                  size += 4;
+          }
+                   
+    internal sealed override bool Check(MetaData md) {
+            if (val != null)
+                    strIndex = md.AddToUSHeap(val);
+            else
+                    strIndex = md.AddToUSHeap (bval);
       return false;\r
     }\r
 \r
@@ -3956,20 +4006,18 @@ if (rsrc != null)
       dest = dst;\r
       dest.AddBranch(this);\r
       size++;\r
+
+      if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
+              shortVer = false;
+              size += 3;
+      }
     }\r
 \r
     internal sealed override bool Check(MetaData md) {\r
       target = (int)dest.GetLabelOffset() - (int)(offset + size);\r
-      if (shortVer && ((target < minByteVal) || (target > maxByteVal))) {\r
-        if (instr < (int)BranchOp.leave) instr += longInstrOffset;\r
-        else instr--;\r
-        shortVer = false;\r
-        size += 3;\r
-        return true;\r
-      }\r
-      return false;\r
+      return false;
     }\r
-\r
+
                 internal sealed override void Write(FileImage output) {\r
                         base.Write(output);\r
                         if (shortVer)\r
@@ -4007,24 +4055,32 @@ if (rsrc != null)
 \r
         public class GenericParameter : MetaDataElement\r
         {\r
-                ClassDef owner; /* FIXME: can also be a MethodDef */\r
+                MetaDataElement owner;
                 MetaData metadata;
                 string name;\r
                 uint nameIx;\r
                 short index;\r
 \r
-                public GenericParameter (ClassDef owner, MetaData metadata, short index) {\r
+                internal GenericParameter (ClassDef owner, MetaData metadata,
+                                short index, string name) : this (owner, metadata, index, name, true)
+                {
+                }
+\r
+                internal GenericParameter (MethodDef owner, MetaData metadata,
+                                short index, string name) : this (owner, metadata, index, name, true)
+                {
+                }
+
+                private GenericParameter (MetaDataElement owner, MetaData metadata,
+                                short index, string name, bool nadda)
+                {
                         this.owner = owner;\r
                         this.metadata = metadata;
                         this.index = index;\r
                         tabIx = MDTable.GenericParam;\r
-                }\r
-\r
-                public GenericParameter (ClassDef owner, MetaData metadata, short index,\r
-                        string name) : this (owner, metadata, index) {\r
                         this.name = name;\r
-                }\r
-\r
+                }
+
                 public void AddConstraint  (Type constraint) {
                         metadata.AddToTable (MDTable.GenericParamConstraint,\r
                                         new GenericParamConstraint (this, constraint));\r
@@ -4039,10 +4095,7 @@ if (rsrc != null)
 \r
                 internal sealed override void BuildTables(MetaData md) {\r
                         if (done) return;\r
-                        if (name == null)\r
-                                nameIx = 0;\r
-                        else\r
-                                nameIx = md.AddToStringsHeap(name);\r
+                        nameIx = md.AddToStringsHeap(name);\r
                         done = true;\r
                 }\r
 \r
@@ -4080,6 +4133,36 @@ if (rsrc != null)
 \r
 \r
         }\r
+
+        internal class MethodSpec : MetaDataElement
+        {
+                Method meth;
+                GenericMethodSig g_sig;
+                uint sidx;
+
+                internal MethodSpec (Method meth, GenericMethodSig g_sig) {
+                        this.meth = meth;
+                        this.g_sig = g_sig;
+                        tabIx = MDTable.MethodSpec;
+                }
+
+                internal sealed override void BuildTables (MetaData md) {
+                        if (done) return;
+                        sidx = g_sig.GetSigIx (md);
+                        done = true;
+                }
+
+                internal sealed override uint Size (MetaData md) {
+                        return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
+                                       md.BlobIndexSize ());
+                }
+
+                internal sealed override void Write (FileImage output) {
+                    output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
+                    output.BlobIndex (sidx);\r
+                }
+        }
+
   /**************************************************************************/\r
         /// <summary>\r
         /// Descriptor for interface implemented by a class\r
@@ -4341,7 +4424,8 @@ if (rsrc != null)
     public MSCorLib mscorlib;\r
     private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];\r
     long mdStart;\r
-\r
+                private ArrayList cattr_list;
+                
     internal MetaData(FileImage file) {\r
       // tilde = new MetaDataStream(tildeName,false,0);\r
       this.file = file;\r
@@ -4371,7 +4455,6 @@ if (rsrc != null)
     }\r
 \r
     internal uint Size() {\r
-      //Console.WriteLine("metaData size = " + metaDataSize);\r
       return metaDataSize;\r
     }\r
 \r
@@ -4382,67 +4465,78 @@ if (rsrc != null)
     internal uint AddToUSHeap(string str) {\r
       if (str == null) return 0;\r
       return us.Add(str,true);\r
-   }\r
-\r
+   }
+
+                internal uint AddToUSHeap(byte[] str) {
+                        if (str == null) return 0;
+                        return us.Add (str, true);
+                }
+                                
     internal uint AddToStringsHeap(string str) {\r
       if ((str == null) || (str.CompareTo("") == 0)) return 0;\r
       return strings.Add(str,false);\r
     }\r
 \r
     internal uint AddToGUIDHeap(Guid guidNum) {\r
-      return guid.Add(guidNum);\r
+      return guid.Add(guidNum, false);\r
     }\r
 \r
     internal uint AddToBlobHeap(byte[] blobBytes) {\r
       if (blobBytes == null) return 0;\r
-      return blob.Add(blobBytes);\r
+      return blob.Add(blobBytes, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(byte val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(sbyte val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(ushort val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(short val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(uint val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(int val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(ulong val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(long val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(float val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(double val) {\r
-      return blob.Add(val);\r
+      return blob.Add(val, true);\r
     }\r
 \r
     internal uint AddToBlobHeap(string val) {\r
       return blob.Add(val,true);\r
     }\r
 \r
-\r
+                internal void AddCustomAttribute (CustomAttribute cattr)
+                {
+                        if (cattr_list == null)
+                                cattr_list = new ArrayList ();
+                        cattr_list.Add (cattr);
+                }
+
     private ArrayList GetTable(MDTable tableIx) {\r
       int tabIx = (int)tableIx;\r
       if (metaDataTables[tabIx] == null) {\r
@@ -4602,12 +4696,9 @@ if (rsrc != null)
         sizeOfHeaders += streams[i].headerSize();\r
       }\r
       metaDataSize = MetaDataHeaderSize + sizeOfHeaders;\r
-      // Console.WriteLine("Size of meta data headers (tildeStart) = " + metaDataSize);\r
       tildeStart = metaDataSize;\r
       metaDataSize += tildeTide + tildePadding;\r
-      //Console.WriteLine(tildeName + " - size = " + (tildeTide + tildePadding));\r
       for (int i=1; i < numStreams; i++) {\r
-        // Console.WriteLine("Stream " + i + " starts at " + metaDataSize);\r
         streams[i].Start = metaDataSize;\r
         metaDataSize += streams[i].Size();\r
         streams[i].WriteDetails();\r
@@ -4674,8 +4765,14 @@ if (rsrc != null)
       BuildTable(metaDataTables[(int)MDTable.TypeDef]);\r
       BuildTable(metaDataTables[(int)MDTable.MemberRef]);\r
       BuildTable(metaDataTables[(int)MDTable.GenericParam]);\r
+      BuildTable(metaDataTables[(int)MDTable.MethodSpec]);\r
       BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);\r
-      BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);\r
+
+      if (cattr_list != null) {
+              foreach (CustomAttribute cattr in cattr_list)
+                      cattr.BuildTables (this);
+      }
+
 /*      for (int i=0; i < metaDataTables.Length; i++) {\r
         ArrayList table = metaDataTables[i];\r
         if (table != null) {\r
@@ -4685,6 +4782,7 @@ if (rsrc != null)
         }\r
       }\r
       */\r
+
                         SetIndexSizes();\r
                         for (int i=1; i < numStreams; i++) {\r
                                 streams[i].EndStream();\r
@@ -4804,16 +4902,7 @@ if (rsrc != null)
       } \r
 //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));\r
     }\r
-\r
-    internal void DoCustomAttributes(MetaData md) {\r
-      if (customAttributes != null) {\r
-        for (int i=0; i < customAttributes.Count; i++) {\r
-          CustomAttribute ca = (CustomAttribute)customAttributes[i];\r
-          ca.BuildTables(md);\r
-        }\r
-      }\r
-    }\r
-\r
+
     internal uint Token() {\r
       return (((uint)tabIx << 24) | row);\r
     }\r
@@ -4844,8 +4933,9 @@ if (rsrc != null)
     bool largeIx = false;\r
     uint sizeOfHeader;\r
     char[] name;\r
-    Hashtable htable = new Hashtable();\r
-\r
+    Hashtable htable = new Hashtable();
+                Hashtable btable = new Hashtable ();
+
     internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {\r
       if (addInitByte) { Write((byte)0); size = 1; }\r
       this.name = name;\r
@@ -4903,9 +4993,26 @@ if (rsrc != null)
         index = (uint)val;\r
       }\r
                         return index;\r
-                }\r
-\r
-                internal uint Add(Guid guid) {\r
+                }
+                internal uint Add (byte[] str, bool prependSize) {
+                        Object val = btable [str];
+                        uint index = 0;
+                        if (val == null) {
+                                index = size;
+                                btable [str] = index;
+                                if (prependSize) CompressNum ((uint) str.Length);
+                                Write (str);
+                                size = (uint) Seek (0, SeekOrigin.Current);
+                        } else {
+                                index = (uint) val;
+                        }
+                        return index;
+                }
+
+                    
+                internal uint Add(Guid guid, bool prependSize) {\r
+                        byte [] b = guid.ToByteArray ();
+                        if (prependSize) CompressNum ((uint) b.Length);
                         Write(guid.ToByteArray());\r
                         size =(uint)Seek(0,SeekOrigin.Current);\r
                         return tide++;\r
@@ -4913,77 +5020,87 @@ if (rsrc != null)
 \r
                 internal uint Add(byte[] blob) {\r
                         uint ix = size;\r
-                        CompressNum((uint)blob.Length);\r
+                        CompressNum((uint)blob.Length);
                         Write(blob);\r
                         size = (uint)Seek(0,SeekOrigin.Current);\r
                         return ix;\r
                 }\r
 \r
-    internal uint Add(byte val) {\r
+    internal uint Add(byte val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (1);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(sbyte val) {\r
+    internal uint Add(sbyte val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (1);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(ushort val) {\r
+    internal uint Add(ushort val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (2);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(short val) {\r
+    internal uint Add(short val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (2);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(uint val) {\r
+    internal uint Add(uint val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (4);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(int val) {\r
+    internal uint Add(int val, bool prependSize) {\r
       uint ix = size;\r
-      Write(val);\r
+      if (prependSize) CompressNum (4);
+      Write (val);
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(ulong val) {\r
+    internal uint Add(ulong val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (8);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(long val) {\r
+    internal uint Add(long val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (8);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(float val) {\r
+    internal uint Add(float val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (4);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
     }\r
 \r
-    internal uint Add(double val) {\r
+    internal uint Add(double val, bool prependSize) {\r
       uint ix = size;\r
+      if (prependSize) CompressNum (8);
       Write(val);\r
       size = (uint)Seek(0,SeekOrigin.Current);\r
       return ix;\r
@@ -5145,6 +5262,15 @@ if (rsrc != null)
       methFlags |= PInvokeImpl;\r
     }\r
 \r
+    /// <summary>\r
+    ///  Add a named generic type parameter\r
+    /// </summary>\r
+    public GenericParameter AddGenericParameter (short index, string name) {\r
+            GenericParameter gp = new GenericParameter (this, metaData, index, name);
+            metaData.AddToTable (MDTable.GenericParam, gp);\r
+            return gp;
+    }\r
+
     /// <summary>\r
     /// Set the maximum stack height for this method\r
     /// </summary>\r
@@ -5240,7 +5366,6 @@ if (rsrc != null)
         varArgSig.BuildTables(md);\r
       }\r
       }\r
-      DoCustomAttributes (md);\r
       // Console.WriteLine("method has " + numPars + " parameters");\r
       done = true;\r
     }\r
@@ -5261,6 +5386,8 @@ if (rsrc != null)
 \r
     internal bool ZeroRva () {
         return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
+                        ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
+                        ((implFlags & (ushort)ImplAttr.InternalCall) != 0) || 
                         (pinvokeImpl != null)); // TODO: Not entirely true but works for now
     }
 
@@ -5405,25 +5532,51 @@ if (rsrc != null)
         /// \r
         public class MethPtrType : Type\r
         {\r
-    // MethPtrType == FNPTR\r
-    Method method;\r
-    uint sigIx = 0;\r
-\r
+                bool varArgMeth;
+                Type retType;
+                Type [] parList;
+                Type [] optParList;
+                CallConv callConv;
+                uint numPars;
+                uint numOptPars;
+                uint sigIx = 0;
+
     /// <summary>\r
     /// Create a new function pointer type\r
     /// </summary>\r
     /// <param name="meth">the function to be referenced</param>\r
-                public MethPtrType(Method meth) : base(0x1B)\r
-                {\r
-      method = meth;\r
-                        tabIx = MDTable.TypeSpec;\r
-                }\r
-\r
-    internal sealed override void TypeSig(MemoryStream str) {\r
-      str.WriteByte(typeIndex);\r
-      method.TypeSig(str);\r
-    }\r
-\r
+    public MethPtrType (CallConv callconv, Type retType, Type[] pars,
+                    bool varArgMeth, Type[] optPars) : base(0x1B) {
+      this.retType = retType;
+      callConv = callconv;
+      parList = pars;
+      this.varArgMeth = varArgMeth;
+      if (parList != null) numPars = (uint)parList.Length;
+      if (varArgMeth) {
+        optParList = optPars;
+        if (optParList != null) numOptPars = (uint)optParList.Length;
+        callConv |= CallConv.Vararg;
+      }
+      tabIx = MDTable.TypeSpec;
+    }
+  
+    internal sealed override void TypeSig(MemoryStream sig) {
+      sig.WriteByte(typeIndex);
+      // Bootlegged from method ref
+      sig.WriteByte((byte)callConv);
+      MetaData.CompressNum (numPars + numOptPars, sig);
+      retType.TypeSig (sig);
+      for (int i=0; i < numPars; i++) {
+              parList[i].TypeSig (sig);
+      }
+      if (varArgMeth) {
+              sig.WriteByte (0x41); // Write the sentinel
+        for (int i=0; i < numOptPars; i++) {
+          optParList[i].TypeSig (sig);
+        }
+      }
+    }
+
     internal sealed override void BuildTables(MetaData md) {\r
       if (done) return;\r
       MemoryStream sig = new MemoryStream();\r
@@ -5477,19 +5630,18 @@ if (rsrc != null)
                         }\r
                         return 0;\r
     }\r
-\r
-        }\r
+  }
   /**************************************************************************/  \r
         /// <summary>\r
         /// Descriptor for another module in THIS assembly\r
         /// </summary>\r
-  public class ModuleRef : ResolutionScope\r
+        public class ModuleRef : ResolutionScope, IExternRef
         {\r
 \r
                 internal ModuleRef(MetaData md, string name) : base(name,md) {\r
       tabIx = MDTable.ModuleRef;\r
-                }\r
-\r
+                }
+
     /// <summary>\r
     /// Add a class to this external module.  This is a class declared in\r
     /// another module of THIS assembly.\r
@@ -5497,7 +5649,7 @@ if (rsrc != null)
     /// <param name="nsName">name space name</param>\r
     /// <param name="name">class name</param>\r
     /// <returns>a descriptor for this class in another module</returns>\r
-    public ClassRef AddClass(string nsName, string name, bool exportClass) {\r
+    public ClassRef AddClass(string nsName, string name) {\r
       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
       metaData.AddToTable(MDTable.TypeRef,aClass);\r
       aClass.SetParent(this);\r
@@ -5915,7 +6067,12 @@ if (rsrc != null)
       fileImage = new FileImage(isDLL,outStream);\r
       InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);\r
     }\r
-\r
+
+    public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {\r
+      fileImage = new FileImage(isDLL,outStream);\r
+      InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);\r
+    }
+
     private void InitPEFile(string name, string fName, bool hasAssembly) {\r
       metaData = fileImage.GetMetaData();\r
       thisMod = new Module(fName,metaData);\r
@@ -6029,6 +6186,12 @@ if (rsrc != null)
             return field;\r
     }\r
 \r
+    public void AddMethodSpec (Method m, GenericMethodSig g_sig)
+    {
+            MethodSpec ms = new MethodSpec (m, g_sig);
+            metaData.AddToTable (MDTable.MethodSpec, ms);
+    }
+
     /// <summary>\r
     /// Add a "global" field to this module\r
     /// </summary>\r
@@ -6106,7 +6269,12 @@ if (rsrc != null)
       metaData.AddToTable(MDTable.ManifestResource,mr);\r
       //mr.FixName(metaData);\r
     }\r
-\r
+
+    public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
+    {
+            metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
+    }
+
     /// <summary>\r
     /// Write out the PEFile (the "bake" function)\r
     /// </summary>\r
@@ -6369,10 +6537,10 @@ if (rsrc != null)
     uint flags = 0, padding = 0;\r
                 uint[] relocs; \r
 \r
-                internal Section(string sName, uint sFlags) {\r
-                        name = sName.ToCharArray();\r
-                        flags = sFlags;\r
-                }\r
+                internal Section(string sName, uint sFlags) {
+                  name = sName.ToCharArray();\r
+                  flags = sFlags;\r
+                }
 \r
                 internal uint Tide() { return tide; }\r
 \r