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 (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);
85 public class EmitContext {
86 public TypeContainer TypeContainer;
87 public ILGenerator ig;
88 public bool CheckState;
91 // Whether we are emitting code inside a static or instance method
96 // The value that is allowed to be returned or NULL if there is no
99 public Type ReturnType;
102 // Whether this is generating code for a constructor
104 public bool IsConstructor;
107 // Keeps track of the Type to LocalBuilder temporary storage created
108 // to store structures (used to compute the address of the structure
109 // value on structure method invocations)
111 public Hashtable temporary_storage;
113 public Block CurrentBlock;
115 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type,
116 int code_flags, bool is_constructor)
120 TypeContainer = parent;
121 CheckState = parent.RootContext.Checked;
122 IsStatic = (code_flags & Modifiers.STATIC) != 0;
123 ReturnType = return_type;
124 IsConstructor = is_constructor;
127 if (ReturnType == TypeManager.void_type)
131 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type, int code_flags)
132 : this (parent, ig, return_type, code_flags, false)
136 public void EmitTopBlock (Block block)
138 bool has_ret = false;
141 int errors = Report.Errors;
143 block.EmitMeta (TypeContainer, ig, block, 0);
145 if (Report.Errors == errors){
146 has_ret = block.Emit (this);
148 if (Report.Errors == errors)
149 block.UsageWarning ();
154 ig.Emit (OpCodes.Ret);
158 // Returns a temporary storage for a variable of type t as
159 // a local variable in the current body.
161 public LocalBuilder GetTemporaryStorage (Type t)
163 LocalBuilder location;
165 if (temporary_storage == null)
166 temporary_storage = new Hashtable ();
168 location = (LocalBuilder) temporary_storage [t];
169 if (location != null)
172 location = ig.DeclareLocal (t);
173 temporary_storage.Add (t, location);
179 // Current loop begin and end labels.
181 public Label LoopBegin, LoopEnd;
184 // Whether we are inside a loop and break/continue are possible.
189 // Whether we are currently emitting code for a ref/out parameter
191 public bool RefOrOutParameter;