* roottypes.cs: Rename from tree.cs.
[mono.git] / mono / mini / driver.c
index 34b7d4ea398d51a6b535ec443e77377f15db82f3..58f900e7bc0f44b46e1bbb508208ca4c7220bf89 100644 (file)
@@ -6,7 +6,7 @@
  *   Dietmar Maurer (dietmar@ximian.com)
  *
  * (C) 2002-2003 Ximian, Inc.
- * (C) 2003-2004 Novell, Inc.
+ * (C) 2003-2006 Novell, Inc.
  */
 
 #include <config.h>
@@ -36,9 +36,9 @@
 #include <mono/metadata/environment.h>
 #include <mono/metadata/verify.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-debug-debugger.h>
 #include <mono/metadata/security-manager.h>
 #include <mono/os/gc_wrapper.h>
+#include "mono/utils/mono-counters.h"
 
 #include "mini.h"
 #include "jit.h"
@@ -51,6 +51,15 @@ static FILE *mini_stats_fd = NULL;
 
 static void mini_usage (void);
 
+extern int mini_wapi_hps (int argc, char **argv);
+extern int mini_wapi_semdel (int argc, char **argv);
+extern int mini_wapi_seminfo (int argc, char **argv);
+
+/* This turns off command line globbing under win32 */
+#ifdef PLATFORM_WIN32
+int _CRT_glob = 0;
+#endif
+
 typedef void (*OptFunc) (const char *p);
 
 /* keep in sync with enum in mini.h */
@@ -62,35 +71,44 @@ typedef struct {
 
 static const OptName 
 opt_names [] = {
-       {"peephole", "Peephole postpass"},
-       {"branch",   "Branch optimizations"},
-       {"inline",   "Inline method calls"},
-       {"cfold",    "Constant folding"},
-       {"consprop", "Constant propagation"},
-       {"copyprop", "Copy propagation"},
-       {"deadce",   "Dead code elimination"},
-       {"linears",  "Linear scan global reg allocation"},
-       {"cmov",     "Conditional moves"},
-       {"shared",   "Emit per-domain code"},
-       {"sched",    "Instruction scheduling"},
-       {"intrins",  "Intrinsic method implementations"},
-       {"tailc",    "Tail recursion and tail calls"},
-       {"loop",     "Loop related optimizations"},
-       {"fcmov",    "Fast x86 FP compares"},
-       {"leaf",     "Leaf procedures optimizations"},
-       {"aot",      "Usage of Ahead Of Time compiled code"},
-       {"precomp",  "Precompile all methods before executing Main"},
-       {"abcrem",   "Array bound checks removal"},     
-       {"ssapre",   "SSA based Partial Redundancy Elimination"}
+       {"peephole",   "Peephole postpass"},
+       {"branch",     "Branch optimizations"},
+       {"inline",     "Inline method calls"},
+       {"cfold",      "Constant folding"},
+       {"consprop",   "Constant propagation"},
+       {"copyprop",   "Copy propagation"},
+       {"deadce",     "Dead code elimination"},
+       {"linears",    "Linear scan global reg allocation"},
+       {"cmov",       "Conditional moves"},
+       {"shared",     "Emit per-domain code"},
+       {"sched",      "Instruction scheduling"},
+       {"intrins",    "Intrinsic method implementations"},
+       {"tailc",      "Tail recursion and tail calls"},
+       {"loop",       "Loop related optimizations"},
+       {"fcmov",      "Fast x86 FP compares"},
+       {"leaf",       "Leaf procedures optimizations"},
+       {"aot",        "Usage of Ahead Of Time compiled code"},
+       {"precomp",    "Precompile all methods before executing Main"},
+       {"abcrem",     "Array bound checks removal"},   
+       {"ssapre",     "SSA based Partial Redundancy Elimination"},
+       {"exception",  "Optimize exception catch blocks"},
+       {"ssa",        "Use plain SSA form"},
+       {"treeprop",   "Tree propagation"}
 };
 
 #define DEFAULT_OPTIMIZATIONS (        \
        MONO_OPT_PEEPHOLE |     \
        MONO_OPT_CFOLD |        \
+       MONO_OPT_INLINE |       \
+       MONO_OPT_CONSPROP |     \
+       MONO_OPT_COPYPROP |     \
+       MONO_OPT_TREEPROP |     \
+       MONO_OPT_DEADCE |       \
        MONO_OPT_BRANCH |       \
        MONO_OPT_LINEARS |      \
        MONO_OPT_INTRINS |  \
        MONO_OPT_LOOP |  \
+       MONO_OPT_EXCEPTION |  \
        MONO_OPT_AOT)
 
 #define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
@@ -229,7 +247,12 @@ opt_sets [] = {
        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_SSA,
+       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_EXCEPTION,
+       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_EXCEPTION | MONO_OPT_ABCREM,
+       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_EXCEPTION | MONO_OPT_ABCREM | MONO_OPT_SSAPRE,
        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,
+       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_TREEPROP,
        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_SSAPRE,
        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 | MONO_OPT_SHARED
 };
@@ -305,6 +328,8 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                /* fixme: ugly hack - delete all previously compiled methods */
                g_hash_table_destroy (mono_domain_get ()->jit_trampoline_hash);
                mono_domain_get ()->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+               g_hash_table_destroy (mono_domain_get ()->jit_code_hash);
+               mono_domain_get ()->jit_code_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
                g_timer_start (timer);
                if (mini_stats_fd)
@@ -318,7 +343,7 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                                comp_time -= start_time; 
                                cfg = mini_method_compile (method, opt_flags, mono_get_root_domain (), TRUE, FALSE, 0);
                                comp_time += g_timer_elapsed (timer, NULL);
-                               if (cfg) {
+                               if (cfg->exception_type == MONO_EXCEPTION_NONE) {
                                        if (verbose >= 2)
                                                g_print ("Running '%s' ...\n", method->name);
 #ifdef MONO_USE_AOT_COMPILER
@@ -326,12 +351,12 @@ mini_regression (MonoImage *image, int verbose, int *total_run) {
                                                func = jinfo->code_start;
                                        else
 #endif
-                                               func = (TestMethod)cfg->native_code;
+                                               func = (TestMethod)(gpointer)cfg->native_code;
+                                       func = (TestMethod)mono_create_ftnptr (mono_get_root_domain (), func);
                                        result = func ();
                                        if (result != expected) {
                                                failed++;
-                                               if (verbose)
-                                                       g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
+                                               g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
                                        }
                                        code_size += cfg->code_len;
                                        mono_destroy_compile (cfg);
@@ -393,12 +418,14 @@ enum {
        DO_REGRESSION,
        DO_COMPILE,
        DO_EXEC,
-       DO_DRAW
+       DO_DRAW,
+       DO_DEBUGGER
 };
 
 typedef struct CompileAllThreadArgs {
        MonoAssembly *ass;
        int verbose;
+       guint32 opts;
 } CompileAllThreadArgs;
 
 static void
@@ -437,19 +464,20 @@ compile_all_methods_thread_main (CompileAllThreadArgs *args)
                        g_print ("Compiling %d %s\n", count, desc);
                        g_free (desc);
                }
-               cfg = mini_method_compile (method, DEFAULT_OPTIMIZATIONS, mono_get_root_domain (), FALSE, FALSE, 0);
+               cfg = mini_method_compile (method, args->opts, mono_get_root_domain (), FALSE, FALSE, 0);
                mono_destroy_compile (cfg);
        }
 
 }
 
 static void
-compile_all_methods (MonoAssembly *ass, int verbose)
+compile_all_methods (MonoAssembly *ass, int verbose, guint32 opts)
 {
        CompileAllThreadArgs args;
 
        args.ass = ass;
        args.verbose = verbose;
+       args.opts = opts;
 
        /* 
         * Need to create a mono thread since compilation might trigger
@@ -483,7 +511,12 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[
        }
 
        method = mono_get_method (image, entry, NULL);
-
+       if (method == NULL){
+               g_print ("The entry point method could not be loaded\n");
+               mono_environment_exitcode_set (1);
+               return 1;
+       }
+       
        return mono_runtime_run_main (method, argc, argv, NULL);
 }
 
@@ -539,6 +572,7 @@ mini_usage_jitdeveloper (void)
                 "    --regression           Runs the regression test contained in the assembly\n"
                 "    --statfile FILE        Sets the stat file to FILE\n"
                 "    --stats                Print statistics about the JIT operations\n"
+                "    --wapi=hps|semdel      IO-layer maintenance\n"
                 "\n"
                 "Other options:\n" 
                 "    --graph[=TYPE] METHOD  Draws a graph of the specified method:\n");
@@ -596,38 +630,23 @@ mini_trace_usage (void)
                 "    N:Namespace          Specifies a namespace\n"
                 "    T:Type               Specifies a type\n"
                 "    +EXPR                Includes expression\n"
-                "    -EXPR                Excludes expression\n");
+                "    -EXPR                Excludes expression\n"
+                "    disabled             Don't print any output until toggled via SIGUSR2\n");
 }
 
-static const char *info = ""
+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 */
+       "\tGC:            " USED_GC_NAME "\n"
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-    "\tSIGSEGV      : altstack\n"
+    "\tSIGSEGV:       altstack\n"
 #else
-    "\tSIGSEGV      : normal\n"
+    "\tSIGSEGV:       normal\n"
 #endif
-#ifdef HAVE_ICU
-       "\tGlobalization: ICU\n"
-#else
-       "\tGlobalization: none\n"
-#endif /* HAVE_ICU */
+       "\tDisabled:      " DISABLED_FEATURES "\n"
        "";
 
 int
@@ -682,11 +701,11 @@ 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-2004 Novell, Inc and Contributors. www.go-mono.com\n", VERSION);
+                       g_print ("Mono JIT compiler version %s, (C) 2002-2006 Novell, Inc and Contributors. www.mono-project.com\n", VERSION);
                        g_print (info);
                        if (mini_verbose) {
-                               const guchar *cerror;
-                               const guchar *clibpath;
+                               const char *cerror;
+                               const char *clibpath;
                                mono_init ("mono");
                                cerror = mono_check_corlib_version ();
                                clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
@@ -711,14 +730,26 @@ mono_main (int argc, char* argv[])
                        mini_usage_list_opt ();
                        return 0;
                } else if (strncmp (argv [i], "--statfile", 10) == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --statfile requires a filename argument\n");
+                               return 1;
+                       }
                        mini_stats_fd = fopen (argv [++i], "w+");
                } else if (strncmp (argv [i], "--optimize=", 11) == 0) {
                        opt = parse_optimizations (argv [i] + 11);
                } else if (strncmp (argv [i], "-O=", 3) == 0) {
                        opt = parse_optimizations (argv [i] + 3);
                } else if (strcmp (argv [i], "--config") == 0) {
+                       if (i +1 >= argc){
+                               fprintf (stderr, "error: --config requires a filename argument\n");
+                               return 1;
+                       }
                        config_file = argv [++i];
                } else if (strcmp (argv [i], "--ncompile") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --ncompile requires an argument\n");
+                               return 1;
+                       }
                        count = atoi (argv [++i]);
                        action = DO_BENCH;
                } else if (strcmp (argv [i], "--trace") == 0) {
@@ -728,11 +759,17 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--breakonex") == 0) {
                        mono_break_on_exc = TRUE;
                } else if (strcmp (argv [i], "--break") == 0) {
+                       if (i+1 >= argc){
+                               fprintf (stderr, "Missing method name in --break command line option\n");
+                               return 1;
+                       }
+                       
                        if (!mono_debugger_insert_breakpoint (argv [++i], FALSE))
-                               g_error ("Invalid method name '%s'", argv [i]);
+                               fprintf (stderr, "Error: invalid method name '%s'\n", argv [i]);
                } else if (strcmp (argv [i], "--print-vtable") == 0) {
                        mono_print_vtable = TRUE;
                } else if (strcmp (argv [i], "--stats") == 0) {
+                       mono_counters_enable (-1);
                        mono_stats.enabled = TRUE;
                        mono_jit_stats.enabled = TRUE;
 #ifndef DISABLE_AOT
@@ -751,13 +788,28 @@ mono_main (int argc, char* argv[])
                        enable_profile = TRUE;
                        profile_options = argv [i] + 10;
                } else if (strcmp (argv [i], "--compile") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --compile option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mname = argv [++i];
                        action = DO_BENCH;
                } else if (strncmp (argv [i], "--graph=", 8) == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --graph option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mono_graph_options = mono_parse_graph_options (argv [i] + 8);
                        mname = argv [++i];
                        action = DO_DRAW;
                } else if (strcmp (argv [i], "--graph") == 0) {
+                       if (i + 1 >= argc){
+                               fprintf (stderr, "error: --graph option requires a method name argument\n");
+                               return 1;
+                       }
+                       
                        mname = argv [++i];
                        mono_graph_options = MONO_GRAPH_CFG;
                        action = DO_DRAW;
@@ -766,6 +818,26 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--security") == 0) {
                        mono_use_security_manager = TRUE;
                        mono_activate_security_manager ();
+               } else if (strcmp (argv [i], "--desktop") == 0) {
+#if defined (HAVE_BOEHM_GC)
+                       GC_dont_expand = 1;
+#endif
+                       /* Put desktop-specific optimizations here */
+               } else if (strcmp (argv [i], "--server") == 0){
+                       /* Put server-specific optimizations here */
+               } else if (strcmp (argv [i], "--inside-mdb") == 0) {
+                       action = DO_DEBUGGER;
+               } else if (strncmp (argv [i], "--wapi=", 7) == 0) {
+                       if (strcmp (argv [i] + 7, "hps") == 0) {
+                               return mini_wapi_hps (argc - i, argv + i);
+                       } else if (strcmp (argv [i] + 7, "semdel") == 0) {
+                               return mini_wapi_semdel (argc - i, argv + i);
+                       } else if (strcmp (argv [i] + 7, "seminfo") == 0) {
+                               return mini_wapi_seminfo (argc - i, argv + i);
+                       } else {
+                               fprintf (stderr, "Invalid --wapi suboption: '%s'\n", argv [i]);
+                               return 1;
+                       }
                } else {
                        fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
                        return 1;
@@ -777,7 +849,10 @@ mono_main (int argc, char* argv[])
                return 1;
        }
 
-       if (mono_compile_aot || action == DO_EXEC) {
+       if ((action == DO_EXEC) && g_getenv ("MONO_INSIDE_MDB"))
+               action = DO_DEBUGGER;
+
+       if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) {
                g_set_prgname (argv[i]);
        }
 
@@ -797,6 +872,22 @@ mono_main (int argc, char* argv[])
                        exit (1);
        }
 
+       if (action == DO_DEBUGGER) {
+               opt |= MONO_OPT_SHARED;
+               opt &= ~MONO_OPT_INLINE;
+               opt &= ~MONO_OPT_COPYPROP;
+               opt &= ~MONO_OPT_CONSPROP;
+               enable_debugging = TRUE;
+
+#ifdef MONO_DEBUGGER_SUPPORTED
+               mono_debug_init (MONO_DEBUG_FORMAT_DEBUGGER);
+               mono_debugger_init ();
+#else
+               g_print ("The Mono Debugger is not supported on this platform.\n");
+               return 1;
+#endif
+       }
+
        mono_set_defaults (mini_verbose, opt);
        domain = mini_init (argv [i]);
        
@@ -843,13 +934,15 @@ mono_main (int argc, char* argv[])
                break;
        }
 
-       if (enable_debugging) {
+       if (action == DO_DEBUGGER)
+               mono_debug_init_1 (domain);
+       else if (enable_debugging) {
                mono_debug_init (MONO_DEBUG_FORMAT_MONO);
                mono_debug_init_1 (domain);
        }
 
        /* Parse gac loading options before loading assemblies. */
-       if (mono_compile_aot || action == DO_EXEC) {
+       if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) {
                mono_config_parse (config_file);
        }
 
@@ -867,7 +960,7 @@ mono_main (int argc, char* argv[])
                mono_debug_init_2 (assembly);
 
        if (mono_compile_aot || action == DO_EXEC) {
-               const guchar *error;
+               const char *error;
 
                //mono_set_rootdir ();
 
@@ -878,6 +971,12 @@ mono_main (int argc, char* argv[])
                        exit (1);
                }
 
+#ifdef PLATFORM_WIN32
+               /* Detach console when executing IMAGE_SUBSYSTEM_WINDOWS_GUI on win32 */
+               if (!mono_compile_aot && ((MonoCLIImageInfo*)(mono_assembly_get_image (assembly)->image_info))->cli_header.nt.pe_subsys_required == IMAGE_SUBSYSTEM_WINDOWS_GUI)
+                       FreeConsole ();
+#endif
+
                main_args.domain = domain;
                main_args.file = aname;         
                main_args.argc = argc - i;
@@ -896,9 +995,26 @@ mono_main (int argc, char* argv[])
                i = mono_environment_exitcode_get ();
                return i;
        } else if (action == DO_COMPILE) {
-               compile_all_methods (assembly, mini_verbose);
+               compile_all_methods (assembly, mini_verbose, opt);
                mini_cleanup (domain);
                return 0;
+       } else if (action == DO_DEBUGGER) {
+#ifdef MONO_DEBUGGER_SUPPORTED
+               const char *error;
+
+               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);
+               }
+
+               mono_debugger_main (domain, assembly, argc - i, argv + i);
+               mini_cleanup (domain);
+               return 0;
+#else
+               return 1;
+#endif
        }
        desc = mono_method_desc_new (mname, 0);
        if (!desc) {