-/*
- * aot-compiler.c: mono Ahead of Time compiler
+/**
+ * \file
+ * mono Ahead of Time compiler
*
* Author:
* Dietmar Maurer (dietmar@ximian.com)
#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"
#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"
guint32 label_generator;
gboolean llvm;
gboolean has_jitted_code;
+ gboolean is_full_aot;
MonoAotFileFlags flags;
MonoDynamicStream blob;
gboolean blob_closed;
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 */
#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
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
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 */
#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 */
/*
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")) {
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")) {
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=")) {
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")) {
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=")) {
} 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")) {
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);
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;
}
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)
{
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);
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
#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"
#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)
}
}
- 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);
}
}
- {
+ 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) {
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;
}
#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);