Merge pull request #3199 from lambdageek/dev/proxy-setter
[mono.git] / mono / mini / aot-compiler.c
index 157054bbbb164f69580070684d81ed73913028b4..5719f5f1207d158d57f30b258e1595631142d73d 100644 (file)
@@ -51,6 +51,7 @@
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-rand.h>
 #include <mono/utils/json.h>
 #include <mono/utils/mono-threads-coop.h>
 
@@ -113,8 +114,8 @@ typedef struct MonoAotOptions {
        gboolean soft_debug;
        gboolean log_generics;
        gboolean log_instances;
-       gboolean gen_seq_points_file;
-       char *gen_seq_points_file_path;
+       gboolean gen_msym_dir;
+       char *gen_msym_dir_path;
        gboolean direct_pinvoke;
        gboolean direct_icalls;
        gboolean no_direct_calls;
@@ -902,7 +903,10 @@ arch_init (MonoAotCompile *acfg)
        if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "darwin")) {
                g_string_append (acfg->llc_args, "-mattr=+v6");
        } else {
-#ifdef ARM_FPU_VFP
+#if defined(ARM_FPU_VFP_HARD)
+               g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16 -float-abi=hard");
+               g_string_append (acfg->as_args, " -mfpu=vfp3");
+#elif defined(ARM_FPU_VFP)
                g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16");
                g_string_append (acfg->as_args, " -mfpu=vfp3");
 #else
@@ -3583,7 +3587,9 @@ get_runtime_invoke_sig (MonoMethodSignature *sig)
 
        mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
        m = mono_mb_create_method (mb, sig, 16);
-       return mono_marshal_get_runtime_invoke (m, FALSE);
+       MonoMethod *invoke = mono_marshal_get_runtime_invoke (m, FALSE);
+       mono_mb_free (mb);
+       return invoke;
 }
 
 static MonoMethod*
@@ -4231,6 +4237,7 @@ add_wrappers (MonoAotCompile *acfg)
                                if (export_name)
                                        g_hash_table_insert (acfg->export_names, wrapper, export_name);
                        }
+                       g_free (cattr);
                }
 
                if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
@@ -4655,9 +4662,11 @@ add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
                for (j = 0; j < header->num_locals; ++j)
                        if (header->locals [j]->type == MONO_TYPE_GENERICINST)
                                add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
+               mono_metadata_free_mh (header);
        } else {
                mono_error_cleanup (&error); /* FIXME report the error */
        }
+
 }
 
 /*
@@ -5393,6 +5402,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                }
        }
 
+       g_ptr_array_free (patches, TRUE);
        g_free (locs);
 }
 
@@ -5888,6 +5898,8 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        encode_patch_list (acfg, patches, n_patches, cfg->compile_llvm, first_got_offset, p, &p);
 
+       g_ptr_array_free (patches, TRUE);
+
        acfg->stats.info_size += p - buf;
 
        g_assert (p - buf < buf_size);
@@ -5974,6 +5986,8 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
 
                unwind_desc = get_unwind_info_offset (acfg, encoded, encoded_len);
                encode_value (unwind_desc, p, &p);
+
+               g_free (encoded);
        } else {
                encode_value (jinfo->unwind_info, p, &p);
        }
@@ -6512,6 +6526,7 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
 
        encode_patch_list (acfg, patches, patches->len, FALSE, got_offset, p, &p);
        g_assert (p - buf < buf_size);
+       g_ptr_array_free (patches, TRUE);
 
        sprintf (symbol, "%s%s_p", acfg->user_symbol_prefix, name);
 
@@ -6549,6 +6564,8 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
                if (acfg->dwarf)
                        mono_dwarf_writer_emit_trampoline (acfg->dwarf, symbol, symbol2, NULL, NULL, code_size, unwind_ops);
        }
+
+       g_free (buf);
 }
 
 static G_GNUC_UNUSED void
@@ -6648,10 +6665,12 @@ emit_trampolines (MonoAotCompile *acfg)
                        offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
                        mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
+                       g_free (info);
 
                        offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
                        mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
+                       g_free (info);
                }
 
 #ifdef MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE
@@ -6672,6 +6691,11 @@ emit_trampolines (MonoAotCompile *acfg)
                        }
                }
 
+#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
+               mono_arch_create_handler_block_trampoline (&info, TRUE);
+               emit_trampoline (acfg, acfg->got_offset, info);
+#endif
+
 #endif /* #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES */
 
                /* Emit trampolines which are numerous */
@@ -7045,12 +7069,13 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                } else if (str_begins_with (arg, "soft-debug")) {
                        opts->soft_debug = TRUE;
                } else if (str_begins_with (arg, "gen-seq-points-file=")) {
-                       debug_options.gen_seq_points_compact_data = TRUE;
-                       opts->gen_seq_points_file = TRUE;
-                       opts->gen_seq_points_file_path = g_strdup (arg + strlen ("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")) {
-                       debug_options.gen_seq_points_compact_data = TRUE;
-                       opts->gen_seq_points_file = TRUE;
+                       fprintf (stderr, "Mono Warning: aot option gen-seq-points-file is deprecated.\n");
+               } else if (str_begins_with (arg, "msym-dir=")) {
+                       debug_options.no_seq_points_compact_data = FALSE;
+                       opts->gen_msym_dir = TRUE;
+                       opts->gen_msym_dir_path = g_strdup (arg + strlen ("msym_dir="));;
                } else if (str_begins_with (arg, "direct-pinvoke")) {
                        opts->direct_pinvoke = TRUE;
                } else if (str_begins_with (arg, "direct-icalls")) {
@@ -7118,7 +7143,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        printf ("    tool-prefix=\n");
                        printf ("    readonly-value=\n");
                        printf ("    soft-debug\n");
-                       printf ("    gen-seq-points-file\n");
+                       printf ("    msym-dir=\n");
                        printf ("    gc-maps\n");
                        printf ("    print-skipped\n");
                        printf ("    no-instances\n");
@@ -7463,7 +7488,6 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                if (acfg->aot_opts.print_skipped_methods)
                        printf ("Skip (disabled): %s\n", mono_method_get_full_name (method));
                InterlockedIncrement (&acfg->stats.ocount);
-               mono_destroy_compile (cfg);
                return;
        }
        cfg->method_index = index;
@@ -7506,7 +7530,6 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                if (acfg->aot_opts.print_skipped_methods)
                        printf ("Skip (abs call): %s\n", mono_method_get_full_name (method));
                InterlockedIncrement (&acfg->stats.abscount);
-               mono_destroy_compile (cfg);
                return;
        }
 
@@ -7535,7 +7558,6 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                if (acfg->aot_opts.print_skipped_methods)
                        printf ("Skip (patches): %s\n", mono_method_get_full_name (method));
                acfg->stats.ocount++;
-               mono_destroy_compile (cfg);
                mono_acfg_unlock (acfg);
                return;
        }
@@ -7712,20 +7734,12 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                        locals [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
                        memcpy (locals [i], cfg->locals [i], sizeof (MonoInst));
                }
+               mono_metadata_free_mh (header);
                cfg->locals = locals;
        }
 
        /* Free some fields used by cfg to conserve memory */
-       mono_mempool_destroy (cfg->mempool);
-       cfg->mempool = NULL;
-       g_free (cfg->varinfo);
-       cfg->varinfo = NULL;
-       g_free (cfg->vars);
-       cfg->vars = NULL;
-       if (cfg->rs) {
-               mono_regstate_free (cfg->rs);
-               cfg->rs = NULL;
-       }
+       mono_empty_compile (cfg);
 
        //printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
 
@@ -8230,7 +8244,7 @@ emit_llvm_file (MonoAotCompile *acfg)
                opts = g_strdup ("");
        else
 #if LLVM_API_VERSION > 100
-               opts = g_strdup ("-O2");
+               opts = g_strdup ("-O2 -disable-tail-calls");
 #else
                opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -inline-cost -inline -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
 #endif
@@ -8247,7 +8261,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        if (acfg->aot_opts.llvm_only) {
                /* Use the stock clang from xcode */
                // FIXME: arch
-               command = g_strdup_printf ("clang -march=x86-64 -fpic -msse -msse2 -msse3 -msse4 -O2 -fno-optimize-sibling-calls -Wno-override-module -c -o \"%s\" \"%s.opt.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
+               command = g_strdup_printf ("clang++ -fexceptions -march=x86-64 -fpic -msse -msse2 -msse3 -msse4 -O2 -fno-optimize-sibling-calls -Wno-override-module -c -o \"%s\" \"%s.opt.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
 
                aot_printf (acfg, "Executing clang: %s\n", command);
                if (execute_system (command) != 0)
@@ -8816,6 +8830,7 @@ emit_extra_methods (MonoAotCompile *acfg)
                        g_ptr_array_add (table, new_entry);
                }
        }
+       g_free (chain_lengths);
 
        //printf ("MAX: %d\n", max_chain_length);
 
@@ -8845,6 +8860,8 @@ emit_extra_methods (MonoAotCompile *acfg)
        /* Emit the table */
        emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_TABLE, "extra_method_table", buf, p - buf);
 
+       g_free (buf);
+
        /* 
         * Emit a table reverse mapping method indexes to their index in extra_method_info.
         * This is used by mono_aot_find_jit_info ().
@@ -8859,8 +8876,27 @@ emit_extra_methods (MonoAotCompile *acfg)
                encode_int (info_offsets [i], p, &p);
        }
        emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_INFO_OFFSETS, "extra_method_info_offsets", buf, p - buf);
+
+       g_free (buf);
+       g_free (info_offsets);
+       g_ptr_array_free (table, TRUE);
 }      
 
+static void
+generate_aotid (guint8* aotid)
+{
+       gpointer *rand_handle;
+       MonoError error;
+
+       mono_rand_open ();
+       rand_handle = mono_rand_init (NULL, 0);
+
+       mono_rand_try_get_bytes (rand_handle, aotid, 16, &error);
+       mono_error_assert_ok (&error);
+
+       mono_rand_close (rand_handle);
+}
+
 static void
 emit_exception_info (MonoAotCompile *acfg)
 {
@@ -8876,7 +8912,7 @@ emit_exception_info (MonoAotCompile *acfg)
 
                        // By design aot-runtime decode_exception_debug_info is not able to load sequence point debug data from a file.
                        // As it is not possible to load debug data from a file its is also not possible to store it in a file.
-                       gboolean method_seq_points_to_file = acfg->aot_opts.gen_seq_points_file &&
+                       gboolean method_seq_points_to_file = acfg->aot_opts.gen_msym_dir &&
                                cfg->gen_seq_points && !cfg->gen_sdb_seq_points;
                        gboolean method_seq_points_to_binary = cfg->gen_seq_points && !method_seq_points_to_file;
                        
@@ -8896,11 +8932,25 @@ emit_exception_info (MonoAotCompile *acfg)
        }
 
        if (seq_points_to_file) {
-               char *seq_points_aot_file = acfg->aot_opts.gen_seq_points_file_path ? acfg->aot_opts.gen_seq_points_file_path
-                       : g_strdup_printf("%s%s", acfg->image->name, SEQ_POINT_AOT_EXT);
-               mono_seq_point_data_write (&sp_data, seq_points_aot_file);
+               char *aotid = mono_guid_to_string_minimal (acfg->image->aotid);
+               char *dir = g_build_filename (acfg->aot_opts.gen_msym_dir_path, aotid, NULL);
+               char *image_basename = g_path_get_basename (acfg->image->name);
+               char *aot_file = g_strdup_printf("%s%s", image_basename, SEQ_POINT_AOT_EXT);
+               char *aot_file_path = g_build_filename (dir, aot_file, NULL);
+
+               if (g_ensure_directory_exists (aot_file_path) == FALSE) {
+                       fprintf (stderr, "AOT : failed to create msym directory: %s\n", aot_file_path);
+                       exit (1);
+               }
+
+               mono_seq_point_data_write (&sp_data, aot_file_path);
                mono_seq_point_data_free (&sp_data);
-               g_free (seq_points_aot_file);
+
+               g_free (aotid);
+               g_free (dir);
+               g_free (image_basename);
+               g_free (aot_file);
+               g_free (aot_file_path);
        }
 
        acfg->stats.offsets_size += emit_offset_table (acfg, "ex_info_offsets", MONO_AOT_TABLE_EX_INFO_OFFSETS, acfg->nmethods, 10, offsets);
@@ -9035,10 +9085,14 @@ emit_class_name_table (MonoAotCompile *acfg)
                        else
                                encode_int16 (0, p, &p);
                }
+               g_free (entry);
        }
        g_assert (p - buf <= buf_size);
+       g_ptr_array_free (table, TRUE);
 
        emit_aot_data (acfg, MONO_AOT_TABLE_CLASS_NAME, "class_name_table", buf, p - buf);
+
+       g_free (buf);
 }
 
 static void
@@ -9354,6 +9408,8 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        info->nshared_got_entries = acfg->nshared_got_entries;
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
+
+       memcpy(&info->aotid, acfg->image->aotid, 16);
 }
 
 static void
@@ -9486,6 +9542,8 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, info->tramp_page_code_offsets [i]);
 
+       emit_bytes (acfg, info->aotid, 16);
+
        if (acfg->aot_opts.static_link) {
                emit_global_inner (acfg, acfg->static_linking_symbol, FALSE);
                emit_alignment (acfg, sizeof (gpointer));
@@ -9904,9 +9962,17 @@ compile_asm (MonoAotCompile *acfg)
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
 #else
        // Default (linux)
-       command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
+       char *args = g_strdup_printf ("%s %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+
+       if (acfg->llvm) {
+               command = g_strdup_printf ("clang++ %s", args);
+       } else {
+               command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
+       }
+       g_free (args);
+
 #endif
        aot_printf (acfg, "Executing the native linker: %s\n", command);
        if (execute_system (command) != 0) {
@@ -9930,7 +9996,7 @@ compile_asm (MonoAotCompile *acfg)
         * gas generates 'mapping symbols' each time code and data is mixed, which 
         * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
         */
-       command = g_strdup_printf ("\"%sstrip\" --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
+       command = g_strdup_printf ("\"%sstrip\" --strip-symbol=\\$a --strip-symbol=\\$d %s", wrap_path(tool_prefix), wrap_path(tmp_outfile_name));
        aot_printf (acfg, "Stripping the binary: %s\n", command);
        if (execute_system (command) != 0) {
                g_free (tmp_outfile_name);
@@ -10045,8 +10111,10 @@ acfg_free (MonoAotCompile *acfg)
        mono_img_writer_destroy (acfg->w);
        for (i = 0; i < acfg->nmethods; ++i)
                if (acfg->cfgs [i])
-                       g_free (acfg->cfgs [i]);
+                       mono_destroy_compile (acfg->cfgs [i]);
+
        g_free (acfg->cfgs);
+
        g_free (acfg->static_linking_symbol);
        g_free (acfg->got_symbol);
        g_free (acfg->plt_symbol);
@@ -10377,6 +10445,12 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
 
+       generate_aotid ((guint8*) &acfg->image->aotid);
+
+       char *aotid = mono_guid_to_string (acfg->image->aotid);
+       aot_printf (acfg, "AOTID %s\n", aotid);
+       g_free (aotid);
+
 #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
        if (mono_aot_mode_is_full (&acfg->aot_opts)) {
                aot_printerrf (acfg, "--aot=full is not supported on this platform.\n");