2002-05-22 Martin Baulig <martin@gnome.org>
[mono.git] / mono / jit / mono.c
1 /*
2  * mono.c: Main driver for the Mono JIT engine
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
8  */
9 #include "jit.h"
10 #include "regset.h"
11 #include "codegen.h"
12 #include "debug.h"
13 #include "mono/metadata/debug-helpers.h"
14 #include "mono/metadata/verify.h"
15 #include "mono/metadata/profiler.h"
16 #include <mono/os/util.h>
17
18 /**
19  * mono_jit_image:
20  * @image: reference to an image
21  * @verbose: If true, print debugging information on stdout.
22  *
23  * JIT compilation of all methods in the image.
24  */
25 void
26 mono_jit_compile_image (MonoImage *image, int verbose)
27 {
28         MonoMethod *method;
29         MonoTableInfo *t = &image->tables [MONO_TABLE_METHOD];
30         int i;
31
32         for (i = 0; i < t->rows; i++) {
33
34                 method = mono_get_method (image, 
35                                           (MONO_TABLE_METHOD << 24) | (i + 1), 
36                                           NULL);
37
38                 if (verbose)
39                         g_print ("Compiling: %s:%s\n\n", image->assembly_name, method->name);
40
41                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) {
42                         if (verbose)
43                                 printf ("ABSTARCT\n");
44                 } else
45                         arch_compile_method (method);
46
47         }
48
49 }
50
51 static MonoClass *
52 find_class_in_assembly (MonoAssembly *assembly, const char *namespace, const char *name)
53 {
54         MonoAssembly **ptr;
55         MonoClass *class;
56
57         class = mono_class_from_name (assembly->image, namespace, name);
58         if (class)
59                 return class;
60
61         for (ptr = assembly->image->references; ptr && *ptr; ptr++) {
62                 class = find_class_in_assembly (*ptr, namespace, name);
63                 if (class)
64                         return class;
65         }
66
67         return NULL;
68 }
69
70 static MonoMethod *
71 find_method_in_assembly (MonoAssembly *assembly, MonoMethodDesc *mdesc)
72 {
73         MonoAssembly **ptr;
74         MonoMethod *method;
75
76         method = mono_method_desc_search_in_image (mdesc, assembly->image);
77         if (method)
78                 return method;
79
80         for (ptr = assembly->image->references; ptr && *ptr; ptr++) {
81                 method = find_method_in_assembly (*ptr, mdesc);
82                 if (method)
83                         return method;
84         }
85
86         return NULL;
87 }
88
89 /**
90  * mono_jit_compile_class:
91  * @assembly: Lookup things in this assembly
92  * @compile_class: Name of the image/class/method to compile
93  * @compile_times: Compile it that many times
94  * @verbose: If true, print debugging information on stdout.
95  *
96  * JIT compilation of the image/class/method.
97  *
98  * @compile_class can be one of:
99  *
100  * - an image name (`@corlib')
101  * - a class name (`System.Int32')
102  * - a method name (`System.Int32:Parse')
103  */
104 void
105 mono_jit_compile_class (MonoAssembly *assembly, char *compile_class,
106                         int compile_times, int verbose)
107 {
108         const char *cmethod = strrchr (compile_class, ':');
109         char *cname;
110         char *code;
111         int i, j;
112         MonoClass *class;
113
114         if (compile_class [0] == '@') {
115                 MonoImage *image = mono_image_loaded (compile_class + 1);
116                 if (!image)
117                         g_error ("Cannot find image %s", compile_class + 1);
118                 if (verbose)
119                         g_print ("Compiling image %s\n", image->name);
120                 for (j = 0; j < compile_times; ++j)
121                         mono_jit_compile_image (image, verbose);
122         } else if (cmethod) {
123                 MonoMethodDesc *mdesc;
124                 MonoMethod *m;
125                 mdesc = mono_method_desc_new (compile_class, FALSE);
126                 if (!mdesc)
127                         g_error ("Invalid method name '%s'", compile_class);
128                 m = find_method_in_assembly (assembly, mdesc);
129                 if (!m)
130                         g_error ("Cannot find method '%s'", compile_class);
131                 for (j = 0; j < compile_times; ++j) {
132                         code = arch_compile_method (m);
133                         // g_free (code);
134                 }
135         } else {
136                 cname = strrchr (compile_class, '.');
137                 if (cname)
138                         *cname++ = 0;
139                 else {
140                         cname = compile_class;
141                         compile_class = (char *)"";
142                 }
143                 class = find_class_in_assembly (assembly, compile_class, cname);
144                 if (!class)
145                         g_error ("Cannot find class %s.%s", compile_class, cname);
146                 mono_class_init (class);
147                 for (j = 0; j < compile_times; ++j) {
148                         for (i = 0; i < class->method.count; ++i) {
149                                 if (class->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
150                                         continue;
151                                 if (class->methods [i]->flags & METHOD_ATTRIBUTE_ABSTRACT)
152                                         continue;
153                                 if (verbose)
154                                         g_print ("Compiling: %s.%s:%s\n",
155                                                  compile_class, cname, class->methods [i]->name);
156                                 code = arch_compile_method (class->methods [i]);
157                                 // g_free (code);
158                         }
159                 }
160         }
161 }
162
163 static void
164 usage (char *name)
165 {
166         fprintf (stderr,
167                  "%s %s, the Mono ECMA CLI JIT Compiler, (C) 2001, 2002 Ximian, Inc.\n\n"
168                  "Usage is: %s [options] executable args...\n\n", name,  VERSION, name);
169         fprintf (stderr,
170                  "Runtime Debugging:\n"
171                  "    -d                 debug the jit, show disassembler output.\n"
172                  "    --dump-asm         dumps the assembly code generated\n"
173                  "    --dump-forest      dumps the reconstructed forest\n"
174                  "    --print-vtable     print the VTable of all used classes\n"
175                  "    --stats            print statistics about the jit operations\n"
176                  "    --trace            printf function call trace\n"
177                  "    --compile NAME     compile NAME, then exit.\n"
178                  "                       NAME is in one of the following formats:\n"
179                  "                         namespace.name          compile the given class\n"
180                  "                         namespace.name:method   compile the given method\n"
181                  "                         @imagename              compile the given image\n"
182                  "    --ncompile NUM     compile methods NUM times (default: 1000)\n"
183                  "\n"
184                  "Development:\n"
185                  "    --debug[=FORMAT]   write a debugging file.  FORMAT is one of:\n"
186                  "                         stabs        to write stabs information\n"
187                  "                         dwarf        to write dwarf2 information\n"
188                  "                         dwarf-plus   to write extended dwarf2 information\n"
189                  "    --debug-args ARGS  comma-separated list of additional arguments for the\n"
190                  "                       symbol writer.  See the manpage for details.\n"
191                  "    --profile          record and dump profile info\n"
192                  "    --break NAME       insert a breakpoint at the start of method NAME\n"
193                  "                       (NAME is in `namespace.name:methodname' format)\n"
194                  "    --precomile name   precompile NAME before executing the main application:\n"
195                  "                       NAME is in one of the following formats:\n"
196                  "                         namespace.name          compile the given class\n"
197                  "                         namespace.name:method   compile the given method\n"
198                  "                         @imagename              compile the given image\n"
199                  "\n"
200                  "Runtime:\n"
201                  "    --fast-iconv       Use fast floating point integer conversion\n"
202                  "    --noinline         Disable code inliner\n"
203                  "    --nols             disable linear scan register allocation\n"
204                  "    --share-code       force jit to produce shared code\n"
205                  "    --workers n        maximum number of worker threads\n"
206                 );
207         exit (1);
208 }
209
210 int 
211 main (int argc, char *argv [])
212 {
213         MonoDomain *domain;
214         MonoAssembly *assembly;
215         int retval = 0, i;
216         int compile_times = 1000;
217         char *compile_class = NULL;
218         char *debug_args = NULL;
219         char *file, *error;
220         gboolean testjit = FALSE;
221         int stack, verbose = FALSE;
222         GList *precompile_classes = NULL;
223
224         g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
225         g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
226         
227         if (argc < 2)
228                 usage (argv [0]);
229
230         for (i = 1; i < argc && argv [i][0] == '-'; i++){
231                 if (strcmp (argv [i], "--help") == 0) {
232                         usage (argv [0]);
233                 } else if (strcmp (argv [i], "-d") == 0) {
234                         testjit = TRUE;
235                         mono_jit_dump_asm = TRUE;
236                         mono_jit_dump_forest = TRUE;
237                 } else if (strcmp (argv [i], "--dump-asm") == 0)
238                         mono_jit_dump_asm = TRUE;
239                 else if (strcmp (argv [i], "--dump-forest") == 0)
240                         mono_jit_dump_forest = TRUE;
241                 else if (strcmp (argv [i], "--trace") == 0)
242                         mono_jit_trace_calls = TRUE;
243                 else if (strcmp (argv [i], "--share-code") == 0)
244                         mono_jit_share_code = TRUE;
245                 else if (strcmp (argv [i], "--noinline") == 0)
246                         mono_jit_inline_code = FALSE;
247                 else if (strcmp (argv [i], "--nols") == 0)
248                         mono_use_linear_scan = FALSE;
249                 else if (strcmp (argv [i], "--print-vtable") == 0)
250                         mono_print_vtable = TRUE;
251                 else if (strcmp (argv [i], "--break") == 0) {
252                         MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
253                         if (!desc)
254                                 g_error ("Invalid method name '%s'", argv [i]);
255                         mono_debug_methods = g_list_append (mono_debug_methods, desc);
256                 } else if (strcmp (argv [i], "--count") == 0) {
257                         compile_times = atoi (argv [++i]);
258                 } else if (strcmp (argv [i], "--workers") == 0) {
259                         mono_worker_threads = atoi (argv [++i]);
260                         if (mono_worker_threads < 1)
261                                 mono_worker_threads = 1;
262                 } else if (strcmp (argv [i], "--profile") == 0) {
263                         mono_jit_profile = TRUE;
264                         mono_profiler_install_simple ();
265                 } else if (strcmp (argv [i], "--compile") == 0) {
266                         compile_class = argv [++i];
267                 } else if (strcmp (argv [i], "--ncompile") == 0) {
268                         compile_times = atoi (argv [++i]);
269                 } else if (strcmp (argv [i], "--stats") == 0) {
270                         memset (&mono_jit_stats, 0, sizeof (MonoJitStats));
271                         mono_jit_stats.enabled = TRUE;
272                 } else if (strncmp (argv [i], "--debug", 7) == 0) {
273                         if (argv [i][7] == '='){
274                                 const char *format = &argv [i][8];
275                                 
276                                 if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
277                                         g_error ("You can only use one debugging format.");
278                                 if (strcmp (format, "stabs") == 0)
279                                         mono_debug_format = MONO_DEBUG_FORMAT_STABS;
280                                 else if (strcmp (format, "dwarf") == 0)
281                                         mono_debug_format = MONO_DEBUG_FORMAT_DWARF2;
282                                 else if (strcmp (format, "dwarf-plus") == 0)
283                                         mono_debug_format = MONO_DEBUG_FORMAT_DWARF2_PLUS;
284                                 else
285                                         g_error ("Unknown debugging format: %s", argv [i]);
286                         } else
287                                 mono_debug_format = MONO_DEBUG_FORMAT_DWARF2_PLUS;
288                 } else if (strcmp (argv [i], "--debug-args") == 0) {
289                         if (debug_args)
290                                 g_error ("You can use --debug-args only once.");
291                         debug_args = argv [++i];
292                 } else if (strcmp (argv [i], "--precompile") == 0) {
293                         precompile_classes = g_list_append (precompile_classes, argv [++i]);
294                 } else if (strcmp (argv [i], "--verbose") == 0) {
295                         verbose = TRUE;;
296                 } else if (strcmp (argv [i], "--fast-iconv") == 0) {
297                         mono_use_fast_iconv = TRUE;
298                 } else
299                         usage (argv [0]);
300         }
301         
302         file = argv [i];
303
304         if (!file)
305                 usage (argv [0]);
306
307         mono_set_rootdir (argv [0]);
308         domain = mono_jit_init (file);
309
310         error = mono_verify_corlib ();
311         if (error) {
312                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
313                 exit (1);
314         }
315
316         assembly = mono_domain_assembly_open (domain, file);
317         if (!assembly){
318                 fprintf (stderr, "Can not open image %s\n", file);
319                 exit (1);
320         }
321
322         if (mono_debug_format != MONO_DEBUG_FORMAT_NONE) {
323                 gchar **args;
324
325                 args = g_strsplit (debug_args ? debug_args : "", ",", -1);
326                 mono_debug_open (assembly, mono_debug_format, (const char **) args);
327                 g_strfreev (args);
328         }
329
330         if (testjit) {
331                 mono_jit_compile_image (assembly->image, TRUE);
332         } else if (compile_class) {
333                 mono_jit_compile_class (assembly, compile_class, compile_times, TRUE);
334         } else {
335                 GList *tmp;
336
337                 for (tmp = precompile_classes; tmp; tmp = tmp->next)
338                         mono_jit_compile_class (assembly, tmp->data, 1, verbose);
339
340                 retval = mono_jit_exec (domain, assembly, argc - i, argv + i);
341                 printf ("RESULT: %d\n", retval);
342         }
343
344         mono_profiler_shutdown ();
345         mono_jit_cleanup (domain);
346
347         return retval;
348 }
349
350