2 // codegen.cs: The code generator
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
11 using System.Collections;
12 using System.Reflection;
13 using System.Reflection.Emit;
15 namespace Mono.CSharp {
18 /// Code generator class.
20 public class CodeGen {
21 AppDomain current_domain;
22 AssemblyBuilder assembly_builder;
23 ModuleBuilder module_builder;
25 string Basename (string name)
27 int pos = name.LastIndexOf ("/");
30 return name.Substring (pos + 1);
32 pos = name.LastIndexOf ("\\");
34 return name.Substring (pos + 1);
39 string TrimExt (string name)
41 int pos = name.LastIndexOf (".");
43 return name.Substring (0, pos);
46 public CodeGen (string name, string output)
50 an = new AssemblyName ();
51 an.Name = TrimExt (Basename (name));
52 current_domain = AppDomain.CurrentDomain;
53 assembly_builder = current_domain.DefineDynamicAssembly (
54 an, AssemblyBuilderAccess.RunAndSave);
57 // Pass a path-less name to DefineDynamicModule. Wonder how
58 // this copes with output in different directories then.
59 // FIXME: figure out how this copes with --output /tmp/blah
61 module_builder = assembly_builder.DefineDynamicModule (
62 Basename (name), Basename (output));
66 public AssemblyBuilder AssemblyBuilder {
68 return assembly_builder;
72 public ModuleBuilder ModuleBuilder {
74 return module_builder;
78 public void Save (string name)
81 assembly_builder.Save (Basename (name));
82 } catch (System.IO.IOException io){
83 Report.Error (16, "Coult not write to file `"+name+"', cause: " + io.Message);
89 /// An Emit Context is created for each body of code (from methods,
90 /// properties bodies, indexer bodies or constructor bodies)
92 public class EmitContext {
93 public TypeContainer TypeContainer;
94 public ILGenerator ig;
95 public bool CheckState;
98 /// Whether we are emitting code inside a static or instance method
100 public bool IsStatic;
103 /// The value that is allowed to be returned or NULL if there is no
106 public Type ReturnType;
109 /// Whether this is generating code for a constructor
111 public bool IsConstructor;
114 /// Keeps track of the Type to LocalBuilder temporary storage created
115 /// to store structures (used to compute the address of the structure
116 /// value on structure method invocations)
118 public Hashtable temporary_storage;
120 public Block CurrentBlock;
122 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type,
123 int code_flags, bool is_constructor)
127 TypeContainer = parent;
128 CheckState = parent.RootContext.Checked;
129 IsStatic = (code_flags & Modifiers.STATIC) != 0;
130 ReturnType = return_type;
131 IsConstructor = is_constructor;
134 if (ReturnType == TypeManager.void_type)
138 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type, int code_flags)
139 : this (parent, ig, return_type, code_flags, false)
143 public void EmitTopBlock (Block block)
145 bool has_ret = false;
148 int errors = Report.Errors;
150 block.EmitMeta (TypeContainer, ig, block, 0);
152 if (Report.Errors == errors){
153 has_ret = block.Emit (this);
155 if (Report.Errors == errors)
156 block.UsageWarning ();
161 Statement s = new Return (null, Location.Null);
168 /// Returns a temporary storage for a variable of type t as
169 /// a local variable in the current body.
171 public LocalBuilder GetTemporaryStorage (Type t)
173 LocalBuilder location;
175 if (temporary_storage == null)
176 temporary_storage = new Hashtable ();
178 location = (LocalBuilder) temporary_storage [t];
179 if (location != null)
182 location = ig.DeclareLocal (t);
183 temporary_storage.Add (t, location);
189 /// Current loop begin and end labels.
191 public Label LoopBegin, LoopEnd;
194 /// Whether we are inside a loop and break/continue are possible.