Fix warnings.
[mono.git] / mono / mini / aot-compiler.c
index f9f546ecf1c2784d2a2bc009fe40efa78a80c6a0..b5516fb8034973468e22a76047c504a9cda3e76a 100644 (file)
@@ -144,7 +144,7 @@ typedef struct MonoAotCompile {
        GPtrArray *extra_methods;
        GPtrArray *image_table;
        GPtrArray *globals;
-       GList *method_order;
+       GPtrArray *method_order;
        guint32 *plt_got_info_offsets;
        guint32 got_offset, plt_offset, plt_got_offset_base;
        guint32 final_got_size;
@@ -185,7 +185,7 @@ typedef struct MonoAotCompile {
        MonoClass **typespec_classes;
        GString *llc_args;
        GString *as_args;
-       gboolean thumb_mixed, need_no_dead_strip;
+       gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack;
 } MonoAotCompile;
 
 typedef struct {
@@ -505,6 +505,13 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
 #endif
 #endif
 
+#ifdef TARGET_POWERPC64
+#ifdef __mono_ilp32__
+#define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
+#else
+#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
+#endif
+#else
 #ifdef TARGET_POWERPC
 #ifdef __mono_ilp32__
 #define AOT_TARGET_STR "POWERPC (mono ilp32)"
@@ -512,13 +519,6 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
 #define AOT_TARGET_STR "POWERPC (!mono ilp32)"
 #endif
 #endif
-
-#ifdef TARGET_POWERPC64
-#ifdef __mono_ilp32__
-#define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
-#else
-#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)"
-#endif
 #endif
 
 #ifdef TARGET_WIN32
@@ -573,6 +573,10 @@ arch_init (MonoAotCompile *acfg)
        acfg->llvm_label_prefix = "_";
        acfg->need_no_dead_strip = TRUE;
 #endif
+
+#if defined(__linux__) && !defined(TARGET_ARM)
+       acfg->need_pt_gnu_stack = TRUE;
+#endif
 }
 
 /*
@@ -2080,6 +2084,15 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                                g_assert_not_reached ();
                        }
                        break;
+               case MONO_WRAPPER_CASTCLASS:
+                       if (!strcmp (method->name, "__castclass_with_cache")) {
+                               encode_value (MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE, p, &p);
+                       } else if (!strcmp (method->name, "__isinst_with_cache")) {
+                               encode_value (MONO_AOT_WRAPPER_ISINST_WITH_CACHE, p, &p);
+                       } else {
+                               g_assert_not_reached ();
+                       }
+                       break;
                default:
                        g_assert_not_reached ();
                }
@@ -2361,8 +2374,7 @@ add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int d
        index = acfg->method_index;
        add_method_with_index (acfg, method, index, extra);
 
-       /* FIXME: Fix quadratic behavior */
-       acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index));
+       g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (index));
 
        g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth));
 
@@ -2653,7 +2665,14 @@ add_wrappers (MonoAotCompile *acfg)
                        klass = mono_class_get (acfg->image, token);
                        if (klass)
                                add_method (acfg, mono_marshal_get_virtual_stelemref (mono_array_class_get (klass, 1)));
+                       else
+                               mono_loader_clear_error ();
                }
+
+               /* castclass_with_check wrapper */
+               add_method (acfg, mono_marshal_get_castclass_with_cache ());
+               /* isinst_with_check wrapper */
+               add_method (acfg, mono_marshal_get_isinst_with_cache ());
        }
 
        /* 
@@ -2686,6 +2705,11 @@ add_wrappers (MonoAotCompile *acfg)
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
                klass = mono_class_get (acfg->image, token);
 
+               if (!klass) {
+                       mono_loader_clear_error ();
+                       continue;
+               }
+
                if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && !klass->generic_container) {
                        method = mono_get_delegate_invoke (klass);
 
@@ -2793,6 +2817,11 @@ add_wrappers (MonoAotCompile *acfg)
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
                klass = mono_class_get (acfg->image, token);
 
+               if (!klass) {
+                       mono_loader_clear_error ();
+                       continue;
+               }
+
                if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass)) {
                        add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
                        add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
@@ -2851,6 +2880,34 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force)
        add_generic_class_with_depth (acfg, klass, 0);
 }
 
+static gboolean
+check_type_depth (MonoType *t, int depth)
+{
+       int i;
+
+       if (depth > 8)
+               return TRUE;
+
+       switch (t->type) {
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericClass *gklass = t->data.generic_class;
+               MonoGenericInst *ginst = gklass->context.class_inst;
+
+               if (ginst) {
+                       for (i = 0; i < ginst->type_argc; ++i) {
+                               if (check_type_depth (ginst->type_argv [i], depth + 1))
+                                       return TRUE;
+                       }
+               }
+               break;
+       }
+       default:
+               break;
+       }
+
+       return FALSE;
+}
+
 /*
  * add_generic_class:
  *
@@ -2873,6 +2930,9 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth)
        if (!klass->generic_class && !klass->rank)
                return;
 
+       if (check_type_depth (&klass->byval_arg, 0))
+               return;
+
        iter = NULL;
        while ((method = mono_class_get_methods (klass, &iter))) {
                if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
@@ -2887,7 +2947,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth)
                 * FIXME: Instances which are referenced by these methods are not added,
                 * for example Array.Resize<int> for List<int>.Add ().
                 */
-               add_extra_method_with_depth (acfg, method, depth);
+               add_extra_method_with_depth (acfg, method, depth + 1);
        }
 
        if (klass->delegate) {
@@ -3121,24 +3181,28 @@ add_generic_instances (MonoAotCompile *acfg)
                token = MONO_TOKEN_TYPE_SPEC | (i + 1);
 
                klass = mono_class_get (acfg->image, token);
-               if (!klass || klass->rank)
+               if (!klass || klass->rank) {
+                       mono_loader_clear_error ();
                        continue;
+               }
 
                add_generic_class (acfg, klass, FALSE);
        }
 
        /* Add types of args/locals */
        for (i = 0; i < acfg->methods->len; ++i) {
-               int j;
+               int j, depth;
 
                method = g_ptr_array_index (acfg->methods, i);
 
+               depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
+
                sig = mono_method_signature (method);
 
                if (sig) {
                        for (j = 0; j < sig->param_count; ++j)
                                if (sig->params [j]->type == MONO_TYPE_GENERICINST)
-                                       add_generic_class (acfg, mono_class_from_mono_type (sig->params [j]), FALSE);
+                                       add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1);
                }
 
                header = mono_method_get_header (method);
@@ -3146,7 +3210,7 @@ add_generic_instances (MonoAotCompile *acfg)
                if (header) {
                        for (j = 0; j < header->num_locals; ++j)
                                if (header->locals [j]->type == MONO_TYPE_GENERICINST)
-                                       add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]), FALSE);
+                                       add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1);
                }
        }
 
@@ -3518,6 +3582,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                break;
        case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+       case MONO_PATCH_INFO_CASTCLASS_CACHE:
                break;
        case MONO_PATCH_INFO_METHOD_REL:
                encode_value ((gint)patch_info->data.offset, p, &p);
@@ -3656,7 +3721,6 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
        MonoMethod *method;
        GList *l;
        int pindex, buf_size, n_patches;
-       guint8 *code;
        GPtrArray *patches;
        MonoJumpInfo *patch_info;
        MonoMethodHeader *header;
@@ -3665,7 +3729,6 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
        guint32 first_got_offset;
 
        method = cfg->orig_method;
-       code = cfg->native_code;
        header = mono_method_get_header (method);
 
        method_index = get_method_index (acfg, method);
@@ -3809,7 +3872,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        seq_points = cfg->seq_point_info;
 
-       buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
+       buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
        p = buf = g_malloc (buf_size);
 
 #ifdef MONO_ARCH_HAVE_XP_UNWIND
@@ -3989,6 +4052,8 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token)
        gpointer iter = NULL;
 
        if (!klass) {
+               mono_loader_clear_error ();
+
                buf_size = 16;
 
                p = buf = g_malloc (buf_size);
@@ -4339,11 +4404,11 @@ static void
 emit_trampolines (MonoAotCompile *acfg)
 {
        char symbol [256];
+       char end_symbol [256];
        int i, tramp_got_offset;
        MonoAotTrampoline ntype;
 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
        int tramp_type;
-       guint8 *code;
 #endif
 
        if (!acfg->aot_opts.full_aot)
@@ -4381,15 +4446,15 @@ emit_trampolines (MonoAotCompile *acfg)
                emit_trampoline (acfg, acfg->got_offset, info);
 
                /* Emit the exception related code pieces */
-               code = mono_arch_get_restore_context (&info, TRUE);
+               mono_arch_get_restore_context (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
-               code = mono_arch_get_call_filter (&info, TRUE);
+               mono_arch_get_call_filter (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
-               code = mono_arch_get_throw_exception (&info, TRUE);
+               mono_arch_get_throw_exception (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
-               code = mono_arch_get_rethrow_exception (&info, TRUE);
+               mono_arch_get_rethrow_exception (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
-               code = mono_arch_get_throw_corlib_exception (&info, TRUE);
+               mono_arch_get_throw_corlib_exception (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
 
 #if defined(MONO_ARCH_HAVE_GET_TRAMPOLINES)
@@ -4409,11 +4474,11 @@ emit_trampolines (MonoAotCompile *acfg)
                        int offset;
 
                        offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
-                       code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
+                       mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
 
                        offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
-                       code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
+                       mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
                }
 
@@ -4481,6 +4546,11 @@ emit_trampolines (MonoAotCompile *acfg)
                                g_assert_not_reached ();
                        }
 
+                       sprintf (end_symbol, "%s_e", symbol);
+
+                       if (acfg->aot_opts.write_symbols)
+                               emit_local_symbol (acfg, symbol, end_symbol, TRUE);
+
                        emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
                        emit_label (acfg, symbol);
 
@@ -4515,6 +4585,8 @@ emit_trampolines (MonoAotCompile *acfg)
                                        acfg->trampoline_size [ntype] = tramp_size;
                                }
                        }
+
+                       emit_label (acfg, end_symbol);
                }
 
                /* Reserve some entries at the end of the GOT for our use */
@@ -4680,6 +4752,13 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                                        return TRUE;
                                else
                                        return FALSE;
+                       case MONO_WRAPPER_CASTCLASS:
+                               if (!strcmp (method->name, "__castclass_with_cache"))
+                                       return TRUE;
+                               else if (!strcmp (method->name, "__isinst_with_cache"))
+                                       return TRUE;
+                               else
+                                       return FALSE;
                        default:
                                //printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
                                return FALSE;
@@ -4783,6 +4862,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                return;
        }
        if (cfg->exception_type != MONO_EXCEPTION_NONE) {
+               //printf ("E: %s\n", mono_method_full_name (method, TRUE));
                /* Let the exception happen at runtime */
                return;
        }
@@ -5035,7 +5115,8 @@ load_profile_files (MonoAotCompile *acfg)
        int file_index, res, method_index, i;
        char ver [256];
        guint32 token;
-       GList *unordered;
+       GList *unordered, *l;
+       gboolean found;
 
        file_index = 0;
        while (TRUE) {
@@ -5081,9 +5162,15 @@ load_profile_files (MonoAotCompile *acfg)
                                token = mono_method_get_token (method);
                                method_index = mono_metadata_token_index (token) - 1;
 
-                               if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index))) {
-                                       acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
+                               found = FALSE;
+                               for (i = 0; i < acfg->method_order->len; ++i) {
+                                       if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) {
+                                               found = TRUE;
+                                               break;
+                                       }
                                }
+                               if (!found)
+                                       g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (method_index));
                        } else {
                                //printf ("No method found matching '%s'.\n", name);
                        }
@@ -5093,15 +5180,20 @@ load_profile_files (MonoAotCompile *acfg)
 
        /* Add missing methods */
        unordered = NULL;
-       for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
-               if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
-                       unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i));
+       for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
+               found = FALSE;
+               for (i = 0; i < acfg->method_order->len; ++i) {
+                       if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) {
+                               found = TRUE;
+                               break;
+                       }
+               }
+               if (!found)
+                       unordered = g_list_prepend (unordered, GUINT_TO_POINTER (method_index));
        }
        unordered = g_list_reverse (unordered);
-       if (acfg->method_order)
-               g_list_last (acfg->method_order)->next = unordered;
-       else
-               acfg->method_order = unordered;
+       for (l = unordered; l; l = l->next)
+               g_ptr_array_add (acfg->method_order, l->data);
 }
  
 /* Used by the LLVM backend */
@@ -5221,7 +5313,7 @@ emit_llvm_file (MonoAotCompile *acfg)
         * then removing tailcallelim + the global opts, and adding a second gvn.
         */
        opts = g_strdup ("-instcombine -simplifycfg");
-       opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify");
+       opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify");
 #if 1
        command = g_strdup_printf ("%sopt -f %s -o temp.opt.bc temp.bc", acfg->aot_opts.llvm_path, opts);
        printf ("Executing opt: %s\n", command);
@@ -5259,10 +5351,9 @@ emit_llvm_file (MonoAotCompile *acfg)
 static void
 emit_code (MonoAotCompile *acfg)
 {
-       int i;
+       int oindex, i;
        char symbol [256];
        char end_symbol [256];
-       GList *l;
 
 #if defined(TARGET_POWERPC64)
        sprintf (symbol, ".Lgot_addr");
@@ -5308,13 +5399,12 @@ emit_code (MonoAotCompile *acfg)
                emit_bytes (acfg, pad_buffer, kPaddingSize);
        }
 #endif
-       
 
-       for (l = acfg->method_order; l != NULL; l = l->next) {
+       for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
                MonoCompile *cfg;
                MonoMethod *method;
 
-               i = GPOINTER_TO_UINT (l->data);
+               i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
 
                cfg = acfg->cfgs [i];
 
@@ -5325,8 +5415,6 @@ emit_code (MonoAotCompile *acfg)
 
                /* Emit unbox trampoline */
                if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
-                       char call_target [256];
-
                        if (!method->wrapper_type && !method->is_inflated) {
                                g_assert (method->token);
                                sprintf (symbol, "ut_%d", mono_metadata_token_index (method->token) - 1);
@@ -5345,9 +5433,7 @@ emit_code (MonoAotCompile *acfg)
 
                        emit_label (acfg, symbol);
 
-                       sprintf (call_target, "%s", cfg->asm_symbol);
-
-                       arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, call_target);
+                       arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, cfg->asm_symbol);
                }
 
                if (cfg->compile_llvm)
@@ -5397,15 +5483,14 @@ emit_code (MonoAotCompile *acfg)
 static void
 emit_info (MonoAotCompile *acfg)
 {
-       int i;
+       int oindex, i;
        char symbol [256];
-       GList *l;
        gint32 *offsets;
 
        offsets = g_new0 (gint32, acfg->nmethods);
 
-       for (l = acfg->method_order; l != NULL; l = l->next) {
-               i = GPOINTER_TO_UINT (l->data);
+       for (oindex = 0; oindex < acfg->method_order->len; ++oindex) {
+               i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex));
 
                if (acfg->cfgs [i]) {
                        emit_method_info (acfg, acfg->cfgs [i]);
@@ -5464,8 +5549,9 @@ mono_aot_type_hash (MonoType *t1)
                return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
        case MONO_TYPE_GENERICINST:
                return ((hash << 5) - hash) ^ 0;
+       default:
+               return hash;
        }
-       return hash;
 }
 
 /*
@@ -5927,8 +6013,10 @@ emit_class_name_table (MonoAotCompile *acfg)
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
                klass = mono_class_get (acfg->image, token);
-               if (!klass)
+               if (!klass) {
+                       mono_loader_clear_error ();
                        continue;
+               }
                full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
                hash = mono_metadata_str_hash (full_name) % table_size;
                g_free (full_name);
@@ -6717,6 +6805,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);
        acfg->unwind_ops = g_ptr_array_new ();
        acfg->method_label_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+       acfg->method_order = g_ptr_array_new ();
        InitializeCriticalSection (&acfg->mutex);
 
        return acfg;
@@ -7030,6 +7119,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_mem_end (acfg);
 
+       if (acfg->need_pt_gnu_stack) {
+               /* This is required so the .so doesn't have an executable stack */
+               /* The bin writer already emits this */
+               if (!acfg->use_bin_writer)
+                       fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
+       }
+
        TV_GETTIME (btv);
 
        acfg->stats.gen_time = TV_ELAPSED (atv, btv);