2004-04-22 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodBuilder.cs
1 //
2 // System.Reflection.Emit/MethodBuilder.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Globalization;
14 using System.Security;
15 using System.Security.Permissions;
16 using System.Runtime.CompilerServices;
17 using System.Runtime.InteropServices;
18
19 namespace System.Reflection.Emit {
20
21         public sealed class MethodBuilder : MethodInfo {
22                 private RuntimeMethodHandle mhandle;
23                 private Type rtype;
24                 private Type[] parameters;
25                 private MethodAttributes attrs;
26                 private MethodImplAttributes iattrs;
27                 private string name;
28                 private int table_idx;
29                 private byte[] code;
30                 private ILGenerator ilgen;
31                 private TypeBuilder type;
32                 private ParameterBuilder[] pinfo;
33                 private CustomAttributeBuilder[] cattrs;
34                 private MethodInfo override_method;
35                 private string pi_dll;
36                 private string pi_entry;
37                 private CharSet ncharset;
38                 private CallingConvention native_cc;
39                 private CallingConventions call_conv;
40                 private bool init_locals = true;
41 #if NET_2_0 | BOOTSTRAP_NET_2_0
42                 private GenericTypeParameterBuilder[] generic_params;
43 #else
44                 private Object generic_params; /* so offsets are the same */
45 #endif
46                 private Type[] returnModReq;
47                 private Type[] returnModOpt;
48                 private Type[][] paramModReq;
49                 private Type[][] paramModOpt;
50                 private RefEmitPermissionSet[] permissions;
51
52                 internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt) {
53                         this.name = name;
54                         this.attrs = attributes;
55                         this.call_conv = callingConvention;
56                         this.rtype = returnType;
57                         this.returnModReq = returnModReq;
58                         this.returnModOpt = returnModOpt;
59                         this.paramModReq = paramModReq;
60                         this.paramModOpt = paramModOpt;
61                         // The MSDN docs does not specify this, but the MS MethodBuilder
62                         // appends a HasThis flag if the method is not static
63                         if ((attributes & MethodAttributes.Static) == 0)
64                                 this.call_conv |= CallingConventions.HasThis;
65                         if (parameterTypes != null) {
66                                 this.parameters = new Type [parameterTypes.Length];
67                                 System.Array.Copy (parameterTypes, this.parameters, parameterTypes.Length);
68                         }
69                         type = tb;
70                         table_idx = get_next_table_index (this, 0x06, true);
71                         //Console.WriteLine ("index for "+name+" set to "+table_idx.ToString());
72                 }
73
74                 internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, 
75                                                                 CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt, 
76                         String dllName, String entryName, CallingConvention nativeCConv, CharSet nativeCharset) 
77                         : this (tb, name, attributes, callingConvention, returnType, returnModReq, returnModOpt, parameterTypes, paramModReq, paramModOpt) {
78                         pi_dll = dllName;
79                         pi_entry = entryName;
80                         native_cc = nativeCConv;
81                         ncharset = nativeCharset;
82                 }
83
84                 public bool InitLocals {
85                         get {return init_locals;}
86                         set {init_locals = value;}
87                 }
88
89                 internal TypeBuilder TypeBuilder {
90                         get {return type;}
91                 }
92
93                 public override RuntimeMethodHandle MethodHandle {
94                         get {
95                                 throw NotSupported ();
96                         }
97                 }
98
99                 public override Type ReturnType {get {return rtype;}}
100                 public override Type ReflectedType {get {return type;}}
101                 public override Type DeclaringType {get {return type;}}
102                 public override string Name {get {return name;}}
103                 public override MethodAttributes Attributes {get {return attrs;}}
104                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
105                         get {return null;}
106                 }
107
108                 public override CallingConventions CallingConvention { 
109                         get { return call_conv; }
110                 }
111
112                 [MonoTODO]
113                 public string Signature {
114                         get {
115                                 throw new NotImplementedException ();
116                         }
117                 }
118
119                 public MethodToken GetToken() {
120                         return new MethodToken(0x06000000 | table_idx);
121                 }
122                 
123                 public override MethodInfo GetBaseDefinition() {
124                         return this;
125                 }
126                 public override MethodImplAttributes GetMethodImplementationFlags() {
127                         return iattrs;
128                 }
129                 public override ParameterInfo[] GetParameters() {
130                         if (parameters == null)
131                                 return null;
132
133                         ParameterInfo[] retval = new ParameterInfo [parameters.Length];
134                         for (int i = 0; i < parameters.Length; i++) {
135                                 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
136                         }
137                         return retval;
138                 }
139                 
140                 internal override int GetParameterCount ()
141                 {
142                         if (parameters == null)
143                                 return 0;
144                         
145                         return parameters.Length;
146                 }
147
148                 public Module GetModule () {
149                         return type.Module;
150                 }
151
152                 public void CreateMethodBody( byte[] il, int count) {
153                         if ((il != null) && ((count < 0) || (count > il.Length)))
154                                 throw new ArgumentException ("Index was out of range.  Must be non-negative and less than the size of the collection.");
155
156                         if ((code != null) || type.is_created)
157                                 throw new InvalidOperationException ("Type definition of the method is complete.");
158
159                         if (il == null)
160                                 code = null;
161                         else {
162                                 code = new byte [count];
163                                 System.Array.Copy(il, code, count);
164                         }
165                 }
166
167                 public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
168                         throw NotSupported ();
169                 }
170                 public override bool IsDefined (Type attribute_type, bool inherit) {
171                         throw NotSupported ();
172                 }
173                 public override object[] GetCustomAttributes( bool inherit) {
174                         throw NotSupported ();
175                 }
176                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
177                         throw NotSupported ();
178                 }
179                 public ILGenerator GetILGenerator () {
180                         return GetILGenerator (64);
181                 }
182
183                 public ILGenerator GetILGenerator (int size) {
184                         if (((iattrs & MethodImplAttributes.CodeTypeMask) != 
185                                  MethodImplAttributes.IL) ||
186                                 ((iattrs & MethodImplAttributes.ManagedMask) != 
187                                  MethodImplAttributes.Managed))
188                                 throw new InvalidOperationException ("Method body should not exist.");
189                         if (ilgen != null)
190                                 return ilgen;
191                         ilgen = new ILGenerator (type.Module, ((ModuleBuilder)type.Module).GetTokenGenerator (), size);
192                         return ilgen;
193                 }
194                 
195                 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string strParamName)
196                 {
197                         //
198                         // Extension: Mono allows position == 0 for the return attribute
199                         //
200                         if ((position < 0) || (position > parameters.Length))
201                                 throw new ArgumentOutOfRangeException ("position");
202
203                         RejectIfCreated ();
204
205                         ParameterBuilder pb = new ParameterBuilder (this, position, attributes, strParamName);
206                         if (pinfo == null)
207                                 pinfo = new ParameterBuilder [parameters.Length + 1];
208                         pinfo [position] = pb;
209                         return pb;
210                 }
211
212                 internal void fixup () {
213                         if (ilgen != null)
214                                 ilgen.label_fixup ();
215                 }
216
217                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
218                         if (customBuilder == null)
219                                 throw new ArgumentNullException ("customBuilder");
220                         string attrname = customBuilder.Ctor.ReflectedType.FullName;
221                         if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute") {
222                                 byte[] data = customBuilder.Data;
223                                 int impla; // the (stupid) ctor takes a short or an int ... 
224                                 impla = (int)data [2];
225                                 impla |= ((int)data [3]) << 8;
226                                 SetImplementationFlags ((MethodImplAttributes)impla);
227                                 return;
228                         }
229                         if (cattrs != null) {
230                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
231                                 cattrs.CopyTo (new_array, 0);
232                                 new_array [cattrs.Length] = customBuilder;
233                                 cattrs = new_array;
234                         } else {
235                                 cattrs = new CustomAttributeBuilder [1];
236                                 cattrs [0] = customBuilder;
237                         }
238                 }
239                 public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
240                         if (con == null)
241                                 throw new ArgumentNullException ("con");
242                         if (binaryAttribute == null)
243                                 throw new ArgumentNullException ("binaryAttribute");
244                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
245                 }
246                 public void SetImplementationFlags( MethodImplAttributes attributes) {
247                         RejectIfCreated ();
248                         iattrs = attributes;
249                 }
250
251                 public void AddDeclarativeSecurity( SecurityAction action, PermissionSet pset) {
252                         if (pset == null)
253                                 throw new ArgumentNullException ("pset");
254                         if ((action == SecurityAction.RequestMinimum) ||
255                                 (action == SecurityAction.RequestOptional) ||
256                                 (action == SecurityAction.RequestRefuse))
257                                 throw new ArgumentException ("Request* values are not permitted", "action");
258
259                         RejectIfCreated ();
260
261                         if (permissions != null) {
262                                 /* Check duplicate actions */
263                                 foreach (RefEmitPermissionSet set in permissions)
264                                         if (set.action == action)
265                                                 throw new InvalidOperationException ("Multiple permission sets specified with the same SecurityAction.");
266
267                                 RefEmitPermissionSet[] new_array = new RefEmitPermissionSet [permissions.Length + 1];
268                                 permissions.CopyTo (new_array, 0);
269                                 permissions = new_array;
270                         }
271                         else
272                                 permissions = new RefEmitPermissionSet [1];
273
274                         permissions [permissions.Length - 1] = new RefEmitPermissionSet (action, pset.ToXml ().ToString ());
275                         attrs |= MethodAttributes.HasSecurity;
276                 }
277
278                 [MonoTODO]
279                 public void SetMarshal (UnmanagedMarshal unmanagedMarshal)
280                 {
281                         RejectIfCreated ();
282                         throw new NotImplementedException ();
283                 }
284
285                 [MonoTODO]
286                 public void SetSymCustomAttribute (string name, byte[] data)
287                 {
288                         RejectIfCreated ();
289                         throw new NotImplementedException ();
290                 }
291
292                 internal override int get_next_table_index (object obj, int table, bool inc) {
293                     return type.get_next_table_index (obj, table, inc);
294                 }
295
296                 internal void set_override (MethodInfo mdecl) {
297                         override_method = mdecl;
298                 }
299
300                 private void RejectIfCreated () {
301                         if (type.is_created)
302                                 throw new InvalidOperationException ("Type definition of the method is complete.");
303                 }
304
305                 private Exception NotSupported () {
306                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
307                 }
308
309 #if NET_2_0 | BOOTSTRAP_NET_2_0
310                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
311                 public override extern MethodInfo BindGenericParameters (Type [] types);
312
313                 public override bool Mono_IsInflatedMethod {
314                         get {
315                                 return false;
316                         }
317                 }
318
319                 public override bool HasGenericParameters {
320                         get {
321                                 return generic_params != null;
322                         }
323                 }
324
325                 public override Type[] GetGenericArguments ()
326                 {
327                         if (generic_params == null)
328                                 return new Type [0];
329
330                         Type[] result = new Type [generic_params.Length];
331                         for (int i = 0; i < generic_params.Length; i++)
332                                 result [i] = generic_params [i];
333
334                         return result;
335                 }
336
337                 public GenericTypeParameterBuilder[] DefineGenericParameters (string[] names)
338                 {
339                         generic_params = new GenericTypeParameterBuilder [names.Length];
340                         for (int i = 0; i < names.Length; i++)
341                                 generic_params [i] = new GenericTypeParameterBuilder (
342                                         type, this, names [i], i);
343
344                         return generic_params;
345                 }
346
347                 public void SetGenericMethodSignature (MethodAttributes attributes, CallingConventions callingConvention, Type return_type, Type[] parameter_types)
348                 {
349                         RejectIfCreated ();
350
351                         this.attrs = attributes;
352                         this.call_conv = callingConvention;
353                         if ((attributes & MethodAttributes.Static) == 0)
354                                 this.call_conv |= CallingConventions.HasThis;
355
356                         this.rtype = return_type;
357                         this.parameters = new Type [parameter_types.Length];
358                         System.Array.Copy (parameter_types, this.parameters, parameter_types.Length);
359                 }
360 #endif
361         }
362 }
363