* CodeGenerator.cs: Deleted one of ILGenerator fields
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / CodeGenerator.cs
1 //
2 // CodeGenerator.cs
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, Cesar Lopez Nataren
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Threading;
14 using Microsoft.JScript.Vsa;
15 using System.Runtime.CompilerServices;
16
17 namespace Microsoft.JScript {
18
19         internal class EmitContext {
20
21                 internal TypeBuilder type_builder;
22                 internal ILGenerator ig;
23                 internal ModuleBuilder mod_builder;
24
25                 internal EmitContext (TypeBuilder type)
26                 {
27                         type_builder = type;
28
29                         if (type_builder != null) {
30                                 MethodBuilder global_code =  type_builder.DefineMethod (
31                                                                         "Global Code",
32                                                                         MethodAttributes.Public,
33                                                                         typeof (System.Object),
34                                                                         new Type [] {});
35                                 ig = global_code.GetILGenerator ();
36                         }
37                 }
38
39                 internal EmitContext (TypeBuilder type_builder, ModuleBuilder mod_builder, ILGenerator ig)
40                 {
41                         this.type_builder = type_builder;
42                         this.mod_builder = mod_builder;
43                         this.ig = ig;
44                 }
45         }
46
47         public class CodeGenerator {
48
49                 private static string MODULE = "JScript Module";
50
51                 internal static string mod_name;
52                 internal static AppDomain app_domain;
53                 internal static AssemblyName assembly_name;
54                 internal static AssemblyBuilder assembly_builder;
55                 internal static ModuleBuilder module_builder;
56
57                 internal static void Init (string file_name)
58                 {
59                         app_domain = Thread.GetDomain ();
60
61                         assembly_name = new AssemblyName ();
62                         assembly_name.Name =  trim_extension (file_name);
63
64                         mod_name = MODULE;
65
66                         assembly_builder = app_domain.DefineDynamicAssembly (
67                                              assembly_name,
68                                              AssemblyBuilderAccess.RunAndSave);
69
70                         ConstructorInfo ctr_info = typeof (Microsoft.JScript.ReferenceAttribute).GetConstructor (new Type [] { typeof (string) });
71                         // FIXME: find out which is the blob.
72                         byte [] blob  = new byte [] {};
73                         assembly_builder.SetCustomAttribute (ctr_info, blob); 
74
75                         module_builder = assembly_builder.DefineDynamicModule (
76                                                 mod_name,
77                                                 assembly_name.Name + ".exe", 
78                                                 false);
79                 }
80
81                 internal static string trim_extension (string file_name)
82                 {
83                         int index = file_name.LastIndexOf ('.');
84
85                         if (index < 0)
86                                 return file_name;
87                         else
88                                 return file_name.Substring (0, index);
89                 }
90
91                 internal static void Save (string target_name)
92                 {
93                         assembly_builder.Save (target_name);
94                 }
95
96                 internal static void Emit (AST prog)
97                 {
98                         if (prog == null)
99                                 return;
100
101                         TypeBuilder type_builder;
102                         type_builder = module_builder.DefineType ("JScript 0", TypeAttributes.Public);
103
104                         type_builder.SetParent (typeof (GlobalScope));
105                         type_builder.SetCustomAttribute (new CustomAttributeBuilder
106                                                          (typeof (CompilerGlobalScopeAttribute).GetConstructor (new Type [] {}), new object [] {}));
107
108                         EmitContext ec = new EmitContext (type_builder);
109                         ec.mod_builder = module_builder;
110                         ILGenerator global_code = ec.ig;
111
112                         emit_default_script_constructor (ec);
113                         emit_default_init_global_code (global_code);
114                         prog.Emit (ec);
115                         emit_default_end_global_code (global_code);
116                         ec.type_builder.CreateType ();
117
118                         //
119                         // Build the default 'JScript Main' class
120                         //
121                         ec.type_builder = module_builder.DefineType ("JScript Main");
122                         emit_jscript_main (ec.type_builder);
123                         ec.type_builder.CreateType ();
124                 }
125
126                 internal static void emit_default_init_global_code (ILGenerator ig)
127                 {
128                         ig.Emit (OpCodes.Ldarg_0);
129                         ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
130                         ig.Emit (OpCodes.Ldarg_0);
131                         ig.Emit (OpCodes.Call,
132                                 typeof (VsaEngine).GetMethod ("PushScriptObject",
133                                                               new Type [] { typeof (ScriptObject)}));
134                 }
135
136                 internal static void emit_default_end_global_code (ILGenerator ig)
137                 {
138                         ig.Emit (OpCodes.Ldnull);
139                         ig.Emit (OpCodes.Ldarg_0);
140                         ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
141                         ig.Emit (OpCodes.Call, typeof (VsaEngine).GetMethod ("PopScriptObject"));
142                         ig.Emit (OpCodes.Pop);
143                         ig.Emit (OpCodes.Ret);          
144                 }
145
146                 internal static void emit_default_script_constructor (EmitContext ec)
147                 {
148                         ConstructorBuilder cons_builder;
149                         TypeBuilder tb = ec.type_builder;
150                         cons_builder = tb.DefineConstructor (MethodAttributes.Public,
151                                                              CallingConventions.Standard,
152                                                              new Type [] { typeof (GlobalScope) });
153
154                         ILGenerator ig = cons_builder.GetILGenerator ();
155                         ig.Emit (OpCodes.Ldarg_0);
156                         ig.Emit (OpCodes.Ldarg_1);
157                         ig.Emit (OpCodes.Dup);
158                         ig.Emit (OpCodes.Ldfld,
159                                  typeof (ScriptObject).GetField ("engine"));
160                         
161                         ig.Emit (OpCodes.Call, 
162                                  typeof (GlobalScope).GetConstructor (new Type [] {typeof (GlobalScope), 
163                                                                                    typeof (VsaEngine)}));
164                         ig.Emit (OpCodes.Ret);
165                 }
166
167                 internal static void emit_jscript_main (TypeBuilder tb)
168                 {
169                         emit_jscript_main_constructor (tb);
170                         emit_jscript_main_entry_point (tb);
171                 }
172
173                 internal static void emit_jscript_main_constructor (TypeBuilder tb)
174                 {
175                         ConstructorBuilder cons = tb.DefineConstructor (MethodAttributes.Public, 
176                                                                         CallingConventions.Standard,
177                                                                         new Type [] {});
178                         ILGenerator ig = cons.GetILGenerator ();
179                         ig.Emit (OpCodes.Ldarg_0);
180                         ig.Emit (OpCodes.Call, typeof (Object).GetConstructor (new Type [] {}));
181                         ig.Emit (OpCodes.Ret);
182                 }
183
184                 internal static void emit_jscript_main_entry_point (TypeBuilder tb)
185                 {
186                         MethodBuilder method;
187                         method = tb.DefineMethod ("Main", 
188                                                   MethodAttributes.Public | MethodAttributes.Static,
189                                                   typeof (void), new Type [] {typeof (String [])});
190
191                         method.SetCustomAttribute (new CustomAttributeBuilder 
192                                                    (typeof (STAThreadAttribute).GetConstructor (
193                                                                                         new Type [] {}),
194                                                      new object [] {}));
195
196                         ILGenerator ig = method.GetILGenerator ();
197
198                         ig.DeclareLocal (typeof (GlobalScope));
199
200                         ig.Emit (OpCodes.Ldc_I4_1);
201                         ig.Emit (OpCodes.Ldc_I4_1);
202                         ig.Emit (OpCodes.Newarr, typeof (string));
203                         ig.Emit (OpCodes.Dup);
204                         ig.Emit (OpCodes.Ldc_I4_0);
205
206                         ig.Emit (OpCodes.Ldstr,
207                                  "mscorlib, Version=1.0.3300.0, Culture=neutral, Pub" + 
208                                  "licKeyToken=b77a5c561934e089");
209
210                         ig.Emit (OpCodes.Stelem_Ref);
211
212                         ig.Emit (OpCodes.Call,
213                                  typeof (VsaEngine).GetMethod ("CreateEngineAndGetGlobalScope", 
214                                                                new Type [] {typeof (bool), 
215                                                                             typeof (string [])}));      
216                         ig.Emit (OpCodes.Stloc_0);
217                         ig.Emit (OpCodes.Ldloc_0);
218                         
219                         ig.Emit (OpCodes.Newobj,
220                                  assembly_builder.GetType ("JScript 0").GetConstructor (
221                                                                         new Type [] {typeof (GlobalScope)})); 
222                         ig.Emit (OpCodes.Call, 
223                                  assembly_builder.GetType ("JScript 0").GetMethod (
224                                                                            "Global Code", new Type [] {}));
225                         ig.Emit (OpCodes.Pop);
226                         ig.Emit (OpCodes.Ret);
227
228                         assembly_builder.SetEntryPoint (method);
229                 }
230
231                 public static void Run (string file_name, AST prog)
232                 {
233                         CodeGenerator.Init (file_name);
234                         CodeGenerator.Emit (prog);
235                         CodeGenerator.Save (trim_extension (file_name) + ".exe");
236                 }       
237         }
238 }