Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / class / corlib / System.Reflection.Emit / SignatureHelper.cs
index 114f01812b4ed0838a8ac1538e7cc516e972104a..d56f96256c0230333e03a1afe31b549d5c289e21 100644 (file)
@@ -31,6 +31,7 @@
 // (C) 2001 Ximian, Inc.  http://www.ximian.com
 //
 
+#if !FULL_AOT_RUNTIME
 using System;
 using System.Reflection;
 using System.Reflection.Emit;
@@ -39,11 +40,10 @@ using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
 namespace System.Reflection.Emit {
-#if NET_2_0
        [ComVisible (true)]
        [ComDefaultInterface (typeof (_SignatureHelper))]
-#endif
        [ClassInterface (ClassInterfaceType.None)]
+       [StructLayout (LayoutKind.Sequential)]
        public sealed class SignatureHelper : _SignatureHelper {
                internal enum SignatureHelperType {
                        HELPER_FIELD,
@@ -52,12 +52,16 @@ namespace System.Reflection.Emit {
                        HELPER_PROPERTY
                }
 
-               private ModuleBuilder module;
+               private ModuleBuilder module; // can be null in 2.0
                private Type[] arguments;
                private SignatureHelperType type;
                private Type returnType;
                private CallingConventions callConv;
                private CallingConvention unmanagedCallConv;
+#pragma warning disable 649
+               private Type[][] modreqs;
+               private Type[][] modopts;
+#pragma warning restore 649
 
                internal SignatureHelper (ModuleBuilder module, SignatureHelperType type)
                {
@@ -67,71 +71,288 @@ namespace System.Reflection.Emit {
 
                public static SignatureHelper GetFieldSigHelper (Module mod)
                {
-                       if (!(mod is ModuleBuilder))
-                               throw new NotImplementedException ();
+                       if (mod != null && !(mod is ModuleBuilder))
+                               throw new ArgumentException ("ModuleBuilder is expected");
 
                        return new SignatureHelper ((ModuleBuilder) mod, SignatureHelperType.HELPER_FIELD);
                }
 
                public static SignatureHelper GetLocalVarSigHelper (Module mod)
                {
-                       if (!(mod is ModuleBuilder))
-                               throw new NotImplementedException ();
+                       if (mod != null && !(mod is ModuleBuilder))
+                               throw new ArgumentException ("ModuleBuilder is expected");
 
                        return new SignatureHelper ((ModuleBuilder) mod, SignatureHelperType.HELPER_LOCAL);
                }
 
-               public static SignatureHelper GetMethodSigHelper( Module mod, CallingConventions callingConvention, Type returnType)
+               public static SignatureHelper GetLocalVarSigHelper ()
+               {
+                       return new SignatureHelper (null, SignatureHelperType.HELPER_LOCAL);
+               }
+
+               public static SignatureHelper GetMethodSigHelper (CallingConventions callingConvention, Type returnType)
+               {
+                       return GetMethodSigHelper (null, callingConvention, (CallingConvention)0, returnType, null);
+               }
+
+               public static SignatureHelper GetMethodSigHelper (CallingConvention unmanagedCallingConvention, Type returnType)
+               {
+                       return GetMethodSigHelper (null, CallingConventions.Standard, unmanagedCallingConvention, returnType, null);
+               }
+
+               public static SignatureHelper GetMethodSigHelper (Module mod, CallingConventions callingConvention, Type returnType)
                {
                        return GetMethodSigHelper (mod, callingConvention, (CallingConvention)0, returnType, null);
                }
 
-               public static SignatureHelper GetMethodSigHelper( Module mod, CallingConvention unmanagedCallingConvention, Type returnType)
+               public static SignatureHelper GetMethodSigHelper (Module mod, CallingConvention unmanagedCallConv, Type returnType)
                {
-                       return GetMethodSigHelper (mod, CallingConventions.Standard, unmanagedCallingConvention, returnType, null);
+                       return GetMethodSigHelper (mod, CallingConventions.Standard, unmanagedCallConv, returnType, null);
                }
 
-               public static SignatureHelper GetMethodSigHelperModule mod, Type returnType, Type[] parameterTypes)
+               public static SignatureHelper GetMethodSigHelper (Module mod, Type returnType, Type[] parameterTypes)
                {
-                       return GetMethodSigHelper (mod, CallingConventions.Standard, 
-                                                                          (CallingConvention)0, returnType, 
-                                                                          parameterTypes);
+                       return GetMethodSigHelper (mod, CallingConventions.Standard, (CallingConvention)0, returnType, parameterTypes);
                }
+
                [MonoTODO("Not implemented")]
-               public static SignatureHelper GetPropertySigHelperModule mod, Type returnType, Type[] parameterTypes)
+               public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType, Type[] parameterTypes)
                {
                        throw new NotImplementedException ();
                }
 
-               public void AddArgument (Type clsArgument)
+               [MonoTODO("Not implemented")]
+               public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType,
+                                                                   Type [] requiredReturnTypeCustomModifiers,
+                                                                   Type [] optionalReturnTypeCustomModifiers,
+                                                                   Type [] parameterTypes,
+                                                                   Type [] [] requiredParameterTypeCustomModifiers,
+                                                                   Type [] [] optionalParameterTypeCustomModifiers)
                {
-                       if (arguments != null) {
-                               Type[] new_a = new Type [arguments.Length + 1];
-                               System.Array.Copy (arguments, new_a, arguments.Length);
-                               new_a [arguments.Length] = clsArgument;
-                               arguments = new_a;
+                       throw new NotImplementedException ();
+               }
+
+#if NET_4_0
+               [MonoTODO("Not implemented")]
+               public static SignatureHelper GetPropertySigHelper (Module mod,
+                                                                       CallingConventions callingConvention,
+                                                                       Type returnType,
+                                                                   Type [] requiredReturnTypeCustomModifiers,
+                                                                   Type [] optionalReturnTypeCustomModifiers,
+                                                                   Type [] parameterTypes,
+                                                                   Type [] [] requiredParameterTypeCustomModifiers,
+                                                                   Type [] [] optionalParameterTypeCustomModifiers)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
+
+               //
+               // Grows the given array, and returns the index where the element
+               // was added
+               //
+               static int AppendArray (ref Type [] array, Type t)
+               {
+                       if (array != null) {
+                               Type[] new_a = new Type [array.Length + 1];
+                               System.Array.Copy (array, new_a, array.Length);
+                               new_a [array.Length] = t;
+                               array = new_a;
+                               return array.Length-1;
                        } else {
-                               arguments = new Type [1];
-                               arguments [0] = clsArgument;
+                               array = new Type [1];
+                               array [0] = t;
+                               return 0;
+                       }
+               }
+
+               //
+               // Appends the given type array @t into the @array passed at
+               // position @pos.   If there is no array, it gets created
+               //
+               // This allows adding data to a null array at position 5 for
+               // example, creating 4 empty slots before the slot where @t
+               // is stored.
+               //
+               //
+               static void AppendArrayAt (ref Type [][] array, Type [] t, int pos)
+               {
+                       int top = Math.Max (pos, array == null ? 0 : array.Length);
+                       Type[][] new_a = new Type [top+1][];
+                       if (array != null)
+                               System.Array.Copy (array, new_a, top);
+                       new_a [pos] = t;
+                       array = new_a;
+               }
+               
+               static void ValidateParameterModifiers (string name, Type [] parameter_modifiers)
+               {
+                       foreach (Type modifier in parameter_modifiers){
+                               if (modifier == null)
+                                       throw new ArgumentNullException (name);
+                               if (modifier.IsArray)
+                                       throw new ArgumentException (Locale.GetText ("Array type not permitted"), name);
+                               if (modifier.ContainsGenericParameters)
+                                       throw new ArgumentException (Locale.GetText ("Open Generic Type not permitted"), name);
+                       }
+               }
+
+               static void ValidateCustomModifier (int n, Type [][] custom_modifiers, string name)
+               {
+                       if (custom_modifiers == null)
+                               return;
+
+                       if (custom_modifiers.Length != n)
+                               throw new ArgumentException (
+                                    Locale.GetText (
+                                       String.Format ("Custom modifiers length `{0}' does not match the size of the arguments")));
+                       
+                       foreach (Type [] parameter_modifiers in custom_modifiers){
+                               if (parameter_modifiers == null)
+                                       continue;
+
+                               ValidateParameterModifiers (name, parameter_modifiers);
+                       }
+               }
+
+               static Exception MissingFeature ()
+               {
+                       throw new NotImplementedException ("Mono does not currently support setting modOpt/modReq through SignatureHelper");
+               }
+
+               [MonoTODO("Currently we ignore requiredCustomModifiers and optionalCustomModifiers")]
+               public void AddArguments (Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       if (arguments == null)
+                               throw new ArgumentNullException ("arguments");
+
+                       // For now
+                       if (requiredCustomModifiers != null || optionalCustomModifiers != null){
+                               throw MissingFeature();
+                       }
+                       
+                       ValidateCustomModifier (arguments.Length, requiredCustomModifiers, "requiredCustomModifiers");
+                       ValidateCustomModifier (arguments.Length, optionalCustomModifiers, "optionalCustomModifiers");
+
+                       for (int i = 0; i < arguments.Length; i++){
+                               AddArgument (arguments [i],
+                                            requiredCustomModifiers != null ? requiredCustomModifiers [i] : null,
+                                            optionalCustomModifiers != null ? optionalCustomModifiers [i] : null);
                        }
                }
 
+               [MonoTODO ("pinned is ignored")]
+               public void AddArgument (Type argument, bool pinned)
+               {
+                       AddArgument (argument);
+               }
+
+               public void AddArgument (Type argument, Type [] requiredCustomModifiers, Type [] optionalCustomModifiers)
+               {
+                       if (argument == null)
+                               throw new ArgumentNullException ("argument");
+
+                       if (requiredCustomModifiers != null)
+                               ValidateParameterModifiers ("requiredCustomModifiers", requiredCustomModifiers);
+                       if (optionalCustomModifiers != null)
+                               ValidateParameterModifiers ("optionalCustomModifiers", optionalCustomModifiers);
+
+                       int p = AppendArray (ref arguments, argument);
+                       if (requiredCustomModifiers != null)
+                               AppendArrayAt (ref modreqs, requiredCustomModifiers, p);
+                       if (optionalCustomModifiers != null)
+                               AppendArrayAt (ref modopts, optionalCustomModifiers, p);
+               }
+
+               public void AddArgument (Type clsArgument)
+               {
+                       if (clsArgument == null)
+                               throw new ArgumentNullException ("clsArgument");
+
+                       AppendArray (ref arguments, clsArgument);
+               }
+
                [MonoTODO("Not implemented")]
                public void AddSentinel ()
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO("Not implemented")]
+               static bool CompareOK (Type [][] one, Type [][] two)
+               {
+                       if (one == null){
+                               if (two == null)
+                                       return true;
+                               return false;
+                       } else if (two == null)
+                               return false;
+
+                       if (one.Length != two.Length)
+                               return false;
+
+                       for (int i = 0; i < one.Length; i++){
+                               Type [] tone = one [i];
+                               Type [] ttwo = two [i];
+
+                               if (tone == null){
+                                       if (ttwo == null)
+                                               continue;
+                               } else if (ttwo == null)
+                                       return false;
+
+                               if (tone.Length != ttwo.Length)
+                                       return false;
+
+                               for (int j = 0; j < tone.Length; j++){
+                                       Type uone = tone [j];
+                                       Type utwo = ttwo [j];
+                                       
+                                       if (uone == null){
+                                               if (utwo == null)
+                                                       continue;
+                                               return false;
+                                       } else if (utwo == null)
+                                               return false;
+
+                                       if (!uone.Equals (utwo))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+               
                public override bool Equals (object obj)
                {
-                       throw new NotImplementedException ();
+                       SignatureHelper other = obj as SignatureHelper;
+                       if (other == null)
+                               return false;
+
+                       if (other.module != module ||
+                           other.returnType != returnType ||
+                           other.callConv != callConv ||
+                           other.unmanagedCallConv != unmanagedCallConv)
+                               return false;
+
+                       if (arguments != null){
+                               if (other.arguments == null)
+                                       return false;
+                               if (arguments.Length != other.arguments.Length)
+                                       return false;
+
+                               for (int i = 0; i < arguments.Length; i++)
+                                       if (!other.arguments [i].Equals (arguments [i]))
+                                               return false;
+                       } else if (other.arguments != null)
+                               return false;
+
+                       return CompareOK (other.modreqs, modreqs) && CompareOK (other.modopts, modopts);
                }
 
-               [MonoTODO("Not implemented")]
                public override int GetHashCode ()
                {
-                       throw new NotImplementedException ();
+                       // Lame, but easy, and will work, and chances are
+                       // you will only need a few of these.
+                       return 0;
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -156,17 +377,29 @@ namespace System.Reflection.Emit {
                        return "SignatureHelper";
                }
 
-               internal static SignatureHelper GetMethodSigHelper( Module mod, CallingConventions callConv, CallingConvention unmanagedCallConv, Type returnType,
+               internal static SignatureHelper GetMethodSigHelper (Module mod, CallingConventions callingConvention, CallingConvention unmanagedCallingConvention, Type returnType,
                                                                                                                   Type [] parameters)
                {
-                       if (!(mod is ModuleBuilder))
-                               throw new NotImplementedException ();
+                       if (mod != null && !(mod is ModuleBuilder))
+                               throw new ArgumentException ("ModuleBuilder is expected");
+
+                       if (returnType == null)
+                               returnType = typeof (void);
+
+                       if (returnType.IsUserType)
+                               throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
+                       if (parameters != null) {
+                               for (int i = 0; i < parameters.Length; ++i)
+                                       if (parameters [i].IsUserType)
+                                               throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
+
+                       }
 
                        SignatureHelper helper = 
                                new SignatureHelper ((ModuleBuilder)mod, SignatureHelperType.HELPER_METHOD);
                        helper.returnType = returnType;
-                       helper.callConv = callConv;
-                       helper.unmanagedCallConv = unmanagedCallConv;
+                       helper.callConv = callingConvention;
+                       helper.unmanagedCallConv = unmanagedCallingConvention;
 
                        if (parameters != null) {
                                helper.arguments = new Type [parameters.Length];
@@ -177,7 +410,7 @@ namespace System.Reflection.Emit {
                        return helper;
                }
 
-                void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+                void _SignatureHelper.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
                 {
                         throw new NotImplementedException ();
                 }
@@ -198,4 +431,4 @@ namespace System.Reflection.Emit {
                 }
        }
 }
-
+#endif