This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / corlib / System.Reflection.Emit / DynamicMethod.cs
1 //
2 // System.Reflection.Emit/DynamicMethod.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Zoltan Varga (vargaz@freemail.hu)
7 //
8 // (C) 2003 Ximian, Inc.  http://www.ximian.com
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 #if NET_2_0 || BOOTSTRAP_NET_2_0
35
36 using System;
37 using System.Reflection;
38 using System.Reflection.Emit;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42
43 namespace System.Reflection.Emit {
44
45         public sealed class DynamicMethod : MethodInfo {
46                 #region Sync with reflection.h
47                 private RuntimeMethodHandle mhandle;
48                 private string name;
49                 private Type returnType;
50                 private Type[] parameters;
51                 private MethodAttributes attributes;
52                 private CallingConventions callingConvention;
53                 private Module module;
54                 private bool skipVisibility;
55                 private bool init_locals = true;
56                 private ILGenerator ilgen;
57                 private int nrefs;
58                 private object[] refs;
59                 #endregion
60                 private Delegate deleg;
61                 private MonoMethod method;
62                 private ParameterBuilder[] pinfo;
63
64                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
65                 }
66
67                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
68                 }
69
70                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) {
71                 }
72
73                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) {
74                 }
75
76                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, owner.Module, skipVisibility) {
77                 }
78
79                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) {
80                         if (name == null)
81                                 throw new ArgumentNullException ("name");
82                         if (name == String.Empty)
83                                 throw new ArgumentException ("Name can't be empty", "name");
84                         if (returnType == null)
85                                 throw new ArgumentNullException ("returnType");
86                         if (m == null)
87                                 throw new ArgumentNullException ("m");
88                         if (returnType.IsByRef)
89                                 throw new ArgumentException ("Return type can't be a byref type", "returnType");
90                         if (parameterTypes != null) {
91                                 for (int i = 0; i < parameterTypes.Length; ++i)
92                                         if (parameterTypes [i] == null)
93                                                 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
94                         }
95
96                         this.name = name;
97                         this.attributes = attributes | MethodAttributes.Static;
98                         this.callingConvention = callingConvention;
99                         this.returnType = returnType;
100                         this.parameters = parameterTypes;
101                         this.module = m;
102                         this.skipVisibility = skipVisibility;
103                 }
104
105                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
106                 private extern void create_dynamic_method (DynamicMethod m);
107
108                 private void CreateDynMethod () {
109                         if (mhandle.Value == IntPtr.Zero)
110                                 create_dynamic_method (this);
111                 }
112
113                 public Delegate CreateDelegate (Type delegateType) {
114                         if (delegateType == null)
115                                 throw new ArgumentNullException ("delegateType");
116                         if (deleg != null)
117                                 return deleg;
118
119                         CreateDynMethod ();
120
121                         deleg = Delegate.CreateDelegate (delegateType, this);
122                         return deleg;
123                 }
124
125                 [MonoTODO]
126                 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string strParamName)
127                 {
128                         //
129                         // Extension: Mono allows position == 0 for the return attribute
130                         //
131                         if ((position < 0) || (position > parameters.Length))
132                                 throw new ArgumentOutOfRangeException ("position");
133
134                         RejectIfCreated ();
135
136                         throw new NotImplementedException ();
137                 }
138
139                 public override MethodInfo GetBaseDefinition () {
140                         return this;
141                 }
142
143                 [MonoTODO]
144                 public override object[] GetCustomAttributes (bool inherit) {
145                         throw new NotImplementedException ();
146                 }
147
148                 [MonoTODO]
149                 public override object[] GetCustomAttributes (Type attributeType,
150                                                                                                           bool inherit) {
151                         throw new NotImplementedException ();
152                 }
153
154                 public ILGenerator GetILGenerator () {
155                         return GetILGenerator (64);
156                 }
157
158                 public ILGenerator GetILGenerator (int size) {
159                         if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) != 
160                                  MethodImplAttributes.IL) ||
161                                 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) != 
162                                  MethodImplAttributes.Managed))
163                                 throw new InvalidOperationException ("Method body should not exist.");
164                         if (ilgen != null)
165                                 return ilgen;
166                         ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), size);
167                         return ilgen;
168                 }               
169
170                 public override MethodImplAttributes GetMethodImplementationFlags () {
171                         return MethodImplAttributes.IL | MethodImplAttributes.Managed;
172                 }
173
174                 public override ParameterInfo[] GetParameters () {
175                         if (parameters == null)
176                                 return new ParameterInfo [0];
177
178                         ParameterInfo[] retval = new ParameterInfo [parameters.Length];
179                         for (int i = 0; i < parameters.Length; i++) {
180                                 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
181                         }
182                         return retval;
183                 }
184
185                 public override object Invoke (object obj, object[] parameters) {
186                         CreateDynMethod ();
187                         if (method == null)
188                                 method = new MonoMethod (mhandle);
189                         return method.Invoke (obj, parameters);
190                 }
191
192                 public override object Invoke (object obj, BindingFlags invokeAttr,
193                                                                            Binder binder, object[] parameters,
194                                                                            CultureInfo culture) {
195                         CreateDynMethod ();
196                         if (method == null)
197                                 method = new MonoMethod (mhandle);
198                         return method.Invoke (obj, parameters);
199                 }
200
201                 [MonoTODO]
202                 public override bool IsDefined (Type attributeType, bool inherit) {
203                         throw new NotImplementedException ();
204                 }
205
206                 public override string ToString () {
207                         string parms = "";
208                         ParameterInfo[] p = GetParameters ();
209                         for (int i = 0; i < p.Length; ++i) {
210                                 if (i > 0)
211                                         parms = parms + ", ";
212                                 parms = parms + p [i].ParameterType.Name;
213                         }
214                         return ReturnType.Name+" "+Name+"("+parms+")";
215                 }
216
217                 public override MethodAttributes Attributes {
218                         get {
219                                 return attributes;
220                         }
221                 }
222
223                 public override CallingConventions CallingConvention {
224                         get {
225                                 return callingConvention;
226                         }
227                 }
228
229                 public override Type DeclaringType {
230                         get {
231                                 return null;
232                         }
233                 }
234
235                 public bool InitLocals {
236                         get {
237                                 return init_locals;
238                         }
239                         set {
240                                 init_locals = value;
241                         }
242                 }
243
244                 public override RuntimeMethodHandle MethodHandle {
245                         get {
246                                 return mhandle;
247                         }
248                 }
249
250                 public Module Module {
251                         get {
252                                 return module;
253                         }
254                 }
255
256                 public override string Name {
257                         get {
258                                 return name;
259                         }
260                 }
261
262                 public override Type ReflectedType {
263                         get {
264                                 return null;
265                         }
266                 }
267
268                 [MonoTODO]
269                 public ParameterInfo ReturnParameter {
270                         get {
271                                 throw new NotImplementedException ();
272                         }
273                 }
274
275                 public override Type ReturnType {
276                         get {
277                                 return returnType;
278                         }
279                 }
280
281                 [MonoTODO]
282                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
283                         get {
284                                 throw new NotImplementedException ();
285                         }
286                 }
287
288                 private void RejectIfCreated () {
289                         if (mhandle.Value != IntPtr.Zero)
290                                 throw new InvalidOperationException ("Type definition of the method is complete.");
291                 }
292
293                 private Exception NotSupported () {
294                         return new NotSupportedException ("The invoked member is not supported on a dynamic method.");
295                 }
296
297                 internal int AddRef (object reference) {
298                         if (refs == null)
299                                 refs = new object [4];
300                         if (nrefs >= refs.Length) {
301                                 object [] new_refs = new object [refs.Length * 2];
302                                 System.Array.Copy (refs, new_refs, refs.Length);
303                                 refs = new_refs;
304                         }
305                         refs [nrefs] = reference;
306                         nrefs ++;
307                         return nrefs;
308                 }
309         }
310
311         internal class DynamicMethodTokenGenerator : TokenGenerator {
312
313                 private DynamicMethod m;
314
315                 public DynamicMethodTokenGenerator (DynamicMethod m) {
316                         this.m = m;
317                 }
318
319                 public int GetToken (string str) {
320                         return m.AddRef (str);
321                 }
322
323                 public int GetToken (MethodInfo method, Type[] opt_param_types) {
324                         throw new InvalidOperationException ();
325                 }
326
327                 public int GetToken (MemberInfo member) {
328                         return m.AddRef (member);
329                 }
330
331                 public int GetToken (SignatureHelper helper) {
332                         return m.AddRef (helper);
333                 }
334         }
335 }
336
337 #endif