2003-11-21 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodBuilder.cs
1
2 //
3 // System.Reflection.Emit/MethodBuilder.cs
4 //
5 // Author:
6 //   Paolo Molaro (lupus@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.Globalization;
15 using System.Runtime.CompilerServices;
16 using System.Runtime.InteropServices;
17
18 namespace System.Reflection.Emit {
19
20         public sealed class MethodBuilder : MethodInfo {
21                 private RuntimeMethodHandle mhandle;
22                 private Type rtype;
23                 private Type[] parameters;
24                 private MethodAttributes attrs;
25                 private MethodImplAttributes iattrs;
26                 private string name;
27                 private int table_idx;
28                 private byte[] code;
29                 private ILGenerator ilgen;
30                 private TypeBuilder type;
31                 private ParameterBuilder[] pinfo;
32                 private CustomAttributeBuilder[] cattrs;
33                 private MethodInfo override_method;
34                 private string pi_dll;
35                 private string pi_entry;
36                 private CharSet ncharset;
37                 private CallingConvention native_cc;
38                 private CallingConventions call_conv;
39                 private bool init_locals = true;
40                 private TypeBuilder.MonoGenericParam[] generic_params;
41                 private Type[] returnModReq;
42                 private Type[] returnModOpt;
43                 private Type[][] paramModReq;
44                 private Type[][] paramModOpt;
45
46                 internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt) {
47                         this.name = name;
48                         this.attrs = attributes;
49                         this.call_conv = callingConvention;
50                         this.rtype = returnType;
51                         this.returnModReq = returnModReq;
52                         this.returnModOpt = returnModOpt;
53                         this.paramModReq = paramModReq;
54                         this.paramModOpt = paramModOpt;
55                         // The MSDN docs does not specify this, but the MS MethodBuilder
56                         // appends a HasThis flag if the method is not static
57                         if ((attributes & MethodAttributes.Static) == 0)
58                                 this.call_conv |= CallingConventions.HasThis;
59                         if (parameterTypes != null) {
60                                 this.parameters = new Type [parameterTypes.Length];
61                                 System.Array.Copy (parameterTypes, this.parameters, parameterTypes.Length);
62                         }
63                         type = tb;
64                         table_idx = get_next_table_index (this, 0x06, true);
65                         //Console.WriteLine ("index for "+name+" set to "+table_idx.ToString());
66                 }
67
68                 internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, 
69                                                                 CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt, 
70                         String dllName, String entryName, CallingConvention nativeCConv, CharSet nativeCharset) 
71                         : this (tb, name, attributes, callingConvention, returnType, returnModReq, returnModOpt, parameterTypes, paramModReq, paramModOpt) {
72                         pi_dll = dllName;
73                         pi_entry = entryName;
74                         native_cc = nativeCConv;
75                         ncharset = nativeCharset;
76                 }
77
78                 public bool InitLocals {
79                         get {return init_locals;}
80                         set {init_locals = value;}
81                 }
82
83                 internal TypeBuilder TypeBuilder {
84                         get {return type;}
85                 }
86
87                 public override RuntimeMethodHandle MethodHandle {
88                         get {
89                                 throw NotSupported ();
90                         }
91                 }
92
93                 public override Type ReturnType {get {return rtype;}}
94                 public override Type ReflectedType {get {return type;}}
95                 public override Type DeclaringType {get {return type;}}
96                 public override string Name {get {return name;}}
97                 public override MethodAttributes Attributes {get {return attrs;}}
98                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
99                         get {return null;}
100                 }
101
102                 public override CallingConventions CallingConvention { 
103                         get { return call_conv; }
104                 }
105
106                 public MethodToken GetToken() {
107                         return new MethodToken(0x06000000 | table_idx);
108                 }
109                 
110                 public override MethodInfo GetBaseDefinition() {
111                         return this;
112                 }
113                 public override MethodImplAttributes GetMethodImplementationFlags() {
114                         return iattrs;
115                 }
116                 public override ParameterInfo[] GetParameters() {
117                         if (parameters == null)
118                                 return null;
119
120                         ParameterInfo[] retval = new ParameterInfo [parameters.Length];
121                         for (int i = 0; i < parameters.Length; i++) {
122                                 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
123                         }
124                         return retval;
125                 }
126
127                 public Module GetModule () {
128                         return type.Module;
129                 }
130
131                 public void CreateMethodBody( byte[] il, int count) {
132                         if ((il != null) && ((count < 0) || (count > il.Length)))
133                                 throw new ArgumentException ("Index was out of range.  Must be non-negative and less than the size of the collection.");
134
135                         if ((code != null) || type.is_created)
136                                 throw new InvalidOperationException ("Type definition of the method is complete.");
137
138                         if (il == null)
139                                 code = null;
140                         else {
141                                 code = new byte [count];
142                                 System.Array.Copy(il, code, count);
143                         }
144                 }
145
146                 public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
147                         throw NotSupported ();
148                 }
149                 public override bool IsDefined (Type attribute_type, bool inherit) {
150                         throw NotSupported ();
151                 }
152                 public override object[] GetCustomAttributes( bool inherit) {
153                         throw NotSupported ();
154                 }
155                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
156                         throw NotSupported ();
157                 }
158                 public ILGenerator GetILGenerator () {
159                         return GetILGenerator (64);
160                 }
161
162                 public ILGenerator GetILGenerator (int size) {
163                         if (((iattrs & MethodImplAttributes.CodeTypeMask) != 
164                                  MethodImplAttributes.IL) ||
165                                 ((iattrs & MethodImplAttributes.ManagedMask) != 
166                                  MethodImplAttributes.Managed))
167                                 throw new InvalidOperationException ("Method body should not exist.");
168                         if (ilgen != null)
169                                 return ilgen;
170                         ilgen = new ILGenerator (this, size);
171                         return ilgen;
172                 }
173                 
174                 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string strParamName)
175                 {
176                         //
177                         // Extension: Mono allows position == 0 for the return attribute
178                         //
179                         if ((position < 0) || (position > parameters.Length))
180                                 throw new ArgumentOutOfRangeException ("position");
181
182                         RejectIfCreated ();
183
184                         ParameterBuilder pb = new ParameterBuilder (this, position, attributes, strParamName);
185                         if (pinfo == null)
186                                 pinfo = new ParameterBuilder [parameters.Length + 1];
187                         pinfo [position] = pb;
188                         return pb;
189                 }
190
191                 internal void fixup () {
192                         if (ilgen != null)
193                                 ilgen.label_fixup ();
194                 }
195
196                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
197                         if (customBuilder == null)
198                                 throw new ArgumentNullException ("customBuilder");
199                         string attrname = customBuilder.Ctor.ReflectedType.FullName;
200                         if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute") {
201                                 byte[] data = customBuilder.Data;
202                                 int impla; // the (stupid) ctor takes a short or an int ... 
203                                 impla = (int)data [2];
204                                 impla |= ((int)data [3]) << 8;
205                                 SetImplementationFlags ((MethodImplAttributes)impla);
206                                 return;
207                         }
208                         if (cattrs != null) {
209                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
210                                 cattrs.CopyTo (new_array, 0);
211                                 new_array [cattrs.Length] = customBuilder;
212                                 cattrs = new_array;
213                         } else {
214                                 cattrs = new CustomAttributeBuilder [1];
215                                 cattrs [0] = customBuilder;
216                         }
217                 }
218                 public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
219                         if (con == null)
220                                 throw new ArgumentNullException ("con");
221                         if (binaryAttribute == null)
222                                 throw new ArgumentNullException ("binaryAttribute");
223                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
224                 }
225                 public void SetImplementationFlags( MethodImplAttributes attributes) {
226                         RejectIfCreated ();
227                         iattrs = attributes;
228                 }
229                 internal override int get_next_table_index (object obj, int table, bool inc) {
230                     return type.get_next_table_index (obj, table, inc);
231                 }
232
233                 internal void set_override (MethodInfo mdecl) {
234                         override_method = mdecl;
235                 }
236
237                 private void RejectIfCreated () {
238                         if (type.is_created)
239                                 throw new InvalidOperationException ("Type definition of the method is complete.");
240                 }
241
242                 private Exception NotSupported () {
243                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
244                 }
245
246 #if NET_1_2
247                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
248                 private extern Type define_generic_parameter (TypeBuilder.MonoGenericParam param);
249                 
250                 public Type DefineGenericParameter (string name, Type[] constraints)
251                 {
252                         TypeBuilder.MonoGenericParam gparam = new TypeBuilder.MonoGenericParam (name, constraints);
253
254                         if (generic_params != null) {
255                                 TypeBuilder.MonoGenericParam[] new_generic_params = new TypeBuilder.MonoGenericParam [generic_params.Length+1];
256                                 System.Array.Copy (generic_params, new_generic_params, generic_params.Length);
257                                 new_generic_params [generic_params.Length] = gparam;
258                                 generic_params = new_generic_params;
259                         } else {
260                                 generic_params = new TypeBuilder.MonoGenericParam [1];
261                                 generic_params [0] = gparam;
262                         }
263
264                         return define_generic_parameter (gparam);
265                 }
266
267                 public override Type[] GetGenericArguments ()
268                 {
269                         if (generic_params == null)
270                                 return new Type [0];
271
272                         Type[] result = new Type [generic_params.Length];
273                         for (int i = 0; i < generic_params.Length; i++)
274                                 result [i] = generic_params [i].Type;
275
276                         return result;
277                 }
278
279                 public void SetGenericMethodSignature (Type return_type, Type[] parameter_types)
280                 {
281                         RejectIfCreated ();
282
283                         this.rtype = return_type;
284                         this.parameters = new Type [parameter_types.Length];
285                         System.Array.Copy (parameter_types, this.parameters, parameter_types.Length);
286                 }
287 #endif
288         }
289 }
290