Wed Jun 16 14:33:22 CEST 2004 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / driver.c
index ab4038f2dd5f1b91f4cfd9f83f4b7a965120509e..4e0ea2f90c279794eeb81c1b31cb66d2d14da0f1 100644 (file)
@@ -5,7 +5,8 @@
  *   Paolo Molaro (lupus@ximian.com)
  *   Dietmar Maurer (dietmar@ximian.com)
  *
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2003 Ximian, Inc.
+ * (C) 2003-2004 Novell, Inc.
  */
 
 #include <config.h>
@@ -33,6 +34,7 @@
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
+#include <mono/metadata/verify.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-debug-debugger.h>
 
@@ -75,7 +77,8 @@ opt_names [] = {
        {"fcmov",    "Fast x86 FP compares"},
        {"leaf",     "Leaf procedures optimizations"},
        {"aot",      "Usage of Ahead Of Time compiled code"},
-       {"precomp",  "Precompile all methods before executing Main"}
+       {"precomp",  "Precompile all methods before executing Main"},
+       {"abcrem",   "Array bound checks removal"}
 };
 
 #define DEFAULT_OPTIMIZATIONS (        \
@@ -84,8 +87,10 @@ opt_names [] = {
        MONO_OPT_BRANCH |       \
        MONO_OPT_LINEARS |      \
        MONO_OPT_INTRINS |  \
+       MONO_OPT_LOOP |  \
     MONO_OPT_AOT)
 
+
 static guint32
 parse_optimizations (const char* p)
 {
@@ -136,7 +141,7 @@ parse_optimizations (const char* p)
                                if (invert)
                                        opt = 0;
                                else
-                                       opt = ~(MONO_OPT_SHARED | MONO_OPT_PRECOMP | exclude);
+                                       opt = ~(MONO_OPT_SHARED | MONO_OPT_PRECOMP | MONO_OPT_ABCREM | exclude);
                                p += 3;
                                if (*p == ',')
                                        p++;
@@ -219,7 +224,8 @@ opt_sets [] = {
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP,
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_CFOLD,
        MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
-       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
+       MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM
 };
 
 typedef int (*TestMethod) (void);
@@ -264,7 +270,7 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
        }
 
        /* load the metadata */
-       for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+       for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                        method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                mono_class_init (method->klass);
 
@@ -285,13 +291,13 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                opt_flags = opt_sets [opt];
                mono_set_defaults (verbose, opt_flags);
                n = opt_descr (opt_flags);
-               g_print ("Test run: image=%s, opts=%s\n", image->name, n);
+               g_print ("Test run: image=%s, opts=%s\n", mono_image_get_filename (image), n);
                g_free (n);
                cfailed = failed = run = code_size = 0;
                comp_time = elapsed = 0.0;
 
                /* fixme: ugly hack - delete all previously compiled methods */
-               for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                        method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                        method->info = NULL;
                }
@@ -299,14 +305,14 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                g_timer_start (timer);
                if (mini_stats_fd)
                        fprintf (mini_stats_fd, "[");
-               for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                        method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                        if (strncmp (method->name, "test_", 5) == 0) {
                                expected = atoi (method->name + 5);
                                run++;
                                start_time = g_timer_elapsed (timer, NULL);
                                comp_time -= start_time; 
-                               cfg = mini_method_compile (method, opt_flags, mono_root_domain, 0);
+                               cfg = mini_method_compile (method, opt_flags, mono_root_domain, TRUE, 0);
                                comp_time += g_timer_elapsed (timer, NULL);
                                if (cfg) {
                                        if (verbose >= 2)
@@ -370,7 +376,7 @@ mini_regression_list (int verbose, int count, char *images [])
                        g_warning ("failed to load assembly: %s", images [i]);
                        continue;
                }
-               total += mini_regression (ass->image, verbose, &run);
+               total += mini_regression (mono_assembly_get_image (ass), verbose, &run);
                total_run += run;
                mono_assembly_close (ass);
        }
@@ -384,7 +390,7 @@ enum {
        DO_REGRESSION,
        DO_COMPILE,
        DO_EXEC,
-       DO_DRAW,
+       DO_DRAW
 };
 
 typedef struct CompileAllThreadArgs {
@@ -397,11 +403,11 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args)
 {
        MonoAssembly *ass = args->ass;
        int verbose = args->verbose;
-       MonoImage *image = ass->image;
+       MonoImage *image = mono_assembly_get_image (ass);
        MonoMethod *method;
        int i, count = 0;
 
-       for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+       for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
                        continue;
@@ -447,12 +453,12 @@ compile_all_methods (MonoAssembly *ass, int verbose)
 int 
 mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
 {
-       MonoImage *image = assembly->image;
+       MonoImage *image = mono_assembly_get_image (assembly);
        MonoMethod *method;
        guint32 entry = mono_image_get_entry_point (image);
 
        if (!entry) {
-               g_print ("Assembly '%s' doesn't have an entry point.\n", image->name);
+               g_print ("Assembly '%s' doesn't have an entry point.\n", mono_image_get_filename (image));
                /* FIXME: remove this silly requirement. */
                mono_environment_exitcode_set (1);
                return 1;
@@ -503,7 +509,7 @@ mini_usage (void)
 {
        int i;
 
-       fprintf (stderr,
+       fprintf (stdout,
                "Usage is: mono [options] assembly\n\n"
                "Runtime and JIT debugging:\n"
                "    --compile METHOD       Just compile METHOD in assembly\n"
@@ -515,7 +521,7 @@ mini_usage (void)
                "    --breakonex            Inserts a breakpoint on exceptions\n"
                "    --break METHOD         Inserts a breakpoint at METHOD entry\n"
                "    --debug                Enable debugging support\n"
-           "    --stats                Print statistics about the JIT operations\n"
+               "    --stats                Print statistics about the JIT operations\n"
                "\n"
                "Development:\n"
                "    --statfile FILE        Sets the stat file to FILE\n"
@@ -524,10 +530,10 @@ mini_usage (void)
                "    --graph[=TYPE] METHOD  Draws a graph of the specified method:\n");
        
        for (i = 0; i < G_N_ELEMENTS (graph_names); ++i) {
-               fprintf (stderr, "                           %-10s %s\n", graph_names [i].name, graph_names [i].desc);
+               fprintf (stdout, "                           %-10s %s\n", graph_names [i].name, graph_names [i].desc);
        }
 
-       fprintf (stderr,
+       fprintf (stdout,
                "\n"
                "Runtime:\n"
                "    --config FILE          Loads FILE as the Mono config\n"
@@ -537,13 +543,13 @@ mini_usage (void)
                "    --optimize=OPT         Turns on a specific optimization:\n");
 
        for (i = 0; i < G_N_ELEMENTS (opt_names); ++i)
-               fprintf (stderr, "                           %-10s %s\n", opt_names [i].name, opt_names [i].desc);
+               fprintf (stdout, "                           %-10s %s\n", opt_names [i].name, opt_names [i].desc);
 }
 
 static void
 mini_trace_usage (void)
 {
-       fprintf (stderr,
+       fprintf (stdout,
                 "Tracing options:\n"
                 "   --trace[=EXPR]        Trace every call, optional EXPR controls the scope\n"
                 "\n"
@@ -559,6 +565,37 @@ mini_trace_usage (void)
                 "    -EXPR                Excludes expression\n");
 }
 
+static const char *info = ""
+#ifdef HAVE_KW_THREAD
+       "\tTLS:           __thread\n"
+#else
+       "\tTLS:           normal\n"
+#endif /* HAVE_KW_THREAD */
+#ifdef HAVE_BOEHM_GC
+#ifdef USE_INCLUDED_LIBGC
+       "\tGC:            Included Boehm (with typed GC)\n"
+#else
+#if HAVE_GC_GCJ_MALLOC
+       "\tGC:            System Boehm (with typed GC)\n"
+#else
+       "\tGC:            System Boehm (no typed GC available)\n"
+#endif
+#endif
+#else
+       "\tGC:            none\n"
+#endif /* HAVE_BOEHM_GC */
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+    "\tSIGSEGV      : altstack\n"
+#else
+    "\tSIGSEGV      : normal\n"
+#endif
+#ifdef HAVE_ICU
+       "\tGlobalization: ICU\n"
+#else
+       "\tGlobalization: none\n"
+#endif /* HAVE_ICU */
+       "";
+
 int
 mono_main (int argc, char* argv[])
 {
@@ -591,7 +628,21 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--verbose") == 0 || strcmp (argv [i], "-v") == 0) {
                        mini_verbose++;
                } else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) {
-                       g_print ("Mono JIT compiler version %s, (C) 2002, 2003 Ximian, Inc.\n", VERSION);
+                       g_print ("Mono JIT compiler version %s, (C) 2002-2004 Novell, Inc and Contributors. www.go-mono.com\n", VERSION);
+                       g_print (info);
+                       if (mini_verbose) {
+                               const guchar *cerror;
+                               const guchar *clibpath;
+                               mono_init ("mono");
+                               cerror = mono_check_corlib_version ();
+                               clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
+                               if (cerror) {
+                                       g_print ("The currently installed mscorlib doesn't match this runtime version.\n");
+                                       g_print ("The error is: %s\n", cerror);
+                                       g_print ("mscorlib.dll loaded at: %s\n", clibpath);
+                                       return 1;
+                               }
+                       }
                        return 0;
                } else if (strcmp (argv [i], "--help") == 0 || strcmp (argv [i], "-h") == 0) {
                        mini_usage ();
@@ -708,6 +759,11 @@ mono_main (int argc, char* argv[])
        if (enable_debugging)
                mono_debug_init (domain, MONO_DEBUG_FORMAT_MONO);
 
+       /* Parse gac loading options before loading assemblies. */
+       if (mono_compile_aot || action == DO_EXEC) {
+               mono_config_parse (config_file);
+       }
+
        assembly = mono_assembly_open (aname, NULL);
        if (!assembly) {
                fprintf (stderr, "cannot open assembly %s\n", aname);
@@ -725,9 +781,17 @@ mono_main (int argc, char* argv[])
                mono_debug_init_2 (assembly);
 
        if (mono_compile_aot || action == DO_EXEC) {
-               mono_config_parse (config_file);
+               const guchar *error;
+
                //mono_set_rootdir ();
 
+               error = mono_check_corlib_version ();
+               if (error) {
+                       fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
+                       fprintf (stderr, "Download a newer corlib or a newer runtime at http://www.go-mono.com/daily.\n");
+                       exit (1);
+               }
+
                main_args.domain = domain;
                main_args.file = aname;         
                main_args.argc = argc - i;
@@ -736,6 +800,7 @@ mono_main (int argc, char* argv[])
             
                mono_runtime_exec_managed_code (domain, main_thread_handler, &main_args);
                mini_cleanup (domain);
+
                /* Look up return value from System.Environment.ExitCode */
                i = mono_environment_exitcode_get ();
                return i;
@@ -750,7 +815,7 @@ mono_main (int argc, char* argv[])
                mini_cleanup (domain);
                return 3;
        }
-       method = mono_method_desc_search_in_image (desc, assembly->image);
+       method = mono_method_desc_search_in_image (desc, mono_assembly_get_image (assembly));
        if (!method) {
                g_print ("Cannot find method %s\n", mname);
                mini_cleanup (domain);
@@ -778,7 +843,7 @@ mono_main (int argc, char* argv[])
                        break;
                }
 
-               cfg = mini_method_compile (method, opt, mono_root_domain, part);
+               cfg = mini_method_compile (method, opt, mono_root_domain, FALSE, part);
                if ((mono_graph_options & MONO_GRAPH_CFG_SSA) && !(cfg->comp_done & MONO_COMP_SSA)) {
                        g_warning ("no SSA info available (use -O=deadce)");
                        return 1;
@@ -810,7 +875,7 @@ mono_main (int argc, char* argv[])
                                opt = opt_sets [i];
                                g_timer_start (timer);
                                for (j = 0; j < count; ++j) {
-                                       cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+                                       cfg = mini_method_compile (method, opt, mono_root_domain, FALSE, 0);
                                        mono_destroy_compile (cfg);
                                }
                                g_timer_stop (timer);
@@ -833,12 +898,12 @@ mono_main (int argc, char* argv[])
                                        (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                                        method = mono_marshal_get_native_wrapper (method);
 
-                               cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+                               cfg = mini_method_compile (method, opt, mono_root_domain, FALSE, 0);
                                mono_destroy_compile (cfg);
                        }
                }
        } else {
-               cfg = mini_method_compile (method, opt, mono_root_domain, 0);
+               cfg = mini_method_compile (method, opt, mono_root_domain, FALSE, 0);
                mono_destroy_compile (cfg);
        }