Add initial reflection dependant code
[mono.git] / mcs / mcs / attribute.cs
index 6d0d8c493b1c81dbf0af22bbcfb26fb7d9ac293f..5a399126b1f91c64becf88ad2a0c1e209a6968f1 100644 (file)
@@ -11,7 +11,6 @@
 //
 
 using System;
-using System.Diagnostics;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Emit;
@@ -102,7 +101,7 @@ namespace Mono.CSharp {
                static Assembly orig_sec_assembly;
                public static readonly object[] EmptyObject = new object [0];
 
-               IList<KeyValuePair<MemberExpr, NamedArgument>> named_values;
+               List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
 
                // Cache for parameter-less attributes
                static Dictionary<TypeSpec, MethodSpec> att_cache;
@@ -119,6 +118,30 @@ namespace Mono.CSharp {
                        this.nameEscaped = nameEscaped;
                }
 
+               void AddModuleCharSet (ResolveContext rc)
+               {
+                       const string dll_import_char_set = "CharSet";
+
+                       //
+                       // Only when not customized by user
+                       //
+                       if (HasField (dll_import_char_set))
+                               return;
+
+                       if (TypeManager.interop_charset == null) {
+                               TypeManager.interop_charset = TypeManager.CoreLookupType (rc.Compiler, "System.Runtime.InteropServices", "CharSet", MemberKind.Enum, true);
+
+                               if (TypeManager.interop_charset == null)
+                                       return;
+                       }
+
+                       if (NamedArguments == null)
+                               NamedArguments = new Arguments (1);
+
+                       var value = Constant.CreateConstant (rc, TypeManager.interop_charset, rc.CurrentMemberDefinition.Module.DefaultCharSet, Location);
+                       NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
+               }
+
                public Attribute Clone ()
                {
                        Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
@@ -142,7 +165,7 @@ namespace Mono.CSharp {
                // we use @target field as a list of targets. The attribute
                // has to be resolved only once but emitted for each target.
                //
-               public virtual void AttachTo (Attributable target, IMemberContext context)
+               public void AttachTo (Attributable target, IMemberContext context)
                {
                        if (this.targets == null) {
                                this.targets = new Attributable[] { target };
@@ -335,29 +358,6 @@ namespace Mono.CSharp {
                        get { return expression.Name; }
                }
 
-               void ApplyModuleCharSet (ResolveContext rc)
-               {
-                       if (Type != context.Compiler.PredefinedAttributes.DllImport)
-                               return;
-
-                       if (!RootContext.ToplevelTypes.HasDefaultCharSet)
-                               return;
-
-                       const string CharSetEnumMember = "CharSet";
-                       if (NamedArguments == null) {
-                               NamedArguments = new Arguments (1);
-                       } else {
-                               foreach (NamedArgument a in NamedArguments) {
-                                       if (a.Name == CharSetEnumMember)
-                                               return;
-                               }
-                       }
-
-                       var char_set = rc.Compiler.MetaImporter.ImportType (typeof (CharSet));  // TODO: typeof
-                       NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
-                               Constant.CreateConstant (rc, char_set, RootContext.ToplevelTypes.DefaultCharSet, Location)));
-               }
-
                public Report Report {
                        get { return context.Compiler.Report; }
                }
@@ -401,7 +401,12 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       ApplyModuleCharSet (rc);
+                       //
+                       // Add [module: DefaultCharSet] to all DllImport import attributes
+                       //
+                       if (Type == context.Compiler.PredefinedAttributes.DllImport && rc.CurrentMemberDefinition.Module.HasDefaultCharSet) {
+                               AddModuleCharSet (rc);
+                       }
 
                        if (NamedArguments != null && !ResolveNamedArguments (rc)) {
                                return null;
@@ -584,11 +589,11 @@ namespace Mono.CSharp {
 
                        AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
 
-                       var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
+                       var field = GetNamedValue ("AllowMultiple") as BoolConstant;
                        if (field != null)
                                usage_attribute.AllowMultiple = field.Value;
 
-                       field = GetPropertyValue ("Inherited") as BoolConstant;
+                       field = GetNamedValue ("Inherited") as BoolConstant;
                        if (field != null)
                                usage_attribute.Inherited = field.Value;
 
@@ -701,6 +706,7 @@ namespace Mono.CSharp {
                                case "field": Target = AttributeTargets.Field; return true;
                                case "method": Target = AttributeTargets.Method; return true;
                                case "property": Target = AttributeTargets.Property; return true;
+                               case "module": Target = AttributeTargets.Module; return true;
                                }
                                throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
                        }
@@ -752,7 +758,7 @@ namespace Mono.CSharp {
 
                System.Security.Permissions.SecurityAction GetSecurityActionValue ()
                {
-                       return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
+                       return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
                }
 
                /// <summary>
@@ -794,7 +800,7 @@ namespace Mono.CSharp {
                        if (orig_assembly_type == null) {
                                args = new object[PosArguments.Count];
                                for (int j = 0; j < args.Length; ++j) {
-                                       args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
+                                       args[j] = ((Constant) PosArguments[j].Expr).GetValue ();
                                }
 
                                sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
@@ -802,7 +808,7 @@ namespace Mono.CSharp {
                                if (named_values != null) {
                                        for (int i = 0; i < named_values.Count; ++i) {
                                                PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
-                                               pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
+                                               pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetValue (), null);
                                        }
                                }
                        } else {
@@ -818,7 +824,7 @@ namespace Mono.CSharp {
                                                // TODO: pi can be null
                                                PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
 
-                                               pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
+                                               pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetValue (), null);
                                        }
                                }
                        }
@@ -857,7 +863,7 @@ namespace Mono.CSharp {
                        ps.AddPermission (perm);
                }
 
-               public Constant GetPropertyValue (string name)
+               public Constant GetNamedValue (string name)
                {
                        if (named_values == null)
                                return null;
@@ -991,27 +997,32 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public bool IsInternalMethodImplAttribute {
-                       get {
-                               if (Type != context.Compiler.PredefinedAttributes.MethodImpl)
-                                       return false;
-
-                               MethodImplOptions options;
-                               if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
-                                       options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
-                               else
-                                       options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
-
-                               return (options & MethodImplOptions.InternalCall) != 0;
+               //
+               // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
+               // 
+               public bool IsInternalCall ()
+               {
+                       MethodImplOptions options = 0;
+                       if (PosArguments.Count == 1) {
+                               options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+                       } else if (HasField ("Value")) {
+                               var named = GetNamedValue ("Value");
+                               options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
                        }
+
+                       return (options & MethodImplOptions.InternalCall) != 0;
                }
 
-               public LayoutKind GetLayoutKindValue ()
+               //
+               // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
+               // 
+               public bool IsExplicitLayoutKind ()
                {
-                       if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
-                               return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
+                       if (PosArguments.Count != 1)
+                               return false;
 
-                       return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
+                       var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+                       return value == LayoutKind.Explicit;
                }
 
                public Constant GetParameterDefaultValue (out TypeSpec type)
@@ -1110,7 +1121,7 @@ namespace Mono.CSharp {
                                        na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
                                }
                        } else {
-                               encoder.Stream.Write ((ushort) 0);
+                               encoder.EncodeEmptyNamedArguments ();
                        }
 
                        byte[] cdata = encoder.ToArray ();
@@ -1214,21 +1225,6 @@ namespace Mono.CSharp {
                {
                        this.ns = ns;
                }
-               
-               public override void AttachTo (Attributable target, IMemberContext context)
-               {
-                       if (ExplicitTarget == "assembly") {
-                               base.AttachTo (CodeGen.Assembly, context);
-                               return;
-                       }
-
-                       if (ExplicitTarget == "module") {
-                               base.AttachTo (RootContext.ToplevelTypes, context);
-                               return;
-                       }
-
-                       throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
-               }
 
                void Enter ()
                {
@@ -1336,8 +1332,16 @@ namespace Mono.CSharp {
                }
 
                public Attribute Search (PredefinedAttribute t)
+               {
+                       return Search (null, t);
+               }
+
+               public Attribute Search (string explicitTarget, PredefinedAttribute t)
                {
                        foreach (Attribute a in Attrs) {
+                               if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
+                                       continue;
+
                                if (a.ResolveType () == t)
                                        return a;
                        }
@@ -1404,8 +1408,18 @@ namespace Mono.CSharp {
                        TypeParameter = 1 << 1
                }
 
+               const ushort Version = 1;
+
+               public static readonly byte[] Empty;
+
                public readonly BinaryWriter Stream;
 
+               static AttributeEncoder ()
+               {
+                       Empty = new byte[4];
+                       Array.Copy (BitConverter.GetBytes (Version), Empty, 2);
+               }
+
                public AttributeEncoder (bool empty)
                {
                        if (empty) {
@@ -1414,14 +1428,35 @@ namespace Mono.CSharp {
                        }
 
                        Stream = new BinaryWriter (new MemoryStream ());
-                       const ushort version = 1;
-                       Stream.Write (version);
+                       Stream.Write (Version);
+               }
+
+               public void Encode (byte value)
+               {
+                       Stream.Write (value);
+               }
+
+               public void Encode (short value)
+               {
+                       Stream.Write (value);
+               }
+
+               public void Encode (int value)
+               {
+                       Stream.Write (value);
+               }
+
+               public void Encode (uint value)
+               {
+                       Stream.Write (value);
                }
 
                public void Encode (string value)
                {
-                       if (value == null)
-                               throw new ArgumentNullException ();
+                       if (value == null) {
+                               Stream.Write ((byte) 0xFF);
+                               return;
+                       }
 
                        var buf = Encoding.UTF8.GetBytes(value);
                        WriteCompressedValue (buf.Length);
@@ -1480,6 +1515,56 @@ namespace Mono.CSharp {
                        Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
                }
 
+               //
+               // Encodes single property named argument per call
+               //
+               public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
+               {
+                       Stream.Write ((ushort) 1);      // length
+                       Stream.Write ((byte) 0x54); // property
+                       Encode (property.MemberType);
+                       Encode (property.Name);
+                       value.EncodeAttributeValue (null, this, property.MemberType);
+               }
+
+               //
+               // Encodes single field named argument per call
+               //
+               public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
+               {
+                       Stream.Write ((ushort) 1);      // length
+                       Stream.Write ((byte) 0x53); // field
+                       Encode (field.MemberType);
+                       Encode (field.Name);
+                       value.EncodeAttributeValue (null, this, field.MemberType);
+               }
+
+               public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
+               {
+                       Stream.Write ((ushort) members.Length);
+
+                       for (int i = 0; i < members.Length; ++i)
+                       {
+                               var member = members[i];
+
+                               if (member.Kind == MemberKind.Field)
+                                       Stream.Write ((byte) 0x53);
+                               else if (member.Kind == MemberKind.Property)
+                                       Stream.Write ((byte) 0x54);
+                               else
+                                       throw new NotImplementedException (member.Kind.ToString ());
+
+                               Encode (member.MemberType);
+                               Encode (member.Name);
+                               values [i].EncodeAttributeValue (null, this, member.MemberType);
+                       }
+               }
+
+               public void EncodeEmptyNamedArguments ()
+               {
+                       Stream.Write ((ushort) 0);
+               }
+
                void WriteCompressedValue (int value)
                {
                        if (value < 0x80) {
@@ -1558,36 +1643,6 @@ namespace Mono.CSharp {
                        return result;
                }
 
-               public static void VerifyModulesClsCompliance (CompilerContext ctx)
-               {
-                       Module[] modules = ctx.GlobalRootNamespace.Modules;
-                       if (modules == null)
-                               return;
-
-                       // The first module is generated assembly
-                       for (int i = 1; i < modules.Length; ++i) {
-                               Module module = modules [i];
-                               if (!GetClsCompliantAttributeValue (module, null)) {
-                                       ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
-                                                     "to match the assembly", module.Name);
-                                       return;
-                               }
-                       }
-               }
-
-               static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a) 
-               {
-                       object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
-                       if (cls_attr.Length == 0) {
-                               if (a == null)
-                                       return false;
-
-                               return GetClsCompliantAttributeValue (a, null);
-                       }
-                       
-                       return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
-               }
-
                /// <summary>
                /// Common method for Obsolete error/warning reporting.
                /// </summary>
@@ -1633,6 +1688,7 @@ namespace Mono.CSharp {
                public readonly PredefinedAttribute AttributeUsage;
                public readonly PredefinedAttribute DefaultParameterValue;
                public readonly PredefinedAttribute OptionalParameter;
+               public readonly PredefinedAttribute UnverifiableCode;
 
                // New in .NET 2.0
                public readonly PredefinedAttribute DefaultCharset;
@@ -1654,7 +1710,7 @@ namespace Mono.CSharp {
                // Optional types which are used as types and for member lookup
                //
                public readonly PredefinedAttribute DefaultMember;
-               public readonly PredefinedAttribute DecimalConstant;
+               public readonly PredefinedDecimalAttribute DecimalConstant;
                public readonly PredefinedAttribute StructLayout;
                public readonly PredefinedAttribute FieldOffset;
 
@@ -1683,6 +1739,7 @@ namespace Mono.CSharp {
                        AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
                        DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
                        OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
+                       UnverifiableCode = new PredefinedAttribute ("System.Security", "UnverifiableCodeAttribute");
 
                        DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
                        TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
@@ -1698,7 +1755,7 @@ namespace Mono.CSharp {
                        Dynamic = new PredefinedDynamicAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
 
                        DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
-                       DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
+                       DecimalConstant = new PredefinedDecimalAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
                        StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
                        FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
                }
@@ -1714,10 +1771,11 @@ namespace Mono.CSharp {
        public class PredefinedAttribute
        {
                protected TypeSpec type;
-               CustomAttributeBuilder cab;
-               MethodSpec ctor;
+               protected MethodSpec ctor;
                readonly string ns, name;
                CompilerContext compiler;
+               List<FieldSpec> fields;
+               List<PropertySpec> properties;
 
                static readonly TypeSpec NotFound = InternalType.Null;
 
@@ -1727,6 +1785,29 @@ namespace Mono.CSharp {
                        this.name = name;
                }
 
+               #region Properties
+
+               public MethodSpec Constructor {
+                       get {
+                               return ctor;
+                       }
+               }
+
+               public bool IsDefined {
+                       get {
+                               return type != null && type != NotFound;
+                       }
+               }
+
+               public TypeSpec Type {
+                       get {
+                               return type;
+                       }
+               }
+
+               #endregion
+
+
                public static bool operator == (TypeSpec type, PredefinedAttribute pa)
                {
                        return type == pa.type;
@@ -1737,10 +1818,6 @@ namespace Mono.CSharp {
                        return type != pa.type;
                }
 
-               public ConstructorInfo Constructor {
-                       get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
-               }
-
                public override int GetHashCode ()
                {
                        return base.GetHashCode ();
@@ -1759,47 +1836,118 @@ namespace Mono.CSharp {
                public void EmitAttribute (ConstructorBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
                }
 
                public void EmitAttribute (MethodBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
                }
 
                public void EmitAttribute (PropertyBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
                }
 
                public void EmitAttribute (FieldBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+               }
+
+               public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
+               {
+                       builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
                }
 
                public void EmitAttribute (TypeBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+               }
+
+               public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
+               {
+                       builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
                }
 
                public void EmitAttribute (AssemblyBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+               }
+
+               public void EmitAttribute (ModuleBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
                }
 
                public void EmitAttribute (ParameterBuilder builder)
                {
                        if (ResolveBuilder ())
-                               builder.SetCustomAttribute (cab);
+                               builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
                }
 
-               public bool IsDefined {
-                       get { return type != null && type != NotFound; }
+               public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
+               {
+                       builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
+               }
+
+               ConstructorInfo GetCtorMetaInfo ()
+               {
+                       return (ConstructorInfo) ctor.GetMetaInfo ();
+               }
+
+               public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
+               {
+                       FieldSpec spec;
+                       if (fields != null) {
+                               spec = fields.Find (l => l.Name == name);
+                       } else {
+                               spec = null;
+                       }
+
+                       if (spec == null) {
+                               spec = TypeManager.GetPredefinedField (type, name, loc, memberType);
+
+                               if (spec != null) {
+                                       if (fields == null) {
+                                               fields = new List<FieldSpec> ();
+                                       }
+
+                                       fields.Add (spec);
+                               }
+                       }
+
+                       return spec;
+               }
+
+               public PropertySpec GetProperty (string name, TypeSpec memberType, Location loc)
+               {
+                       PropertySpec spec;
+
+                       if (properties != null) {
+                               spec = properties.Find (l => l.Name == name);
+                       } else {
+                               spec = null;
+                       }
+
+                       if (spec == null) {
+                               spec = TypeManager.GetPredefinedProperty (type, name, loc, memberType);
+
+                               if (spec != null) {
+                                       if (properties == null) {
+                                               properties = new List<PropertySpec> ();
+                                       }
+
+                                       properties.Add (spec);
+                               }
+                       }
+
+                       return spec;
                }
 
                public void Initialize (CompilerContext ctx, bool canFail)
@@ -1826,9 +1974,9 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               bool ResolveBuilder ()
+               public bool ResolveBuilder ()
                {
-                       if (cab != null)
+                       if (ctor != null)
                                return true;
 
                        //
@@ -1837,12 +1985,8 @@ namespace Mono.CSharp {
                        if (!Resolve (true))
                                return false;
 
-                       var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
-                       if (ci == null)
-                               return false;
-
-                       cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
-                       return true;
+                       ctor = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
+                       return ctor != null;
                }
 
                public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
@@ -1856,9 +2000,53 @@ namespace Mono.CSharp {
                        ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
                        return ctor != null;
                }
+       }
 
-               public TypeSpec Type {
-                       get { return type; }
+       public class PredefinedDecimalAttribute : PredefinedAttribute
+       {
+               public PredefinedDecimalAttribute (string ns, string name)
+                       : base (ns, name)
+               {
+               }
+
+               public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
+               {
+                       if (!Resolve (false))
+                               return;
+
+                       if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+                               return;
+
+                       int[] bits = decimal.GetBits (value);
+                       AttributeEncoder encoder = new AttributeEncoder (false);
+                       encoder.Encode ((byte) (bits[3] >> 16));
+                       encoder.Encode ((byte) (bits[3] >> 31));
+                       encoder.Encode ((uint) bits[2]);
+                       encoder.Encode ((uint) bits[1]);
+                       encoder.Encode ((uint) bits[0]);
+                       encoder.EncodeEmptyNamedArguments ();
+
+                       EmitAttribute (builder, encoder);
+               }
+
+               public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
+               {
+                       if (!Resolve (false))
+                               return;
+
+                       if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+                               return;
+
+                       int[] bits = decimal.GetBits (value);
+                       AttributeEncoder encoder = new AttributeEncoder (false);
+                       encoder.Encode ((byte) (bits[3] >> 16));
+                       encoder.Encode ((byte) (bits[3] >> 31));
+                       encoder.Encode ((uint) bits[2]);
+                       encoder.Encode ((uint) bits[1]);
+                       encoder.Encode ((uint) bits[0]);
+                       encoder.EncodeEmptyNamedArguments ();
+
+                       EmitAttribute (builder, encoder);
                }
        }