2 // Mono.ILASM.CodeGen.cs
5 // Sergey Chaban (serge@wildwestsoftware.com)
6 // Jackson Harper (Jackson@LatitudeGeo.com)
9 // (C) 2003 Jackson Harper, All rights reserved
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
;
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
;
68 this.is_assembly
= is_assembly
;
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 ();
89 private string CreateDebugFile (string output_file
)
91 int ext_index
= output_file
.LastIndexOf ('.');
94 ext_index
= output_file
.Length
;
96 return String
.Format ("{0}.{1}", output_file
.Substring (0, ext_index
),
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
);
213 typedef
= new TypeDef (attr
, current_namespace
,
214 name
, parent
, impl_list
, location
);
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
);
229 global_field_table
.Add (fielddef
.Name
,
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
;
249 public void BeginMethodDef (MethodDef methoddef
)
251 if (current_typedef
!= null) {
252 current_typedef
.AddMethodDef (methoddef
);
254 global_method_table
.Add (methoddef
.Signature
,
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 ();
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
);
327 FileStream out_stream
= null;
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
);
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
);
376 if (out_stream
!= null)
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
)
410 return current_namespace
+ "." + name
;