5 // Cesar Lopez Nataren (cesar@ciencias.unam.mx)
7 // (C) 2003, Cesar Lopez Nataren
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Threading;
14 using Microsoft.JScript.Vsa;
15 using System.Runtime.CompilerServices;
17 namespace Microsoft.JScript {
19 internal class EmitContext {
21 internal TypeBuilder type_builder;
22 internal ILGenerator ig;
23 internal ModuleBuilder mod_builder;
25 internal EmitContext (TypeBuilder type)
29 if (type_builder != null) {
30 MethodBuilder global_code = type_builder.DefineMethod (
32 MethodAttributes.Public,
33 typeof (System.Object),
35 ig = global_code.GetILGenerator ();
39 internal EmitContext (TypeBuilder type_builder, ModuleBuilder mod_builder, ILGenerator ig)
41 this.type_builder = type_builder;
42 this.mod_builder = mod_builder;
47 public class CodeGenerator {
49 private static string MODULE = "JScript Module";
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;
57 internal static void Init (string file_name)
59 app_domain = Thread.GetDomain ();
61 assembly_name = new AssemblyName ();
62 assembly_name.Name = trim_extension (file_name);
66 assembly_builder = app_domain.DefineDynamicAssembly (
68 AssemblyBuilderAccess.RunAndSave);
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);
75 module_builder = assembly_builder.DefineDynamicModule (
77 assembly_name.Name + ".exe",
81 internal static string trim_extension (string file_name)
83 int index = file_name.LastIndexOf ('.');
88 return file_name.Substring (0, index);
91 internal static void Save (string target_name)
93 assembly_builder.Save (target_name);
96 internal static void Emit (AST prog)
101 TypeBuilder type_builder;
102 type_builder = module_builder.DefineType ("JScript 0", TypeAttributes.Public);
104 type_builder.SetParent (typeof (GlobalScope));
105 type_builder.SetCustomAttribute (new CustomAttributeBuilder
106 (typeof (CompilerGlobalScopeAttribute).GetConstructor (new Type [] {}), new object [] {}));
108 EmitContext ec = new EmitContext (type_builder);
109 ec.mod_builder = module_builder;
110 ILGenerator global_code = ec.ig;
112 emit_default_script_constructor (ec);
113 emit_default_init_global_code (global_code);
115 emit_default_end_global_code (global_code);
116 ec.type_builder.CreateType ();
119 // Build the default 'JScript Main' class
121 ec.type_builder = module_builder.DefineType ("JScript Main");
122 emit_jscript_main (ec.type_builder);
123 ec.type_builder.CreateType ();
126 internal static void emit_default_init_global_code (ILGenerator ig)
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)}));
136 internal static void emit_default_end_global_code (ILGenerator ig)
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);
146 internal static void emit_default_script_constructor (EmitContext ec)
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) });
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"));
161 ig.Emit (OpCodes.Call,
162 typeof (GlobalScope).GetConstructor (new Type [] {typeof (GlobalScope),
163 typeof (VsaEngine)}));
164 ig.Emit (OpCodes.Ret);
167 internal static void emit_jscript_main (TypeBuilder tb)
169 emit_jscript_main_constructor (tb);
170 emit_jscript_main_entry_point (tb);
173 internal static void emit_jscript_main_constructor (TypeBuilder tb)
175 ConstructorBuilder cons = tb.DefineConstructor (MethodAttributes.Public,
176 CallingConventions.Standard,
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);
184 internal static void emit_jscript_main_entry_point (TypeBuilder tb)
186 MethodBuilder method;
187 method = tb.DefineMethod ("Main",
188 MethodAttributes.Public | MethodAttributes.Static,
189 typeof (void), new Type [] {typeof (String [])});
191 method.SetCustomAttribute (new CustomAttributeBuilder
192 (typeof (STAThreadAttribute).GetConstructor (
196 ILGenerator ig = method.GetILGenerator ();
198 ig.DeclareLocal (typeof (GlobalScope));
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);
206 ig.Emit (OpCodes.Ldstr,
207 "mscorlib, Version=1.0.3300.0, Culture=neutral, Pub" +
208 "licKeyToken=b77a5c561934e089");
210 ig.Emit (OpCodes.Stelem_Ref);
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);
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);
228 assembly_builder.SetEntryPoint (method);
231 public static void Run (string file_name, AST prog)
233 CodeGenerator.Init (file_name);
234 CodeGenerator.Emit (prog);
235 CodeGenerator.Save (trim_extension (file_name) + ".exe");