Merge branch 'master' of http://github.com/mono/mono
[mono.git] / mono / mini / aot-compiler.c
index 2811af7abdf728764c43f464d2ad65810fcc66c9..9814b972d6d6f979058d6569bfaaf0d57b876165 100644 (file)
@@ -882,9 +882,6 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri
        guint8 *code;
        int this_pos = 4;
 
-       if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret))
-               this_pos = 8;
-           
        code = buf;
 
        x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject));
@@ -897,14 +894,10 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri
 #elif defined(TARGET_ARM)
        guint8 buf [128];
        guint8 *code;
-       int this_pos = 0;
 
        code = buf;
 
-       if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret))
-               this_pos = 1;
-
-       ARM_ADD_REG_IMM8 (code, this_pos, this_pos, sizeof (MonoObject));
+       ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject));
 
        emit_bytes (acfg, buf, code - buf);
        /* jump to method */
@@ -923,9 +916,6 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri
 #elif defined(TARGET_POWERPC)
        int this_pos = 3;
 
-       if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret))
-               this_pos = 4;
-
        g_assert (!acfg->use_bin_writer);
 
        fprintf (acfg->fp, "\n\taddi %d, %d, %d\n", this_pos, this_pos, (int)sizeof (MonoObject));
@@ -1070,36 +1060,38 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        /* FIXME: Optimize this, i.e. use binary search etc. */
        /* Maybe move the body into a separate function (slower, but much smaller) */
 
-       /* R10 is a free register */
+       /* R11 is a free register */
 
        labels [0] = code;
-       amd64_alu_membase_imm (code, X86_CMP, AMD64_R10, 0, 0);
+       amd64_alu_membase_imm (code, X86_CMP, AMD64_R11, 0, 0);
        labels [1] = code;
        amd64_branch8 (code, X86_CC_Z, FALSE, 0);
 
        /* Check key */
-       amd64_alu_membase_reg (code, X86_CMP, AMD64_R10, 0, MONO_ARCH_IMT_REG);
+       amd64_alu_membase_reg (code, X86_CMP, AMD64_R11, 0, MONO_ARCH_IMT_REG);
        labels [2] = code;
        amd64_branch8 (code, X86_CC_Z, FALSE, 0);
 
        /* Loop footer */
-       amd64_alu_reg_imm (code, X86_ADD, AMD64_R10, 2 * sizeof (gpointer));
+       amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, 2 * sizeof (gpointer));
        amd64_jump_code (code, labels [0]);
 
        /* Match */
        mono_amd64_patch (labels [2], code);
-       amd64_mov_reg_membase (code, AMD64_R10, AMD64_R10, sizeof (gpointer), 8);
-       amd64_jump_membase (code, AMD64_R10, 0);
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, sizeof (gpointer), 8);
+       amd64_jump_membase (code, AMD64_R11, 0);
 
        /* No match */
        /* FIXME: */
        mono_amd64_patch (labels [1], code);
        x86_breakpoint (code);
 
-       /* mov <OFFSET>(%rip), %r10 */
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 12345678, 8);
+
+       /* mov <OFFSET>(%rip), %r11 */
        emit_byte (acfg, '\x4d');
        emit_byte (acfg, '\x8b');
-       emit_byte (acfg, '\x15');
+       emit_byte (acfg, '\x1d');
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4);
 
        emit_bytes (acfg, buf, code - buf);
@@ -1871,6 +1863,26 @@ compare_patches (gconstpointer a, gconstpointer b)
                return 0;
 }
 
+static G_GNUC_UNUSED char*
+patch_to_string (MonoJumpInfo *patch_info)
+{
+       GString *str;
+
+       str = g_string_new ("");
+
+       g_string_append_printf (str, "%s(", get_patch_name (patch_info->type));
+
+       switch (patch_info->type) {
+       case MONO_PATCH_INFO_VTABLE:
+               mono_type_get_desc (str, &patch_info->data.klass->byval_arg, TRUE);
+               break;
+       default:
+               break;
+       }
+       g_string_append_printf (str, ")");
+       return g_string_free (str, FALSE);
+}
+
 /*
  * is_plt_patch:
  *
@@ -2496,13 +2508,21 @@ method_has_type_vars (MonoMethod *method)
        return FALSE;
 }
 
+static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth);
+
+static void
+add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
+{
+       add_generic_class_with_depth (acfg, klass, 0);
+}
+
 /*
  * add_generic_class:
  *
  *   Add all methods of a generic class.
  */
 static void
-add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
+add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth)
 {
        MonoMethod *method;
        gpointer iter;
@@ -2532,7 +2552,7 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
                 * FIXME: Instances which are referenced by these methods are not added,
                 * for example Array.Resize<int> for List<int>.Add ().
                 */
-               add_extra_method (acfg, method);
+               add_extra_method_with_depth (acfg, method, depth);
        }
 
        if (klass->delegate) {
@@ -2577,7 +2597,7 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
                while ((method = mono_class_get_methods (array_class, &iter))) {
                        if (strstr (method->name, name_prefix)) {
                                MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
-                               add_extra_method (acfg, m);
+                               add_extra_method_with_depth (acfg, m, depth);
                        }
                }
 
@@ -3054,7 +3074,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
        method = cfg->orig_method;
        code = cfg->native_code;
-       header = mono_method_get_header (method);
+       header = cfg->header;
 
        method_index = get_method_index (acfg, method);
 
@@ -3388,7 +3408,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        method = cfg->orig_method;
        code = cfg->native_code;
-       header = mono_method_get_header (method);
+       header = cfg->header;
 
        method_index = get_method_index (acfg, method);
 
@@ -3435,6 +3455,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        /* Exception table */
        if (cfg->compile_llvm) {
+               /*
+                * When using LLVM, we can't emit some data, like pc offsets, this reg/offset etc.,
+                * since the information is only available to llc. Instead, we let llc save the data
+                * into the LSDA, and read it from there at runtime.
+                */
                /* The assembly might be CIL stripped so emit the data ourselves */
                if (header->num_clauses)
                        encode_value (header->num_clauses, p, &p);
@@ -3451,6 +3476,18 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        } else {
                                encode_value (0, p, &p);
                        }
+
+                       /* Emit a list of nesting clauses */
+                       for (i = 0; i < header->num_clauses; ++i) {
+                               gint32 cindex1 = k;
+                               MonoExceptionClause *clause1 = &header->clauses [cindex1];
+                               gint32 cindex2 = i;
+                               MonoExceptionClause *clause2 = &header->clauses [cindex2];
+
+                               if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset)
+                                       encode_value (i, p, &p);
+                       }
+                       encode_value (-1, p, &p);
                }
        } else {
                if (jinfo->num_clauses)
@@ -3482,9 +3519,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        if (jinfo->has_generic_jit_info) {
                MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
 
-               encode_value (gi->has_this ? 1 : 0, p, &p);
-               encode_value (gi->this_reg, p, &p);
-               encode_value (gi->this_offset, p, &p);
+               if (!cfg->compile_llvm) {
+                       encode_value (gi->has_this ? 1 : 0, p, &p);
+                       encode_value (gi->this_reg, p, &p);
+                       encode_value (gi->this_offset, p, &p);
+               }
 
                /* 
                 * Need to encode jinfo->method too, since it is not equal to 'method'
@@ -3551,6 +3590,20 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token)
        gboolean no_special_static, cant_encode;
        gpointer iter = NULL;
 
+       if (!klass) {
+               buf_size = 16;
+
+               p = buf = g_malloc (buf_size);
+
+               /* Mark as unusable */
+               encode_value (-1, p, &p);
+
+               res = add_to_blob (acfg, buf, p - buf);
+               g_free (buf);
+
+               return res;
+       }
+               
        buf_size = 10240 + (klass->vtable_size * 16);
        p = buf = g_malloc (buf_size);
 
@@ -4319,7 +4372,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                                        add_extra_method_with_depth (acfg, m, depth + 1);
                                                }
                                        }
-                                       add_generic_class (acfg, m->klass);
+                                       add_generic_class_with_depth (acfg, m->klass, depth + 5);
                                }
                                if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && !strcmp (m->name, "ElementAddr"))
                                        add_extra_method_with_depth (acfg, m, depth + 1);
@@ -4329,7 +4382,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                MonoClass *klass = patch_info->data.klass;
 
                                if (klass->generic_class && !mono_generic_context_is_sharable (&klass->generic_class->context, FALSE))
-                                       add_generic_class (acfg, klass);
+                                       add_generic_class_with_depth (acfg, klass, depth + 5);
                                break;
                        }
                        default:
@@ -4655,12 +4708,13 @@ emit_llvm_file (MonoAotCompile *acfg)
         * a lot of time, and doesn't seem to save much space.
         * The following optimizations cannot be enabled:
         * - 'tailcallelim'
+        * - 'jump-threading' changes our blockaddress references to int constants.
         * The opt list below was produced by taking the output of:
         * llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
         * 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 -jump-threading -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 -jump-threading -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 -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");
 #if 1
        command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts);
        printf ("Executing opt: %s\n", command);
@@ -5062,7 +5116,7 @@ emit_extra_methods (MonoAotCompile *acfg)
                if (!cfg)
                        continue;
 
-               buf_size = 512;
+               buf_size = 1024;
                p = buf = g_malloc (buf_size);
 
                nmethods ++;
@@ -5310,6 +5364,8 @@ 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)
+                       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);