Merge pull request #4444 from lateralusX/jlorenss/windows-unwind-info
[mono.git] / mono / mini / aot-compiler.c
index 9b606579522a8f000722179b1806288878ad7013..22dc64f95197ac60691c4a89eac17f793438fc2f 100644 (file)
@@ -4,6 +4,7 @@
  * Author:
  *   Dietmar Maurer (dietmar@ximian.com)
  *   Zoltan Varga (vargaz@gmail.com)
+ *   Johan Lorensson (lateralusx.github@gmail.com)
  *
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2011 Novell, Inc 
@@ -54,6 +55,8 @@
 #include <mono/utils/mono-rand.h>
 #include <mono/utils/json.h>
 #include <mono/utils/mono-threads-coop.h>
+#include <mono/profiler/mono-profiler-aot.h>
+#include <mono/utils/w32api.h>
 
 #include "aot-compiler.h"
 #include "seq-points.h"
 
 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
 
+// Use MSVC toolchain, Clang for MSVC using MSVC codegen and linker, when compiling for AMD64
+// targeting WIN32 platforms running AOT compiler on WIN32 platform with VS installation.
+#if defined(TARGET_AMD64) && defined(TARGET_WIN32) && defined(HOST_WIN32) && defined(_MSC_VER)
+#define TARGET_X86_64_WIN32_MSVC
+#endif
+
+#if defined(TARGET_X86_64_WIN32_MSVC)
+#define TARGET_WIN32_MSVC
+#endif
+
 #if defined(__linux__) || defined(__native_client_codegen__)
 #define RODATA_SECT ".rodata"
 #elif defined(TARGET_MACH)
 #define RODATA_SECT ".section __TEXT, __const"
+#elif defined(TARGET_WIN32_MSVC)
+#define RODATA_SECT ".rdata"
 #else
 #define RODATA_SECT ".text"
 #endif
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
 
+typedef struct {
+       char *name;
+       MonoImage *image;
+} ImageProfileData;
+
+typedef struct ClassProfileData ClassProfileData;
+
+typedef struct {
+       int argc;
+       ClassProfileData **argv;
+       MonoGenericInst *inst;
+} GInstProfileData;
+
+struct ClassProfileData {
+       ImageProfileData *image;
+       char *ns, *name;
+       GInstProfileData *inst;
+       MonoClass *klass;
+};
+
+typedef struct {
+       ClassProfileData *klass;
+       int id;
+       char *name;
+       int param_count;
+       char *signature;
+       GInstProfileData *inst;
+       MonoMethod *method;
+} MethodProfileData;
+
+typedef struct {
+       GHashTable *images, *classes, *ginsts, *methods;
+} ProfileData;
+
 /* predefined values for static readonly fields without needed to run the .cctor */
 typedef struct _ReadOnlyValue ReadOnlyValue;
 struct _ReadOnlyValue {
@@ -100,6 +149,7 @@ typedef struct MonoAotOptions {
        char *outfile;
        char *llvm_outfile;
        char *data_outfile;
+       GList *profile_files;
        gboolean save_temps;
        gboolean write_symbols;
        gboolean metadata_only;
@@ -132,6 +182,7 @@ typedef struct MonoAotOptions {
        int nrgctx_fetch_trampolines;
        gboolean print_skipped_methods;
        gboolean stats;
+       gboolean verbose;
        char *tool_prefix;
        char *ld_flags;
        char *mtriple;
@@ -140,6 +191,7 @@ typedef struct MonoAotOptions {
        char *instances_logfile_path;
        char *logfile;
        gboolean dump_json;
+       gboolean profile_only;
 } MonoAotOptions;
 
 typedef enum {
@@ -260,6 +312,8 @@ typedef struct MonoAotCompile {
        int objc_selector_index, objc_selector_index_2;
        GPtrArray *objc_selectors;
        GHashTable *objc_selector_to_index;
+       GList *profile_data;
+       GHashTable *profile_methods;
        FILE *logfile;
        FILE *instances_logfile;
        FILE *data_outfile;
@@ -329,6 +383,9 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
 static void
 add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
 
+static void
+add_profile_instances (MonoAotCompile *acfg, ProfileData *data);
+
 static void
 aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
 {
@@ -605,11 +662,29 @@ emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
 
 #endif
 
+static inline gboolean
+link_shared_library (MonoAotCompile *acfg)
+{
+       return !acfg->aot_opts.static_link && !acfg->aot_opts.asm_only;
+}
+
+static inline gboolean
+add_to_global_symbol_table (MonoAotCompile *acfg)
+{
+#ifdef TARGET_WIN32_MSVC
+       return acfg->aot_opts.no_dlsym || link_shared_library (acfg);
+#else
+       return acfg->aot_opts.no_dlsym;
+#endif
+}
+
 static void
 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
 {
-       if (acfg->aot_opts.no_dlsym) {
+       if (add_to_global_symbol_table (acfg))
                g_ptr_array_add (acfg->globals, g_strdup (name));
+
+       if (acfg->aot_opts.no_dlsym) {
                mono_img_writer_emit_local_symbol (acfg->w, name, NULL, func);
        } else {
                emit_global_inner (acfg, name, func);
@@ -814,6 +889,10 @@ emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
 #define EMIT_DWARF_INFO 1
 #endif
 
+#ifdef TARGET_WIN32_MSVC
+#undef EMIT_DWARF_INFO
+#endif
+
 #if defined(TARGET_ARM)
 #define AOT_FUNC_ALIGNMENT 4
 #else
@@ -828,7 +907,9 @@ emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
 #define PPC_LDX_OP "lwzx"
 #endif
 
-#ifdef TARGET_AMD64
+#ifdef TARGET_X86_64_WIN32_MSVC
+#define AOT_TARGET_STR "AMD64 (WIN32) (MSVC codegen)"
+#elif TARGET_AMD64
 #define AOT_TARGET_STR "AMD64"
 #endif
 
@@ -1432,7 +1513,6 @@ arch_emit_got_access (MonoAotCompile *acfg, const char *got_symbol, guint8 *code
 #elif defined(TARGET_POWERPC)
        {
                guint8 buf [32];
-               guint8 *code;
 
                emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
                code = buf;
@@ -2489,9 +2569,10 @@ mono_get_field_token (MonoClassField *field)
        MonoClass *klass = field->parent;
        int i;
 
-       for (i = 0; i < klass->field.count; ++i) {
+       int fcount = mono_class_get_field_count (klass);
+       for (i = 0; i < fcount; ++i) {
                if (field == &klass->fields [i])
-                       return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
+                       return MONO_TOKEN_FIELD_DEF | (mono_class_get_first_field_idx (klass) + 1 + i);
        }
 
        g_assert_not_reached ();
@@ -2770,7 +2851,7 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
         * information.
         */
 
-       if (klass->generic_class) {
+       if (mono_class_is_ginst (klass)) {
                guint32 token;
                g_assert (klass->type_token);
 
@@ -2780,8 +2861,8 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                        encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
                        encode_value (token, p, &p);
                } else {
-                       MonoClass *gclass = klass->generic_class->container_class;
-                       MonoGenericInst *inst = klass->generic_class->context.class_inst;
+                       MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
+                       MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
                        static int count = 0;
                        guint8 *p1 = p;
 
@@ -2855,7 +2936,7 @@ encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **
        /* 
         * The encoding of generic instances is large so emit them only once.
         */
-       if (klass->generic_class) {
+       if (mono_class_is_ginst (klass)) {
                guint32 token;
                g_assert (klass->type_token);
 
@@ -3107,8 +3188,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                case MONO_WRAPPER_PROXY_ISINST:
                case MONO_WRAPPER_LDFLD:
                case MONO_WRAPPER_LDFLDA:
-               case MONO_WRAPPER_STFLD:
-               case MONO_WRAPPER_ISINST: {
+               case MONO_WRAPPER_STFLD: {
                        g_assert (info);
                        encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
                        break;
@@ -3616,7 +3696,7 @@ can_marshal_struct (MonoClass *klass)
        MonoMarshalType *info;
        int i;
 
-       if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+       if (mono_class_is_auto_layout (klass))
                return FALSE;
 
        info = mono_marshal_load_type_info (klass);
@@ -3688,8 +3768,8 @@ create_gsharedvt_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericCont
 
        memset (ctx, 0, sizeof (MonoGenericContext));
 
-       if (method->klass->generic_container) {
-               shared_context = method->klass->generic_container->context;
+       if (mono_class_is_gtd (method->klass)) {
+               shared_context = mono_class_get_generic_container (method->klass)->context;
                inst = shared_context.class_inst;
 
                args = g_new0 (MonoType*, inst->type_argc);
@@ -3888,15 +3968,13 @@ add_wrappers (MonoAotCompile *acfg)
                /* stelemref */
                add_method (acfg, mono_marshal_get_stelemref ());
 
-               if (MONO_ARCH_HAVE_TLS_GET) {
-                       /* Managed Allocators */
-                       nallocators = mono_gc_get_managed_allocator_types ();
-                       for (i = 0; i < nallocators; ++i) {
-                               if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
-                                       add_method (acfg, m);
-                               if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
-                                       add_method (acfg, m);
-                       }
+               /* Managed Allocators */
+               nallocators = mono_gc_get_managed_allocator_types ();
+               for (i = 0; i < nallocators; ++i) {
+                       if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
+                               add_method (acfg, m);
+                       if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
+                               add_method (acfg, m);
                }
 
                /* write barriers */
@@ -3968,7 +4046,7 @@ add_wrappers (MonoAotCompile *acfg)
                if (!klass->delegate || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class)
                        continue;
 
-               if (!klass->generic_container) {
+               if (!mono_class_is_gtd (klass)) {
                        method = mono_get_delegate_invoke (klass);
 
                        m = mono_marshal_get_delegate_invoke (method, NULL);
@@ -4008,7 +4086,7 @@ add_wrappers (MonoAotCompile *acfg)
                                        add_method (acfg, del_invoke);
                                }
                        }
-               } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->generic_container) {
+               } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (klass)) {
                        MonoError error;
                        MonoGenericContext ctx;
                        MonoMethod *inst, *gshared;
@@ -4031,30 +4109,33 @@ add_wrappers (MonoAotCompile *acfg)
 
                        /* begin-invoke */
                        method = mono_get_delegate_begin_invoke (klass);
-                       create_gsharedvt_inst (acfg, method, &ctx);
+                       if (method) {
+                               create_gsharedvt_inst (acfg, method, &ctx);
 
-                       inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                               inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
+                               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
 
-                       m = mono_marshal_get_delegate_begin_invoke (inst);
-                       g_assert (m->is_inflated);
+                               m = mono_marshal_get_delegate_begin_invoke (inst);
+                               g_assert (m->is_inflated);
 
-                       gshared = mini_get_shared_method_full (m, FALSE, TRUE);
-                       add_extra_method (acfg, gshared);
+                               gshared = mini_get_shared_method_full (m, FALSE, TRUE);
+                               add_extra_method (acfg, gshared);
+                       }
 
                        /* end-invoke */
                        method = mono_get_delegate_end_invoke (klass);
-                       create_gsharedvt_inst (acfg, method, &ctx);
-
-                       inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       if (method) {
+                               create_gsharedvt_inst (acfg, method, &ctx);
 
-                       m = mono_marshal_get_delegate_end_invoke (inst);
-                       g_assert (m->is_inflated);
+                               inst = mono_class_inflate_generic_method_checked (method, &ctx, &error);
+                               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
 
-                       gshared = mini_get_shared_method_full (m, FALSE, TRUE);
-                       add_extra_method (acfg, gshared);
+                               m = mono_marshal_get_delegate_end_invoke (inst);
+                               g_assert (m->is_inflated);
 
+                               gshared = mini_get_shared_method_full (m, FALSE, TRUE);
+                               add_extra_method (acfg, gshared);
+                       }
                }
        }
 
@@ -4102,7 +4183,7 @@ add_wrappers (MonoAotCompile *acfg)
                if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
                        if (method->is_generic) {
                                // FIXME:
-                       } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && method->klass->generic_container) {
+                       } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (method->klass)) {
                                MonoError error;
                                MonoGenericContext ctx;
                                MonoMethod *inst, *gshared, *m;
@@ -4249,7 +4330,9 @@ add_wrappers (MonoAotCompile *acfg)
                                        named += slen;
                                }
 
-                               wrapper = mono_marshal_get_managed_wrapper (method, klass, 0);
+                               wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, &error);
+                               mono_error_assert_ok (&error);
+
                                add_method (acfg, wrapper);
                                if (export_name)
                                        g_hash_table_insert (acfg->export_names, wrapper, export_name);
@@ -4276,7 +4359,7 @@ add_wrappers (MonoAotCompile *acfg)
                        continue;
                }
 
-               if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass) &&
+               if (klass->valuetype && !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
                        !(klass->nested_in && strstr (klass->nested_in->name, "<PrivateImplementationDetails>") == klass->nested_in->name)) {
                        add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
                        add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
@@ -4291,8 +4374,8 @@ has_type_vars (MonoClass *klass)
                return TRUE;
        if (klass->rank)
                return has_type_vars (klass->element_class);
-       if (klass->generic_class) {
-               MonoGenericContext *context = &klass->generic_class->context;
+       if (mono_class_is_ginst (klass)) {
+               MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
                if (context->class_inst) {
                        int i;
 
@@ -4301,7 +4384,7 @@ has_type_vars (MonoClass *klass)
                                        return TRUE;
                }
        }
-       if (klass->generic_container)
+       if (mono_class_is_gtd (klass))
                return TRUE;
        return FALSE;
 }
@@ -4411,13 +4494,13 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
 
        mono_class_init (klass);
 
-       if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+       if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
                return;
 
        if (has_type_vars (klass))
                return;
 
-       if (!klass->generic_class && !klass->rank)
+       if (!mono_class_is_ginst (klass) && !klass->rank)
                return;
 
        if (mono_class_has_failure (klass))
@@ -4441,7 +4524,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
         * Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
         * Enable this only for some classes since gsharedvt might not support all methods.
         */
-       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
                (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
                use_gsharedvt = TRUE;
 
@@ -4498,7 +4581,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
         */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
                (!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
                gpointer iter;
                char *name_prefix;
@@ -4519,7 +4602,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                                        break;
                        }
                        g_assert (nclass);
-                       nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error);
+                       nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
                        mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                        add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
                }
@@ -4539,7 +4622,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
                MonoError error;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *icomparable, *gcomparer, *icomparable_inst;
                MonoGenericContext ctx;
                MonoType *args [16];
@@ -4567,7 +4650,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
                MonoError error;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *iface, *gcomparer, *iface_inst;
                MonoGenericContext ctx;
                MonoType *args [16];
@@ -4596,7 +4679,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
                MonoClass *enum_comparer;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoGenericContext ctx;
                MonoType *args [16];
 
@@ -4618,7 +4701,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
                MonoClass *comparer;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoGenericContext ctx;
                MonoType *args [16];
 
@@ -4794,7 +4877,7 @@ add_generic_instances (MonoAotCompile *acfg)
                                g_free (type_argv);
                        }
 
-                       if (method->is_generic || method->klass->generic_container)
+                       if (method->is_generic || mono_class_is_gtd (method->klass))
                                declaring_method = method;
                        else
                                declaring_method = mono_method_get_declaring_generic_method (method);
@@ -5013,7 +5096,7 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
                if (callee_cfg) {
                        gboolean direct_callable = TRUE;
 
-                       if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+                       if (direct_callable && !(!callee_cfg->has_got_slots && mono_class_is_before_field_init (callee_cfg->method->klass)))
                                direct_callable = FALSE;
                        if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
                                // FIXME: Maybe call the wrapper directly ?
@@ -5163,11 +5246,11 @@ compute_line_numbers (MonoMethod *method, int code_size, MonoDebugMethodJitInfo
                if (il_offset == -1 || il_offset == prev_il_offset)
                        continue;
                prev_il_offset = il_offset;
-               loc = mono_debug_symfile_lookup_location (minfo, il_offset);
+               loc = mono_debug_method_lookup_location (minfo, il_offset);
                if (!(loc && loc->source_file))
                        continue;
                if (loc->row == prev_line) {
-                       mono_debug_symfile_free_location (loc);
+                       mono_debug_free_source_location (loc);
                        continue;
                }
                prev_line = loc->row;
@@ -5266,7 +5349,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                options = "";
                        prologue_end = TRUE;
                        fprintf (acfg->fp, ".loc %d %d 0%s\n", findex, loc->row, options);
-                       mono_debug_symfile_free_location (loc);
+                       mono_debug_free_source_location (loc);
                }
 
                skip = FALSE;
@@ -5625,7 +5708,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
                break;
        case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
-       case MONO_PATCH_INFO_JIT_TLS_ID:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
        case MONO_PATCH_INFO_GC_NURSERY_BITS:
@@ -5655,6 +5737,8 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_method_ref (acfg, patch_info->data.method, p, &p);
                break;
        case MONO_PATCH_INFO_AOT_JIT_INFO:
+       case MONO_PATCH_INFO_GET_TLS_TRAMP:
+       case MONO_PATCH_INFO_SET_TLS_TRAMP:
                encode_value (patch_info->data.index, p, &p);
                break;
        case MONO_PATCH_INFO_INTERNAL_METHOD:
@@ -5764,9 +5848,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
                encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
                break;
-       case MONO_PATCH_INFO_TLS_OFFSET:
-               encode_value (GPOINTER_TO_INT (patch_info->data.target), p, &p);
-               break;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                encode_signature (acfg, (MonoMethodSignature*)patch_info->data.gsharedvt->sig, p, &p);
                encode_method_ref (acfg, patch_info->data.gsharedvt->method, p, &p);
@@ -5809,7 +5890,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
                break;
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
-       case MONO_PATCH_INFO_GET_TLS_TRAMP:
+       case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
                break;
        default:
                g_warning ("unable to handle jump info %d", patch_info->type);
@@ -6272,12 +6353,15 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token)
        }
 
        mono_class_has_finalizer (klass);
+       if (mono_class_has_failure (klass))
+               cant_encode = TRUE;
 
-       if (klass->generic_container || cant_encode) {
+       if (mono_class_is_gtd (klass) || cant_encode) {
                encode_value (-1, p, &p);
        } else {
+               gboolean has_nested = mono_class_get_nested_classes_property (klass) != NULL;
                encode_value (klass->vtable_size, p, &p);
-               encode_value ((klass->generic_container ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | ((klass->ext && klass->ext->nested_classes) ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
+               encode_value ((mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | (has_nested ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
                if (klass->has_cctor)
                        encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
                if (klass->has_finalize)
@@ -7142,6 +7226,12 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->llvm_only = TRUE;
                } else if (str_begins_with (arg, "data-outfile=")) {
                        opts->data_outfile = g_strdup (arg + strlen ("data-outfile="));
+               } else if (str_begins_with (arg, "profile=")) {
+                       opts->profile_files = g_list_append (opts->profile_files, g_strdup (arg + strlen ("profile=")));
+               } else if (!strcmp (arg, "profile-only")) {
+                       opts->profile_only = TRUE;
+               } else if (!strcmp (arg, "verbose")) {
+                       opts->verbose = TRUE;
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
                        printf ("    outfile=\n");
@@ -7174,6 +7264,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        printf ("    stats\n");
                        printf ("    dump\n");
                        printf ("    info\n");
+                       printf ("    verbose\n");
                        printf ("    help/?\n");
                        exit (0);
                } else {
@@ -7232,7 +7323,6 @@ can_encode_method (MonoAotCompile *acfg, MonoMethod *method)
                        case MONO_WRAPPER_LDFLD:
                        case MONO_WRAPPER_LDFLDA:
                        case MONO_WRAPPER_STELEMREF:
-                       case MONO_WRAPPER_ISINST:
                        case MONO_WRAPPER_PROXY_ISINST:
                        case MONO_WRAPPER_ALLOC:
                        case MONO_WRAPPER_REMOTING_INVOKE:
@@ -7330,7 +7420,7 @@ is_concrete_type (MonoType *t)
                if (!MONO_TYPE_ISSTRUCT (t))
                        return TRUE;
                klass = mono_class_from_mono_type (t);
-               orig_ctx = &klass->generic_class->context;
+               orig_ctx = &mono_class_get_generic_class (klass)->context;
 
                inst = orig_ctx->class_inst;
                if (inst) {
@@ -7464,10 +7554,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        if (method->wrapper_type == MONO_WRAPPER_COMINTEROP)
                return;
 
+       if (acfg->aot_opts.profile_only && !method->is_inflated && !g_hash_table_lookup (acfg->profile_methods, method))
+               return;
+
        InterlockedIncrement (&acfg->stats.mcount);
 
 #if 0
-       if (method->is_generic || method->klass->generic_container) {
+       if (method->is_generic || mono_class_is_gtd (method->klass)) {
                InterlockedIncrement (&acfg->stats.genericcount);
                return;
        }
@@ -7490,6 +7583,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                flags = (JitFlags)(flags | JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS);
        if (acfg->aot_opts.no_direct_calls)
                flags = (JitFlags)(flags | JIT_FLAG_NO_DIRECT_ICALLS);
+       if (acfg->aot_opts.direct_pinvoke)
+               flags = (JitFlags)(flags | JIT_FLAG_DIRECT_PINVOKE);
 
        jit_timer = mono_time_track_start ();
        cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
@@ -7602,7 +7697,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         * encountered.
         */
        depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
-       if (!acfg->aot_opts.no_instances && depth < 32) {
+       if (!acfg->aot_opts.no_instances && depth < 32 && mono_aot_mode_is_full (&acfg->aot_opts)) {
                for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
                        switch (patch_info->type) {
                        case MONO_PATCH_INFO_RGCTX_FETCH:
@@ -7621,7 +7716,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
 
                                if (!m)
                                        break;
-                               if (m->is_inflated) {
+                               if (m->is_inflated && mono_aot_mode_is_full (&acfg->aot_opts)) {
                                        if (!(mono_class_generic_sharing_enabled (m->klass) &&
                                                  mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
                                                (!method_has_type_vars (m) || mono_method_is_generic_sharable_full (m, TRUE, TRUE, FALSE))) {
@@ -7646,7 +7741,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                        case MONO_PATCH_INFO_VTABLE: {
                                MonoClass *klass = patch_info->data.klass;
 
-                               if (klass->generic_class && !mini_class_is_generic_sharable (klass))
+                               if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
                                        add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
                                break;
                        }
@@ -7654,7 +7749,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                MonoClass *klass = patch_info->data.field->parent;
 
                                /* The .cctor needs to run at runtime. */
-                               if (klass->generic_class && !mono_generic_context_is_sharable_full (&klass->generic_class->context, FALSE, FALSE) && mono_class_get_cctor (klass))
+                               if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
                                        add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
                                break;
                        }
@@ -7794,17 +7889,16 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        InterlockedIncrement (&acfg->stats.ccount);
 }
  
-static gsize WINAPI
+static mono_thread_start_return_t WINAPI
 compile_thread_main (gpointer user_data)
 {
-       MonoDomain *domain = ((MonoDomain **)user_data) [0];
-       MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [1];
-       GPtrArray *methods = ((GPtrArray **)user_data) [2];
+       MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [0];
+       GPtrArray *methods = ((GPtrArray **)user_data) [1];
        int i;
 
        MonoError error;
-       MonoThread *thread = mono_thread_attach (domain);
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "AOT compiler"), TRUE, &error);
+       MonoInternalThread *internal = mono_thread_internal_current ();
+       mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "AOT compiler"), TRUE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        for (i = 0; i < methods->len; ++i)
@@ -7812,95 +7906,6 @@ compile_thread_main (gpointer user_data)
 
        return 0;
 }
-
-static void
-load_profile_files (MonoAotCompile *acfg)
-{
-       FILE *infile;
-       char *tmp;
-       int file_index, res, method_index, i;
-       char ver [256];
-       guint32 token;
-       GList *unordered, *l;
-       gboolean found;
-
-       file_index = 0;
-       while (TRUE) {
-               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);
-                       break;
-               }
-
-               infile = fopen (tmp, "r");
-               g_assert (infile);
-
-               printf ("Using profile data file '%s'\n", tmp);
-               g_free (tmp);
-
-               file_index ++;
-
-               res = fscanf (infile, "%32s\n", ver);
-               if ((res != 1) || strcmp (ver, "#VER:2") != 0) {
-                       printf ("Profile file has wrong version or invalid.\n");
-                       fclose (infile);
-                       continue;
-               }
-
-               while (TRUE) {
-                       char name [1024];
-                       MonoMethodDesc *desc;
-                       MonoMethod *method;
-
-                       if (fgets (name, 1023, infile) == NULL)
-                               break;
-
-                       /* 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 (method && mono_method_get_token (method)) {
-                               token = mono_method_get_token (method);
-                               method_index = mono_metadata_token_index (token) - 1;
-
-                               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);
-                       }
-               }
-               fclose (infile);
-       }
-
-       /* Add missing methods */
-       unordered = NULL;
-       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);
-       for (l = unordered; l; l = l->next)
-               g_ptr_array_add (acfg->method_order, l->data);
-}
  
 /* Used by the LLVM backend */
 guint32
@@ -8193,20 +8198,20 @@ mono_aot_patch_info_dup (MonoJumpInfo* ji)
 static int
 execute_system (const char * command)
 {
-       int status;
+       int status = 0;
 
-#if _WIN32
+#if defined(HOST_WIN32) && defined(HAVE_SYSTEM)
        // We need an extra set of quotes around the whole command to properly handle commands 
        // with spaces since internally the command is called through "cmd /c.
-       command = g_strdup_printf ("\"%s\"", command);
+       char * quoted_command = g_strdup_printf ("\"%s\"", command);
 
-       int size =  MultiByteToWideChar (CP_UTF8, 0 , command , -1, NULL , 0);
+       int size =  MultiByteToWideChar (CP_UTF8, 0 , quoted_command , -1, NULL , 0);
        wchar_t* wstr = g_malloc (sizeof (wchar_t) * size);
-       MultiByteToWideChar (CP_UTF8, 0, command, -1, wstr , size);
+       MultiByteToWideChar (CP_UTF8, 0, quoted_command, -1, wstr , size);
        status = _wsystem (wstr);
        g_free (wstr);
 
-       g_free (command);
+       g_free (quoted_command);
 #elif defined (HAVE_SYSTEM)
        status = system (command);
 #else
@@ -8459,7 +8464,8 @@ emit_code (MonoAotCompile *acfg)
        emit_section_change (acfg, ".text", 1);
        emit_alignment_code (acfg, 8);
        emit_info_symbol (acfg, symbol);
-       emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
+       if (acfg->aot_opts.write_symbols)
+               emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
        emit_unset_mode (acfg);
        if (acfg->need_no_dead_strip)
                fprintf (acfg->fp, "    .no_dead_strip %s\n", symbol);
@@ -8631,8 +8637,8 @@ mono_aot_method_hash (MonoMethod *method)
 
        sig = mono_method_signature (method);
 
-       if (method->klass->generic_class)
-               class_ginst = method->klass->generic_class->context.class_inst;
+       if (mono_class_is_ginst (method->klass))
+               class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
        if (method->is_inflated)
                ginst = ((MonoMethodInflated*)method)->context.method_inst;
 
@@ -8649,8 +8655,8 @@ mono_aot_method_hash (MonoMethod *method)
        if (!method->wrapper_type) {
                char *full_name;
 
-               if (klass->generic_class)
-                       full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+               if (mono_class_is_ginst (klass))
+                       full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
                else
                        full_name = mono_type_full_name (&klass->byval_arg);
 
@@ -9254,7 +9260,8 @@ emit_got (MonoAotCompile *acfg)
 #else
        emit_section_change (acfg, ".bss", 0);
        emit_alignment (acfg, 8);
-       emit_local_symbol (acfg, symbol, "got_end", FALSE);
+       if (acfg->aot_opts.write_symbols)
+               emit_local_symbol (acfg, symbol, "got_end", FALSE);
        emit_label (acfg, symbol);
        if (acfg->llvm)
                emit_info_symbol (acfg, "jit_got");
@@ -9271,6 +9278,53 @@ typedef struct GlobalsTableEntry {
        struct GlobalsTableEntry *next;
 } GlobalsTableEntry;
 
+#ifdef TARGET_WIN32_MSVC
+#define DLL_ENTRY_POINT "DllMain"
+
+static void
+emit_library_info (MonoAotCompile *acfg)
+{
+       // Only include for shared libraries linked directly from generated object.
+       if (link_shared_library (acfg)) {
+               char    *name = NULL;
+               char    symbol [MAX_SYMBOL_SIZE];
+
+               // Ask linker to export all global symbols.
+               emit_section_change (acfg, ".drectve", 0);
+               for (guint i = 0; i < acfg->globals->len; ++i) {
+                       name = (char *)g_ptr_array_index (acfg->globals, i);
+                       g_assert (name != NULL);
+                       sprintf_s (symbol, MAX_SYMBOL_SIZE, " /EXPORT:%s", name);
+                       emit_string (acfg, symbol);
+               }
+
+               // Emit DLLMain function, needed by MSVC linker for DLL's.
+               // NOTE, DllMain should not go into exports above.
+               emit_section_change (acfg, ".text", 0);
+               emit_global (acfg, DLL_ENTRY_POINT, TRUE);
+               emit_label (acfg, DLL_ENTRY_POINT);
+
+               // Simple implementation of DLLMain, just returning TRUE.
+               // For more information about DLLMain: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
+               fprintf (acfg->fp, "movl $1, %%eax\n");
+               fprintf (acfg->fp, "ret\n");
+
+               // Inform linker about our dll entry function.
+               emit_section_change (acfg, ".drectve", 0);
+               emit_string (acfg, "/ENTRY:" DLL_ENTRY_POINT);
+               return;
+       }
+}
+
+#else
+
+static inline void
+emit_library_info (MonoAotCompile *acfg)
+{
+       return;
+}
+#endif
+
 static void
 emit_globals (MonoAotCompile *acfg)
 {
@@ -9282,6 +9336,7 @@ emit_globals (MonoAotCompile *acfg)
 
        if (!acfg->aot_opts.static_link)
                return;
+
        if (acfg->aot_opts.llvm_only) {
                g_assert (acfg->globals->len == 0);
                return;
@@ -9747,7 +9802,7 @@ collect_methods (MonoAotCompile *acfg)
                }
                */
 
-               if (method->is_generic || method->klass->generic_container)
+               if (method->is_generic || mono_class_is_gtd (method->klass))
                        /* Compile the ref shared version instead */
                        method = mini_get_shared_method (method);
 
@@ -9768,7 +9823,7 @@ collect_methods (MonoAotCompile *acfg)
                method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
                report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
 
-               if (method->is_generic || method->klass->generic_container) {
+               if (method->is_generic || mono_class_is_gtd (method->klass)) {
                        MonoMethod *gshared;
 
                        gshared = mini_get_shared_method_full (method, TRUE, TRUE);
@@ -9776,7 +9831,8 @@ collect_methods (MonoAotCompile *acfg)
                }
        }
 
-       add_generic_instances (acfg);
+       if (mono_aot_mode_is_full (&acfg->aot_opts))
+               add_generic_instances (acfg);
 
        if (mono_aot_mode_is_full (&acfg->aot_opts))
                add_wrappers (acfg);
@@ -9812,6 +9868,9 @@ compile_methods (MonoAotCompile *acfg)
                        methods [i] = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
                i = 0;
                while (i < methods_len) {
+                       MonoError error;
+                       MonoInternalThread *thread;
+
                        frag = g_ptr_array_new ();
                        for (j = 0; j < len; ++j) {
                                if (i < methods_len) {
@@ -9821,17 +9880,19 @@ compile_methods (MonoAotCompile *acfg)
                        }
 
                        user_data = g_new0 (gpointer, 3);
-                       user_data [0] = mono_domain_get ();
-                       user_data [1] = acfg;
-                       user_data [2] = frag;
+                       user_data [0] = acfg;
+                       user_data [1] = frag;
                        
-                       thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+                       thread = mono_thread_create_internal (mono_domain_get (), compile_thread_main, (gpointer) user_data, MONO_THREAD_CREATE_FLAGS_NONE, &error);
+                       mono_error_assert_ok (&error);
+
+                       thread_handle = mono_threads_open_thread_handle (thread->handle);
                        g_ptr_array_add (threads, thread_handle);
                }
                g_free (methods);
 
                for (i = 0; i < threads->len; ++i) {
-                       mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), INFINITE, FALSE);
+                       mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), MONO_INFINITE_WAIT, FALSE);
                        mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
                }
        } else {
@@ -9840,7 +9901,7 @@ compile_methods (MonoAotCompile *acfg)
 
        /* Compile methods added by compile_method () or all methods if nthreads == 0 */
        for (i = methods_len; i < acfg->methods->len; ++i) {
-               /* This can new methods to acfg->methods */
+               /* This can add new methods to acfg->methods */
                compile_method (acfg, (MonoMethod *)g_ptr_array_index (acfg->methods, i));
        }
 }
@@ -9853,7 +9914,9 @@ compile_asm (MonoAotCompile *acfg)
        const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : "";
        char *ld_flags = acfg->aot_opts.ld_flags ? acfg->aot_opts.ld_flags : g_strdup("");
 
-#if defined(TARGET_AMD64) && !defined(TARGET_MACH)
+#ifdef TARGET_WIN32_MSVC
+#define AS_OPTIONS "-c -x assembler"
+#elif defined(TARGET_AMD64) && !defined(TARGET_MACH)
 #define AS_OPTIONS "--64"
 #elif defined(TARGET_POWERPC64)
 #define AS_OPTIONS "-a64 -mppc64"
@@ -9873,10 +9936,18 @@ compile_asm (MonoAotCompile *acfg)
 #endif
 #elif defined(TARGET_OSX)
 #define AS_NAME "clang"
+#elif defined(TARGET_WIN32_MSVC)
+#define AS_NAME "clang.exe"
 #else
 #define AS_NAME "as"
 #endif
 
+#ifdef TARGET_WIN32_MSVC
+#define AS_OBJECT_FILE_SUFFIX "obj"
+#else
+#define AS_OBJECT_FILE_SUFFIX "o"
+#endif
+
 #if defined(sparc)
 #define LD_NAME "ld"
 #define LD_OPTIONS "-shared -G"
@@ -9886,6 +9957,9 @@ compile_asm (MonoAotCompile *acfg)
 #elif defined(TARGET_AMD64) && defined(TARGET_MACH)
 #define LD_NAME "clang"
 #define LD_OPTIONS "--shared"
+#elif defined(TARGET_WIN32_MSVC)
+#define LD_NAME "link.exe"
+#define LD_OPTIONS "/DLL /MACHINE:X64 /NOLOGO"
 #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
 #define LD_NAME "gcc"
 #define LD_OPTIONS "-shared"
@@ -9916,9 +9990,9 @@ compile_asm (MonoAotCompile *acfg)
                if (acfg->aot_opts.outfile)
                        objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
                else
-                       objfile = g_strdup_printf ("%s.o", acfg->image->name);
+                       objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->image->name);
        } else {
-               objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
+               objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname);
        }
 
 #ifdef TARGET_OSX
@@ -9975,30 +10049,34 @@ compile_asm (MonoAotCompile *acfg)
        if (acfg->aot_opts.llvm_only)
                ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
 
-#ifdef LD_NAME
+#ifdef TARGET_WIN32_MSVC
+       g_assert (tmp_outfile_name != NULL);
+       g_assert (objfile != NULL);
+       command = g_strdup_printf ("\"%s%s\" %s %s /OUT:\"%s\" \"%s\"", tool_prefix, LD_NAME, LD_OPTIONS,
+               ld_flags, tmp_outfile_name, objfile);
+#elif defined(LD_NAME)
        command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
-               wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+               wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
 #else
        // Default (linux)
        if (acfg->aot_opts.tool_prefix) {
                /* Cross compiling */
                command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
                                                                   wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
-                                                                  wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+                                                                  wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
        } else {
                char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
                                                                          wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
-                                                                         wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+                                                                         wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX, acfg->tmpfname)), ld_flags);
 
-               if (acfg->llvm) {
+               if (acfg->aot_opts.llvm_only) {
                        command = g_strdup_printf ("clang++ %s", args);
                } else {
                        command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
                }
                g_free (args);
        }
-
 #endif
        aot_printf (acfg, "Executing the native linker: %s\n", command);
        if (execute_system (command) != 0) {
@@ -10064,7 +10142,460 @@ compile_asm (MonoAotCompile *acfg)
        return 0;
 }
 
-static void init_got_info (GotInfo *info)
+static guint8
+profread_byte (FILE *infile)
+{
+       guint8 i;
+       int res;
+
+       res = fread (&i, 1, 1, infile);
+       g_assert (res == 1);
+       return i;
+}
+
+static int
+profread_int (FILE *infile)
+{
+       int i, res;
+
+       res = fread (&i, 4, 1, infile);
+       g_assert (res == 1);
+       return i;
+}
+
+static char*
+profread_string (FILE *infile)
+{
+       int len, res;
+       char buf [1024];
+       char *pbuf;
+
+       len = profread_int (infile);
+       if (len + 1 > 1024)
+               pbuf = g_malloc (len + 1);
+       else
+               pbuf = buf;
+       res = fread (pbuf, 1, len, infile);
+       g_assert (res == len);
+       pbuf [len] = '\0';
+       if (pbuf == buf)
+               return g_strdup (buf);
+       else
+               return pbuf;
+}
+
+static void
+load_profile_file (MonoAotCompile *acfg, char *filename)
+{
+       FILE *infile;
+       char buf [1024];
+       int res, len, version;
+       char magic [32];
+
+       infile = fopen (filename, "r");
+       if (!infile) {
+               fprintf (stderr, "Unable to open file '%s': %s.\n", filename, strerror (errno));
+               exit (1);
+       }
+
+       printf ("Using profile data file '%s'\n", filename);
+
+       sprintf (magic, AOT_PROFILER_MAGIC);
+       len = strlen (magic);
+       res = fread (buf, 1, len, infile);
+       magic [len] = '\0';
+       buf [len] = '\0';
+       if ((res != len) || strcmp (buf, magic) != 0) {
+               printf ("Profile file has wrong header: '%s'.\n", buf);
+               fclose (infile);
+               exit (1);
+       }
+       guint32 expected_version = (AOT_PROFILER_MAJOR_VERSION << 16) | AOT_PROFILER_MINOR_VERSION;
+       version = profread_int (infile);
+       if (version != expected_version) {
+               printf ("Profile file has wrong version 0x%4x, expected 0x%4x.\n", version, expected_version);
+               fclose (infile);
+               exit (1);
+       }
+
+       ProfileData *data = g_new0 (ProfileData, 1);
+       data->images = g_hash_table_new (NULL, NULL);
+       data->classes = g_hash_table_new (NULL, NULL);
+       data->ginsts = g_hash_table_new (NULL, NULL);
+       data->methods = g_hash_table_new (NULL, NULL);
+
+       while (TRUE) {
+               int type = profread_byte (infile);
+               int id = profread_int (infile);
+
+               if (type == AOTPROF_RECORD_NONE)
+                       break;
+
+               switch (type) {
+               case AOTPROF_RECORD_IMAGE: {
+                       ImageProfileData *idata = g_new0 (ImageProfileData, 1);
+                       idata->name = profread_string (infile);
+                       char *mvid = profread_string (infile);
+                       g_free (mvid);
+                       g_hash_table_insert (data->images, GINT_TO_POINTER (id), idata);
+                       break;
+               }
+               case AOTPROF_RECORD_GINST: {
+                       int i;
+                       int len = profread_int (infile);
+
+                       GInstProfileData *gdata = g_new0 (GInstProfileData, 1);
+                       gdata->argc = len;
+                       gdata->argv = g_new0 (ClassProfileData*, len);
+
+                       for (i = 0; i < len; ++i) {
+                               int class_id = profread_int (infile);
+
+                               gdata->argv [i] = g_hash_table_lookup (data->classes, GINT_TO_POINTER (class_id));
+                               g_assert (gdata->argv [i]);
+                       }
+                       g_hash_table_insert (data->ginsts, GINT_TO_POINTER (id), gdata);
+                       break;
+               }
+               case AOTPROF_RECORD_TYPE: {
+                       int type = profread_byte (infile);
+
+                       switch (type) {
+                       case MONO_TYPE_CLASS: {
+                               int image_id = profread_int (infile);
+                               int ginst_id = profread_int (infile);
+                               char *class_name = profread_string (infile);
+
+                               ImageProfileData *image = g_hash_table_lookup (data->images, GINT_TO_POINTER (image_id));
+                               g_assert (image);
+
+                               char *p = strrchr (class_name, '.');
+                               g_assert (p);
+                               *p = '\0';
+
+                               ClassProfileData *cdata = g_new0 (ClassProfileData, 1);
+                               cdata->image = image;
+                               cdata->ns = g_strdup (class_name);
+                               cdata->name = g_strdup (p + 1);
+
+                               if (ginst_id != -1) {
+                                       cdata->inst = g_hash_table_lookup (data->ginsts, GINT_TO_POINTER (ginst_id));
+                                       g_assert (cdata->inst);
+                               }
+                               g_free (class_name);
+
+                               g_hash_table_insert (data->classes, GINT_TO_POINTER (id), cdata);
+                               break;
+                       }
+#if 0
+                       case MONO_TYPE_SZARRAY: {
+                               int elem_id = profread_int (infile);
+                               // FIXME:
+                               break;
+                       }
+#endif
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+                       break;
+               }
+               case AOTPROF_RECORD_METHOD: {
+                       int class_id = profread_int (infile);
+                       int ginst_id = profread_int (infile);
+                       int param_count = profread_int (infile);
+                       char *method_name = profread_string (infile);
+                       char *sig = profread_string (infile);
+
+                       ClassProfileData *klass = g_hash_table_lookup (data->classes, GINT_TO_POINTER (class_id));
+                       g_assert (klass);
+
+                       MethodProfileData *mdata = g_new0 (MethodProfileData, 1);
+                       mdata->id = id;
+                       mdata->klass = klass;
+                       mdata->name = method_name;
+                       mdata->signature = sig;
+                       mdata->param_count = param_count;
+
+                       if (ginst_id != -1) {
+                               mdata->inst = g_hash_table_lookup (data->ginsts, GINT_TO_POINTER (ginst_id));
+                               g_assert (mdata->inst);
+                       }
+                       g_hash_table_insert (data->methods, GINT_TO_POINTER (id), mdata);
+                       break;
+               }
+               default:
+                       printf ("%d\n", type);
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       fclose (infile);
+       acfg->profile_data = g_list_append (acfg->profile_data, data);
+}
+
+static void
+resolve_class (ClassProfileData *cdata);
+
+static void
+resolve_ginst (GInstProfileData *inst_data)
+{
+       int i;
+
+       if (inst_data->inst)
+               return;
+
+       for (i = 0; i < inst_data->argc; ++i) {
+               resolve_class (inst_data->argv [i]);
+               if (!inst_data->argv [i]->klass)
+                       return;
+       }
+       MonoType **args = g_new0 (MonoType*, inst_data->argc);
+       for (i = 0; i < inst_data->argc; ++i)
+               args [i] = &inst_data->argv [i]->klass->byval_arg;
+
+       inst_data->inst = mono_metadata_get_generic_inst (inst_data->argc, args);
+}
+
+static void
+resolve_class (ClassProfileData *cdata)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       if (!cdata->image->image)
+               return;
+
+       klass = mono_class_from_name_checked (cdata->image->image, cdata->ns, cdata->name, &error);
+       if (!klass) {
+               //printf ("[%s] %s.%s\n", cdata->image->name, cdata->ns, cdata->name);
+               return;
+       }
+       if (cdata->inst) {
+               resolve_ginst (cdata->inst);
+               if (!cdata->inst->inst)
+                       return;
+               MonoGenericContext ctx;
+
+               memset (&ctx, 0, sizeof (ctx));
+               ctx.class_inst = cdata->inst->inst;
+               cdata->klass = mono_class_inflate_generic_class_checked (klass, &ctx, &error);
+       } else {
+               cdata->klass = klass;
+       }
+}
+
+/*
+ * Resolve the profile data to the corresponding loaded classes/methods etc. if possible.
+ */
+static void
+resolve_profile_data (MonoAotCompile *acfg, ProfileData *data)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       int i;
+
+       if (!data)
+               return;
+
+       /* Images */
+       GPtrArray *assemblies = mono_domain_get_assemblies (mono_get_root_domain (), FALSE);
+       g_hash_table_iter_init (&iter, data->images);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               ImageProfileData *idata = (ImageProfileData*)value;
+
+               for (i = 0; i < assemblies->len; ++i) {
+                       MonoAssembly *ass = g_ptr_array_index (assemblies, i);
+
+                       if (!strcmp (ass->aname.name, idata->name)) {
+                               idata->image = ass->image;
+                               break;
+                       }
+               }
+       }
+       g_ptr_array_free (assemblies, TRUE);
+
+       /* Classes */
+       g_hash_table_iter_init (&iter, data->classes);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               ClassProfileData *cdata = (ClassProfileData*)value;
+
+               if (!cdata->image->image) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load class '%s.%s' because its image '%s' is not loaded.\n", cdata->ns, cdata->name, cdata->image->name);
+                       continue;
+               }
+
+               resolve_class (cdata);
+               /*
+               if (cdata->klass)
+                       printf ("%s %s %s\n", cdata->ns, cdata->name, mono_class_full_name (cdata->klass));
+               */
+       }
+
+       /* Methods */
+       g_hash_table_iter_init (&iter, data->methods);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               MethodProfileData *mdata = (MethodProfileData*)value;
+               MonoClass *klass;
+               MonoMethod *m;
+               gpointer miter;
+
+               resolve_class (mdata->klass);
+               klass = mdata->klass->klass;
+               if (!klass) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load method '%s' because its class '%s.%s' is not loaded.\n", mdata->name, mdata->klass->ns, mdata->klass->name);
+                       continue;
+               }
+               miter = NULL;
+               while ((m = mono_class_get_methods (klass, &miter))) {
+                       MonoError error;
+
+                       if (strcmp (m->name, mdata->name))
+                               continue;
+                       MonoMethodSignature *sig = mono_method_signature (m);
+                       if (!sig)
+                               continue;
+                       if (sig->param_count != mdata->param_count)
+                               continue;
+                       if (mdata->inst) {
+                               resolve_ginst (mdata->inst);
+                               if (!mdata->inst->inst)
+                                       continue;
+                               MonoGenericContext ctx;
+
+                               memset (&ctx, 0, sizeof (ctx));
+                               ctx.method_inst = mdata->inst->inst;
+
+                               m = mono_class_inflate_generic_method_checked (m, &ctx, &error);
+                               if (!m)
+                                       continue;
+                               sig = mono_method_signature_checked (m, &error);
+                               if (!is_ok (&error)) {
+                                       mono_error_cleanup (&error);
+                                       continue;
+                               }
+                       }
+                       char *sig_str = mono_signature_full_name (sig);
+                       gboolean match = !strcmp (sig_str, mdata->signature);
+                       g_free (sig_str);
+                       if (!match)
+
+                               continue;
+                       //printf ("%s\n", mono_method_full_name (m, 1));
+                       mdata->method = m;
+                       break;
+               }
+               if (!mdata->method) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load method '%s' from class '%s', not found.\n", mdata->name, mono_class_full_name (klass));
+               }
+       }
+}
+
+static gboolean
+inst_references_image (MonoGenericInst *inst, MonoImage *image)
+{
+       int i;
+
+       for (i = 0; i < inst->type_argc; ++i) {
+               MonoClass *k = mono_class_from_mono_type (inst->type_argv [i]);
+               if (k->image == image)
+                       return TRUE;
+               if (mono_class_is_ginst (k)) {
+                       MonoGenericInst *kinst = mono_class_get_context (k)->class_inst;
+                       if (inst_references_image (kinst, image))
+                               return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static gboolean
+is_local_inst (MonoGenericInst *inst, MonoImage *image)
+{
+       int i;
+
+       for (i = 0; i < inst->type_argc; ++i) {
+               MonoClass *k = mono_class_from_mono_type (inst->type_argv [i]);
+               if (!MONO_TYPE_IS_PRIMITIVE (inst->type_argv [i]) && k->image != image)
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+static void
+add_profile_instances (MonoAotCompile *acfg, ProfileData *data)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       int count = 0;
+
+       if (!data)
+               return;
+
+       if (acfg->aot_opts.profile_only) {
+               /* Add methods referenced by the profile */
+               g_hash_table_iter_init (&iter, data->methods);
+               while (g_hash_table_iter_next (&iter, &key, &value)) {
+                       MethodProfileData *mdata = (MethodProfileData*)value;
+                       MonoMethod *m = mdata->method;
+
+                       if (!m)
+                               continue;
+                       if (m->is_inflated)
+                               continue;
+                       add_extra_method (acfg, m);
+                       g_hash_table_insert (acfg->profile_methods, m, m);
+                       count ++;
+               }
+       }
+
+       /*
+        * Add method instances 'related' to this assembly to the AOT image.
+        */
+       g_hash_table_iter_init (&iter, data->methods);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               MethodProfileData *mdata = (MethodProfileData*)value;
+               MonoMethod *m = mdata->method;
+               MonoGenericContext *ctx;
+
+               if (!m)
+                       continue;
+               if (!m->is_inflated)
+                       continue;
+
+               ctx = mono_method_get_context (m);
+               /* For simplicity, add instances which reference the assembly we are compiling */
+               if (((ctx->class_inst && inst_references_image (ctx->class_inst, acfg->image)) ||
+                        (ctx->method_inst && inst_references_image (ctx->method_inst, acfg->image))) &&
+                       !mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) {
+                       //printf ("%s\n", mono_method_full_name (m, TRUE));
+                       add_extra_method (acfg, m);
+                       count ++;
+               } else if (m->klass->image == acfg->image &&
+                       ((ctx->class_inst && is_local_inst (ctx->class_inst, acfg->image)) ||
+                        (ctx->method_inst && is_local_inst (ctx->method_inst, acfg->image))) &&
+                       !mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE))  {
+                       /* Add instances where the gtd is in the assembly and its inflated with types from this assembly or corlib */
+                       //printf ("%s\n", mono_method_full_name (m, TRUE));
+                       add_extra_method (acfg, m);
+                       count ++;
+               }
+               /*
+                * FIXME: We might skip some instances, for example:
+                * Foo<Bar> won't be compiled when compiling Foo's assembly since it doesn't match the first case,
+                * and it won't be compiled when compiling Bar's assembly if Foo's assembly is not loaded.
+                */
+       }
+
+       printf ("Added %d methods from profile.\n", count);
+}
+
+static void
+init_got_info (GotInfo *info)
 {
        int i;
 
@@ -10109,6 +10640,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->plt_entry_debug_sym_cache = g_hash_table_new (g_str_hash, g_str_equal);
        acfg->gsharedvt_in_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
        acfg->gsharedvt_out_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
+       acfg->profile_methods = g_hash_table_new (NULL, NULL);
        mono_os_mutex_init_recursive (&acfg->mutex);
 
        init_got_info (&acfg->got_info);
@@ -10368,11 +10900,6 @@ add_preinit_got_slots (MonoAotCompile *acfg)
        get_got_offset (acfg, FALSE, ji);
        get_got_offset (acfg, TRUE, ji);
 
-       ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-       ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
-       get_got_offset (acfg, FALSE, ji);
-       get_got_offset (acfg, TRUE, ji);
-
        ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
        ji->type = MONO_PATCH_INFO_AOT_MODULE;
        get_got_offset (acfg, FALSE, ji);
@@ -10383,8 +10910,22 @@ add_preinit_got_slots (MonoAotCompile *acfg)
        get_got_offset (acfg, FALSE, ji);
        get_got_offset (acfg, TRUE, ji);
 
+       for (i = 0; i < TLS_KEY_NUM; i++) {
+               ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+               ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
+               ji->data.index = i;
+               get_got_offset (acfg, FALSE, ji);
+               get_got_offset (acfg, TRUE, ji);
+
+               ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+               ji->type = MONO_PATCH_INFO_SET_TLS_TRAMP;
+               ji->data.index = i;
+               get_got_offset (acfg, FALSE, ji);
+               get_got_offset (acfg, TRUE, ji);
+       }
+
        ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-       ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
+       ji->type = MONO_PATCH_INFO_JIT_THREAD_ATTACH;
        get_got_offset (acfg, FALSE, ji);
        get_got_offset (acfg, TRUE, ji);
 
@@ -10535,7 +11076,21 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
        }
 
-       load_profile_files (acfg);
+       if (acfg->aot_opts.profile_files) {
+               GList *l;
+
+               for (l = acfg->aot_opts.profile_files; l; l = l->next) {
+                       load_profile_file (acfg, (char*)l->data);
+               }
+       }
+
+       {
+               int method_index;
+
+       for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) {
+                  g_ptr_array_add (acfg->method_order,GUINT_TO_POINTER (method_index));
+       }
+       }
 
        acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ntrampolines : 0;
 #ifdef MONO_ARCH_GSHARED_SUPPORTED
@@ -10596,6 +11151,15 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (!res)
                return 1;
 
+       {
+               GList *l;
+
+               for (l = acfg->profile_data; l; l = l->next)
+                       resolve_profile_data (acfg, (ProfileData*)l->data);
+               for (l = acfg->profile_data; l; l = l->next)
+                       add_profile_instances (acfg, (ProfileData*)l->data);
+       }
+
        acfg->cfgs_size = acfg->methods->len + 32;
        acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);
 
@@ -10653,7 +11217,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
                else
                        acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
-                       acfg->fp = fopen (acfg->tmpfname, "w+");
+               acfg->fp = fopen (acfg->tmpfname, "w+");
        } else {
                int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
                acfg->fp = fdopen (i, "w+");
@@ -10691,6 +11255,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                acfg->gas_line_numbers = TRUE;
        }
 
+#ifdef EMIT_DWARF_INFO
        if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
                if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
                        aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
@@ -10698,6 +11263,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
                acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, !acfg->gas_line_numbers);
        }
+#endif /* EMIT_DWARF_INFO */
 
        if (acfg->w)
                mono_img_writer_emit_start (acfg->w);
@@ -10748,6 +11314,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_file_info (acfg);
 
+       emit_library_info (acfg);
+
        if (acfg->dwarf) {
                emit_dwarf_info (acfg);
                mono_dwarf_writer_close (acfg->dwarf);