From b9d0e294de2f534b03ee65572bab19042710cb86 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 21 Feb 2024 15:45:33 -0500 Subject: [PATCH 01/11] [mono][aot] Collect command line arguments and pass them to the aot compiler. --- src/mono/mono/mini/aot-compiler.c | 8 ++++++-- src/mono/mono/mini/aot-compiler.h | 2 +- src/mono/mono/mini/driver.c | 15 +++++++++++---- src/mono/mono/utils/options.c | 11 ++++++++++- src/mono/mono/utils/options.h | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 48de41e36bd94..76f7c7d0a073d 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -258,6 +258,8 @@ typedef struct MonoAotOptions { char *clangxx; char *depfile; char *runtime_init_callback; + GPtrArray *runtime_args; + const char *aot_options; } MonoAotOptions; typedef enum { @@ -15528,13 +15530,15 @@ emit_aot_image (MonoAotCompile *acfg) } int -mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opts, const char *aot_options) +mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opts, GPtrArray *runtime_args, const char *aot_options) { int res = 0; MonoAotOptions aot_opts; init_options (&aot_opts); mono_aot_parse_options (aot_options, &aot_opts); + aot_opts.runtime_args = runtime_args; + aot_opts.aot_options = aot_options; if (aot_opts.direct_extern_calls && !(aot_opts.llvm && aot_opts.static_link)) { fprintf (stderr, "The 'direct-extern-calls' option requires the 'llvm' and 'static' options.\n"); res = 1; @@ -15637,7 +15641,7 @@ mono_aot_get_method_index (MonoMethod *method) } int -mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 opts, const char *aot_options) +mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opts, GPtrArray *runtime_args, const char *aot_options) { return 0; } diff --git a/src/mono/mono/mini/aot-compiler.h b/src/mono/mono/mini/aot-compiler.h index 7aaf862f2e92d..5856134b8eff0 100644 --- a/src/mono/mono/mini/aot-compiler.h +++ b/src/mono/mono/mini/aot-compiler.h @@ -7,7 +7,7 @@ #include "mini.h" -int mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 opts, const char *aot_options); +int mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 opts, GPtrArray *runtime_args, const char *aot_options); void* mono_aot_readonly_field_override (MonoClassField *field); gboolean mono_aot_direct_icalls_enabled_for_method (MonoCompile *cfg, MonoMethod *method); gboolean mono_aot_is_shared_got_offset (int offset); diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index 2077f30d412d2..56e20eeb5eb01 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -1386,6 +1386,7 @@ typedef struct char **argv; guint32 opts; char *aot_options; + GPtrArray *runtime_args; } MainThreadArgs; static void @@ -1421,7 +1422,7 @@ main_thread_handler (gpointer user_data) assemblies [i] = assembly; } - res = mono_aot_assemblies (assemblies, main_args->argc, main_args->opts, main_args->aot_options); + res = mono_aot_assemblies (assemblies, main_args->argc, main_args->opts, main_args->runtime_args, main_args->aot_options); if (res) exit (1); return; @@ -1767,7 +1768,7 @@ mono_jit_parse_options (int argc, char * argv[]) memcpy (copy_argv, argv, sizeof (char*) * argc); argv = copy_argv; - mono_options_parse_options ((const char**)argv, argc, &argc, error); + mono_options_parse_options ((const char**)argv, argc, &argc, NULL, error); if (!is_ok (error)) { g_printerr ("%s", mono_error_get_message (error)); mono_error_cleanup (error); @@ -2067,6 +2068,7 @@ mono_main (int argc, char* argv[]) GPtrArray *agents = NULL; char *extra_bindings_config_file = NULL; GList *paths = NULL; + GPtrArray *args; #ifdef MONO_JIT_INFO_TABLE_TEST int test_jit_info_table = FALSE; #endif @@ -2095,7 +2097,9 @@ mono_main (int argc, char* argv[]) enable_debugging = TRUE; - mono_options_parse_options ((const char**)argv + 1, argc - 1, &argc, error); + args = g_ptr_array_new (); + + mono_options_parse_options ((const char**)argv + 1, argc - 1, &argc, args, error); argc ++; if (!is_ok (error)) { g_printerr ("%s", mono_error_get_message (error)); @@ -2103,9 +2107,11 @@ mono_main (int argc, char* argv[]) return 1; } + g_ptr_array_add (args, argv [0]); for (i = 1; i < argc; ++i) { if (argv [i] [0] != '-') break; + g_ptr_array_add (args, argv [i]); if (strcmp (argv [i], "--regression") == 0) { action = DO_REGRESSION; } else if (strncmp (argv [i], "--single-method=", 16) == 0) { @@ -2464,7 +2470,7 @@ mono_main (int argc, char* argv[]) /* Parse newly added options */ int n = argc; - mono_options_parse_options ((const char**)(argv + orig_argc), argc - orig_argc, &n, error); + mono_options_parse_options ((const char**)(argv + orig_argc), argc - orig_argc, &n, args, error); if (!is_ok (error)) { g_printerr ("%s", mono_error_get_message (error)); mono_error_cleanup (error); @@ -2649,6 +2655,7 @@ mono_main (int argc, char* argv[]) main_args.argv = argv + i; main_args.opts = opt; main_args.aot_options = aot_options; + main_args.runtime_args = args; main_thread_handler (&main_args); mono_thread_manage_internal (); diff --git a/src/mono/mono/utils/options.c b/src/mono/mono/utils/options.c index bf092372828c3..2a8dc6f60480b 100644 --- a/src/mono/mono/utils/options.c +++ b/src/mono/mono/utils/options.c @@ -121,12 +121,13 @@ get_option_hash (void) * Set options based on the command line arguments in ARGV/ARGC. * Remove processed arguments from ARGV and set *OUT_ARGC to the * number of remaining arguments. + * If PROCESSED is != NULL, add the processed arguments to it. * * NOTE: This only sets the variables, the caller might need to do * additional processing based on the new values of the variables. */ void -mono_options_parse_options (const char **argv, int argc, int *out_argc, MonoError *error) +mono_options_parse_options (const char **argv, int argc, int *out_argc, GPtrArray *processed, MonoError *error) { int aindex = 0; GHashTable *option_hash = NULL; @@ -187,6 +188,8 @@ mono_options_parse_options (const char **argv, int argc, int *out_argc, MonoErro break; } *(gboolean*)option->addr = negate ? FALSE : TRUE; + if (processed) + g_ptr_array_add (processed, (gpointer)argv [aindex]); argv [aindex] = NULL; break; } @@ -202,12 +205,18 @@ mono_options_parse_options (const char **argv, int argc, int *out_argc, MonoErro break; } value = argv [aindex + 1]; + if (processed) { + g_ptr_array_add (processed, (gpointer)argv [aindex]); + g_ptr_array_add (processed, (gpointer)argv [aindex + 1]); + } argv [aindex] = NULL; argv [aindex + 1] = NULL; aindex ++; } else if (equals_sign_index != -1) { // option=value value = arg + equals_sign_index + 1; + if (processed) + g_ptr_array_add (processed, (gpointer)argv [aindex]); argv [aindex] = NULL; } else { g_assert_not_reached (); diff --git a/src/mono/mono/utils/options.h b/src/mono/mono/utils/options.h index 41090e3897ca3..e7f2906eeb052 100644 --- a/src/mono/mono/utils/options.h +++ b/src/mono/mono/utils/options.h @@ -26,7 +26,7 @@ extern int mono_options_version; void mono_options_print_usage (void); -void mono_options_parse_options (const char **args, int argc, int *out_argc, MonoError *error); +void mono_options_parse_options (const char **args, int argc, int *out_argc, GPtrArray *processed, MonoError *error); /* returns a json blob representing the current values of all options */ char * mono_options_get_as_json (void); From 08361eb2594177f1281b5de54fa4e1f1c57d6b76 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 23 Feb 2024 12:30:28 -0500 Subject: [PATCH 02/11] [mono][aot] Extract the code invoking external tools into separate functions. --- src/mono/mono/mini/aot-compiler.c | 173 +++++++++++++++--------- src/mono/mono/mini/interp/jiterpreter.c | 2 +- 2 files changed, 111 insertions(+), 64 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 76f7c7d0a073d..ea7761c9e510b 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -368,10 +368,12 @@ typedef struct MonoAotCompile { MonoDwarfWriter *dwarf; FILE *fp; char *tmpbasename; - char *tmpfname; + char *asm_fname; char *temp_dir_to_delete; char *llvm_sfile; char *llvm_ofile; + char *bc_fname; + char *optbc_fname; GSList *cie_program; GHashTable *unwind_info_offsets; GPtrArray *unwind_ops; @@ -484,9 +486,15 @@ get_patch_name (int info) static int aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options); +static void +set_paths (MonoAotCompile *acfg); + static int emit_aot_image (MonoAotCompile *acfg); +static int +assemble_link (MonoAotCompile *acfg); + static guint32 get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len); @@ -10654,32 +10662,21 @@ execute_system (const char * command) #endif /* - * emit_llvm_file: + * compile_llvm_file: * - * Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM - * tools. + * Compile the llvm bitcode file using the LLVM tools. */ static gboolean -emit_llvm_file (MonoAotCompile *acfg) +compile_llvm_file (MonoAotCompile *acfg) { char *command, *opts, *tempbc, *optbc, *output_fname; - if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) { - if (acfg->aot_opts.no_opt) - tempbc = g_strdup (acfg->aot_opts.llvm_outfile); - else - tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename); - optbc = g_strdup (acfg->aot_opts.llvm_outfile); - } else { - tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename); - optbc = g_strdup_printf ("%s.opt.bc", acfg->tmpbasename); - } - - mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name)); - if (acfg->aot_opts.no_opt) return TRUE; + tempbc = acfg->bc_fname; + optbc = acfg->optbc_fname; + #if (defined(TARGET_X86) || defined(TARGET_AMD64)) if (acfg->aot_opts.llvm_cpu_attr && strstr (acfg->aot_opts.llvm_cpu_attr, "sse4.2")) /* @@ -10802,7 +10799,7 @@ emit_llvm_file (MonoAotCompile *acfg) #if ( defined(TARGET_MACH) && defined(TARGET_ARM) ) || defined(TARGET_ORBIS) || defined(TARGET_X86_64_WIN32_MSVC) || defined(TARGET_ANDROID) g_string_append_printf (acfg->llc_args, " -relocation-model=pic"); #else - if (llvm_acfg->aot_opts.static_link) + if (acfg->aot_opts.static_link) g_string_append_printf (acfg->llc_args, " -relocation-model=static"); else g_string_append_printf (acfg->llc_args, " -relocation-model=pic"); @@ -13185,7 +13182,7 @@ compile_asm (MonoAotCompile *acfg) #endif if (acfg->aot_opts.asm_only) { - aot_printf (acfg, "Output file: '%s'.\n", acfg->tmpfname); + aot_printf (acfg, "Output file: '%s'.\n", acfg->asm_fname); if (acfg->aot_opts.static_link) aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol); if (acfg->llvm) @@ -13199,7 +13196,7 @@ compile_asm (MonoAotCompile *acfg) else objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->image->name); } else { - objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname); + objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->asm_fname); } #ifdef TARGET_OSX @@ -13208,7 +13205,7 @@ compile_asm (MonoAotCompile *acfg) command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", as_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", - wrap_path (objfile), wrap_path (acfg->tmpfname)); + wrap_path (objfile), wrap_path (acfg->asm_fname)); aot_printf (acfg, "Executing the native assembler: %s\n", command); if (execute_system (command) != 0) { g_free (command); @@ -13293,7 +13290,7 @@ compile_asm (MonoAotCompile *acfg) #endif g_string_append_printf (str, " -o %s %s %s %s", wrap_path (tmp_outfile_name), wrap_path (llvm_ofile), - wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags); + wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->asm_fname)), ld_flags); #if defined(TARGET_MACH) g_string_append_printf (str, " \"-Wl,-install_name,%s%s\"", g_path_get_basename (acfg->image->name), MONO_SOLIB_EXT); @@ -13360,7 +13357,7 @@ compile_asm (MonoAotCompile *acfg) if (acfg->aot_opts.save_temps) aot_printf (acfg, "Retained input file.\n"); else - g_unlink (acfg->tmpfname); + g_unlink (acfg->asm_fname); return 0; } @@ -15055,6 +15052,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) arch_init (acfg); if (mono_use_llvm || acfg->aot_opts.llvm) { + acfg->llvm = TRUE; /* * Emit all LLVM code into a separate assembly/object file and link with it * normally. @@ -15069,6 +15067,8 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) } } + set_paths (acfg); + if (acfg->llvm && acfg->thumb_mixed) acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_THUMB); if (acfg->aot_opts.llvm_only) @@ -15290,24 +15290,18 @@ create_depfile (MonoAotCompile *acfg) fclose (depfile); } -static int -emit_aot_image (MonoAotCompile *acfg) +static void +set_paths (MonoAotCompile *acfg) { - int res; - TV_DECLARE (atv); - TV_DECLARE (btv); - - TV_GETTIME (atv); - #ifdef ENABLE_LLVM if (acfg->llvm) { if (acfg->aot_opts.asm_only) { if (acfg->aot_opts.outfile) { - acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile); - acfg->tmpbasename = g_strdup (acfg->tmpfname); + acfg->asm_fname = g_strdup_printf ("%s", acfg->aot_opts.outfile); + acfg->tmpbasename = g_strdup (acfg->asm_fname); } else { acfg->tmpbasename = g_strdup_printf ("%s", acfg->image->name); - acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename); + acfg->asm_fname = g_strdup_printf ("%s.s", acfg->tmpbasename); } g_assert (acfg->aot_opts.llvm_outfile); acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile); @@ -15326,7 +15320,7 @@ emit_aot_image (MonoAotCompile *acfg) } acfg->tmpbasename = g_build_filename (temp_path, "temp", (const char*)NULL); - acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename); + acfg->asm_fname = g_strdup_printf ("%s.s", acfg->tmpbasename); acfg->llvm_sfile = g_strdup_printf ("%s-llvm.s", acfg->tmpbasename); if (acfg->aot_opts.static_link) @@ -15336,26 +15330,88 @@ emit_aot_image (MonoAotCompile *acfg) g_free (temp_path); } + + if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) { + if (acfg->aot_opts.no_opt) + acfg->bc_fname = g_strdup (acfg->aot_opts.llvm_outfile); + else + acfg->bc_fname = g_strdup_printf ("%s.bc", acfg->tmpbasename); + acfg->optbc_fname = g_strdup (acfg->aot_opts.llvm_outfile); + } else { + acfg->bc_fname = g_strdup_printf ("%s.bc", acfg->tmpbasename); + acfg->optbc_fname = g_strdup_printf ("%s.opt.bc", acfg->tmpbasename); + } } #endif if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_only) { if (acfg->aot_opts.outfile) - acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile); + acfg->asm_fname = g_strdup_printf ("%s", acfg->aot_opts.outfile); else - acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name); - acfg->fp = g_fopen (acfg->tmpfname, "w+"); + acfg->asm_fname = g_strdup_printf ("%s.s", acfg->image->name); } else { if (strcmp (acfg->aot_opts.temp_path, "") == 0) { - acfg->fp = fdopen (g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL), "w+"); + /* Done later */ } else { acfg->tmpbasename = g_build_filename (acfg->aot_opts.temp_path, "temp", (const char*)NULL); - acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename); - acfg->fp = g_fopen (acfg->tmpfname, "w+"); + acfg->asm_fname = g_strdup_printf ("%s.s", acfg->tmpbasename); + } + } +} + +/* Run external tools to assemble/link the aot image */ +static int +assemble_link (MonoAotCompile *acfg) +{ + int res; + TV_DECLARE (atv); + TV_DECLARE (btv); + + TV_GETTIME (atv); + +#ifdef ENABLE_LLVM + if (acfg->llvm) { + gboolean emit_res; + + emit_res = compile_llvm_file (acfg); + if (!emit_res) + return 1; + } +#endif + + if (!acfg->aot_opts.llvm_only) { + res = compile_asm (acfg); + if (res != 0) { + acfg_free (acfg); + return res; + } + } + TV_GETTIME (btv); + acfg->stats.link_time = GINT64_TO_INT (TV_ELAPSED (atv, btv)); + + return 0; +} + +static int +emit_aot_image (MonoAotCompile *acfg) +{ + int res; + TV_DECLARE (atv); + TV_DECLARE (btv); + + TV_GETTIME (atv); + + if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_only) { + acfg->fp = g_fopen (acfg->asm_fname, "w+"); + } else { + if (strcmp (acfg->aot_opts.temp_path, "") == 0) { + acfg->fp = fdopen (g_file_open_tmp ("mono_aot_XXXXXX", &acfg->asm_fname, NULL), "w+"); + } else { + acfg->fp = g_fopen (acfg->asm_fname, "w+"); } } if (acfg->fp == 0 && !acfg->aot_opts.llvm_only) { - aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno)); + aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->asm_fname, strerror (errno)); return 1; } if (acfg->fp) @@ -15473,13 +15529,8 @@ emit_aot_image (MonoAotCompile *acfg) fclose (acfg->data_outfile); #ifdef ENABLE_LLVM - if (acfg->llvm) { - gboolean emit_res; - - emit_res = emit_llvm_file (acfg); - if (!emit_res) - return 1; - } + if (acfg->llvm) + mono_llvm_emit_aot_module (acfg->bc_fname, g_path_get_basename (acfg->image->name)); #endif emit_library_info (acfg); @@ -15491,26 +15542,13 @@ emit_aot_image (MonoAotCompile *acfg) if (!acfg->aot_opts.stats) aot_printf (acfg, "Compiled: %d/%d\n", acfg->stats.ccount, acfg->stats.mcount); - TV_GETTIME (atv); if (acfg->w) { res = mono_img_writer_emit_writeout (acfg->w); if (res != 0) { acfg_free (acfg); return res; } - res = compile_asm (acfg); - if (res != 0) { - acfg_free (acfg); - return res; - } } - TV_GETTIME (btv); - acfg->stats.link_time = GINT64_TO_INT (TV_ELAPSED (atv, btv)); - - if (acfg->aot_opts.stats) - print_stats (acfg); - - aot_printf (acfg, "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000); if (acfg->aot_opts.depfile) create_depfile (acfg); @@ -15518,6 +15556,15 @@ emit_aot_image (MonoAotCompile *acfg) if (acfg->aot_opts.dump_json) aot_dump (acfg); + res = assemble_link (acfg); + if (res) + return res; + + if (acfg->aot_opts.stats) + print_stats (acfg); + + aot_printf (acfg, "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000); + if (!acfg->aot_opts.save_temps && acfg->temp_dir_to_delete) { char *command = g_strdup_printf ("rm -r %s", acfg->temp_dir_to_delete); execute_system (command); diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 52a6f74f47d63..c4cb8d04db53a 100644 --- a/src/mono/mono/mini/interp/jiterpreter.c +++ b/src/mono/mono/mini/interp/jiterpreter.c @@ -999,7 +999,7 @@ mono_jiterp_parse_option (const char *option) const char *arr[2] = { option, NULL }; int temp; - mono_options_parse_options (arr, 1, &temp, NULL); + mono_options_parse_options (arr, 1, &temp, NULL, NULL); return TRUE; } From 3cd0a4752b11f5a32b7a7f66852178a3acf0cb97 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 24 Feb 2024 00:43:40 -0500 Subject: [PATCH 03/11] [mono][aot] Add a 'compile-in-child' aot argument. When set, the JIT compilation is done in a child process. This helps to reduce overall memory usage since memory used during JITting is no longer going to be reserved when running external tools like opt/llc. --- src/mono/mono/mini/aot-compiler.c | 93 ++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ea7761c9e510b..5d107790d9934 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -238,6 +238,8 @@ typedef struct MonoAotOptions { gboolean verbose; gboolean deterministic; gboolean allow_errors; + gboolean driver; + gboolean child; char *tool_prefix; char *as_prefix; char *ld_flags; @@ -519,6 +521,9 @@ is_direct_pinvoke_specified_for_method (MonoAotCompile *acfg, MonoMethod *method static inline const char* lookup_direct_pinvoke_symbol_name_aot (MonoAotCompile *acfg, MonoMethod *method); +static int +compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options); + static gboolean mono_aot_mode_is_full (MonoAotOptions *opts) { @@ -9083,6 +9088,10 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) // direct pinvokes (managed-to-native wrappers) and fallbacks to JIT for majority of managed methods. } else if (str_begins_with (arg, "wrappers-only")) { opts->wrappers_only = TRUE; + } else if (!strcmp (arg, "compile-in-child")) { + opts->driver = TRUE; + } else if (!strcmp (arg, "_child")) { + opts->child = TRUE; } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) { printf ("Supported options for --aot:\n"); printf (" asmonly - \n"); @@ -9133,6 +9142,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) printf (" verbose - \n"); printf (" allow-errors - \n"); printf (" no-opt - \n"); + printf (" compile-in-child - \n"); printf (" llvmopts= - \n"); printf (" llvmllc= - \n"); printf (" clangxx= - \n"); @@ -14890,14 +14900,14 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) if (acfg->jit_opts & MONO_OPT_GSHAREDVT) mono_set_generic_sharing_vt_supported (TRUE); - if (acfg->dedup_phase != DEDUP_COLLECT) + if (acfg->dedup_phase != DEDUP_COLLECT && !acfg->aot_opts.child) aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name); if (!acfg->aot_opts.deterministic) generate_aotid ((guint8*) &acfg->image->aotid); char *aotid = mono_guid_to_string (acfg->image->aotid); - if (acfg->dedup_phase != DEDUP_COLLECT && !acfg->aot_opts.deterministic) + if (acfg->dedup_phase != DEDUP_COLLECT && !acfg->aot_opts.deterministic && !acfg->aot_opts.child) aot_printf (acfg, "AOTID %s\n", aotid); g_free (aotid); @@ -15089,6 +15099,15 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) acfg->llvm_eh_frame_symbol = g_strdup_printf ("%s_eh_frame", acfg->global_prefix); } + if (acfg->aot_opts.driver) { + /* Run the compilation part in a child process */ + res = compile_assemblies_in_child (&acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); + if (res) + return res; + + return assemble_link (acfg); + } + acfg->method_index = 1; if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts)) @@ -15556,6 +15575,10 @@ emit_aot_image (MonoAotCompile *acfg) if (acfg->aot_opts.dump_json) aot_dump (acfg); + if (acfg->aot_opts.child) + /* The rest is done in the parent */ + return 0; + res = assemble_link (acfg); if (res) return res; @@ -15576,6 +15599,61 @@ emit_aot_image (MonoAotCompile *acfg) return 0; } +static int +compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options) +{ + /* Find --aot argument */ + int aot_index = -1; + for (guint32 i = 1; i < runtime_args->len; ++i) { + const char *arg = (const char*)g_ptr_array_index (runtime_args, i); + if (strncmp (arg, "--aot=", strlen ("--aot=")) == 0) { + aot_index = i; + break; + } + } + g_assert (aot_index != -1); + + GString *command; + + command = g_string_new (""); + + g_string_append_printf (command, "%s", (const char*)g_ptr_array_index (runtime_args, 0)); + + for (guint32 i = 1; i < runtime_args->len; ++i) { + const char *arg = (const char*)g_ptr_array_index (runtime_args, i); + if (strncmp (arg, "--response=", strlen ("--response=")) == 0) + /* Already expanded */ + continue; + if (i != aot_index) + g_string_append_printf (command, " %s", arg); + } + + /* Pass '_child' instead of 'compile-in-child' */ + GPtrArray *aot_split_args = mono_aot_split_options (aot_options); + GString *new_aot_args = g_string_new (""); + for (guint32 i = 0; i < aot_split_args->len; ++i) { + const char *aot_arg = (const char*)g_ptr_array_index (aot_split_args, i); + if (i > 0) + g_string_append_printf (new_aot_args, ","); + if (!strcmp (aot_arg, "compile-in-child")) + g_string_append_printf (new_aot_args, "%s", "_child"); + else + g_string_append_printf (new_aot_args, "%s", aot_arg); + } + + g_string_append_printf (command, " --aot=%s", g_string_free (new_aot_args, FALSE)); + + for (int i = 0; i < nassemblies; ++i) + g_string_append_printf (command, " %s", assemblies [i]->image->name); + + char *cmd = g_string_free (command, FALSE); + printf ("Executing: %s\n", cmd); + int res = execute_system (cmd); + g_free (cmd); + + return res; +} + int mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opts, GPtrArray *runtime_args, const char *aot_options) { @@ -15598,6 +15676,17 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt goto early_exit; } + if (aot_opts.driver) { + if (aot_opts.temp_path [0] == '\0') { + fprintf (stderr, "The 'compile-in-child' option requires the 'temp-path=' option.\n"); + res = 1; + goto early_exit; + } + // FIXME: + if (nassemblies > 1) + aot_opts.driver = FALSE; + } + if (aot_opts.dedup_include) { /* Find the assembly which will contain the dedup-ed code */ int dedup_aindex = -1; From d434f3f059676b9dd1c51066234aad5f8d98b7da Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 24 Feb 2024 13:59:48 -0500 Subject: [PATCH 04/11] Enable by default on wasm on unix. --- src/mono/wasm/build/WasmApp.Common.targets | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 5393cfb84ba79..2d2a6c03e4371 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -624,6 +624,7 @@ + From 66d770d2799d44a1ef150d395b0fcfdc74c2dac5 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 24 Feb 2024 16:29:43 -0500 Subject: [PATCH 05/11] Handle spaces correctly. --- src/mono/mono/mini/aot-compiler.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 5d107790d9934..58120ffd958b2 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -15625,7 +15625,7 @@ compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArr /* Already expanded */ continue; if (i != aot_index) - g_string_append_printf (command, " %s", arg); + g_string_append_printf (command, " \"%s\"", arg); } /* Pass '_child' instead of 'compile-in-child' */ @@ -15641,10 +15641,10 @@ compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArr g_string_append_printf (new_aot_args, "%s", aot_arg); } - g_string_append_printf (command, " --aot=%s", g_string_free (new_aot_args, FALSE)); + g_string_append_printf (command, " \"--aot=%s\"", g_string_free (new_aot_args, FALSE)); for (int i = 0; i < nassemblies; ++i) - g_string_append_printf (command, " %s", assemblies [i]->image->name); + g_string_append_printf (command, " \"%s\"", assemblies [i]->image->name); char *cmd = g_string_free (command, FALSE); printf ("Executing: %s\n", cmd); From c5a59727ac9e6370829b12c65560288b5edd116d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 29 Feb 2024 09:40:30 -0500 Subject: [PATCH 06/11] Disable on windows for now. --- src/mono/mono/mini/aot-compiler.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 58120ffd958b2..98271771762b4 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -238,7 +238,7 @@ typedef struct MonoAotOptions { gboolean verbose; gboolean deterministic; gboolean allow_errors; - gboolean driver; + gboolean compile_in_child; gboolean child; char *tool_prefix; char *as_prefix; @@ -9089,7 +9089,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) } else if (str_begins_with (arg, "wrappers-only")) { opts->wrappers_only = TRUE; } else if (!strcmp (arg, "compile-in-child")) { - opts->driver = TRUE; + opts->compile_in_child = TRUE; } else if (!strcmp (arg, "_child")) { opts->child = TRUE; } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) { @@ -15099,8 +15099,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) acfg->llvm_eh_frame_symbol = g_strdup_printf ("%s_eh_frame", acfg->global_prefix); } - if (acfg->aot_opts.driver) { - /* Run the compilation part in a child process */ + if (acfg->aot_opts.compile_in_child) { res = compile_assemblies_in_child (&acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); if (res) return res; @@ -15676,7 +15675,7 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt goto early_exit; } - if (aot_opts.driver) { + if (aot_opts.compile_in_child) { if (aot_opts.temp_path [0] == '\0') { fprintf (stderr, "The 'compile-in-child' option requires the 'temp-path=' option.\n"); res = 1; @@ -15684,7 +15683,11 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt } // FIXME: if (nassemblies > 1) - aot_opts.driver = FALSE; + aot_opts.compile_in_child = FALSE; +#ifdef HOST_WIN32 + // Need to create response files + aot_opts.compile_in_child = FALSE; +#endif } if (aot_opts.dedup_include) { From 156f2a800e8783997a266b464322332c359bc616 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 29 Feb 2024 15:35:03 -0500 Subject: [PATCH 07/11] Add dedup support. --- src/mono/mono/mini/aot-compiler.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 98271771762b4..a34dbe8a85c6d 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -15100,11 +15100,18 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) } if (acfg->aot_opts.compile_in_child) { - res = compile_assemblies_in_child (&acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); - if (res) - return res; + if (acfg->aot_opts.dedup_include) { + if (acfg->image->assembly == dedup_assembly) + return assemble_link (acfg); + else + return 0; + } else { + res = compile_assemblies_in_child (&acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); + if (res) + return res; - return assemble_link (acfg); + return assemble_link (acfg); + } } acfg->method_index = 1; @@ -15681,8 +15688,7 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt res = 1; goto early_exit; } - // FIXME: - if (nassemblies > 1) + if (nassemblies > 1 && !aot_opts.dedup_include) aot_opts.compile_in_child = FALSE; #ifdef HOST_WIN32 // Need to create response files @@ -15690,6 +15696,12 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt #endif } + if (aot_opts.dedup_include && aot_opts.compile_in_child) { + res = compile_assemblies_in_child (assemblies, nassemblies, aot_opts.runtime_args, aot_opts.aot_options); + if (res) + return res; + } + if (aot_opts.dedup_include) { /* Find the assembly which will contain the dedup-ed code */ int dedup_aindex = -1; From b89c1e0a894f4d19ce2a37f2f7fe39db41fe6e36 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 1 Mar 2024 16:54:19 -0500 Subject: [PATCH 08/11] Add windows support. --- src/mono/mono/mini/aot-compiler.c | 54 +++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index a34dbe8a85c6d..32a19871f6364 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -522,7 +522,7 @@ static inline const char* lookup_direct_pinvoke_symbol_name_aot (MonoAotCompile *acfg, MonoMethod *method); static int -compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options); +compile_assemblies_in_child (MonoAotOptions *aot_opts, MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options); static gboolean mono_aot_mode_is_full (MonoAotOptions *opts) @@ -15106,7 +15106,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) else return 0; } else { - res = compile_assemblies_in_child (&acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); + res = compile_assemblies_in_child (&acfg->aot_opts, &acfg->image->assembly, 1, acfg->aot_opts.runtime_args, acfg->aot_opts.aot_options); if (res) return res; @@ -15606,8 +15606,11 @@ emit_aot_image (MonoAotCompile *acfg) } static int -compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options) +compile_assemblies_in_child (MonoAotOptions *aot_opts, MonoAssembly **assemblies, int nassemblies, GPtrArray *runtime_args, const char *aot_options) { + FILE *response = NULL; + char *response_fname = NULL; + /* Find --aot argument */ int aot_index = -1; for (guint32 i = 1; i < runtime_args->len; ++i) { @@ -15619,6 +15622,12 @@ compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArr } g_assert (aot_index != -1); +#ifdef TARGET_WIN32 + response_fname = g_build_filename (aot_opts->temp_path, "temp.rsp", (const char*)NULL); + response = fopen (response_fname, "w"); + g_assert (response); +#endif + GString *command; command = g_string_new (""); @@ -15630,8 +15639,12 @@ compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArr if (strncmp (arg, "--response=", strlen ("--response=")) == 0) /* Already expanded */ continue; - if (i != aot_index) - g_string_append_printf (command, " \"%s\"", arg); + if (i != aot_index) { + if (response) + fprintf (response, "%s\n", arg); + else + g_string_append_printf (command, " \"%s\"", arg); + } } /* Pass '_child' instead of 'compile-in-child' */ @@ -15639,19 +15652,30 @@ compile_assemblies_in_child (MonoAssembly **assemblies, int nassemblies, GPtrArr GString *new_aot_args = g_string_new (""); for (guint32 i = 0; i < aot_split_args->len; ++i) { const char *aot_arg = (const char*)g_ptr_array_index (aot_split_args, i); + if (!strcmp (aot_arg, "compile-in-child")) + aot_arg = "_child"; if (i > 0) g_string_append_printf (new_aot_args, ","); - if (!strcmp (aot_arg, "compile-in-child")) - g_string_append_printf (new_aot_args, "%s", "_child"); - else - g_string_append_printf (new_aot_args, "%s", aot_arg); + g_string_append_printf (new_aot_args, "%s", aot_arg); } - g_string_append_printf (command, " \"--aot=%s\"", g_string_free (new_aot_args, FALSE)); + if (response) + fprintf (response, "\"--aot=%s\"\n", g_string_free (new_aot_args, FALSE)); + else + g_string_append_printf (command, " \"--aot=%s\"", g_string_free (new_aot_args, FALSE)); + + for (int i = 0; i < nassemblies; ++i) { + if (response) + fprintf (response, "\"%s\"\n", assemblies [i]->image->name); + else + g_string_append_printf (command, " \"%s\"", assemblies [i]->image->name); + } - for (int i = 0; i < nassemblies; ++i) - g_string_append_printf (command, " \"%s\"", assemblies [i]->image->name); + if (response) + fclose (response); + if (response) + g_string_append_printf (command, " \"--response=%s\"", response_fname); char *cmd = g_string_free (command, FALSE); printf ("Executing: %s\n", cmd); int res = execute_system (cmd); @@ -15690,14 +15714,10 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt } if (nassemblies > 1 && !aot_opts.dedup_include) aot_opts.compile_in_child = FALSE; -#ifdef HOST_WIN32 - // Need to create response files - aot_opts.compile_in_child = FALSE; -#endif } if (aot_opts.dedup_include && aot_opts.compile_in_child) { - res = compile_assemblies_in_child (assemblies, nassemblies, aot_opts.runtime_args, aot_opts.aot_options); + res = compile_assemblies_in_child (&aot_opts, assemblies, nassemblies, aot_opts.runtime_args, aot_opts.aot_options); if (res) return res; } From 6ec0f682f57959b3da4debe947d6c1a51406a106 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 1 Mar 2024 16:55:04 -0500 Subject: [PATCH 09/11] Enable on wasm on windows. --- src/mono/wasm/build/WasmApp.Common.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 2d2a6c03e4371..02ec3b82b1129 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -624,7 +624,7 @@ - + From 7f5f640c7b32a6ca381ed02eef72562f86247ded Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 1 Mar 2024 18:01:32 -0500 Subject: [PATCH 10/11] Fix windows support. --- src/mono/mono/mini/aot-compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 32a19871f6364..59791291da8c3 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -15622,7 +15622,7 @@ compile_assemblies_in_child (MonoAotOptions *aot_opts, MonoAssembly **assemblies } g_assert (aot_index != -1); -#ifdef TARGET_WIN32 +#ifdef HOST_WIN32 response_fname = g_build_filename (aot_opts->temp_path, "temp.rsp", (const char*)NULL); response = fopen (response_fname, "w"); g_assert (response); From d9ed9a39da3b7d9acf0e480ce565869cd1a08c21 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 4 Mar 2024 00:37:24 -0500 Subject: [PATCH 11/11] Disable on windows. --- src/mono/wasm/build/WasmApp.Common.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 02ec3b82b1129..2d2a6c03e4371 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -624,7 +624,7 @@ - +