**** Merged r40464 from MCS ****
authorMartin Baulig <martin@novell.com>
Tue, 22 Mar 2005 10:01:15 +0000 (10:01 -0000)
committerMartin Baulig <martin@novell.com>
Tue, 22 Mar 2005 10:01:15 +0000 (10:01 -0000)
svn path=/trunk/mcs/; revision=42077

12 files changed:
mcs/gmcs/ChangeLog
mcs/gmcs/anonymous.cs
mcs/gmcs/attribute.cs
mcs/gmcs/class.cs
mcs/gmcs/const.cs
mcs/gmcs/cs-parser.jay
mcs/gmcs/ecore.cs
mcs/gmcs/expression.cs
mcs/gmcs/flowanalysis.cs
mcs/gmcs/rootcontext.cs
mcs/gmcs/statement.cs
mcs/gmcs/typemanager.cs

index e2305345a6300d796ca51fadeccded93b9d41029..f6747aea879794f6d52921d6b4d8d935d5c02bcb 100644 (file)
@@ -1,3 +1,54 @@
+2005-02-11  Marek Safar  <marek.safar@seznam.cz>
+
+       C# 2.0 Fixed buffer implementation
+
+       * anonymous.cs: Update after RegisterHelperClass renaming.
+
+       * attribute.cs (AttributeTester.fixed_buffer_cache):
+       Cache of external fixed buffers.
+       (AttributeTester.GetFixedBuffer): Returns IFixedBuffer
+       implementation if field is fixed buffer else null.
+
+       * class.cs
+       (TypeContainer.AddField): Accept FieldMember instead of Field.
+       (FieldBase.IsFieldClsCompliant): Extracted code from
+       VerifyClsCompliance descendant customization.
+       (FixedField): New class handles fixed buffer fields.
+       (FixedFieldExternal): Keeps information about imported fixed
+       buffer.
+       (IFixedField): Make access to internal or external fixed buffer
+       same.
+
+       * cs-parser.jay: Add fixed buffer parsing.
+
+       * ecore.cs (FieldExpr.Emit): Add special emit case for fixed
+       buffer.
+
+       * expression.cs (Indirection): Extended implementation to accept
+       fixed buffer field.
+       (PointerArithmetic.Emit): Get element from fixed buffer as well.
+       (ElementAccess.MakePointerAccess): Get type as parameter.
+       (DoResolve): Add fixed buffer field expression conversion.
+       (DoResolveLValue): Ditto.
+       (FixedBufferPtr): New class. Moved most of original ArrayPtr.
+       (ArrayPtr): Derives from FixedBufferPtr.
+       (ArrayPtr.Emit): Add extra emit for array elements.
+
+       * flowanalysis.cs.cs (StructInfo): Use FieldMember.
+
+       * rootcontext.cs (CloseTypes): Emit CompilerGenerated attribute
+       for compiler generated types.
+       (RegisterCompilerGeneratedType): Renamed from RegisterHelperClass.
+
+       * statement.cs (Fixed): Refactored to be easier add fixed buffer
+       and consume less memory.
+       (Fixed.Resolve): Add fixed buffer case.
+
+       * typemanager.cs (compiler_generated_attr_ctor,
+       fixed_buffer_attr_ctor): Add new 2.0 compiler attributes.
+       (HasElementType): Add our own implementation to work on every
+       runtime.
+
 2005-02-11  Miguel de Icaza  <miguel@novell.com>
 
        * anonymous.cs (CaptureContext): Track whether `this' has been
index 206b1a9653283504d7913cfb6705bda21a5c74a2..4e1016ebf14609729a66e6413e7111d1aacbc173 100644 (file)
@@ -561,7 +561,7 @@ namespace Mono.CSharp {
 
                public void CloseTypes ()
                {
-                       RootContext.RegisterHelperClass (ScopeTypeBuilder);
+                       RootContext.RegisterCompilerGeneratedType (ScopeTypeBuilder);
                        foreach (ScopeInfo si in children)
                                si.CloseTypes ();
                }
index 3613cd4afaaf8fb6a6180476bdb097094109e423..0451f60cb2b1c882cba36dc3f6a8a4dfac65c086 100644 (file)
@@ -1371,6 +1371,10 @@ namespace Mono.CSharp {
                static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
                static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
                static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+               static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+
+               static object TRUE = new object ();
+               static object FALSE = new object ();
 
                private AttributeTester ()
                {
@@ -1463,10 +1467,39 @@ namespace Mono.CSharp {
                        }
                        analyzed_types.Add (type, result ? TRUE : FALSE);
                        return result;
-               }                
+               }        
+        
+               /// <summary>
+               /// Returns IFixedBuffer implementation if field is fixed buffer else null.
+               /// </summary>
+               public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
+               {
+                       FieldBase fb = TypeManager.GetField (fi);
+                       if (fb != null) {
+                               return fb as IFixedBuffer;
+                       }
 
-               static object TRUE = new object ();
-               static object FALSE = new object ();
+#if NET_2_0
+                       object o = fixed_buffer_cache [fi];
+                       if (o == null) {
+                               if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) {
+                                       fixed_buffer_cache.Add (fi, FALSE);
+                                       return null;
+                               }
+                               
+                               IFixedBuffer iff = new FixedFieldExternal (fi);
+                               fixed_buffer_cache.Add (fi, iff);
+                               return iff;
+                       }
+
+                       if (o == FALSE)
+                               return null;
+
+                       return (IFixedBuffer)o;
+#else
+                       return null;
+#endif
+               }
 
                public static void VerifyModulesClsCompliance ()
                {
index 62b39abcef232960177d329712a9c8c93d7a547f..6027fe321f6e7e56c76e966cf4bf08f0f079ce55 100644 (file)
@@ -581,7 +581,7 @@ namespace Mono.CSharp {
                        interfaces.Add (iface);
                }
 
-               public void AddField (Field field)
+               public void AddField (FieldMember field)
                {
                        if (!AddToMemberContainer (field))
                                return;
@@ -1762,7 +1762,7 @@ namespace Mono.CSharp {
                                if (fields != null) {
                                        int len = fields.Count;
                                        for (int i = 0; i < len; i++) {
-                                               Field f = (Field) fields [i];
+                                               FieldMember f = (FieldMember) fields [i];
                                                
                                                if ((f.ModFlags & modflags) == 0)
                                                        continue;
@@ -2223,7 +2223,7 @@ namespace Mono.CSharp {
                        }
                        
                        if (fields != null)
-                               foreach (Field f in fields)
+                               foreach (FieldMember f in fields)
                                        f.Emit ();
 
                        if (events != null){
@@ -5693,6 +5693,15 @@ namespace Mono.CSharp {
                        return TypeManager.GetFullNameSignature (FieldBuilder);
                }
 
+               protected virtual bool IsFieldClsCompliant {
+                       get {
+                               if (FieldBuilder == null)
+                                       return true;
+
+                               return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
+                       }
+               }
+
                public override string[] ValidAttributeTargets {
                        get {
                                return attribute_targets;
@@ -5704,11 +5713,7 @@ namespace Mono.CSharp {
                        if (!base.VerifyClsCompliance (ds))
                                return false;
 
-                       if (FieldBuilder == null) {
-                               return true;
-                       }
-
-                       if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
+                       if (!IsFieldClsCompliant) {
                                Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
                        }
                        return true;
@@ -5795,6 +5800,11 @@ namespace Mono.CSharp {
 
                public override void Emit ()
                {
+                       if (OptAttributes != null) {
+                               EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
+                               OptAttributes.Emit (ec, this);
+                       }
+
                        if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
                                Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
                        }
@@ -5810,6 +5820,163 @@ namespace Mono.CSharp {
                }
        }
 
+       interface IFixedBuffer
+       {
+               FieldInfo Element { get; }
+               Type ElementType { get; }
+       }
+
+       public class FixedFieldExternal: IFixedBuffer
+       {
+               FieldInfo element_field;
+
+               public FixedFieldExternal (FieldInfo fi)
+               {
+                       element_field = fi.FieldType.GetField (FixedField.FixedElementName);
+               }
+
+               #region IFixedField Members
+
+               public FieldInfo Element {
+                       get {
+                               return element_field;
+                       }
+               }
+
+               public Type ElementType {
+                       get {
+                               return element_field.FieldType;
+                       }
+               }
+
+               #endregion
+       }
+
+       /// <summary>
+       /// Fixed buffer implementation
+       /// </summary>
+       public class FixedField: FieldMember, IFixedBuffer
+       {
+               public const string FixedElementName = "FixedElementField";
+               static int GlobalCounter = 0;
+               static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
+               static FieldInfo[] fi;
+
+               TypeBuilder fixed_buffer_type;
+               FieldBuilder element;
+               Expression size_expr;
+               int buffer_size;
+
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE;
+
+               public FixedField (TypeContainer parent, Expression type, int mod, string name,
+                       Expression size_expr, Attributes attrs, Location loc):
+                       base (parent, type, mod, AllowedModifiers, new MemberName (name), null, attrs, loc)
+               {
+                       if (RootContext.Version == LanguageVersion.ISO_1)
+                               Report.FeatureIsNotStandardized (loc, "fixed sized buffers");
+
+                       this.size_expr = size_expr;
+               }
+
+               public override bool Define()
+               {
+#if !NET_2_0
+                       if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
+                               Report.Warning (-23, Location, "Only not private or internal fixed sized buffers are supported by .NET 1.x");
+#endif
+
+                       if (Parent.Kind != Kind.Struct) {
+                               Report.Error (1642, Location, "Fixed buffer fields may only be members of structs");
+                               return false;
+                       }
+
+                       if (!base.Define ())
+                               return false;
+
+                       if (!MemberType.IsPrimitive) {
+                               Report.Error (1663, Location, "Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double");
+                               return false;
+                       }
+
+                       Expression e = size_expr.Resolve (Parent.EmitContext);
+                       if (e == null)
+                               return false;
+
+                       Constant c = e as Constant;
+                       if (c == null) {
+                               Report.Error (133, Location, "The expression being assigned to '{0}' must be constant", GetSignatureForError ());
+                               return false;
+                       }
+
+                       buffer_size = (int)c.GetValue ();
+                       if (buffer_size <= 0) {
+                               Report.Error (1665, Location, "Fixed sized buffer '{0}' must have a length greater than zero", GetSignatureForError ());
+                               return false;
+                       }
+                       buffer_size *= Expression.GetTypeSize (MemberType);
+
+                       // Define nested
+                       string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
+
+                       fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
+                               TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
+                       element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
+                       RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
+
+                       FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
+                       TypeManager.RegisterFieldBase (FieldBuilder, this);
+
+                       return true;
+               }
+
+               public override void Emit()
+               {
+                       if (fi == null)
+                               fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
+
+                       object[] fi_val = new object[1];
+                       fi_val [0] = buffer_size;
+
+                       CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
+                               ctor_args, fi, fi_val);
+                       fixed_buffer_type.SetCustomAttribute (cab);
+
+#if NET_2_0
+                       cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
+                       FieldBuilder.SetCustomAttribute (cab);
+#endif
+                       base.Emit ();
+               }
+
+               protected override bool IsFieldClsCompliant {
+                       get {
+                               return false;
+                       }
+               }
+
+               #region IFixedField Members
+
+               public FieldInfo Element {
+                       get {
+                               return element;
+                       }
+               }
+
+               public Type ElementType {
+                       get {
+                               return MemberType;
+                       }
+               }
+
+               #endregion
+       }
+
        //
        // The Field class is used to represents class/struct fields during parsing.
        //
@@ -5910,18 +6077,6 @@ namespace Mono.CSharp {
 
                        return true;
                }
-
-               public override void Emit ()
-               {
-                       if (OptAttributes != null) {
-                               EmitContext ec = new EmitContext (
-                                       Parent, Location, null, FieldBuilder.FieldType,
-                                       ModFlags);
-                               OptAttributes.Emit (ec, this);
-               }
-
-                       base.Emit ();
-               }
        }
 
        //
index 956ed4fb9da83369ad8be260c165ebcd3ab10bf0..4fbd98552b08e6084d91b76920f2dde14c5d0521 100644 (file)
@@ -308,11 +308,6 @@ namespace Mono.CSharp {
                {
                        object value;
                        LookupConstantValue (out value);
-
-                       if (OptAttributes != null) {
-                               OptAttributes.Emit (const_ec, this);
-                       }
-
                        base.Emit ();
                }
        }
index 811ba6f3486fe314f0d403569bce459e578d1f64..418a146183ca887b2ab914581452fcddd31a727f 100644 (file)
@@ -937,11 +937,9 @@ field_declaration
                int mod = (int) $2;
 
                foreach (VariableDeclaration var in (ArrayList) $4){
-                       Location l = var.Location;
-
                        Field field = new Field (current_class, type, mod, var.identifier, 
                                                 var.expression_or_array_initializer, 
-                                                (Attributes) $1, l);
+                                                (Attributes) $1, var.Location);
 
                        if (RootContext.Documentation != null) {
                                field.DocComment = Lexer.consume_doc_comment ();
@@ -950,6 +948,27 @@ field_declaration
                        current_container.AddField (field);
                }
          }
+       | opt_attributes
+         opt_modifiers
+         FIXED
+         type 
+         fixed_variable_declarators
+         SEMICOLON
+         { 
+                       Expression type = (Expression) $4;
+                       int mod = (int) $2;
+
+                       foreach (VariableDeclaration var in (ArrayList) $5) {
+                               FixedField field = new FixedField (current_class, type, mod, var.identifier,
+                                       (Expression)var.expression_or_array_initializer, (Attributes) $1, var.Location);
+
+                               if (RootContext.Documentation != null) {
+                                       field.DocComment = Lexer.consume_doc_comment ();
+                                       Lexer.doc_state = XmlCommentState.Allowed;
+                               }
+                               current_container.AddField (field);
+                       }
+         }
        | opt_attributes
          opt_modifiers
          VOID  
@@ -959,6 +978,28 @@ field_declaration
          }
        ;
 
+fixed_variable_declarators
+       : fixed_variable_declarator
+               {
+                       ArrayList decl = new ArrayList (2);
+                       decl.Add ($1);
+                       $$ = decl;
+               }
+       | fixed_variable_declarators COMMA fixed_variable_declarator
+               {
+                       ArrayList decls = (ArrayList) $1;
+                       decls.Add ($3);
+                       $$ = $1;
+               }
+       ;
+
+fixed_variable_declarator
+       : IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
+               {
+                       $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+               }
+       ;
+
 variable_declarators
        : variable_declarator 
          {
index 31f0ecbb4c7a8c7854d02ceedde4eca4211a6fc8..a6c5029d760896cd0017c9244d5b626c648d45cd 100644 (file)
@@ -3033,7 +3033,15 @@ namespace Mono.CSharp {
                                if (is_volatile)
                                        ig.Emit (OpCodes.Volatile);
 
-                               ig.Emit (OpCodes.Ldfld, FieldInfo);
+                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
+                               if (ff != null)
+                               {
+                                       ig.Emit (OpCodes.Ldflda, FieldInfo);
+                                       ig.Emit (OpCodes.Ldflda, ff.Element);
+                               }
+                               else {
+                                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                               }
                        }
 
                        if (leave_copy) {
index 9a5c6b8170054f4fd1fa948351c8556b4bb3d4f0..61c49a610cadea2ffd7190564027fe984cd3d456 100644 (file)
@@ -671,7 +671,7 @@ namespace Mono.CSharp {
                public Indirection (Expression expr, Location l)
                {
                        this.expr = expr;
-                       this.type = TypeManager.GetElementType (expr.Type);
+                       type = TypeManager.HasElementType (expr.Type) ? TypeManager.GetElementType (expr.Type) : expr.Type;
                        eclass = ExprClass.Variable;
                        loc = l;
                }
@@ -3449,7 +3449,12 @@ namespace Mono.CSharp {
                {
                        Type op_type = left.Type;
                        ILGenerator ig = ec.ig;
-                       Type element = TypeManager.GetElementType (op_type);
+                       
+                       // It must be either array or fixed buffer
+                       Type element = TypeManager.HasElementType (op_type) ?
+                               element = TypeManager.GetElementType (op_type) :
+                               element = AttributeTester.GetFixedBuffer (((FieldExpr)left).FieldInfo).ElementType;
+
                        int size = GetTypeSize (element);
                        Type rtype = right.Type;
                        
@@ -7852,10 +7857,8 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               Expression MakePointerAccess (EmitContext ec)
+               Expression MakePointerAccess (EmitContext ec, Type t)
                {
-                       Type t = Expr.Type;
-
                        if (t == TypeManager.void_ptr_type){
                                Error (242, "The array index operation is not valid for void pointers");
                                return null;
@@ -7892,10 +7895,17 @@ namespace Mono.CSharp {
                        
                        if (t.IsArray)
                                return (new ArrayAccess (this, loc)).Resolve (ec);
-                       else if (t.IsPointer)
-                               return MakePointerAccess (ec);
-                       else
-                               return (new IndexerAccess (this, loc)).Resolve (ec);
+                       if (t.IsPointer)
+                               return MakePointerAccess (ec, Expr.Type);
+
+                       FieldExpr fe = Expr as FieldExpr;
+                       if (fe != null) {
+                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
+                               if (ff != null) {
+                                       return MakePointerAccess (ec, ff.ElementType);
+                               }
+                       }
+                       return (new IndexerAccess (this, loc)).Resolve (ec);
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
@@ -7906,10 +7916,24 @@ namespace Mono.CSharp {
                        Type t = Expr.Type;
                        if (t.IsArray)
                                return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
-                       else if (t.IsPointer)
-                               return MakePointerAccess (ec);
-                       else
-                               return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
+
+                       if (t.IsPointer)
+                               return MakePointerAccess (ec, Expr.Type);
+
+                       FieldExpr fe = Expr as FieldExpr;
+                       if (fe != null) {
+                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
+                               if (ff != null) {
+// TODO: not sure whether it is correct
+//                                     if (!ec.InFixedInitializer) {
+//                                     if (!ec.InFixedInitializer) {
+//                                             Error (1666, "You cannot use fixed sized buffers contained in unfixed expressions. Try using the fixed statement.");
+//                                             return null;
+//                                     }
+                                       return MakePointerAccess (ec, ff.ElementType);
+                               }
+                       }
+                       return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
                }
                
                public override void Emit (EmitContext ec)
@@ -8935,31 +8959,21 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // This class is used to represent the address of an array, used
-       // only by the Fixed statement, this is like the C "&a [0]" construct.
-       //
-       public class ArrayPtr : Expression {
+       public class FixedBufferPtr: Expression {
                Expression array;
-               
-               public ArrayPtr (Expression array, Location l)
-               {
-                       Type array_type = TypeManager.GetElementType (array.Type);
 
+               public FixedBufferPtr (Expression array, Type array_type, Location l)
+               {
                        this.array = array;
+                       this.loc = l;
 
                        type = TypeManager.GetPointerType (array_type);
                        eclass = ExprClass.Value;
-                       loc = l;
                }
 
-               public override void Emit (EmitContext ec)
+               public override void Emit(EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       
                        array.Emit (ec);
-                       IntLiteral.EmitInt (ig, 0);
-                       ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -8971,6 +8985,31 @@ namespace Mono.CSharp {
                }
        }
 
+
+       //
+       // This class is used to represent the address of an array, used
+       // only by the Fixed statement, this generates "&a [0]" construct
+       // for fixed (char *pa = a)
+       //
+       public class ArrayPtr : FixedBufferPtr {
+               Type array_type;
+               
+               public ArrayPtr (Expression array, Type array_type, Location l):
+                       base (array, array_type, l)
+               {
+                       this.array_type = array_type;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       
+                       ILGenerator ig = ec.ig;
+                       IntLiteral.EmitInt (ig, 0);
+                       ig.Emit (OpCodes.Ldelema, array_type);
+               }
+       }
+
        //
        // Used by the fixed statement
        //
index 9118631e509b83f4577e2a97a51f984d6327a80a..476f23d6aa109237f06a82d120a7e3867bed0863 100644 (file)
@@ -1678,13 +1678,15 @@ namespace Mono.CSharp
                                if (type is TypeBuilder) {
                                        TypeContainer tc = TypeManager.LookupTypeContainer (type);
 
-                                       ArrayList fields = tc.Fields;
+                                       ArrayList fields = null;
+                                       if (tc != null)
+                                               fields = tc.Fields;
 
                                        ArrayList public_fields = new ArrayList ();
                                        ArrayList non_public_fields = new ArrayList ();
 
                                        if (fields != null) {
-                                               foreach (Field field in fields) {
+                                               foreach (FieldMember field in fields) {
                                                        if ((field.ModFlags & Modifiers.STATIC) != 0)
                                                                continue;
                                                        if ((field.ModFlags & Modifiers.PUBLIC) != 0)
index 4fbc27ec19df55f6539cba1e14189fc6338badd1..dffeaeda752431eefb44d53b2282f3e9887bda9f 100644 (file)
@@ -465,8 +465,12 @@ namespace Mono.CSharp {
                        // If we have a <PrivateImplementationDetails> class, close it
                        //
                        if (helper_classes != null){
-                               foreach (TypeBuilder type_builder in helper_classes)
+                               foreach (TypeBuilder type_builder in helper_classes) {
+#if NET_2_0
+                                       type_builder.SetCustomAttribute (TypeManager.compiler_generated_attr);
+#endif
                                        type_builder.CreateType ();
+                               }
                        }
                        
                        attribute_types = null;
@@ -480,10 +484,11 @@ namespace Mono.CSharp {
                ///   Used to register classes that need to be closed after all the
                ///   user defined classes
                /// </summary>
-               public static void RegisterHelperClass (TypeBuilder helper_class)
+               public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
                {
                        if (helper_classes == null)
                                helper_classes = new ArrayList ();
+
                        helper_classes.Add (helper_class);
                }
                
@@ -692,7 +697,7 @@ namespace Mono.CSharp {
                                         TypeAttributes.NotPublic,
                                         TypeManager.object_type);
                                 
-                               RegisterHelperClass (impl_details_class);
+                               RegisterCompilerGeneratedType (impl_details_class);
                        }
 
                        fb = impl_details_class.DefineInitializedData (
index 5b30e0e57e7c8c6eebae9c625a51a1b0bdbe1aa1..f9936936343c2e51727fb04e16f9805e684f1cfb 100644 (file)
@@ -3312,15 +3312,81 @@ namespace Mono.CSharp {
                ArrayList declarators;
                Statement statement;
                Type expr_type;
-               FixedData[] data;
+               Emitter[] data;
                bool has_ret;
 
-               struct FixedData {
-                       public bool is_object;
-                       public LocalInfo vi;
-                       public Expression expr;
-                       public Expression converted;
-               }                       
+               abstract class Emitter
+               {
+                       protected LocalInfo vi;
+                       protected Expression converted;
+
+                       protected Emitter (Expression expr, LocalInfo li)
+                       {
+                               converted = expr;
+                               vi = li;
+                       }
+
+                       public abstract void Emit (EmitContext ec);
+                       public abstract void EmitExit (ILGenerator ig);
+               }
+
+               class ExpressionEmitter: Emitter {
+                       public ExpressionEmitter (Expression converted, LocalInfo li) :
+                               base (converted, li)
+                       {
+                       }
+
+                       public override void Emit (EmitContext ec) {
+                               //
+                               // Store pointer in pinned location
+                               //
+                               converted.Emit (ec);
+                               ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                       }
+
+                       public override void EmitExit (ILGenerator ig)
+                       {
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Conv_U);
+                               ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                       }
+               }
+
+               class StringEmitter: Emitter {
+                       LocalBuilder pinned_string;
+                       Location loc;
+
+                       public StringEmitter (Expression expr, LocalInfo li, Location loc):
+                               base (expr, li)
+                       {
+                               this.loc = loc;
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               ILGenerator ig = ec.ig;
+                               pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
+                                       
+                               converted.Emit (ec);
+                               ig.Emit (OpCodes.Stloc, pinned_string);
+
+                               Expression sptr = new StringPtr (pinned_string, loc);
+                               converted = Convert.ImplicitConversionRequired (
+                                       ec, sptr, vi.VariableType, loc);
+                                       
+                               if (converted == null)
+                                       return;
+
+                               converted.Emit (ec);
+                               ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                       }
+
+                       public override void EmitExit(ILGenerator ig)
+                       {
+                               ig.Emit (OpCodes.Ldnull);
+                               ig.Emit (OpCodes.Stloc, pinned_string);
+                       }
+               }
 
                public Fixed (Expression type, ArrayList decls, Statement stmt, Location l)
                {
@@ -3350,7 +3416,7 @@ namespace Mono.CSharp {
                                return false;
                        }
                        
-                       data = new FixedData [declarators.Count];
+                       data = new Emitter [declarators.Count];
 
                        if (!expr_type.IsPointer){
                                Report.Error (209, loc, "Variables in a fixed statement must be pointers");
@@ -3407,10 +3473,7 @@ namespace Mono.CSharp {
                                        if (!TypeManager.VerifyUnManaged (child.Type, loc))
                                                return false;
 
-                                       data [i].is_object = true;
-                                       data [i].expr = e;
-                                       data [i].converted = null;
-                                       data [i].vi = vi;
+                                       data [i] = new ExpressionEmitter (e, vi);
                                        i++;
 
                                        continue;
@@ -3438,17 +3501,14 @@ namespace Mono.CSharp {
                                        // and T* is implicitly convertible to the
                                        // pointer type given in the fixed statement.
                                        //
-                                       ArrayPtr array_ptr = new ArrayPtr (e, loc);
+                                       ArrayPtr array_ptr = new ArrayPtr (e, array_type, loc);
                                        
                                        Expression converted = Convert.ImplicitConversionRequired (
                                                ec, array_ptr, vi.VariableType, loc);
                                        if (converted == null)
                                                return false;
 
-                                       data [i].is_object = false;
-                                       data [i].expr = e;
-                                       data [i].converted = converted;
-                                       data [i].vi = vi;
+                                       data [i] = new ExpressionEmitter (converted, vi);
                                        i++;
 
                                        continue;
@@ -3458,14 +3518,30 @@ namespace Mono.CSharp {
                                // Case 3: string
                                //
                                if (e.Type == TypeManager.string_type){
-                                       data [i].is_object = false;
-                                       data [i].expr = e;
-                                       data [i].converted = null;
-                                       data [i].vi = vi;
+                                       data [i] = new StringEmitter (e, vi, loc);
                                        i++;
                                        continue;
                                }
 
+                               // Case 4: fixed buffer
+                               FieldExpr fe = e as FieldExpr;
+                               if (fe != null) {
+                                       IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
+                                       if (ff != null) {
+                                               Expression fixed_buffer_ptr = new FixedBufferPtr (fe, ff.ElementType, loc);
+                                       
+                                               Expression converted = Convert.ImplicitConversionRequired (
+                                                       ec, fixed_buffer_ptr, vi.VariableType, loc);
+                                               if (converted == null)
+                                                       return false;
+
+                                               data [i] = new ExpressionEmitter (converted, vi);
+                                               i++;
+
+                                               continue;
+                                       }
+                               }
+
                                //
                                // For other cases, flag a `this is already fixed expression'
                                //
@@ -3495,60 +3571,8 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
-                       LocalBuilder [] clear_list = new LocalBuilder [data.Length];
-                       
                        for (int i = 0; i < data.Length; i++) {
-                               LocalInfo vi = data [i].vi;
-
-                               //
-                               // Case 1: & object.
-                               //
-                               if (data [i].is_object) {
-                                       //
-                                       // Store pointer in pinned location
-                                       //
-                                       data [i].expr.Emit (ec);
-                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-                                       clear_list [i] = vi.LocalBuilder;
-                                       continue;
-                               }
-
-                               //
-                               // Case 2: Array
-                               //
-                               if (data [i].expr.Type.IsArray){
-                                       //
-                                       // Store pointer in pinned location
-                                       //
-                                       data [i].converted.Emit (ec);
-                                       
-                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-                                       clear_list [i] = vi.LocalBuilder;
-                                       continue;
-                               }
-
-                               //
-                               // Case 3: string
-                               //
-                               if (data [i].expr.Type == TypeManager.string_type){
-                                       LocalBuilder pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
-                                       clear_list [i] = pinned_string;
-                                       
-                                       data [i].expr.Emit (ec);
-                                       ig.Emit (OpCodes.Stloc, pinned_string);
-
-                                       Expression sptr = new StringPtr (pinned_string, loc);
-                                       Expression converted = Convert.ImplicitConversionRequired (
-                                               ec, sptr, vi.VariableType, loc);
-                                       
-                                       if (converted == null)
-                                               continue;
-
-                                       converted.Emit (ec);
-                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-                               }
+                               data [i].Emit (ec);
                        }
 
                        statement.Emit (ec);
@@ -3556,18 +3580,13 @@ namespace Mono.CSharp {
                        if (has_ret)
                                return;
 
+                       ILGenerator ig = ec.ig;
+
                        //
                        // Clear the pinned variable
                        //
                        for (int i = 0; i < data.Length; i++) {
-                               if (data [i].is_object || data [i].expr.Type.IsArray) {
-                                       ig.Emit (OpCodes.Ldc_I4_0);
-                                       ig.Emit (OpCodes.Conv_U);
-                                       ig.Emit (OpCodes.Stloc, clear_list [i]);
-                               } else if (data [i].expr.Type == TypeManager.string_type){
-                                       ig.Emit (OpCodes.Ldnull);
-                                       ig.Emit (OpCodes.Stloc, clear_list [i]);
-                               }
+                               data [i].EmitExit (ig);
                        }
                }
        }
index db7b639a837264fe363c880a168d303f2d860c24..603288ff5a7b7ef7ab005e9074cd63895e1e1bdb 100644 (file)
@@ -99,6 +99,14 @@ public partial class TypeManager {
        static public Type field_offset_attribute_type;
        static public Type security_attr_type;
 
+       /// 
+       /// .NET 2.0
+       ///
+#if NET_2_0
+       static internal Type compiler_generated_attr_type;
+       static internal Type fixed_buffer_attr_type;
+#endif
+
        //
        // An empty array of types
        //
@@ -184,10 +192,18 @@ public partial class TypeManager {
        static public ConstructorInfo void_decimal_ctor_five_args;
        static public ConstructorInfo void_decimal_ctor_int_arg;
        static public ConstructorInfo unverifiable_code_ctor;
-       static public ConstructorInfo invalid_operation_ctor;
        static public ConstructorInfo default_member_ctor;
        static public ConstructorInfo decimal_constant_attribute_ctor;
-       
+       static internal ConstructorInfo struct_layout_attribute_ctor;
+
+       ///
+       /// A new in C# 2.0
+       /// 
+#if NET_2_0
+       static internal CustomAttributeBuilder compiler_generated_attr;
+       static internal ConstructorInfo fixed_buffer_attr_ctor;
+#endif
+
        // <remarks>
        //   Holds the Array of Assemblies that have been loaded
        //   (either because it is the default or the user used the
@@ -1163,6 +1179,13 @@ public partial class TypeManager {
 
                InitGenericCoreTypes ();
 
+               //
+               // .NET 2.0
+               //
+#if NET_2_0
+               compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
+               fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices.FixedBufferAttribute");
+#endif
                //
                // When compiling corlib, store the "real" types here.
                //
@@ -1375,23 +1398,27 @@ public partial class TypeManager {
                //
                // Attributes
                //
-               cons_param_array_attribute = GetConstructor (
-                       param_array_type, void_arg);
+               cons_param_array_attribute = GetConstructor (param_array_type, void_arg);
+               unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg);
+               default_member_ctor = GetConstructor (default_member_type, string_);
 
-               unverifiable_code_ctor = GetConstructor (
-                       unverifiable_code_type, void_arg);
+               Type[] short_arg = { short_type };
+               struct_layout_attribute_ctor = GetConstructor (struct_layout_attribute_type, short_arg);
 
                decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
                        { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
 
-               default_member_ctor = GetConstructor (default_member_type, string_);
 
                //
-               // InvalidOperationException
+               // .NET 2.0 types
                //
-               invalid_operation_ctor = GetConstructor (
-                       invalid_operation_exception_type, void_arg);
+#if NET_2_0
+               compiler_generated_attr = new CustomAttributeBuilder (
+                       GetConstructor (compiler_generated_attr_type, void_arg), new object[0]);
 
+               Type[] type_int_arg = { type_type, int32_type };
+               fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
+#endif
 
                // Object
                object_ctor = GetConstructor (object_type, void_arg);
@@ -1804,6 +1831,14 @@ public partial class TypeManager {
                         return TypeToCoreType (t.GetElementType ());
         }
 
+       /// <summary>
+       /// This method is not implemented by MS runtime for dynamic types
+       /// </summary>
+       public static bool HasElementType (Type t)
+       {
+               return t.IsArray || t.IsPointer || t.IsByRef;
+       }
+
        /// <summary>
        ///   Returns the User Defined Types
        /// </summary>
@@ -2074,7 +2109,7 @@ public partial class TypeManager {
                if (tc.Fields == null)
                        return true;
 
-               foreach (Field field in tc.Fields) {
+               foreach (FieldMember field in tc.Fields) {
                        if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
                                continue;