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;
17 public class CodeGen {
18 AppDomain current_domain;
19 AssemblyBuilder assembly_builder;
20 ModuleBuilder module_builder;
22 string Basename (string name)
24 int pos = name.LastIndexOf ("/");
27 return name.Substring (pos + 1);
29 pos = name.LastIndexOf ("\\");
31 return name.Substring (pos + 1);
36 string TrimExt (string name)
38 int pos = name.LastIndexOf (".");
40 return name.Substring (0, pos);
43 public CodeGen (string name, string output)
47 an = new AssemblyName ();
48 an.Name = TrimExt (Basename (name));
49 current_domain = AppDomain.CurrentDomain;
50 assembly_builder = current_domain.DefineDynamicAssembly (
51 an, AssemblyBuilderAccess.RunAndSave);
54 // Pass a path-less name to DefineDynamicModule. Wonder how
55 // this copes with output in different directories then.
56 // FIXME: figure out how this copes with --output /tmp/blah
58 module_builder = assembly_builder.DefineDynamicModule (
59 Basename (name), Basename (output));
63 public AssemblyBuilder AssemblyBuilder {
65 return assembly_builder;
69 public ModuleBuilder ModuleBuilder {
71 return module_builder;
75 public void Save (string name)
78 assembly_builder.Save (Basename (name));
79 } catch (System.IO.IOException io){
80 Report.Error (16, "Coult not write to file `"+name+"', cause: " + io.Message);
86 // An Emit Context is created for each body of code (from methods,
87 // properties bodies, indexer bodies or constructor bodies)
89 public class EmitContext {
90 public TypeContainer TypeContainer;
91 public ILGenerator ig;
92 public bool CheckState;
95 // Whether we are emitting code inside a static or instance method
100 // The value that is allowed to be returned or NULL if there is no
103 public Type ReturnType;
106 // Whether this is generating code for a constructor
108 public bool IsConstructor;
111 // Keeps track of the Type to LocalBuilder temporary storage created
112 // to store structures (used to compute the address of the structure
113 // value on structure method invocations)
115 public Hashtable temporary_storage;
117 public Block CurrentBlock;
119 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type,
120 int code_flags, bool is_constructor)
124 TypeContainer = parent;
125 CheckState = parent.RootContext.Checked;
126 IsStatic = (code_flags & Modifiers.STATIC) != 0;
127 ReturnType = return_type;
128 IsConstructor = is_constructor;
131 if (ReturnType == TypeManager.void_type)
135 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type, int code_flags)
136 : this (parent, ig, return_type, code_flags, false)
140 public void EmitTopBlock (Block block)
142 bool has_ret = false;
145 int errors = Report.Errors;
147 block.EmitMeta (TypeContainer, ig, block, 0);
149 if (Report.Errors == errors){
150 has_ret = block.Emit (this);
152 if (Report.Errors == errors)
153 block.UsageWarning ();
158 Statement s = new Return (null, Location.Null);
165 // Returns a temporary storage for a variable of type t as
166 // a local variable in the current body.
168 public LocalBuilder GetTemporaryStorage (Type t)
170 LocalBuilder location;
172 if (temporary_storage == null)
173 temporary_storage = new Hashtable ();
175 location = (LocalBuilder) temporary_storage [t];
176 if (location != null)
179 location = ig.DeclareLocal (t);
180 temporary_storage.Add (t, location);
186 // Current loop begin and end labels.
188 public Label LoopBegin, LoopEnd;
191 // Whether we are inside a loop and break/continue are possible.