New test.
[mono.git] / mono / mini / aot-compiler.c
index ae0af34cfab1b6f33e20425f895f170527d6b08c..0afd5ba593f32b784d7f93d424757d18e01bd034 100644 (file)
@@ -57,7 +57,7 @@
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/threads-types.h>
-#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-mmap.h>
@@ -100,6 +100,7 @@ typedef struct MonoAotOptions {
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
+       int nimt_trampolines;
        gboolean print_skipped_methods;
        gboolean stats;
        char *tool_prefix;
@@ -161,10 +162,12 @@ typedef struct MonoAotCompile {
        GHashTable *unwind_info_offsets;
        GPtrArray *unwind_ops;
        guint32 unwind_info_offset;
+       char *got_symbol_base;
        char *got_symbol;
        char *plt_symbol;
        GHashTable *method_label_hash;
        const char *temp_prefix;
+       const char *llvm_label_prefix;
        guint32 label_generator;
        gboolean llvm;
        MonoAotFileFlags flags;
@@ -454,6 +457,23 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
 #define PPC_LDX_OP "lwzx"
 #endif
 
+//#define TARGET_ARM
+
+#ifdef TARGET_ARM
+#define LLVM_LABEL_PREFIX "_"
+#else
+#define LLVM_LABEL_PREFIX ""
+#endif
+
+#ifdef TARGET_ARM
+/* iphone */
+#define LLC_TARGET_ARGS "-march=arm -mattr=+v6 -mtriple=arm-apple-darwin"
+/* ELF */
+//#define LLC_TARGET_ARGS "-march=arm -mtriple=arm-linux-gnueabi -soft-float"
+#else
+#define LLC_TARGET_ARGS ""
+#endif
+
 /*
  * arch_emit_direct_call:
  *
@@ -1118,7 +1138,7 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
        img_writer_emit_unset_mode (acfg->w);
 
        fprintf (acfg->fp,
-#ifdef _MSC_VER  
+#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE) 
                         ".section      .ctors,\"aw\",@progbits\n"
                         ".align 2\n"
                         ".globl        %s\n"
@@ -1130,6 +1150,7 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
                         ".size %s,.-%s\n"
                         ".section .text\n"
                         ".type .%s,@function\n"
+                        ".align 2\n"
                         ".%s:\n", symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol);
 #else
                         ".section      .ctors,\"aw\",@progbits\n"
@@ -1143,6 +1164,7 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
                         ".size %1$s,.-%1$s\n"
                         ".section .text\n"
                         ".type .%1$s,@function\n"
+                        ".align 2\n"
                         ".%1$s:\n", symbol);
 #endif
 
@@ -1164,7 +1186,7 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
                         "mr 1,11\n"
                         "blr\n"
                         );
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE) 
                fprintf (acfg->fp,
                         ".size .%s,.-.%s\n", symbol, symbol);
 #else
@@ -1175,32 +1197,6 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
 #endif
 }
 
-/*
- * arch_get_cie_program:
- *
- *   Get the unwind bytecode for the DWARF CIE.
- */
-static GSList*
-arch_get_cie_program (void)
-{
-#ifdef TARGET_AMD64
-       GSList *l = NULL;
-
-       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, AMD64_RSP, 8);
-       mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, AMD64_RIP, -8);
-
-       return l;
-#elif defined(TARGET_POWERPC)
-       GSList *l = NULL;
-
-       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0);
-
-       return l;
-#else
-       return NULL;
-#endif
-}
-
 /* END OF ARCH SPECIFIC CODE */
 
 static guint32
@@ -1597,7 +1593,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                case MONO_WRAPPER_LDFLDA:
                case MONO_WRAPPER_STFLD:
                case MONO_WRAPPER_ISINST: {
-                       MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (method);
+                       MonoClass *proxy_class = mono_marshal_get_wrapper_info (method);
                        encode_klass_ref (acfg, proxy_class, p, &p);
                        break;
                }
@@ -1605,11 +1601,14 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                case MONO_WRAPPER_STFLD_REMOTE:
                        break;
                case MONO_WRAPPER_ALLOC: {
-                       int alloc_type = mono_gc_get_managed_allocator_type (method);
-                       g_assert (alloc_type != -1);
-                       encode_value (alloc_type, p, &p);
+                       AllocatorWrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+                       g_assert (info->alloc_type != -1);
+                       encode_value (info->alloc_type, p, &p);
                        break;
                }
+               case MONO_WRAPPER_WRITE_BARRIER:
+                       break;
                case MONO_WRAPPER_STELEMREF:
                        break;
                case MONO_WRAPPER_UNKNOWN:
@@ -1631,6 +1630,18 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                        encode_method_ref (acfg, m, p, &p);
                        break;
                }
+               case MONO_WRAPPER_MANAGED_TO_MANAGED:
+                       if (!strcmp (method->name, "ElementAddr")) {
+                               ElementAddrWrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+                               g_assert (info);
+                               encode_value (MONO_AOT_WRAPPER_ELEMENT_ADDR, p, &p);
+                               encode_value (info->rank, p, &p);
+                               encode_value (info->elem_size, p, &p);
+                       } else {
+                               g_assert_not_reached ();
+                       }
+                       break;
                default:
                        g_assert_not_reached ();
                }
@@ -1807,11 +1818,12 @@ get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
        if (got_offset)
                return got_offset - 1;
 
-       g_assert (!acfg->final_got_size);
-
        got_offset = acfg->got_offset;
        acfg->got_offset ++;
 
+       if (acfg->final_got_size)
+               g_assert (got_offset < acfg->final_got_size);
+
        acfg->stats.got_slots ++;
        acfg->stats.got_slot_types [ji->type] ++;
 
@@ -1950,7 +1962,7 @@ can_marshal_struct (MonoClass *klass)
                case MONO_TYPE_STRING:
                        break;
                case MONO_TYPE_VALUETYPE:
-                       if (!can_marshal_struct (mono_class_from_mono_type (field->type)))
+                       if (!mono_class_from_mono_type (field->type)->enumtype && !can_marshal_struct (mono_class_from_mono_type (field->type)))
                                can_marshal = FALSE;
                        break;
                default:
@@ -2015,8 +2027,14 @@ add_wrappers (MonoAotCompile *acfg)
 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
                if (!method->klass->contextbound) {
                        MonoDynCallInfo *info = mono_arch_dyn_call_prepare (sig);
+                       gboolean has_nullable = FALSE;
 
-                       if (info) {
+                       for (j = 0; j < sig->param_count; j++) {
+                               if (sig->params [j]->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->params [j])))
+                                       has_nullable = TRUE;
+                       }
+
+                       if (info && !has_nullable) {
                                /* Supported by the dynamic runtime-invoke wrapper */
                                skip = TRUE;
                                g_free (info);
@@ -2185,7 +2203,7 @@ add_wrappers (MonoAotCompile *acfg)
                token = MONO_TOKEN_METHOD_DEF | (i + 1);
                method = mono_get_method (acfg->image, token, NULL);
 
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+               if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !method->is_generic)
                        add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
        }
 
@@ -2201,6 +2219,69 @@ add_wrappers (MonoAotCompile *acfg)
                        add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
                }
        }
+       /* native-to-managed wrappers */
+       for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               MonoMethod *method;
+               guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
+               MonoCustomAttrInfo *cattr;
+               int j;
+
+               method = mono_get_method (acfg->image, token, NULL);
+
+               /* 
+                * Only generate native-to-managed wrappers for methods which have an
+                * attribute named MonoPInvokeCallbackAttribute. We search for the attribute by
+                * name to avoid defining a new assembly to contain it.
+                */
+               cattr = mono_custom_attrs_from_method (method);
+
+               if (cattr) {
+                       for (j = 0; j < cattr->num_attrs; ++j)
+                               if (cattr->attrs [j].ctor && !strcmp (cattr->attrs [j].ctor->klass->name, "MonoPInvokeCallbackAttribute"))
+                                       break;
+                       if (j < cattr->num_attrs) {
+                               MonoCustomAttrEntry *e = &cattr->attrs [j];
+                               MonoMethodSignature *sig = mono_method_signature (e->ctor);
+                               const char *p = (const char*)e->data;
+                               int slen;
+                               char *n;
+                               MonoType *t;
+                               MonoClass *klass;
+
+                               g_assert (method->flags & METHOD_ATTRIBUTE_STATIC);
+
+                               g_assert (sig->param_count == 1);
+                               g_assert (sig->params [0]->type == MONO_TYPE_CLASS && !strcmp (mono_class_from_mono_type (sig->params [0])->name, "Type"));
+
+                               /* 
+                                * Decode the cattr manually since we can't create objects
+                                * during aot compilation.
+                                */
+                                       
+                               /* Skip prolog */
+                               p += 2;
+
+                               /* From load_cattr_value () in reflection.c */
+                               slen = mono_metadata_decode_value (p, &p);
+                               n = g_memdup (p, slen + 1);
+                               n [slen] = 0;
+                               t = mono_reflection_type_from_name (n, acfg->image);
+                               g_assert (t);
+                               g_free (n);
+
+                               klass = mono_class_from_mono_type (t);
+                               g_assert (klass->parent == mono_defaults.multicastdelegate_class);
+
+                               add_method (acfg, mono_marshal_get_managed_wrapper (method, klass, NULL));
+                       }
+               }
+
+               if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+                       (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+                       add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
+               }
+       }
 
        /* StructureToPtr/PtrToStructure wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
@@ -2279,7 +2360,7 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
 
        iter = NULL;
        while ((method = mono_class_get_methods (klass, &iter))) {
-               if (mono_method_is_generic_sharable_impl (method, FALSE))
+               if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
                        /* Already added */
                        continue;
 
@@ -2400,18 +2481,98 @@ add_generic_instances (MonoAotCompile *acfg)
                token = MONO_TOKEN_METHOD_SPEC | (i + 1);
                method = mono_get_method (acfg->image, token, NULL);
 
-               context = mono_method_get_context (method);
-               if (context && ((context->class_inst && context->class_inst->is_open) ||
-                                               (context->method_inst && context->method_inst->is_open)))
+               if (method->klass->image != acfg->image)
                        continue;
 
-               if (method->klass->image != acfg->image)
+               context = mono_method_get_context (method);
+
+               if (context && ((context->class_inst && context->class_inst->is_open)))
                        continue;
 
-               if (mono_method_is_generic_sharable_impl (method, FALSE))
-                       /* Already added */
+               /*
+                * For open methods, create an instantiation which can be passed to the JIT.
+                * FIXME: Handle class_inst as well.
+                */
+               if (context && context->method_inst && context->method_inst->is_open) {
+                       MonoGenericContext shared_context;
+                       MonoGenericInst *inst;
+                       MonoType **type_argv;
+                       int i;
+                       MonoMethod *declaring_method;
+                       gboolean supported = TRUE;
+
+                       /* Check that the context doesn't contain open constructed types */
+                       if (context->class_inst) {
+                               inst = context->class_inst;
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               continue;
+                                       if (mono_class_is_open_constructed_type (inst->type_argv [i]))
+                                               supported = FALSE;
+                               }
+                       }
+                       if (context->method_inst) {
+                               inst = context->method_inst;
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               continue;
+                                       if (mono_class_is_open_constructed_type (inst->type_argv [i]))
+                                               supported = FALSE;
+                               }
+                       }
+
+                       if (!supported)
+                               continue;
+
+                       memset (&shared_context, 0, sizeof (MonoGenericContext));
+
+                       inst = context->class_inst;
+                       if (inst) {
+                               type_argv = g_new0 (MonoType*, inst->type_argc);
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               type_argv [i] = &mono_defaults.object_class->byval_arg;
+                                       else
+                                               type_argv [i] = inst->type_argv [i];
+                               }
+                               
+                               shared_context.class_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
+                               g_free (type_argv);
+                       }
+
+                       inst = context->method_inst;
+                       if (inst) {
+                               type_argv = g_new0 (MonoType*, inst->type_argc);
+                               for (i = 0; i < inst->type_argc; ++i) {
+                                       if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
+                                               type_argv [i] = &mono_defaults.object_class->byval_arg;
+                                       else
+                                               type_argv [i] = inst->type_argv [i];
+                               }
+
+                               shared_context.method_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
+                               g_free (type_argv);
+                       }
+
+                       if (method->is_generic || method->klass->generic_container)
+                               declaring_method = method;
+                       else
+                               declaring_method = mono_method_get_declaring_generic_method (method);
+
+                       method = mono_class_inflate_generic_method (declaring_method, &shared_context);
+               }
+
+               /* 
+                * If the method is fully sharable, it was already added in place of its
+                * generic definition.
+                */
+               if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE))
                        continue;
 
+               /*
+                * FIXME: Partially shared methods are not shared here, so we end up with
+                * many identical methods.
+                */
                add_extra_method (acfg, method);
        }
 
@@ -2607,7 +2768,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                                MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
                                                //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
                                                direct_call = TRUE;
-                                               sprintf (direct_call_target, "%sm_%x", acfg->temp_prefix, get_method_index (acfg, callee_cfg->orig_method));
+                                               sprintf (direct_call_target, callee_cfg->asm_symbol);
                                                patch_info->type = MONO_PATCH_INFO_NONE;
                                                acfg->stats.direct_calls ++;
                                        }
@@ -2620,7 +2781,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                        if (plt_offset != -1) {
                                                /* This patch has a PLT entry, so we must emit a call to the PLT entry */
                                                direct_call = TRUE;
-                                               sprintf (direct_call_target, "%sp_%d", acfg->temp_prefix, plt_offset);
+                                               sprintf (direct_call_target, "%s%sp_%d", acfg->llvm_label_prefix, acfg->temp_prefix, plt_offset);
                
                                                /* Nullify the patch */
                                                patch_info->type = MONO_PATCH_INFO_NONE;
@@ -2737,28 +2898,8 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
        method_index = get_method_index (acfg, method);
 
-       /* 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);
-               } else {
-                       sprintf (symbol, "ut_e_%d", get_method_index (acfg, method));
-               }
-
-               emit_section_change (acfg, ".text", 0);
-               emit_global (acfg, symbol, TRUE);
-               emit_label (acfg, symbol);
-
-               sprintf (call_target, "%sm_%x", acfg->temp_prefix, method_index);
-
-               arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target);
-       }
-
        /* Make the labels local */
-       sprintf (symbol, "%sm_%x", acfg->temp_prefix, method_index);
+       sprintf (symbol, "%s", cfg->asm_symbol);
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment (acfg, func_alignment);
@@ -3083,7 +3224,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        MonoJitInfo *jinfo = cfg->jit_info;
        guint32 flags;
        gboolean use_unwind_ops = FALSE;
-       GPtrArray *seq_points;
+       MonoSeqPointInfo *seq_points;
 
        method = cfg->orig_method;
        code = cfg->native_code;
@@ -3098,15 +3239,15 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                debug_info_size = 0;
        }
 
-       buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (cfg->seq_points ? (cfg->seq_points->len * 16) : 0);
+       seq_points = cfg->seq_point_info;
+
+       buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0);
        p = buf = g_malloc (buf_size);
 
 #ifdef MONO_ARCH_HAVE_XP_UNWIND
        use_unwind_ops = cfg->unwind_ops != NULL;
 #endif
 
-       seq_points = cfg->seq_points;
-
        flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0) | (cfg->compile_llvm ? 16 : 0);
 
        encode_value (flags, p, &p);
@@ -3127,29 +3268,49 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        }
 
        /* Exception table */
-       if (jinfo->num_clauses)
-               encode_value (jinfo->num_clauses, p, &p);
+       if (cfg->compile_llvm) {
+               /* The assembly might be CIL stripped so emit the data ourselves */
+               if (header->num_clauses)
+                       encode_value (header->num_clauses, p, &p);
 
-       for (k = 0; k < jinfo->num_clauses; ++k) {
-               MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+               for (k = 0; k < header->num_clauses; ++k) {
+                       MonoExceptionClause *clause;
 
-               encode_value (ei->flags, p, &p);
-               encode_value (ei->exvar_offset, p, &p);
+                       clause = &header->clauses [k];
 
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
-                       encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
-               else {
-                       if (ei->data.catch_class) {
+                       encode_value (clause->flags, p, &p);
+                       if (clause->data.catch_class) {
                                encode_value (1, p, &p);
-                               encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                               encode_klass_ref (acfg, clause->data.catch_class, p, &p);
                        } else {
                                encode_value (0, p, &p);
                        }
                }
+       } else {
+               if (jinfo->num_clauses)
+                       encode_value (jinfo->num_clauses, p, &p);
+
+               for (k = 0; k < jinfo->num_clauses; ++k) {
+                       MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+
+                       encode_value (ei->flags, p, &p);
+                       encode_value (ei->exvar_offset, p, &p);
+
+                       if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
+                               encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
+                       else {
+                               if (ei->data.catch_class) {
+                                       encode_value (1, p, &p);
+                                       encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                               } else {
+                                       encode_value (0, p, &p);
+                               }
+                       }
 
-               encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
-               encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
-               encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
+                       encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
+               }
        }
 
        if (jinfo->has_generic_jit_info) {
@@ -3167,17 +3328,22 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        }
 
        if (seq_points) {
-               int il_offset, native_offset, last_il_offset, last_native_offset;
+               int il_offset, native_offset, last_il_offset, last_native_offset, j;
 
                encode_value (seq_points->len, p, &p);
                last_il_offset = last_native_offset = 0;
-               for (i = 0; i < seq_points->len; i += 2) {
-                       il_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i));
-                       native_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i + 1));
+               for (i = 0; i < seq_points->len; ++i) {
+                       SeqPoint *sp = &seq_points->seq_points [i];
+                       il_offset = sp->il_offset;
+                       native_offset = sp->native_offset;
                        encode_value (il_offset - last_il_offset, p, &p);
                        encode_value (native_offset - last_native_offset, p, &p);
                        last_il_offset = il_offset;
                        last_native_offset = native_offset;
+
+                       encode_value (sp->next_len, p, &p);
+                       for (j = 0; j < sp->next_len; ++j)
+                               encode_value (sp->next [j], p, &p);
                }
        }
                
@@ -3309,7 +3475,7 @@ emit_plt (MonoAotCompile *acfg)
                char *debug_sym = NULL;
                MonoJumpInfo *ji;
 
-               sprintf (label, "%sp_%d", acfg->temp_prefix, i);
+               sprintf (label, "%s%sp_%d", acfg->llvm_label_prefix, acfg->temp_prefix, i);
 
                if (acfg->llvm) {
                        /*
@@ -3322,7 +3488,7 @@ emit_plt (MonoAotCompile *acfg)
                        ji = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
                        if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
                                MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
-                               fprintf (acfg->fp, "\n.set %s, .Lm_%x\n", label, get_method_index (acfg, callee_cfg->orig_method));
+                               fprintf (acfg->fp, "\n.set %s, %s\n", label, callee_cfg->asm_symbol);
                                continue;
                        }
                }
@@ -3479,7 +3645,7 @@ emit_trampolines (MonoAotCompile *acfg)
        
        g_assert (acfg->image->assembly);
 
-       /* Currently, we only emit most trampolines into the mscorlib AOT image. */
+       /* Currently, we emit most trampolines into the mscorlib AOT image. */
        if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
                /*
@@ -3520,8 +3686,10 @@ emit_trampolines (MonoAotCompile *acfg)
                emit_trampoline (acfg, "throw_exception", code, code_size, acfg->got_offset, ji, NULL);
                code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
                emit_trampoline (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji, NULL);
+#ifdef MONO_ARCH_HAVE_THROW_EXCEPTION_BY_NAME
                code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
                emit_trampoline (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji, NULL);
+#endif
                code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
                emit_trampoline (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji, NULL);
 
@@ -3693,12 +3861,12 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->ntrampolines = atoi (arg + strlen ("ntrampolines="));
                } else if (str_begins_with (arg, "nrgctx-trampolines=")) {
                        opts->nrgctx_trampolines = atoi (arg + strlen ("nrgctx-trampolines="));
+               } else if (str_begins_with (arg, "nimt-trampolines=")) {
+                       opts->nimt_trampolines = atoi (arg + strlen ("nimt-trampolines="));
                } else if (str_begins_with (arg, "autoreg")) {
                        opts->autoreg = TRUE;
                } else if (str_begins_with (arg, "tool-prefix=")) {
                        opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
-               } else if (str_begins_with (arg, "autoreg")) {
-                       opts->autoreg = TRUE;
                } else if (str_begins_with (arg, "soft-debug")) {
                        opts->soft_debug = TRUE;
                } else if (str_begins_with (arg, "print-skipped")) {
@@ -3763,7 +3931,13 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                        case MONO_WRAPPER_ALLOC:
                        case MONO_WRAPPER_REMOTING_INVOKE:
                        case MONO_WRAPPER_UNKNOWN:
+                       case MONO_WRAPPER_WRITE_BARRIER:
                                break;
+                       case MONO_WRAPPER_MANAGED_TO_MANAGED:
+                               if (!strcmp (method->name, "ElementAddr"))
+                                       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;
@@ -3967,6 +4141,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                        }
                                        add_generic_class (acfg, m->klass);
                                }
+                               if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && !strcmp (m->name, "ElementAddr"))
+                                       add_extra_method_with_depth (acfg, m, depth + 1);
                                break;
                        }
                        case MONO_PATCH_INFO_VTABLE: {
@@ -4123,7 +4299,7 @@ load_profile_files (MonoAotCompile *acfg)
 
        file_index = 0;
        while (TRUE) {
-               tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%s-%d", g_get_home_dir (), acfg->image->assembly_name, acfg->image->guid, file_index);
+               tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%d", g_get_home_dir (), acfg->image->assembly_name, file_index);
 
                if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) {
                        g_free (tmp);
@@ -4139,21 +4315,38 @@ load_profile_files (MonoAotCompile *acfg)
                file_index ++;
 
                res = fscanf (infile, "%32s\n", ver);
-               if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
+               if ((res != 1) || strcmp (ver, "#VER:2") != 0) {
                        printf ("Profile file has wrong version or invalid.\n");
                        fclose (infile);
                        continue;
                }
 
                while (TRUE) {
-                       res = fscanf (infile, "%d\n", &token);
-                       if (res < 1)
+                       char name [1024];
+                       MonoMethodDesc *desc;
+                       MonoMethod *method;
+
+                       if (fgets (name, 1023, infile) == NULL)
                                break;
 
-                       method_index = mono_metadata_token_index (token) - 1;
+                       /* Kill the newline */
+                       if (strlen (name) > 0)
+                               name [strlen (name) - 1] = '\0';
+
+                       desc = mono_method_desc_new (name, TRUE);
+
+                       method = mono_method_desc_search_in_image (desc, acfg->image);
 
-                       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));
+                       if (method && mono_method_get_token (method)) {
+                               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));
+                               }
+                       } else {
+                               //printf ("No method found matching '%s'.\n", name);
+                       }
                }
                fclose (infile);
        }
@@ -4183,7 +4376,6 @@ mono_aot_get_method_name (MonoCompile *cfg)
 {
        guint32 method_index = get_method_index (llvm_acfg, cfg->orig_method);
 
-       /* LLVM converts these to .Lm_%x */
        return g_strdup_printf ("m_%x", method_index);
 }
 
@@ -4207,7 +4399,7 @@ mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 
        offset = get_plt_offset (llvm_acfg, ji);
 
-       return g_strdup_printf (".Lp_%d", offset);
+       return g_strdup_printf ("%sp_%d", llvm_acfg->temp_prefix, offset);
 }
 
 MonoJumpInfo*
@@ -4236,6 +4428,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        char *command, *opts;
        int i;
        MonoJumpInfo *patch_info;
+       char *llc_target_args;
 
        /*
         * When using LLVM, we let llvm emit the got since the LLVM IL needs to refer
@@ -4255,22 +4448,41 @@ emit_llvm_file (MonoAotCompile *acfg)
                        }
                }
        }
+
        acfg->final_got_size = acfg->got_offset + acfg->plt_offset;
 
+       if (acfg->aot_opts.full_aot) {
+               int ntype;
+
+               /* 
+                * Need to add the got entries used by the trampolines.
+                * This is only a conservative approximation.
+                */
+               if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
+                       /* For the generic + rgctx trampolines */
+                       acfg->final_got_size += 200;
+                       /* For the specific trampolines */
+                       for (ntype = 0; ntype < MONO_AOT_TRAMP_NUM; ++ntype)
+                               acfg->final_got_size += acfg->num_trampolines [ntype] * 2;
+               }
+       }
+
+
        mono_llvm_emit_aot_module ("temp.bc", acfg->final_got_size);
 
        /*
         * FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
         * a lot of time, and doesn't seem to save much space.
         * The following optimizations cannot be enabled:
-        * - 'globalopt', which seems to remove our methods, even though they have a global
-        *   alias pointing at them.
-        * - 'constmerge'/'globaldce', which seems to remove our got symbol.
         * - 'tailcallelim'
+        * 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");
 #if 1
-       command = g_strdup_printf ("opt -f %s -o temp.bc temp.bc", opts);
+       command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts);
        printf ("Executing opt: %s\n", command);
        if (system (command) != 0) {
                exit (1);
@@ -4278,8 +4490,11 @@ emit_llvm_file (MonoAotCompile *acfg)
 #endif
        g_free (opts);
 
-       //command = g_strdup_printf ("llc -march=arm -mtriple=arm-linux-gnueabi -f -relocation-model=pic -unwind-tables temp.bc");
-       command = g_strdup_printf ("llc -f -relocation-model=pic -unwind-tables -o temp.s temp.bc");
+       llc_target_args = g_strdup (LLC_TARGET_ARGS);
+
+       command = g_strdup_printf ("llc %s -f -relocation-model=pic -unwind-tables -o %s temp.opt.bc", llc_target_args, acfg->tmpfname);
+       g_free (llc_target_args);
+
        printf ("Executing llc: %s\n", command);
 
        if (system (command) != 0) {
@@ -4293,6 +4508,7 @@ emit_code (MonoAotCompile *acfg)
 {
        int i;
        char symbol [256];
+       char end_symbol [256];
        GList *l;
 
 #if defined(TARGET_POWERPC64)
@@ -4303,11 +4519,26 @@ emit_code (MonoAotCompile *acfg)
        emit_pointer (acfg, acfg->got_symbol);
 #endif
 
-       if (!acfg->llvm) {
-               sprintf (symbol, "methods");
-               emit_section_change (acfg, ".text", 0);
-               emit_global (acfg, symbol, TRUE);
-               emit_alignment (acfg, 8);
+       /* 
+        * This global symbol is used to compute the address of each method using the
+        * code_offsets array. It is also used to compute the memory ranges occupied by
+        * AOT code, so it must be equal to the address of the first emitted method.
+        */
+       sprintf (symbol, "methods");
+       emit_section_change (acfg, ".text", 0);
+       emit_global (acfg, symbol, TRUE);
+       emit_alignment (acfg, 8);
+       if (acfg->llvm) {
+               for (i = 0; i < acfg->nmethods; ++i) {
+                       if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) {
+                               fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol);
+                               break;
+                       }
+               }
+               if (i == acfg->nmethods)
+                       /* No LLVM compiled methods */
+                       emit_label (acfg, symbol);
+       } else {
                emit_label (acfg, symbol);
        }
 
@@ -4318,14 +4549,42 @@ emit_code (MonoAotCompile *acfg)
        emit_zero_bytes (acfg, 16);
 
        for (l = acfg->method_order; l != NULL; l = l->next) {
+               MonoCompile *cfg;
+               MonoMethod *method;
+
                i = GPOINTER_TO_UINT (l->data);
 
-               if (acfg->cfgs [i]) {
-                       if (acfg->cfgs [i]->compile_llvm)
-                               acfg->stats.llvm_count ++;
-                       else
-                               emit_method_code (acfg, acfg->cfgs [i]);
+               cfg = acfg->cfgs [i];
+
+               if (!cfg)
+                       continue;
+
+               method = cfg->orig_method;
+
+               /* 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);
+                       } else {
+                               sprintf (symbol, "ut_e_%d", get_method_index (acfg, method));
+                       }
+
+                       emit_section_change (acfg, ".text", 0);
+                       emit_global (acfg, symbol, TRUE);
+                       emit_label (acfg, symbol);
+
+                       sprintf (call_target, "%s", cfg->asm_symbol);
+
+                       arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target);
                }
+
+               if (cfg->compile_llvm)
+                       acfg->stats.llvm_count ++;
+               else
+                       emit_method_code (acfg, cfg);
        }
 
        sprintf (symbol, "methods_end");
@@ -4342,10 +4601,10 @@ emit_code (MonoAotCompile *acfg)
 
        acfg->stats.offsets_size += acfg->nmethods * 4;
 
+       sprintf (end_symbol, "methods");
        for (i = 0; i < acfg->nmethods; ++i) {
                if (acfg->cfgs [i]) {
-                       sprintf (symbol, "%sm_%x", acfg->temp_prefix, i);
-                       emit_symbol_diff (acfg, symbol, "methods", 0);
+                       emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
                } else {
                        emit_int32 (acfg, 0xffffffff);
                }
@@ -4387,27 +4646,6 @@ emit_info (MonoAotCompile *acfg)
 
 #endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
 
-/*
- * mono_aot_str_hash:
- *
- * Hash function for strings which we use to hash strings for things which are
- * saved in the AOT image, since g_str_hash () can change.
- */
-guint
-mono_aot_str_hash (gconstpointer v1)
-{
-       /* Same as g_str_hash () in glib */
-       char *p = (char *) v1;
-       guint hash = *p;
-
-       while (*p++) {
-               if (*p)
-                       hash = (hash << 5) - hash + *p;
-       }
-
-       return hash;
-} 
-
 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
 #define mix(a,b,c) { \
        a -= c;  a ^= rot(c, 4);  c += b; \
@@ -4438,11 +4676,11 @@ mono_aot_type_hash (MonoType *t1)
        case MONO_TYPE_CLASS:
        case MONO_TYPE_SZARRAY:
                /* check if the distribution is good enough */
-               return ((hash << 5) - hash) ^ mono_aot_str_hash (t1->data.klass->name);
+               return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
        case MONO_TYPE_PTR:
-               return ((hash << 5) - hash) ^ mono_aot_type_hash (t1->data.type);
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
        case MONO_TYPE_ARRAY:
-               return ((hash << 5) - hash) ^ mono_aot_type_hash (&t1->data.array->eklass->byval_arg);
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
        case MONO_TYPE_GENERICINST:
                return ((hash << 5) - hash) ^ 0;
        }
@@ -4481,18 +4719,18 @@ mono_aot_method_hash (MonoMethod *method)
        if (!method->wrapper_type) {
                char *full_name = mono_type_full_name (&klass->byval_arg);
 
-               hashes [0] = mono_aot_str_hash (full_name);
+               hashes [0] = mono_metadata_str_hash (full_name);
                hashes [1] = 0;
                g_free (full_name);
        } else {
-               hashes [0] = mono_aot_str_hash (klass->name);
-               hashes [1] = mono_aot_str_hash (klass->name_space);
+               hashes [0] = mono_metadata_str_hash (klass->name);
+               hashes [1] = mono_metadata_str_hash (klass->name_space);
        }
        if (method->wrapper_type == MONO_WRAPPER_STFLD || method->wrapper_type == MONO_WRAPPER_LDFLD || method->wrapper_type == MONO_WRAPPER_LDFLDA)
                /* The method name includes a stringified pointer */
                hashes [2] = 0;
        else
-               hashes [2] = mono_aot_str_hash (method->name);
+               hashes [2] = mono_metadata_str_hash (method->name);
        hashes [3] = method->wrapper_type;
        hashes [4] = mono_aot_type_hash (sig->ret);
        for (i = 0; i < sig->param_count; i++) {
@@ -4549,12 +4787,6 @@ mono_aot_wrapper_name (MonoMethod *method)
                else
                        name = g_strdup_printf ("%s (%s)", method->name, tmpsig);
                break;
-       case MONO_WRAPPER_DELEGATE_INVOKE:
-       case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
-       case MONO_WRAPPER_DELEGATE_END_INVOKE:
-               /* This is a hack to work around the fact that these wrappers get assigned to some random class */
-               name = g_strdup_printf ("%s (%s)", method->name, tmpsig);
-               break;
        default:
                klass_desc = mono_type_full_name (&method->klass->byval_arg);
                name = g_strdup_printf ("%s:%s (%s)", klass_desc, method->name, tmpsig);
@@ -4669,6 +4901,8 @@ emit_extra_methods (MonoAotCompile *acfg)
 
                nmethods ++;
 
+               method = cfg->method_to_register;
+
                name = NULL;
                if (method->wrapper_type) {
                        /* 
@@ -4911,7 +5145,7 @@ emit_class_name_table (MonoAotCompile *acfg)
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
                klass = mono_class_get (acfg->image, token);
                full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
-               hash = mono_aot_str_hash (full_name) % table_size;
+               hash = mono_metadata_str_hash (full_name) % table_size;
                g_free (full_name);
 
                /* FIXME: Allocate from the mempool */
@@ -5115,7 +5349,7 @@ emit_globals_table (MonoAotCompile *acfg)
        for (i = 0; i < acfg->globals->len; ++i) {
                char *name = g_ptr_array_index (acfg->globals, i);
 
-               hash = mono_aot_str_hash (name) % table_size;
+               hash = mono_metadata_str_hash (name) % table_size;
 
                /* FIXME: Allocate from the mempool */
                new_entry = g_new0 (GlobalsTableEntry, 1);
@@ -5341,7 +5575,7 @@ emit_dwarf_info (MonoAotCompile *acfg)
                if (cfg->compile_llvm)
                        continue;
 
-               sprintf (symbol, "%sm_%x", acfg->temp_prefix, i);
+               sprintf (symbol, "%s", cfg->asm_symbol);
                sprintf (symbol2, "%sme_%x", acfg->temp_prefix, i);
 
                mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, symbol, symbol2, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
@@ -5660,7 +5894,7 @@ int
 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 {
        MonoImage *image = ass->image;
-       int res;
+       int i, res;
        MonoAotCompile *acfg;
        char *outfile_name, *tmp_outfile_name, *p;
        TV_DECLARE (atv);
@@ -5674,6 +5908,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        acfg->aot_opts.write_symbols = TRUE;
        acfg->aot_opts.ntrampolines = 1024;
        acfg->aot_opts.nrgctx_trampolines = 1024;
+       acfg->aot_opts.nimt_trampolines = 128;
 
        mono_aot_parse_options (aot_options, &acfg->aot_opts);
 
@@ -5719,13 +5954,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef MONO_ARCH_HAVE_STATIC_RGCTX_TRAMPOLINE
        acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0;
 #endif
-       acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? 128 : 0;
+       acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? acfg->aot_opts.nimt_trampolines : 0;
 
-       acfg->got_symbol = g_strdup_printf ("mono_aot_%s_got", acfg->image->assembly->aname.name);
+       acfg->got_symbol_base = g_strdup_printf ("mono_aot_%s_got", acfg->image->assembly->aname.name);
        acfg->plt_symbol = g_strdup_printf ("mono_aot_%s_plt", acfg->image->assembly->aname.name);
 
        /* Get rid of characters which cannot occur in symbols */
-       for (p = acfg->got_symbol; *p; ++p) {
+       for (p = acfg->got_symbol_base; *p; ++p) {
                if (!(isalnum (*p) || *p == '_'))
                        *p = '_';
        }
@@ -5734,6 +5969,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        *p = '_';
        }
 
+       acfg->temp_prefix = img_writer_get_temp_label_prefix (NULL);
+
        acfg->method_index = 1;
 
        collect_methods (acfg);
@@ -5746,7 +5983,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
 #ifdef ENABLE_LLVM
        llvm_acfg = acfg;
-       mono_llvm_create_aot_module (acfg->got_symbol);
+       mono_llvm_create_aot_module (acfg->got_symbol_base);
 #endif
 
        /* GOT offset 0 is reserved for the address of the current assembly */
@@ -5776,6 +6013,17 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        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);
+                       else
+                               acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
+               } else {
+                       acfg->tmpfname = g_strdup ("temp.s");
+               }
+       }
+
        emit_llvm_file (acfg);
 #endif
 
@@ -5803,8 +6051,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                if (acfg->llvm) {
                        /* Append to the .s file created by llvm */
                        /* FIXME: Use multiple files instead */
-                       acfg->tmpfname = g_strdup ("temp.s");
-                       acfg->fp = fopen (acfg->tmpfname, "a");
+                       acfg->fp = fopen (acfg->tmpfname, "a+");
                } else {
                        if (acfg->aot_opts.asm_only) {
                                if (acfg->aot_opts.outfile)
@@ -5824,7 +6071,27 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                outfile_name = NULL;
        }
 
-       acfg->temp_prefix = img_writer_get_temp_label_prefix (acfg->w);
+       /*
+        * The prefix LLVM likes to put in front of symbol names on darwin.
+        * The mach-os specs require this for globals, but LLVM puts them in front of all
+        * symbols. We need to handle this, since we need to refer to LLVM generated
+        * symbols.
+        */
+       acfg->llvm_label_prefix = "";
+       if (acfg->llvm)
+               acfg->llvm_label_prefix = LLVM_LABEL_PREFIX;
+
+       acfg->got_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, acfg->got_symbol_base);
+
+       /* Compute symbols for methods */
+       for (i = 0; i < acfg->nmethods; ++i) {
+               if (acfg->cfgs [i]) {
+                       MonoCompile *cfg = acfg->cfgs [i];
+                       int method_index = get_method_index (acfg, cfg->orig_method);
+
+                       cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, LLVM_LABEL_PREFIX, method_index);
+               }
+       }
 
        if (!acfg->aot_opts.nodebug)
                acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE);
@@ -5832,7 +6099,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        img_writer_emit_start (acfg->w);
 
        if (acfg->dwarf)
-               mono_dwarf_writer_emit_base_info (acfg->dwarf, arch_get_cie_program ());
+               mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_unwind_get_cie_program ());
 
        emit_code (acfg);
 
@@ -5878,7 +6145,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        acfg->stats.gen_time = TV_ELAPSED (atv, btv);
 
        if (acfg->llvm)
-               g_assert (acfg->got_offset == acfg->final_got_size);
+               g_assert (acfg->got_offset <= acfg->final_got_size);
 
        printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);
 
@@ -5934,311 +6201,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        
        return 0;
 }
-/*
- * Support for emitting debug info for JITted code.
- *
- *   This works as follows:
- * - the runtime writes out an xdb.s file containing DWARF debug info.
- * - the user calls a gdb macro
- * - the macro compiles and loads this shared library using add-symbol-file.
- *
- * This is based on the xdebug functionality in the Kaffe Java VM.
- * 
- * We emit assembly code instead of using the ELF writer, so we can emit debug info
- * incrementally as each method is JITted, and the debugger doesn't have to call
- * into the runtime to emit the shared library, which would cause all kinds of
- * complications, like threading issues, and the fact that the ELF writer's
- * emit_writeout () function cannot be called more than once.
- * GDB 7.0 and later has a JIT interface.
- */
-
-#define USE_GDB_JIT_INTERFACE
-
-/* The recommended gdb macro is: */
-/*
-  define xdb
-  shell rm -f xdb.so && as --64 -o xdb.o xdb.s && ld -shared -o xdb.so xdb.o
-  add-symbol-file xdb.so 0
-  end
-*/
-
-/*
- * GDB JIT interface definitions.
- *
- *     http://sources.redhat.com/gdb/onlinedocs/gdb_30.html
- */
-typedef enum
-{
-  JIT_NOACTION = 0,
-  JIT_REGISTER_FN,
-  JIT_UNREGISTER_FN
-} jit_actions_t;
-
-struct jit_code_entry
-{
-  struct jit_code_entry *next_entry;
-  struct jit_code_entry *prev_entry;
-  const char *symfile_addr;
-  guint64 symfile_size;
-};
-
-struct jit_descriptor
-{
-  guint32 version;
-  /* This type should be jit_actions_t, but we use guint32
-     to be explicit about the bitwidth.  */
-  guint32 action_flag;
-  struct jit_code_entry *relevant_entry;
-  struct jit_code_entry *first_entry;
-};
-
-
-#ifdef _MSC_VER
-#define MONO_NOINLINE __declspec (noinline)
-#else
-#define MONO_NOINLINE __attribute__((noinline))
-#endif
-
-/* GDB puts a breakpoint in this function.  */
-void MONO_NOINLINE __jit_debug_register_code(void);
-
-#if defined(ENABLE_LLVM) && ((LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION >= 7) || LLVM_MAJOR_VERSION > 2)
-/* LLVM already defines these */
-extern struct jit_descriptor __jit_debug_descriptor;
-#else
-
-/* Make sure to specify the version statically, because the
-   debugger may check the version before we can set it.  */
-struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
-
-void MONO_NOINLINE __jit_debug_register_code(void) { };
-#endif
-
-static MonoImageWriter *xdebug_w;
-static MonoDwarfWriter *xdebug_writer;
-static FILE *xdebug_fp, *il_file;
-static gboolean use_gdb_interface, save_symfiles;
-static int il_file_line_index;
-static GHashTable *xdebug_syms;
-
-void
-mono_xdebug_init (char *options)
-{
-       MonoImageWriter *w;
-       char **args, **ptr;
-
-       args = g_strsplit (options, ",", -1);
-       for (ptr = args; ptr && *ptr; ptr ++) {
-               char *arg = *ptr;
-
-               if (!strcmp (arg, "gdb"))
-                       use_gdb_interface = TRUE;
-               if (!strcmp (arg, "save-symfiles"))
-                       save_symfiles = TRUE;
-       }
-
-       /* This file will contain the IL code for methods which don't have debug info */
-       il_file = fopen ("xdb.il", "w");
-
-       if (use_gdb_interface)
-               return;
-
-       unlink ("xdb.s");
-       xdebug_fp = fopen ("xdb.s", "w");
-       
-       w = img_writer_create (xdebug_fp, FALSE);
-
-       img_writer_emit_start (w);
-
-       xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE);
-
-       /* Emit something so the file has a text segment */
-       img_writer_emit_section_change (w, ".text", 0);
-       img_writer_emit_string (w, "");
-
-       mono_dwarf_writer_emit_base_info (xdebug_writer, arch_get_cie_program ());
-}
-
-static void
-xdebug_begin_emit (MonoImageWriter **out_w, MonoDwarfWriter **out_dw)
-{
-       MonoImageWriter *w;
-       MonoDwarfWriter *dw;
-
-       w = img_writer_create (NULL, TRUE);
-
-       img_writer_emit_start (w);
-
-       /* This file will contain the IL code for methods which don't have debug info */
-       if (!il_file)
-               il_file = fopen ("xdb.il", "w");
-
-       dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, FALSE);
-
-       mono_dwarf_writer_emit_base_info (dw, arch_get_cie_program ());
-
-       *out_w = w;
-       *out_dw = dw;
-}
-
-static void
-xdebug_end_emit (MonoImageWriter *w, MonoDwarfWriter *dw, MonoMethod *method)
-{
-       guint8 *img;
-       guint32 img_size;
-       struct jit_code_entry *entry;
-
-       il_file_line_index = mono_dwarf_writer_get_il_file_line_index (dw);
-       mono_dwarf_writer_close (dw);
-
-       img_writer_emit_writeout (w);
-
-       img = img_writer_get_output (w, &img_size);
-
-       img_writer_destroy (w);
-
-       if (FALSE) {
-               /* Save the symbol files to help debugging */
-               FILE *fp;
-               char *file_name;
-               static int file_counter;
-
-               file_counter ++;
-               file_name = g_strdup_printf ("xdb-%d.o", file_counter);
-               //printf ("%s -> %s\n", mono_method_full_name (method, TRUE), file_name);
-
-               fp = fopen (file_name, "w");
-               fwrite (img, img_size, 1, fp);
-               fclose (fp);
-               g_free (file_name);
-       }
-
-       /* Register the image with GDB */
-
-       entry = g_malloc (sizeof (struct jit_code_entry));
-
-       entry->symfile_addr = (const char*)img;
-       entry->symfile_size = img_size;
-
-       entry->next_entry = __jit_debug_descriptor.first_entry;
-       if (__jit_debug_descriptor.first_entry)
-               __jit_debug_descriptor.first_entry->prev_entry = entry;
-       __jit_debug_descriptor.first_entry = entry;
-       
-       __jit_debug_descriptor.relevant_entry = entry;
-       __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
-
-       __jit_debug_register_code ();
-}
-
-/*
- * mono_xdebug_flush:
- *
- *   This could be called from inside gdb to flush the debugging information not yet
- * registered with gdb.
- */
-static void
-mono_xdebug_flush (void)
-{
-       if (xdebug_w)
-               xdebug_end_emit (xdebug_w, xdebug_writer, NULL);
-
-       xdebug_begin_emit (&xdebug_w, &xdebug_writer);
-}
-
-static int xdebug_method_count;
-
-/*
- * mono_save_xdebug_info:
- *
- *   Emit debugging info for METHOD into an assembly file which can be assembled
- * and loaded into gdb to provide debugging info for JITted code.
- * LOCKING: Acquires the loader lock.
- */
-void
-mono_save_xdebug_info (MonoCompile *cfg)
-{
-       if (use_gdb_interface) {
-               mono_loader_lock ();
-
-               if (!xdebug_syms)
-                       xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-               /*
-                * gdb is not designed to handle 1000s of symbol files (one per method). So we
-                * group them into groups of 100.
-                */
-               if ((xdebug_method_count % 100) == 0)
-                       mono_xdebug_flush ();
-
-               xdebug_method_count ++;
-
-               mono_dwarf_writer_emit_method (xdebug_writer, cfg, cfg->jit_info->method, NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
-
-#if 0
-               /* 
-                * Emit a symbol for the code by emitting it at the beginning of the text 
-                * segment, and setting the text segment to have an absolute address.
-                * This symbol can be used to set breakpoints in gdb.
-                * FIXME: This doesn't work when multiple methods are emitted into the same file.
-                */
-               sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms);
-               img_writer_emit_section_change (w, ".text", 0);
-               if (!xdebug_text_addr) {
-                       xdebug_text_addr = cfg->jit_info->code_start;
-                       img_writer_set_section_addr (w, (gssize)xdebug_text_addr);
-               }
-               img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE);
-               img_writer_emit_label (w, sym);
-               img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size);
-               g_free (sym);
-#endif
-               
-               mono_loader_unlock ();
-       } else {
-               if (!xdebug_writer)
-                       return;
-
-               mono_loader_lock ();
-               mono_dwarf_writer_emit_method (xdebug_writer, cfg, cfg->jit_info->method, NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
-               fflush (xdebug_fp);
-               mono_loader_unlock ();
-       }
-}
-
-/*
- * mono_save_trampoline_xdebug_info:
- *
- *   Same as mono_save_xdebug_info, but for trampolines.
- * LOCKING: Acquires the loader lock.
- */
-void
-mono_save_trampoline_xdebug_info (const char *tramp_name, guint8 *code, guint32 code_size, GSList *unwind_info)
-{
-       if (use_gdb_interface) {
-               MonoImageWriter *w;
-               MonoDwarfWriter *dw;
-
-               mono_loader_lock ();
-
-               xdebug_begin_emit (&w, &dw);
-
-               mono_dwarf_writer_emit_trampoline (dw, tramp_name, NULL, NULL, code, code_size, unwind_info);
-
-               xdebug_end_emit (w, dw, NULL);
-               
-               mono_loader_unlock ();
-       } else {
-               if (!xdebug_writer)
-                       return;
-
-               mono_loader_lock ();
-               mono_dwarf_writer_emit_trampoline (xdebug_writer, tramp_name, NULL, NULL, code, code_size, unwind_info);
-               fflush (xdebug_fp);
-               mono_loader_unlock ();
-       }
-}
 
 #else
 
@@ -6250,19 +6212,4 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        return 0;
 }
 
-void
-mono_xdebug_init (char *options)
-{
-}
-
-void
-mono_save_xdebug_info (MonoCompile *cfg)
-{
-}
-
-void
-mono_save_trampoline_xdebug_info (const char *tramp_name, guint8 *code, guint32 code_size, GSList *unwind_info)
-{
-}
-
 #endif