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