Merge pull request #4967 from kumpera/profiler-arg-cleanup
[mono.git] / mono / mini / aot-compiler.c
index 5ef9b0253805706ec4d2ebda94cdea752542d534..3c4e3aa899f535656ae0429158f5bf8af40dec6c 100644 (file)
@@ -56,7 +56,7 @@
 #include <mono/utils/mono-rand.h>
 #include <mono/utils/json.h>
 #include <mono/utils/mono-threads-coop.h>
-#include <mono/profiler/mono-profiler-aot.h>
+#include <mono/profiler/aot.h>
 #include <mono/utils/w32api.h>
 
 #include "aot-compiler.h"
@@ -78,7 +78,7 @@
 #define TARGET_WIN32_MSVC
 #endif
 
-#if defined(__linux__) || defined(__native_client_codegen__)
+#if defined(__linux__)
 #define RODATA_SECT ".rodata"
 #elif defined(TARGET_MACH)
 #define RODATA_SECT ".section __TEXT, __const"
@@ -298,6 +298,7 @@ typedef struct MonoAotCompile {
        guint32 label_generator;
        gboolean llvm;
        gboolean has_jitted_code;
+       gboolean is_full_aot;
        MonoAotFileFlags flags;
        MonoDynamicStream blob;
        gboolean blob_closed;
@@ -438,7 +439,10 @@ report_loader_error (MonoAotCompile *acfg, MonoError *error, const char *format,
        va_end (args);
        mono_error_cleanup (error);
 
-       g_error ("FullAOT cannot continue if there are loader errors");
+       if (acfg->is_full_aot) {
+               fprintf (output, "FullAOT cannot continue if there are loader errors.\n");
+               exit (1);
+       }
 }
 
 /* Wrappers around the image writer functions */
@@ -949,10 +953,8 @@ emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
 #ifdef TARGET_X86
 #ifdef TARGET_WIN32
 #define AOT_TARGET_STR "X86 (WIN32)"
-#elif defined(__native_client_codegen__)
-#define AOT_TARGET_STR "X86 (native client codegen)"
 #else
-#define AOT_TARGET_STR "X86 (!native client codegen)"
+#define AOT_TARGET_STR "X86"
 #endif
 #endif
 
@@ -4425,7 +4427,13 @@ method_has_type_vars (MonoMethod *method)
 static
 gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
 {
-       return opts->mode == MONO_AOT_MODE_FULL;
+       return opts->mode == MONO_AOT_MODE_FULL || opts->mode == MONO_AOT_MODE_INTERP;
+}
+
+static
+gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
+{
+       return opts->mode == MONO_AOT_MODE_INTERP;
 }
 
 static
@@ -6130,11 +6138,23 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
                        clause = &header->clauses [k];
 
                        encode_value (clause->flags, p, &p);
-                       if (clause->data.catch_class) {
-                               encode_value (1, p, &p);
-                               encode_klass_ref (acfg, clause->data.catch_class, p, &p);
-                       } else {
-                               encode_value (0, p, &p);
+                       if (!(clause->flags == MONO_EXCEPTION_CLAUSE_FILTER || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
+                               if (clause->data.catch_class) {
+                                       guint8 *buf2, *p2;
+                                       int len;
+
+                                       buf2 = (guint8 *)g_malloc (4096);
+                                       p2 = buf2;
+                                       encode_klass_ref (acfg, clause->data.catch_class, p2, &p2);
+                                       len = p2 - buf2;
+                                       g_assert (len < 4096);
+                                       encode_value (len, p, &p);
+                                       memcpy (p, buf2, len);
+                                       p += p2 - buf2;
+                                       g_free (buf2);
+                               } else {
+                                       encode_value (0, p, &p);
+                               }
                        }
 
                        /* Emit the IL ranges too, since they might not be available at runtime */
@@ -6807,6 +6827,11 @@ emit_trampolines (MonoAotCompile *acfg)
 
 #endif /* #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES */
 
+               if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
+                       mono_arch_get_enter_icall_trampoline (&info);
+                       emit_trampoline (acfg, acfg->got_offset, info);
+               }
+
                /* Emit trampolines which are numerous */
 
                /*
@@ -7138,6 +7163,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->write_symbols = TRUE;
                } else if (str_begins_with (arg, "no-write-symbols")) {
                        opts->write_symbols = FALSE;
+               // Intentionally undocumented -- one-off experiment
                } else if (str_begins_with (arg, "metadata-only")) {
                        opts->metadata_only = TRUE;
                } else if (str_begins_with (arg, "bind-to-runtime-version")) {
@@ -7146,6 +7172,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->mode = MONO_AOT_MODE_FULL;
                } else if (str_begins_with (arg, "hybrid")) {
                        opts->mode = MONO_AOT_MODE_HYBRID;                      
+               } else if (str_begins_with (arg, "interp")) {
+                       opts->mode = MONO_AOT_MODE_INTERP;
                } else if (str_begins_with (arg, "threads=")) {
                        opts->nthreads = atoi (arg + strlen ("threads="));
                } else if (str_begins_with (arg, "static")) {
@@ -7159,6 +7187,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->nodebug = TRUE;
                } else if (str_begins_with (arg, "dwarfdebug")) {
                        opts->dwarf_debug = TRUE;
+               // Intentionally undocumented -- No one remembers what this does. It appears to be ARM-only
                } else if (str_begins_with (arg, "nopagetrampolines")) {
                        opts->use_trampolines_page = FALSE;
                } else if (str_begins_with (arg, "ntrampolines=")) {
@@ -7177,6 +7206,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->ld_flags = g_strdup (arg + strlen ("ld-flags="));                 
                } else if (str_begins_with (arg, "soft-debug")) {
                        opts->soft_debug = TRUE;
+               // Intentionally undocumented x2-- deprecated
                } else if (str_begins_with (arg, "gen-seq-points-file=")) {
                        fprintf (stderr, "Mono Warning: aot option gen-seq-points-file= is deprecated.\n");
                } else if (str_begins_with (arg, "gen-seq-points-file")) {
@@ -7195,8 +7225,10 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->print_skipped_methods = TRUE;
                } else if (str_begins_with (arg, "stats")) {
                        opts->stats = TRUE;
+               // Intentionally undocumented-- has no known function other than to debug the compiler
                } else if (str_begins_with (arg, "no-instances")) {
                        opts->no_instances = TRUE;
+               // Intentionally undocumented x4-- Used for internal debugging of compiler
                } else if (str_begins_with (arg, "log-generics")) {
                        opts->log_generics = TRUE;
                } else if (str_begins_with (arg, "log-instances=")) {
@@ -7217,8 +7249,10 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                } else if (str_begins_with (arg, "info")) {
                        printf ("AOT target setup: %s.\n", AOT_TARGET_STR);
                        exit (0);
+               // Intentionally undocumented: Used for precise stack maps, which are not available yet
                } else if (str_begins_with (arg, "gc-maps")) {
                        mini_gc_enable_gc_maps_for_aot ();
+               // Intentionally undocumented: Used for internal debugging
                } else if (str_begins_with (arg, "dump")) {
                        opts->dump_json = TRUE;
                } else if (str_begins_with (arg, "llvmonly")) {
@@ -7235,36 +7269,44 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->verbose = TRUE;
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
-                       printf ("    outfile=\n");
-                       printf ("    llvm-outfile=\n");
-                       printf ("    llvm-path=\n");
-                       printf ("    temp-path=\n");
-                       printf ("    save-temps\n");
-                       printf ("    keep-temps\n");
-                       printf ("    write-symbols\n");
-                       printf ("    metadata-only\n");
+                       printf ("    asmonly\n");
                        printf ("    bind-to-runtime-version\n");
+                       printf ("    bitcode\n");
+                       printf ("    data-outfile=\n");
+                       printf ("    direct-icalls\n");
+                       printf ("    direct-pinvoke\n");
+                       printf ("    dwarfdebug\n");
                        printf ("    full\n");
-                       printf ("    threads=\n");
-                       printf ("    static\n");
-                       printf ("    asmonly\n");
-                       printf ("    asmwriter\n");
+                       printf ("    hybrid\n");
+                       printf ("    info\n");
+                       printf ("    keep-temps\n");
+                       printf ("    llvm\n");
+                       printf ("    llvmonly\n");
+                       printf ("    llvm-outfile=\n");
+                       printf ("    llvm-path=\n");
+                       printf ("    msym-dir=\n");
+                       printf ("    mtriple\n");
+                       printf ("    nimt-trampolines=\n");
                        printf ("    nodebug\n");
-                       printf ("    dwarfdebug\n");
-                       printf ("    ntrampolines=\n");
+                       printf ("    no-direct-calls\n");
+                       printf ("    no-write-symbols\n");
                        printf ("    nrgctx-trampolines=\n");
-                       printf ("    nimt-trampolines=\n");
+                       printf ("    nrgctx-fetch-trampolines=\n");
                        printf ("    ngsharedvt-trampolines=\n");
-                       printf ("    tool-prefix=\n");
+                       printf ("    ntrampolines=\n");
+                       printf ("    outfile=\n");
+                       printf ("    profile=\n");
+                       printf ("    profile-only\n");
+                       printf ("    print-skipped-methods\n");
                        printf ("    readonly-value=\n");
+                       printf ("    save-temps\n");
                        printf ("    soft-debug\n");
-                       printf ("    msym-dir=\n");
-                       printf ("    gc-maps\n");
-                       printf ("    print-skipped\n");
-                       printf ("    no-instances\n");
+                       printf ("    static\n");
                        printf ("    stats\n");
-                       printf ("    dump\n");
-                       printf ("    info\n");
+                       printf ("    temp-path=\n");
+                       printf ("    tool-prefix=\n");
+                       printf ("    threads=\n");
+                       printf ("    write-symbols\n");
                        printf ("    verbose\n");
                        printf ("    help/?\n");
                        exit (0);
@@ -7598,11 +7640,9 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                return;
        }
        if (cfg->exception_type != MONO_EXCEPTION_NONE) {
-               if (acfg->aot_opts.print_skipped_methods) {
-                       printf ("Skip (JIT failure): %s\n", mono_method_get_full_name (method));
-                       if (cfg->exception_message)
-                               printf ("Caused by: %s\n", cfg->exception_message);
-               }
+               /* Some instances cannot be JITted due to constraints etc. */
+               if (!method->is_inflated)
+                       report_loader_error (acfg, &cfg->error, "Unable to compile method '%s' due to: '%s'.\n", mono_method_get_full_name (method), mono_error_get_message (&cfg->error));
                /* Let the exception happen at runtime */
                return;
        }
@@ -7902,7 +7942,9 @@ compile_thread_main (gpointer user_data)
 
        MonoError error;
        MonoInternalThread *internal = mono_thread_internal_current ();
-       mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "AOT compiler"), TRUE, FALSE, &error);
+       MonoString *str = mono_string_new_checked (mono_domain_get (), "AOT compiler", &error);
+       mono_error_assert_ok (&error);
+       mono_thread_set_name_internal (internal, str, TRUE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        for (i = 0; i < methods->len; ++i)
@@ -8608,7 +8650,7 @@ execute_system (const char * command)
 {
        int status = 0;
 
-#if defined(HOST_WIN32) && defined(HAVE_SYSTEM)
+#if defined(HOST_WIN32)
        // We need an extra set of quotes around the whole command to properly handle commands 
        // with spaces since internally the command is called through "cmd /c.
        char * quoted_command = g_strdup_printf ("\"%s\"", command);
@@ -8725,7 +8767,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        g_string_append_printf (acfg->llc_args, " -disable-tail-calls");
 #endif
 
-#if defined(TARGET_MACH) && defined(TARGET_ARM)
+#if ( defined(TARGET_MACH) && defined(TARGET_ARM) ) || defined(TARGET_ORBIS)
        /* ios requires PIC code now */
        g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
 #else
@@ -10330,19 +10372,13 @@ compile_asm (MonoAotCompile *acfg)
 #define AS_OPTIONS "-a64 -mppc64"
 #elif defined(sparc) && SIZEOF_VOID_P == 8
 #define AS_OPTIONS "-xarch=v9"
-#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH)
 #define AS_OPTIONS "-arch i386"
 #else
 #define AS_OPTIONS ""
 #endif
 
-#ifdef __native_client_codegen__
-#if defined(TARGET_AMD64)
-#define AS_NAME "nacl64-as"
-#else
-#define AS_NAME "nacl-as"
-#endif
-#elif defined(TARGET_OSX)
+#if defined(TARGET_OSX)
 #define AS_NAME "clang"
 #elif defined(TARGET_WIN32_MSVC)
 #define AS_NAME "clang.exe"
@@ -10371,7 +10407,7 @@ compile_asm (MonoAotCompile *acfg)
 #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
 #define LD_NAME "gcc"
 #define LD_OPTIONS "-shared"
-#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH)
 #define LD_NAME "clang"
 #define LD_OPTIONS "-m32 -dynamiclib"
 #elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
@@ -11470,8 +11506,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
        }
 
-       if (mono_aot_mode_is_full (&acfg->aot_opts))
+       if (mono_aot_mode_is_full (&acfg->aot_opts)) {
                acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_FULL_AOT);
+               acfg->is_full_aot = TRUE;
+       }
 
        if (mono_threads_is_coop_enabled ())
                acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SAFEPOINTS);
@@ -11492,7 +11530,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
        }
 
-       {
+       if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
                int method_index;
 
        for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
@@ -11555,9 +11593,12 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
                mono_set_partial_sharing_supported (TRUE);
 
-       res = collect_methods (acfg);
-       if (!res)
-               return 1;
+       if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
+               res = collect_methods (acfg);
+
+               if (!res)
+                       return 1;
+       }
 
        {
                GList *l;
@@ -11582,6 +11623,26 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        }
 #endif
 
+       if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
+               MonoMethod *wrapper;
+               MonoMethodSignature *sig;
+
+               /* object object:interp_in_static (object,intptr,intptr,intptr) */
+               sig = mono_create_icall_signature ("object object ptr ptr ptr");
+               wrapper = mini_get_interp_in_wrapper (sig);
+               add_method (acfg, wrapper);
+
+               /* int object:interp_in_static (intptr,int,intptr) */
+               sig = mono_create_icall_signature ("int32 ptr int32 ptr");
+               wrapper = mini_get_interp_in_wrapper (sig);
+               add_method (acfg, wrapper);
+
+               /* void object:interp_in_static (object,intptr,intptr,intptr) */
+               sig = mono_create_icall_signature ("void object ptr ptr ptr");
+               wrapper = mini_get_interp_in_wrapper (sig);
+               add_method (acfg, wrapper);
+       }
+
        TV_GETTIME (atv);
 
        compile_methods (acfg);