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));
62 public AssemblyBuilder AssemblyBuilder {
64 return assembly_builder;
68 public ModuleBuilder ModuleBuilder {
70 return module_builder;
74 public void Save (string name)
77 assembly_builder.Save (Basename (name));
78 } catch (System.IO.IOException io){
79 Report.Error (16, "Coult not write to file `"+name+"', cause: " + io.Message);
84 public class EmitContext {
85 public TypeContainer TypeContainer;
86 public ILGenerator ig;
87 public bool CheckState;
90 // Whether we are emitting code inside a static or instance method
95 // The value that is allowed to be returned or NULL if there is no
98 public Type ReturnType;
101 // Whether this is generating code for a constructor
103 public bool IsConstructor;
106 // Keeps track of the Type to LocalBuilder temporary storage created
107 // to store structures (used to compute the address of the structure
108 // value on structure method invocations)
110 public Hashtable temporary_storage;
112 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type,
113 int code_flags, bool is_constructor)
117 TypeContainer = parent;
119 IsStatic = (code_flags & Modifiers.STATIC) != 0;
120 ReturnType = return_type;
121 IsConstructor = is_constructor;
123 if (ReturnType == TypeManager.void_type)
127 public EmitContext (TypeContainer parent, ILGenerator ig, Type return_type, int code_flags)
128 : this (parent, ig, return_type, code_flags, false)
132 public void EmitTopBlock (Block block)
134 bool has_ret = false;
137 int errors = Report.Errors;
139 block.EmitMeta (TypeContainer, ig, block, 0);
141 if (Report.Errors == errors){
142 has_ret = block.Emit (this);
144 if (Report.Errors == errors)
145 block.UsageWarning ();
150 ig.Emit (OpCodes.Ret);
154 // Returns a temporary storage for a variable of type t as
155 // a local variable in the current body.
157 public LocalBuilder GetTemporaryStorage (Type t)
159 LocalBuilder location;
161 if (temporary_storage == null)
162 temporary_storage = new Hashtable ();
164 location = (LocalBuilder) temporary_storage [t];
165 if (location != null)
168 location = ig.DeclareLocal (t);
169 temporary_storage.Add (t, location);
175 // Current loop begin and end labels.
177 public Label LoopBegin, LoopEnd;
180 // Whether we are inside a loop and break/continue are possible.