Tue Sep 10 12:12:51 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ModuleBuilder.cs
1
2 //
3 // System.Reflection.Emit/ModuleBuilder.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.Collections;
14 using System.Runtime.CompilerServices;
15 using System.Runtime.InteropServices;
16 using System.Diagnostics.SymbolStore;
17 using System.IO;
18
19 namespace System.Reflection.Emit {
20         public class ModuleBuilder : Module {
21                 private TypeBuilder[] types;
22                 private CustomAttributeBuilder[] cattrs;
23                 private byte[] guid;
24                 private int table_idx;
25                 internal AssemblyBuilder assemblyb;
26                 private ISymbolWriter symbol_writer;
27                 private MethodInfo symwriter_define_local;
28                 Hashtable name_cache;
29
30                 internal ModuleBuilder (AssemblyBuilder assb, string name, string fullyqname, bool emitSymbolInfo) {
31                         this.name = this.scopename = name;
32                         this.fqname = fullyqname;
33                         this.assembly = this.assemblyb = assb;
34                         guid = Guid.NewGuid().ToByteArray ();
35                         table_idx = get_next_table_index (this, 0x00, true);
36                         name_cache = new Hashtable ();
37
38                         if (emitSymbolInfo)
39                                 GetSymbolWriter (fullyqname);
40                 }
41
42                 internal void GetSymbolWriter (string filename)
43                 {
44                         Assembly assembly;
45                         try {
46                                 assembly = Assembly.Load ("Mono.CSharp.Debugger");
47                         } catch (FileNotFoundException) {
48                                 return;
49                         }
50
51                         Type type = assembly.GetType ("Mono.CSharp.Debugger.MonoSymbolWriter");
52                         if (type == null)
53                                 return;
54
55                         if (assemblyb.methods == null)
56                                 assemblyb.methods = new ArrayList ();
57
58                         // First get the constructor.
59                         {
60                                 Type[] arg_types = new Type [3];
61                                 arg_types [0] = typeof (ModuleBuilder);
62                                 arg_types [1] = typeof (string);
63                                 arg_types [2] = typeof (ArrayList);
64                                 ConstructorInfo constructor = type.GetConstructor (arg_types);
65
66                                 object[] args = new object [3];
67                                 args [0] = this;
68                                 args [1] = filename;
69                                 args [2] = assemblyb.methods;
70
71                                 if (constructor == null)
72                                         return;
73
74                                 Object instance = constructor.Invoke (args);
75                                 if (instance == null)
76                                         return;
77
78                                 if (!(instance is ISymbolWriter))
79                                         return;
80
81                                 symbol_writer = (ISymbolWriter) instance;
82                         }
83
84                         // Get the DefineLocalVariable method.
85                         {
86                                 Type[] arg_types = new Type [6];
87                                 arg_types [0] = typeof (string);
88                                 arg_types [1] = typeof (LocalBuilder);
89                                 arg_types [2] = typeof (FieldAttributes);
90                                 arg_types [3] = typeof (int);
91                                 arg_types [4] = typeof (int);
92                                 arg_types [5] = typeof (int);
93
94                                 symwriter_define_local = type.GetMethod ("DefineLocalVariable", arg_types);
95
96                                 if (symwriter_define_local == null)
97                                         throw new NotSupportedException ();
98                         }
99                 }
100
101                 internal void SymWriter_DefineLocalVariable (string name, LocalBuilder local,
102                                                              FieldAttributes attributes,
103                                                              int position, int startOffset, int endOffset)
104                 {
105                         if ((symbol_writer == null) || (symwriter_define_local == null))
106                                 return;
107
108                         object[] args = new object [6];
109                         args [0] = name;
110                         args [1] = local;
111                         args [2] = attributes;
112                         args [3] = position;
113                         args [4] = startOffset;
114                         args [5] = endOffset;
115
116                         symwriter_define_local.Invoke (symbol_writer, args);
117                 }                                                            
118         
119                 public override string FullyQualifiedName {get { return fqname;}}
120
121                 [MonoTODO]
122                 public TypeBuilder DefineType (string name) {
123                         // FIXME: LAMESPEC: what other attributes should we use here as default?
124                         return DefineType (name, TypeAttributes.Public, typeof(object), null);
125                 }
126
127                 public TypeBuilder DefineType (string name, TypeAttributes attr) {
128                         return DefineType (name, attr, typeof(object), null);
129                 }
130
131                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent) {
132                         return DefineType (name, attr, parent, null);
133                 }
134
135                 private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packsize, int typesize) {
136                         TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packsize, typesize);
137                         if (types != null) {
138                                 TypeBuilder[] new_types = new TypeBuilder [types.Length + 1];
139                                 System.Array.Copy (types, new_types, types.Length);
140                                 new_types [types.Length] = res;
141                                 types = new_types;
142                         } else {
143                                 types = new TypeBuilder [1];
144                                 types [0] = res;
145                         }
146                         name_cache.Add (name, res);
147                         return res;
148                 }
149
150                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces) {
151                         return DefineType (name, attr, parent, interfaces, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
152                 }
153
154                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, int typesize) {
155                         return DefineType (name, attr, parent, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
156                 }
157
158                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packsize) {
159                         return DefineType (name, attr, parent, null, packsize, TypeBuilder.UnspecifiedTypeSize);
160                 }
161
162                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packsize, int typesize) {
163                         return DefineType (name, attr, parent, null, packsize, typesize);
164                 }
165
166                 public MethodInfo GetArrayMethod( Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) {
167                         return new MonoArrayMethod (arrayClass, methodName, callingConvention, returnType, parameterTypes);
168                 }
169
170                 public EnumBuilder DefineEnum( string name, TypeAttributes visibility, Type underlyingType) {
171                         EnumBuilder eb = new EnumBuilder (this, name, visibility, underlyingType);
172                         return eb;
173                 }
174
175                 public override Type GetType( string className) {
176                         return GetType (className, false, false);
177                 }
178                 
179                 public override Type GetType( string className, bool ignoreCase) {
180                         return GetType (className, false, ignoreCase);
181                 }
182
183                 private TypeBuilder search_in_array (TypeBuilder[] arr, string className, bool ignoreCase) {
184                         int i;
185                         if (arr == types && !ignoreCase)
186                                 return (TypeBuilder)name_cache [className];
187                         for (i = 0; i < arr.Length; ++i) {
188                                 if (String.Compare (className, arr [i].FullName, ignoreCase) == 0) {
189                                         return arr [i];
190                                 }
191                         }
192                         return null;
193                 }
194
195                 private TypeBuilder search_nested_in_array (TypeBuilder[] arr, string className, bool ignoreCase) {
196                         int i;
197                         for (i = 0; i < arr.Length; ++i) {
198                                 if (String.Compare (className, arr [i].Name, ignoreCase) == 0)
199                                         return arr [i];
200                         }
201                         return null;
202                 }
203
204                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
205                 private static extern Type create_modified_type (TypeBuilder tb, string modifiers);
206
207                 static char[] type_modifiers = {'&', '[', '*'};
208
209                 private TypeBuilder GetMaybeNested (TypeBuilder t, string className, bool ignoreCase) {
210                         int subt;
211                         string pname, rname;
212
213                         subt = className.IndexOf ('+');
214                         if (subt < 0) {
215                                 if (t.subtypes != null)
216                                         return search_nested_in_array (t.subtypes, className, ignoreCase);
217                                 return null;
218                         }
219                         if (t.subtypes != null) {
220                                 pname = className.Substring (0, subt);
221                                 rname = className.Substring (subt + 1);
222                                 TypeBuilder result = search_nested_in_array (t.subtypes, pname, ignoreCase);
223                                 if (result != null)
224                                         return GetMaybeNested (result, rname, ignoreCase);
225                         }
226                         return null;
227                 }
228                 
229                 public override Type GetType( string className, bool throwOnError, bool ignoreCase) {
230                         int subt;
231                         string orig = className;
232                         string modifiers;
233                         TypeBuilder result = null;
234
235                         if (types == null && throwOnError)
236                                 throw new TypeLoadException (className);
237
238                         subt = className.IndexOfAny (type_modifiers);
239                         if (subt >= 0) {
240                                 modifiers = className.Substring (subt);
241                                 className = className.Substring (0, subt);
242                         } else
243                                 modifiers = null;
244                         
245                         subt = className.IndexOf ('+');
246                         if (subt < 0) {
247                                 if (types != null)
248                                         result = search_in_array (types, className, ignoreCase);
249                         } else {
250                                 string pname, rname;
251                                 pname = className.Substring (0, subt);
252                                 rname = className.Substring (subt + 1);
253                                 result = search_in_array (types, pname, ignoreCase);
254                                 if (result != null)
255                                         result = GetMaybeNested (result, rname, ignoreCase);
256                         }
257                         if ((result == null) && throwOnError)
258                                 throw new TypeLoadException (orig);
259                         if (result != null && (modifiers != null))
260                                 return create_modified_type (result, modifiers);
261                         return result;
262                 }
263
264                 internal int get_next_table_index (object obj, int table, bool inc) {
265                         return assemblyb.get_next_table_index (obj, table, inc);
266                 }
267
268                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
269                         if (cattrs != null) {
270                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
271                                 cattrs.CopyTo (new_array, 0);
272                                 new_array [cattrs.Length] = customBuilder;
273                                 cattrs = new_array;
274                         } else {
275                                 cattrs = new CustomAttributeBuilder [1];
276                                 cattrs [0] = customBuilder;
277                         }
278                 }
279                 public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
280                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
281                 }
282
283                 public ISymbolWriter GetSymWriter () {
284                         return symbol_writer;
285                 }
286
287                 public ISymbolDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType) {
288                         if (symbol_writer == null)
289                                 throw new InvalidOperationException ();
290
291                         return symbol_writer.DefineDocument (url, language, languageVendor, documentType);
292                 }
293         }
294 }