Exemplo n.º 1
0
        public override void Emit()
        {
            ResolveContext rc = new ResolveContext(this);
            IntConstant    buffer_size_const = initializer.Resolve(rc) as IntConstant;

            if (buffer_size_const == null)
            {
                return;
            }

            int buffer_size = buffer_size_const.Value;

            if (buffer_size <= 0)
            {
                Report.Error(1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError());
                return;
            }

            int type_size = Expression.GetTypeSize(MemberType);

            if (buffer_size > int.MaxValue / type_size)
            {
                Report.Error(1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
                             GetSignatureForError(), buffer_size.ToString(), TypeManager.CSharpName(MemberType));
                return;
            }

            EmitFieldSize(buffer_size);

#if STATIC
            if (Module.HasDefaultCharSet)
            {
                fixed_buffer_type.__SetAttributes(fixed_buffer_type.Attributes | Module.DefaultCharSetType);
            }
#endif

            Module.PredefinedAttributes.UnsafeValueType.EmitAttribute(fixed_buffer_type);
            Module.PredefinedAttributes.CompilerGenerated.EmitAttribute(fixed_buffer_type);
            fixed_buffer_type.CreateType();

            base.Emit();
        }
        void EmitFieldSize(int buffer_size)
        {
            int type_size = Expression.GetTypeSize(MemberType);

            if (buffer_size > int.MaxValue / type_size)
            {
                Report.Error(1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
                             GetSignatureForError(), buffer_size.ToString(), TypeManager.CSharpName(MemberType));
                return;
            }

            PredefinedAttribute pa;
            AttributeEncoder    encoder;

            pa = Module.PredefinedAttributes.StructLayout;
            if (pa.Constructor == null && !pa.ResolveConstructor(Location, TypeManager.short_type))
            {
                return;
            }

            var char_set_type = Module.PredefinedTypes.CharSet.Resolve(Location);

            if (char_set_type == null)
            {
                return;
            }

            var field_size    = pa.GetField("Size", TypeManager.int32_type, Location);
            var field_charset = pa.GetField("CharSet", char_set_type, Location);

            if (field_size == null || field_charset == null)
            {
                return;
            }

            var char_set = CharSet ?? Module.DefaultCharSet;

            encoder = new AttributeEncoder();
            encoder.Encode((short)LayoutKind.Sequential);
            encoder.EncodeNamedArguments(
                new [] { field_size, field_charset },
                new Constant [] { new IntConstant(buffer_size * type_size, Location), new IntConstant((int)char_set, Location) }
                );

            pa.EmitAttribute(fixed_buffer_type, encoder);

            //
            // Don't emit FixedBufferAttribute attribute for private types
            //
            if ((ModFlags & Modifiers.PRIVATE) != 0)
            {
                return;
            }

            pa = Module.PredefinedAttributes.FixedBuffer;
            if (pa.Constructor == null && !pa.ResolveConstructor(Location, TypeManager.type_type, TypeManager.int32_type))
            {
                return;
            }

            encoder = new AttributeEncoder();
            encoder.EncodeTypeName(MemberType);
            encoder.Encode(buffer_size);
            encoder.EncodeEmptyNamedArguments();

            pa.EmitAttribute(FieldBuilder, encoder);
        }