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