**** Merged from MCS ****
[mono-project.git] / mcs / ilasm / codegen / CodeGen.cs
blob7eb90407c5e8ee0f495b2870293cbcb7abc9050f
1 //
2 // Mono.ILASM.CodeGen.cs
3 //
4 // Author(s):
5 // Sergey Chaban (serge@wildwestsoftware.com)
6 // Jackson Harper (Jackson@LatitudeGeo.com)
7 //
8 // (C) Sergey Chaban
9 // (C) 2003 Jackson Harper, All rights reserved
12 using PEAPI;
13 using System;
14 using System.IO;
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
19 namespace Mono.ILASM {
21 public class CodeGen {
23 private PEFile pefile;
24 private string assembly_name;
25 private Report report;
26 private ExternAssembly current_assemblyref;
27 private ExternModule current_moduleref;
28 private string current_namespace;
29 private TypeDef current_typedef;
30 private MethodDef current_methoddef;
31 private Stack typedef_stack;
32 private SymbolWriter symwriter;
34 private byte [] assembly_public_key;
35 private int assembly_major_version;
36 private int assembly_minor_version;
37 private int assembly_build_version;
38 private int assembly_revision_version;
39 private string assembly_locale;
40 private int assembly_hash_algorithm;
41 private ArrayList assembly_custom_attributes;
43 private TypeManager type_manager;
44 private ExternTable extern_table;
45 private Hashtable global_field_table;
46 private Hashtable global_method_table;
47 private ArrayList data_list;
48 private FileRef file_ref;
50 private ArrayList defcont_list;
52 private int sub_system;
53 private int cor_flags;
54 private long image_base;
56 private string output_file;
57 private string debug_file;
58 private bool is_dll;
59 private bool is_assembly;
61 private string module_name;
63 public CodeGen (string output_file, bool is_dll, bool is_assembly,
64 bool debugging_info, Report report)
66 this.output_file = output_file;
67 this.is_dll = is_dll;
68 this.is_assembly = is_assembly;
69 this.report = report;
71 if (debugging_info)
72 symwriter = new SymbolWriter (CreateDebugFile (output_file));
74 type_manager = new TypeManager (this);
75 extern_table = new ExternTable ();
76 typedef_stack = new Stack ();
77 global_field_table = new Hashtable ();
78 global_method_table = new Hashtable ();
80 data_list = new ArrayList ();
82 defcont_list = new ArrayList ();
84 sub_system = -1;
85 cor_flags = -1;
86 image_base = -1;
89 private string CreateDebugFile (string output_file)
91 int ext_index = output_file.LastIndexOf ('.');
93 if (ext_index == -1)
94 ext_index = output_file.Length;
96 return String.Format ("{0}.{1}", output_file.Substring (0, ext_index),
97 "mdb");
100 public PEFile PEFile {
101 get { return pefile; }
104 public Report Report {
105 get { return report; }
108 public SymbolWriter SymbolWriter {
109 get { return symwriter; }
112 public string CurrentNameSpace {
113 get { return current_namespace; }
114 set { current_namespace = value; }
117 public TypeDef CurrentTypeDef {
118 get { return current_typedef; }
121 public MethodDef CurrentMethodDef {
122 get { return current_methoddef; }
125 public ExternAssembly CurrentAssemblyRef {
126 get { return current_assemblyref; }
129 public ExternModule CurrentModuleRef {
130 get { return current_moduleref; }
133 public ExternTable ExternTable {
134 get { return extern_table; }
137 public TypeManager TypeManager {
138 get { return type_manager; }
141 public void SetSubSystem (int sub_system)
143 this.sub_system = sub_system;
146 public void SetCorFlags (int cor_flags)
148 this.cor_flags = cor_flags;
151 public void SetImageBase (long image_base)
153 this.image_base = image_base;
156 public void SetAssemblyName (string name)
158 assembly_name = name;
161 public void SetModuleName (string module_name)
163 this.module_name = module_name;
166 public void SetFileRef (FileRef file_ref)
168 this.file_ref = file_ref;
171 public bool IsThisAssembly (string name)
173 return (name == assembly_name);
176 public bool IsThisModule (string name)
178 return (name == module_name);
181 public void BeginSourceFile (string name)
183 if (symwriter != null)
184 symwriter.BeginSourceFile (name);
187 public void EndSourceFile ()
189 if (symwriter != null)
190 symwriter.EndSourceFile ();
193 public void BeginTypeDef (TypeAttr attr, string name, IClassRef parent,
194 ArrayList impl_list, Location location)
196 TypeDef outer = null;
197 string cache_name = CacheName (name);
199 if (typedef_stack.Count > 0) {
200 outer = (TypeDef) typedef_stack.Peek ();
201 cache_name = CacheName (outer.Name + '/' + name);
204 TypeDef typedef = type_manager[cache_name];
206 if (typedef != null) {
207 // Class head is allready defined, we are just reopening the class
208 current_typedef = typedef;
209 typedef_stack.Push (current_typedef);
210 return;
213 typedef = new TypeDef (attr, current_namespace,
214 name, parent, impl_list, location);
216 if (outer != null)
217 typedef.OuterType = outer;
219 type_manager[cache_name] = typedef;
220 current_typedef = typedef;
221 typedef_stack.Push (typedef);
224 public void AddFieldDef (FieldDef fielddef)
226 if (current_typedef != null) {
227 current_typedef.AddFieldDef (fielddef);
228 } else {
229 global_field_table.Add (fielddef.Name,
230 fielddef);
234 public void AddDataDef (DataDef datadef)
236 data_list.Add (datadef);
239 public PEAPI.DataConstant GetDataConst (string name)
241 foreach (DataDef def in data_list) {
242 if (def.Name == name)
243 return (DataConstant) def.PeapiConstant;
245 return null;
249 public void BeginMethodDef (MethodDef methoddef)
251 if (current_typedef != null) {
252 current_typedef.AddMethodDef (methoddef);
253 } else {
254 global_method_table.Add (methoddef.Signature,
255 methoddef);
258 current_methoddef = methoddef;
261 public void EndMethodDef (Location location)
263 if (symwriter != null)
264 symwriter.EndMethod (location);
266 current_methoddef = null;
269 public void EndTypeDef ()
271 typedef_stack.Pop ();
273 if (typedef_stack.Count > 0)
274 current_typedef = (TypeDef) typedef_stack.Peek ();
275 else
276 current_typedef = null;
280 public void BeginAssemblyRef (string name, AssemblyName asmb_name)
282 current_assemblyref = ExternTable.AddAssembly (name, asmb_name);
285 public void EndAssemblyRef ()
287 current_assemblyref = null;
290 public void AddToDefineContentsList (TypeDef typedef)
292 defcont_list.Add (typedef);
295 public void SetAssemblyPublicKey (byte [] public_key)
297 assembly_public_key = public_key;
300 public void SetAssemblyVersion (int major, int minor, int build, int revision)
302 assembly_major_version = major;
303 assembly_minor_version = minor;
304 assembly_build_version = build;
305 assembly_revision_version = revision;
308 public void SetAssemblyLocale (string locale)
310 assembly_locale = locale;
313 public void SetAssemblyHashAlgorithm (int algorithm)
315 assembly_hash_algorithm = algorithm;
318 public void AddAssemblyCustomAttribute (CustomAttr attribute)
320 if (assembly_custom_attributes == null)
321 assembly_custom_attributes = new ArrayList ();
322 assembly_custom_attributes.Add (attribute);
325 public void Write ()
327 FileStream out_stream = null;
329 try {
330 out_stream = new FileStream (output_file, FileMode.Create, FileAccess.Write);
331 pefile = new PEFile (assembly_name, module_name, is_dll, is_assembly, out_stream);
332 PEAPI.Assembly asmb = pefile.GetThisAssembly ();
334 if (file_ref != null)
335 file_ref.Resolve (this);
337 extern_table.Resolve (this);
338 type_manager.DefineAll ();
340 foreach (FieldDef fielddef in global_field_table.Values) {
341 fielddef.Define (this);
344 foreach (MethodDef methoddef in global_method_table.Values) {
345 methoddef.Define (this);
348 foreach (TypeDef typedef in defcont_list) {
349 typedef.DefineContents (this);
352 if (assembly_custom_attributes != null) {
353 foreach (CustomAttr cattr in assembly_custom_attributes)
354 cattr.AddTo (this, asmb);
357 if (sub_system != -1)
358 pefile.SetSubSystem ((PEAPI.SubSystem) sub_system);
359 if (cor_flags != -1)
360 pefile.SetCorFlags (cor_flags);
362 asmb.AddAssemblyInfo(assembly_major_version,
363 assembly_minor_version, assembly_build_version,
364 assembly_revision_version, assembly_public_key,
365 (uint) assembly_hash_algorithm, assembly_locale);
367 pefile.WritePEFile ();
369 if (symwriter != null) {
370 Guid guid = pefile.GetThisModule ().Guid;
371 symwriter.Write (guid);
373 } catch {
374 throw;
375 } finally {
376 if (out_stream != null)
377 out_stream.Close ();
381 public PEAPI.Method ResolveMethod (string signature)
383 MethodDef methoddef = (MethodDef) global_method_table[signature];
385 return methoddef.Resolve (this);
388 public PEAPI.Method ResolveVarargMethod (string signature,
389 CodeGen code_gen, PEAPI.Type[] opt)
391 MethodDef methoddef = (MethodDef) global_method_table[signature];
392 methoddef.Resolve (code_gen);
394 return methoddef.GetVarargSig (opt);
397 public PEAPI.Field ResolveField (string name)
399 FieldDef fielddef = (FieldDef) global_field_table[name];
401 return fielddef.Resolve (this);
404 private string CacheName (string name)
406 if (current_namespace == null ||
407 current_namespace == String.Empty)
408 return name;
410 return current_namespace + "." + name;