Merge remote-tracking branch 'mfoliveira/ppc64el-v2'
[mono.git] / mono / mini / aot-compiler.c
index aa04ced89dd20f011d9fa71594f5bdbfd6910623..bc9c01f401fc9f688c25190250d77ad4a934f8cd 100644 (file)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  */
 
-/* Remaining AOT-only work:
- * - optimize the trampolines, generate more code in the arch files.
- * - make things more consistent with how elf works, for example, use ELF 
- *   relocations.
- * Remaining generics sharing work:
- * - optimize the size of the data which is encoded.
- * - optimize the runtime loading of data:
- *   - the trampoline code calls mono_jit_info_table_find () to find the rgctx, 
- *     which loads the debugging+exception handling info for the method. This is a 
- *     huge waste of time and code, since the rgctx structure is currently empty.
- */
 #include "config.h"
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
@@ -42,7 +31,6 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-
 #include <mono/metadata/abi-details.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/class.h>
 #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
 #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
 
-#ifdef TARGET_WIN32
-#define SHARED_EXT ".dll"
-#elif defined(__ppc__) && defined(TARGET_MACH)
-#define SHARED_EXT ".dylib"
-#elif defined(TARGET_MACH) && defined(TARGET_X86) && !defined(__native_client_codegen__)
-#define SHARED_EXT ".dylib"
-#elif defined(TARGET_MACH) && defined(TARGET_AMD64) && !defined(__native_client_codegen__)
-#define SHARED_EXT ".dylib"
-#else
-#define SHARED_EXT ".so"
-#endif
-
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
@@ -136,6 +112,7 @@ typedef struct MonoAotOptions {
        gboolean use_trampolines_page;
        gboolean no_instances;
        gboolean gnu_asm;
+       gboolean llvm;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -149,6 +126,7 @@ typedef struct MonoAotOptions {
        char *mtriple;
        char *llvm_path;
        char *instances_logfile_path;
+       char *logfile;
 } MonoAotOptions;
 
 typedef struct MonoAotStats {
@@ -206,7 +184,7 @@ typedef struct MonoAotCompile {
        MonoAotStats stats;
        int method_index;
        char *static_linking_symbol;
-       CRITICAL_SECTION mutex;
+       mono_mutex_t mutex;
        gboolean use_bin_writer;
        gboolean gas_line_numbers;
        MonoImageWriter *w;
@@ -244,6 +222,7 @@ typedef struct MonoAotCompile {
        int objc_selector_index, objc_selector_index_2;
        GPtrArray *objc_selectors;
        GHashTable *objc_selector_to_index;
+       FILE *logfile;
        FILE *instances_logfile;
 } MonoAotCompile;
 
@@ -254,8 +233,8 @@ typedef struct {
        gboolean jit_used, llvm_used;
 } MonoPltEntry;
 
-#define mono_acfg_lock(acfg) EnterCriticalSection (&((acfg)->mutex))
-#define mono_acfg_unlock(acfg) LeaveCriticalSection (&((acfg)->mutex))
+#define mono_acfg_lock(acfg) mono_mutex_lock (&((acfg)->mutex))
+#define mono_acfg_unlock(acfg) mono_mutex_unlock (&((acfg)->mutex))
 
 /* This points to the current acfg in LLVM mode */
 static MonoAotCompile *llvm_acfg;
@@ -303,6 +282,38 @@ get_patch_name (int info)
 static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
 
+static void
+aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
+{
+       FILE *output;
+       va_list args;
+
+       if (acfg->logfile)
+               output = acfg->logfile;
+       else
+               output = stdout;
+
+       va_start (args, format);
+       vfprintf (output, format, args);
+       va_end (args);
+}
+
+static void
+aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...)
+{
+       FILE *output;
+       va_list args;
+
+       if (acfg->logfile)
+               output = acfg->logfile;
+       else
+               output = stderr;
+
+       va_start (args, format);
+       vfprintf (output, format, args);
+       va_end (args);
+}
+
 /* Wrappers around the image writer functions */
 
 static inline void
@@ -667,6 +678,10 @@ arch_init (MonoAotCompile *acfg)
        acfg->llvm_label_prefix = "";
        acfg->user_symbol_prefix = "";
 
+#if defined(TARGET_X86)
+       g_string_append (acfg->llc_args, " -march=x86 -mattr=sse4.1");
+#endif
+
 #if defined(TARGET_AMD64)
        g_string_append (acfg->llc_args, " -march=x86-64 -mattr=sse4.1");
 #endif
@@ -1235,6 +1250,11 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
                g_assert (code - buf == 8);
                emit_bytes (acfg, buf, code - buf);
        }
+
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
 #elif defined(TARGET_ARM64)
        arm64_emit_specific_trampoline_pages (acfg);
 #endif
@@ -1902,14 +1922,14 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        code = buf;
 
        /* Load the mscorlib got address */
-       ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r30);
+       ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r30);
        /* Load the parameter from the GOT */
        ppc_load (code, ppc_r0, offset * sizeof (gpointer));
-       ppc_ldptr_indexed (code, ppc_r11, ppc_r11, ppc_r0);
+       ppc_ldptr_indexed (code, ppc_r12, ppc_r12, ppc_r0);
 
        /* Load and check key */
        labels [1] = code;
-       ppc_ldptr (code, ppc_r0, 0, ppc_r11);
+       ppc_ldptr (code, ppc_r0, 0, ppc_r12);
        ppc_cmp (code, 0, sizeof (gpointer) == 8 ? 1 : 0, ppc_r0, MONO_ARCH_IMT_REG);
        labels [2] = code;
        ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
@@ -1920,18 +1940,18 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
 
        /* Loop footer */
-       ppc_addi (code, ppc_r11, ppc_r11, 2 * sizeof (gpointer));
+       ppc_addi (code, ppc_r12, ppc_r12, 2 * sizeof (gpointer));
        labels [4] = code;
        ppc_b (code, 0);
        mono_ppc_patch (labels [4], labels [1]);
 
        /* Match */
        mono_ppc_patch (labels [2], code);
-       ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r11);
-       /* r11 now contains the value of the vtable slot */
+       ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r12);
+       /* r12 now contains the value of the vtable slot */
        /* this is not a function descriptor on ppc64 */
-       ppc_ldptr (code, ppc_r11, 0, ppc_r11);
-       ppc_mtctr (code, ppc_r11);
+       ppc_ldptr (code, ppc_r12, 0, ppc_r12);
+       ppc_mtctr (code, ppc_r12);
        ppc_bcctr (code, PPC_BR_ALWAYS, 0);
 
        /* Fail */
@@ -2299,7 +2319,9 @@ find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
        if (!acfg->typespec_classes) {
                acfg->typespec_classes = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoClass*) * len);
                for (i = 0; i < len; ++i) {
-                       acfg->typespec_classes [i] = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
+                       MonoError error;
+                       acfg->typespec_classes [i] = mono_class_get_and_inflate_typespec_checked (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL, &error);
+                       g_assert (mono_error_ok (&error)); /* FIXME error handling */
                }
        }
        for (i = 0; i < len; ++i) {
@@ -2666,8 +2688,10 @@ 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 = mono_marshal_get_wrapper_info (method);
-                       encode_klass_ref (acfg, proxy_class, p, &p);
+                       WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+                       g_assert (info);
+                       encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
                        break;
                }
                case MONO_WRAPPER_LDFLD_REMOTE:
@@ -3111,7 +3135,7 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth
                method = mini_get_shared_method (method);
 
        if (acfg->aot_opts.log_generics)
-               printf ("%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
+               aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
 
        add_method_full (acfg, method, TRUE, depth);
 }
@@ -3328,8 +3352,9 @@ add_wrappers (MonoAotCompile *acfg)
                        if (info && !has_nullable) {
                                /* Supported by the dynamic runtime-invoke wrapper */
                                skip = TRUE;
-                               g_free (info);
                        }
+                       if (info)
+                               mono_arch_dyn_call_free (info);
                }
 #endif
 
@@ -3501,14 +3526,15 @@ add_wrappers (MonoAotCompile *acfg)
 
        /* delegate-invoke wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+               MonoError error;
                MonoClass *klass;
                MonoCustomAttrInfo *cattr;
                
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
-               klass = mono_class_get (acfg->image, token);
+               klass = mono_class_get_checked (acfg->image, token, &error);
 
                if (!klass) {
-                       mono_loader_clear_error ();
+                       mono_error_cleanup (&error);
                        continue;
                }
 
@@ -3589,13 +3615,14 @@ add_wrappers (MonoAotCompile *acfg)
 
        /* array access wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
+               MonoError error;
                MonoClass *klass;
                
                token = MONO_TOKEN_TYPE_SPEC | (i + 1);
-               klass = mono_class_get (acfg->image, token);
+               klass = mono_class_get_checked (acfg->image, token, &error);
 
                if (!klass) {
-                       mono_loader_clear_error ();
+                       mono_error_cleanup (&error);
                        continue;
                }
 
@@ -3772,13 +3799,14 @@ add_wrappers (MonoAotCompile *acfg)
 
        /* StructureToPtr/PtrToStructure wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+               MonoError error;
                MonoClass *klass;
                
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
-               klass = mono_class_get (acfg->image, token);
+               klass = mono_class_get_checked (acfg->image, token, &error);
 
                if (!klass) {
-                       mono_loader_clear_error ();
+                       mono_error_cleanup (&error);
                        continue;
                }
 
@@ -3819,7 +3847,7 @@ is_vt_inst (MonoGenericInst *inst)
 
        for (i = 0; i < inst->type_argc; ++i) {
                MonoType *t = inst->type_argv [i];
-               if (t->type == MONO_TYPE_VALUETYPE)
+               if (MONO_TYPE_ISSTRUCT (t) || t->type == MONO_TYPE_VALUETYPE)
                        return TRUE;
        }
        return FALSE;
@@ -3927,7 +3955,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                return;
 
        if (acfg->aot_opts.log_generics)
-               printf ("%*sAdding generic instance %s [%s].\n", depth, "", mono_type_full_name (&klass->byval_arg), ref);
+               aot_printf (acfg, "%*sAdding generic instance %s [%s].\n", depth, "", mono_type_full_name (&klass->byval_arg), ref);
 
        g_hash_table_insert (acfg->ginst_hash, klass, klass);
 
@@ -3977,7 +4005,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                method = mono_marshal_get_delegate_invoke (method, NULL);
 
                if (acfg->aot_opts.log_generics)
-                       printf ("%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
+                       aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
 
                add_method (acfg, method);
        }
@@ -4237,13 +4265,14 @@ add_generic_instances (MonoAotCompile *acfg)
        }
 
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
+               MonoError error;
                MonoClass *klass;
 
                token = MONO_TOKEN_TYPE_SPEC | (i + 1);
 
-               klass = mono_class_get (acfg->image, token);
+               klass = mono_class_get_checked (acfg->image, token, &error);
                if (!klass || klass->rank) {
-                       mono_loader_clear_error ();
+                       mono_error_cleanup (&error);
                        continue;
                }
 
@@ -4831,13 +4860,14 @@ get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
        char *name1, *name2, *cached;
        int i, j, len, count;
 
+       name1 = mono_method_full_name (method, TRUE);
+
 #ifdef TARGET_MACH
        // This is so that we don't accidentally create a local symbol (which starts with 'L')
-       if (!prefix || !*prefix)
+       if ((!prefix || !*prefix) && name1 [0] == 'L')
                prefix = "_";
 #endif
 
-       name1 = mono_method_full_name (method, TRUE);
        len = strlen (name1);
        name2 = malloc (strlen (prefix) + len + 16);
        memcpy (name2, prefix, strlen (prefix));
@@ -4960,7 +4990,9 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
        case MONO_PATCH_INFO_JIT_TLS_ID:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+               break;
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
+               encode_value (patch_info->data.index, p, &p);
                break;
        case MONO_PATCH_INFO_METHOD_REL:
                encode_value ((gint)patch_info->data.offset, p, &p);
@@ -5043,6 +5075,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                } else {
                        encode_value (0, p, &p);
                }
+               encode_value (patch_info->data.del_tramp->virtual, p, &p);
                break;
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -5330,18 +5363,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                encoded = mono_unwind_ops_encode (cfg->unwind_ops, &encoded_len);
 
                unwind_desc = get_unwind_info_offset (acfg, encoded, encoded_len);
-               g_assert (unwind_desc < 0xffff);
-               if (cfg->has_unwind_info_for_epilog) {
-                       /*
-                        * The lower 16 bits identify the unwind descriptor, the upper 16 bits contain the offset of
-                        * the start of the epilog from the end of the method.
-                        */
-                       g_assert (cfg->code_size - cfg->epilog_begin < 0xffff);
-                       encode_value (((cfg->code_size - cfg->epilog_begin) << 16) | unwind_desc, p, &p);
-                       g_free (encoded);
-               } else {
-                       encode_value (unwind_desc, p, &p);
-               }
+               encode_value (unwind_desc, p, &p);
        } else {
                encode_value (jinfo->unwind_info, p, &p);
        }
@@ -5352,6 +5374,15 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                encode_value (table->num_holes, p, &p);
        }
 
+       if (jinfo->has_arch_eh_info) {
+               /*
+                * In AOT mode, the code length is calculated from the address of the previous method,
+                * which could include alignment padding, so calculating the start of the epilog as
+                * code_len - epilog_size is correct any more. Save the real code len as a workaround.
+                */
+               encode_value (jinfo->code_size, p, &p);
+       }
+
        /* Exception table */
        if (cfg->compile_llvm) {
                /*
@@ -5440,6 +5471,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
                eh_info = mono_jit_info_get_arch_eh_info (jinfo);
                encode_value (eh_info->stack_size, p, &p);
+               encode_value (eh_info->epilog_size, p, &p);
        }
 
        if (jinfo->has_generic_jit_info) {
@@ -5573,14 +5605,15 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 static guint32
 emit_klass_info (MonoAotCompile *acfg, guint32 token)
 {
-       MonoClass *klass = mono_class_get (acfg->image, token);
+       MonoError error;
+       MonoClass *klass = mono_class_get_checked (acfg->image, token, &error);
        guint8 *p, *buf;
        int i, buf_size, res;
        gboolean no_special_static, cant_encode;
        gpointer iter = NULL;
 
        if (!klass) {
-               mono_loader_clear_error ();
+               mono_error_cleanup (&error);
 
                buf_size = 16;
 
@@ -5734,41 +5767,16 @@ emit_plt (MonoAotCompile *acfg)
                plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
                ji = plt_entry->ji;
 
-               if (acfg->llvm) {
-                       /*
-                        * If the target is directly callable, alias the plt symbol to point to
-                        * the method code.
-                        * FIXME: Use this to simplify emit_and_reloc_code ().
-                        * FIXME: Avoid the got slot.
-                        * FIXME: Add support to the binary writer.
-                        */
-                       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);
-
-                               if (callee_cfg) {
-                                       if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
-                                               /* LLVM calls the PLT entries using bl, so emit a stub */
-                                               emit_set_thumb_mode (acfg);
-                                               fprintf (acfg->fp, "\n.thumb_func\n");
-                                               emit_label (acfg, plt_entry->llvm_symbol);
-                                               fprintf (acfg->fp, "bx pc\n");
-                                               fprintf (acfg->fp, "nop\n");
-                                               emit_set_arm_mode (acfg);
-                                               fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
-                                       } else {
-                                               fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
-                                       }
-                                       continue;
-                               }
-                       }
-               }
-
                debug_sym = plt_entry->debug_sym;
 
                if (acfg->thumb_mixed && !plt_entry->jit_used)
                        /* Emit only a thumb version */
                        continue;
 
+               /* Skip plt entries not actually called */
+               if (!plt_entry->jit_used && !plt_entry->llvm_used)
+                       continue;
+
                if (acfg->llvm && !acfg->thumb_mixed)
                        emit_label (acfg, plt_entry->llvm_symbol);
 
@@ -5808,9 +5816,6 @@ emit_plt (MonoAotCompile *acfg)
                        plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
                        ji = plt_entry->ji;
 
-                       if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer)
-                               continue;
-
                        /* Skip plt entries not actually called by LLVM code */
                        if (!plt_entry->llvm_used)
                                continue;
@@ -6358,10 +6363,14 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances="));
                } else if (str_begins_with (arg, "log-instances")) {
                        opts->log_instances = TRUE;
+               } else if (str_begins_with (arg, "internal-logfile=")) {
+                       opts->logfile = g_strdup (arg + strlen ("internal-logfile="));
                } else if (str_begins_with (arg, "mtriple=")) {
                        opts->mtriple = g_strdup (arg + strlen ("mtriple="));
                } else if (str_begins_with (arg, "llvm-path=")) {
                        opts->llvm_path = g_strdup (arg + strlen ("llvm-path="));
+               } else if (!strcmp (arg, "llvm")) {
+                       opts->llvm = TRUE;
                } else if (str_begins_with (arg, "readonly-value=")) {
                        add_readonly_value (opts, arg + strlen ("readonly-value="));
                } else if (str_begins_with (arg, "info")) {
@@ -6419,9 +6428,10 @@ add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
 {
        MonoMethod *method = (MonoMethod*)key;
        MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
-       MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
        MonoAotCompile *acfg = user_data;
+       MonoJumpInfoToken *new_ji;
 
+       new_ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
        new_ji->image = ji->image;
        new_ji->token = ji->token;
        g_hash_table_insert (acfg->token_info_hash, method, new_ji);
@@ -6549,6 +6559,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        gboolean skip;
        int index, depth;
        MonoMethod *wrapped;
+       JitFlags flags;
 
        if (acfg->aot_opts.metadata_only)
                return;
@@ -6593,7 +6604,12 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         * the runtime will not see AOT methods during AOT compilation,so it
         * does not need to support them by creating a fake GOT etc.
         */
-       cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), acfg->aot_opts.full_aot ? (JIT_FLAG_AOT|JIT_FLAG_FULL_AOT) : (JIT_FLAG_AOT), 0);
+       flags = JIT_FLAG_AOT;
+       if (acfg->aot_opts.full_aot)
+               flags |= JIT_FLAG_FULL_AOT;
+       if (acfg->llvm)
+               flags |= JIT_FLAG_LLVM;
+       cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0);
        mono_loader_clear_error ();
 
        if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
@@ -6634,6 +6650,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        mono_acfg_lock (acfg);
        g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
        mono_acfg_unlock (acfg);
+       g_hash_table_destroy (cfg->token_info_hash);
+       cfg->token_info_hash = NULL;
 
        /*
         * Check for absolute addresses.
@@ -6972,6 +6990,21 @@ mono_aot_get_method_name (MonoCompile *cfg)
                return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash);
 }
 
+gboolean
+mono_aot_is_direct_callable (MonoJumpInfo *patch_info)
+{
+       return is_direct_callable (llvm_acfg, NULL, patch_info);
+}
+
+void
+mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
+{
+       MonoPltEntry *plt_entry;
+
+       plt_entry = get_plt_entry (llvm_acfg, patch_info);
+       plt_entry->llvm_used = FALSE;
+}
+
 char*
 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 {
@@ -7021,7 +7054,7 @@ mono_aot_patch_info_dup (MonoJumpInfo* ji)
  *   Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM
  * tools.
  */
-static void
+static gboolean
 emit_llvm_file (MonoAotCompile *acfg)
 {
        char *command, *opts, *tempbc;
@@ -7067,7 +7100,7 @@ emit_llvm_file (MonoAotCompile *acfg)
 
 
        tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
-       mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
+       mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name), acfg->final_got_size);
        g_free (tempbc);
 
        /*
@@ -7101,10 +7134,9 @@ emit_llvm_file (MonoAotCompile *acfg)
        opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
 #if 1
        command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename);
-       printf ("Executing opt: %s\n", command);
-       if (system (command) != 0) {
-               exit (1);
-       }
+       aot_printf (acfg, "Executing opt: %s\n", command);
+       if (system (command) != 0)
+               return FALSE;
 #endif
        g_free (opts);
 
@@ -7130,11 +7162,11 @@ emit_llvm_file (MonoAotCompile *acfg)
 
        command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpbasename);
 
-       printf ("Executing llc: %s\n", command);
+       aot_printf (acfg, "Executing llc: %s\n", command);
 
-       if (system (command) != 0) {
-               exit (1);
-       }
+       if (system (command) != 0)
+               return FALSE;
+       return TRUE;
 }
 #endif
 
@@ -7807,10 +7839,11 @@ emit_class_name_table (MonoAotCompile *acfg)
        for (i = 0; i < table_size; ++i)
                g_ptr_array_add (table, NULL);
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+               MonoError error;
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
-               klass = mono_class_get (acfg->image, token);
+               klass = mono_class_get_checked (acfg->image, token, &error);
                if (!klass) {
-                       mono_loader_clear_error ();
+                       mono_error_cleanup (&error);
                        continue;
                }
                full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
@@ -8378,7 +8411,7 @@ emit_dwarf_info (MonoAotCompile *acfg)
 #endif
 }
 
-static void
+static gboolean
 collect_methods (MonoAotCompile *acfg)
 {
        int mindex, i;
@@ -8392,9 +8425,9 @@ collect_methods (MonoAotCompile *acfg)
                method = mono_get_method (acfg->image, token, NULL);
 
                if (!method) {
-                       printf ("Failed to load method 0x%x from '%s'.\n", token, image->name);
-                       printf ("Run with MONO_LOG_LEVEL=debug for more information.\n");
-                       exit (1);
+                       aot_printerrf (acfg, "Failed to load method 0x%x from '%s'.\n", token, image->name);
+                       aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n");
+                       return FALSE;
                }
                        
                /* Load all methods eagerly to skip the slower lazy loading code */
@@ -8458,6 +8491,7 @@ collect_methods (MonoAotCompile *acfg)
 
        if (acfg->aot_opts.full_aot)
                add_wrappers (acfg);
+       return TRUE;
 }
 
 static void
@@ -8570,9 +8604,9 @@ compile_asm (MonoAotCompile *acfg)
 #endif
 
        if (acfg->aot_opts.asm_only) {
-               printf ("Output file: '%s'.\n", acfg->tmpfname);
+               aot_printf (acfg, "Output file: '%s'.\n", acfg->tmpfname);
                if (acfg->aot_opts.static_link)
-                       printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
+                       aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol);
                return 0;
        }
 
@@ -8585,7 +8619,7 @@ compile_asm (MonoAotCompile *acfg)
                objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
        }
        command = g_strdup_printf ("%s%s %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->as_args ? acfg->as_args->str : "", objfile, acfg->tmpfname);
-       printf ("Executing the native assembler: %s\n", command);
+       aot_printf (acfg, "Executing the native assembler: %s\n", command);
        if (system (command) != 0) {
                g_free (command);
                g_free (objfile);
@@ -8595,8 +8629,8 @@ compile_asm (MonoAotCompile *acfg)
        g_free (command);
 
        if (acfg->aot_opts.static_link) {
-               printf ("Output file: '%s'.\n", objfile);
-               printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
+               aot_printf (acfg, "Output file: '%s'.\n", objfile);
+               aot_printf (acfg, "Linking symbol: '%s'.\n", acfg->static_linking_symbol);
                g_free (objfile);
                return 0;
        }
@@ -8604,7 +8638,7 @@ compile_asm (MonoAotCompile *acfg)
        if (acfg->aot_opts.outfile)
                outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
        else
-               outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
+               outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
 
        tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
 
@@ -8613,7 +8647,7 @@ compile_asm (MonoAotCompile *acfg)
 #else
        command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
 #endif
-       printf ("Executing the native linker: %s\n", command);
+       aot_printf (acfg, "Executing the native linker: %s\n", command);
        if (system (command) != 0) {
                g_free (tmp_outfile_name);
                g_free (outfile_name);
@@ -8624,7 +8658,7 @@ compile_asm (MonoAotCompile *acfg)
 
        g_free (command);
 
-       /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
+       /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, MONO_SOLIB_EXT);
        printf ("Stripping the binary: %s\n", com);
        system (com);
        g_free (com);*/
@@ -8635,7 +8669,7 @@ compile_asm (MonoAotCompile *acfg)
         * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
         */
        command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
-       printf ("Stripping the binary: %s\n", command);
+       aot_printf (acfg, "Stripping the binary: %s\n", command);
        if (system (command) != 0) {
                g_free (tmp_outfile_name);
                g_free (outfile_name);
@@ -8649,7 +8683,7 @@ compile_asm (MonoAotCompile *acfg)
 
 #if defined(TARGET_MACH)
        command = g_strdup_printf ("dsymutil %s", outfile_name);
-       printf ("Executing dsymutil: %s\n", command);
+       aot_printf (acfg, "Executing dsymutil: %s\n", command);
        if (system (command) != 0) {
                return 1;
        }
@@ -8663,7 +8697,7 @@ compile_asm (MonoAotCompile *acfg)
        g_free (objfile);
 
        if (acfg->aot_opts.save_temps)
-               printf ("Retained input file.\n");
+               aot_printf (acfg, "Retained input file.\n");
        else
                unlink (acfg->tmpfname);
 
@@ -8689,7 +8723,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
                acfg->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
        acfg->got_patches = g_ptr_array_new ();
        acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
-       acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+       acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL);
        acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free);
        acfg->image_hash = g_hash_table_new (NULL, NULL);
        acfg->image_table = g_ptr_array_new ();
@@ -8708,7 +8742,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->klass_blob_hash = g_hash_table_new (NULL, NULL);
        acfg->method_blob_hash = g_hash_table_new (NULL, NULL);
        acfg->plt_entry_debug_sym_cache = g_hash_table_new (g_str_hash, g_str_equal);
-       InitializeCriticalSection (&acfg->mutex);
+       mono_mutex_init_recursive (&acfg->mutex);
 
        return acfg;
 }
@@ -8768,15 +8802,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        TV_DECLARE (atv);
        TV_DECLARE (btv);
 
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
-       if (opts & MONO_OPT_GSHAREDVT) {
-               fprintf (stderr, "-O=gsharedvt not supported on this platform.\n");
-               exit (1);
-       }
-#endif
-
-       printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
-
        acfg = acfg_create (ass, opts);
 
        memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts));
@@ -8793,21 +8818,34 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        mono_aot_parse_options (aot_options, &acfg->aot_opts);
 
+       if (acfg->aot_opts.logfile) {
+               acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
+       }
+
        if (acfg->aot_opts.static_link)
                acfg->aot_opts.autoreg = TRUE;
 
        //acfg->aot_opts.print_skipped_methods = TRUE;
 
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
+       if (opts & MONO_OPT_GSHAREDVT) {
+               aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
+               return 1;
+       }
+#endif
+
+       aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
+
 #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
        if (acfg->aot_opts.full_aot) {
-               printf ("--aot=full is not supported on this platform.\n");
+               aot_printerrf (acfg, "--aot=full is not supported on this platform.\n");
                return 1;
        }
 #endif
 
        if (acfg->aot_opts.direct_pinvoke && !acfg->aot_opts.static_link) {
-               fprintf (stderr, "The 'direct-pinvoke' AOT option also requires the 'static' AOT option.\n");
-               exit (1);
+               aot_printerrf (acfg, "The 'direct-pinvoke' AOT option also requires the 'static' AOT option.\n");
+               return 1;
        }
 
        if (acfg->aot_opts.static_link)
@@ -8820,21 +8858,23 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                opt->gen_seq_points = TRUE;
 
                if (!mono_debug_enabled ()) {
-                       fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n");
+                       aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n");
                        return 1;
                }
                acfg->flags |= MONO_AOT_FILE_FLAG_DEBUG;
        }
 
-       if (mono_use_llvm) {
+       if (mono_use_llvm || acfg->aot_opts.llvm) {
                acfg->llvm = TRUE;
                acfg->aot_opts.asm_writer = TRUE;
                acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
 
                if (acfg->aot_opts.soft_debug) {
-                       fprintf (stderr, "The 'soft-debug' option is not supported when compiling with LLVM.\n");
-                       exit (1);
+                       aot_printerrf (acfg, "The 'soft-debug' option is not supported when compiling with LLVM.\n");
+                       return 1;
                }
+
+               mini_llvm_init ();
        }
 
        if (acfg->aot_opts.full_aot)
@@ -8843,8 +8883,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->aot_opts.instances_logfile_path) {
                acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
                if (!acfg->instances_logfile) {
-                       fprintf (stderr, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
-                       exit (1);
+                       aot_printerrf (acfg, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
+                       return 1;
                }
        }
 
@@ -8890,7 +8930,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                mono_set_partial_sharing_supported (TRUE);
        */
 
-       collect_methods (acfg);
+       res = collect_methods (acfg);
+       if (!res)
+               return 1;
 
        acfg->cfgs_size = acfg->methods->len + 32;
        acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);
@@ -8942,6 +8984,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
+               gboolean res;
+
                if (acfg->aot_opts.asm_only) {
                        if (acfg->aot_opts.outfile) {
                                acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
@@ -8955,7 +8999,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
                }
 
-               emit_llvm_file (acfg);
+               res = emit_llvm_file (acfg);
+               if (!res)
+                       return 1;
        }
 #endif
 
@@ -8963,7 +9009,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                if (acfg->aot_opts.outfile)
                        outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
                else
-                       outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
+                       outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
 
                /* 
                 * Can't use g_file_open_tmp () as it will be deleted at exit, and
@@ -8973,7 +9019,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
                acfg->fp = fopen (tmp_outfile_name, "w");
                if (!acfg->fp) {
-                       printf ("Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno));
+                       aot_printf (acfg, "Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno));
                        return 1;
                }
 
@@ -8997,7 +9043,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        }
                }
                if (acfg->fp == 0) {
-                       fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
+                       aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
                        return 1;
                }
                acfg->w = img_writer_create (acfg->fp, FALSE);
@@ -9034,7 +9080,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
                if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
-                       fprintf (stderr, "The dwarf AOT option requires the --debug option.\n");
+                       aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
                        return 1;
                }
                acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers);
@@ -9122,7 +9168,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size;
 
-       printf ("Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
+       aot_printf (acfg, "Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
                        acfg->stats.code_size, acfg->stats.code_size * 100 / all_sizes,
                        acfg->stats.info_size, acfg->stats.info_size * 100 / all_sizes,
                        acfg->stats.ex_info_size, acfg->stats.ex_info_size * 100 / all_sizes,
@@ -9132,19 +9178,19 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        acfg->stats.got_info_size, acfg->stats.got_info_size * 100 / all_sizes,
                        acfg->stats.offsets_size, acfg->stats.offsets_size * 100 / all_sizes,
                        (int)(acfg->got_offset * sizeof (gpointer)));
-       printf ("Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", 
+       aot_printf (acfg, "Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", 
                        acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
                        llvm_stats_msg,
                        acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100,
                        acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
        if (acfg->stats.genericcount)
-               printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
+               aot_printf (acfg, "%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
        if (acfg->stats.abscount)
-               printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
+               aot_printf (acfg, "%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
        if (acfg->stats.lmfcount)
-               printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
+               aot_printf (acfg, "%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
        if (acfg->stats.ocount)
-               printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
+               aot_printf (acfg, "%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
 
        TV_GETTIME (atv);
        res = img_writer_emit_writeout (acfg->w);
@@ -9156,7 +9202,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                int err = rename (tmp_outfile_name, outfile_name);
 
                if (err) {
-                       printf ("Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno));
+                       aot_printf (acfg, "Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno));
                        return 1;
                }
        } else {
@@ -9172,13 +9218,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->aot_opts.stats) {
                int i;
 
-               printf ("GOT slot distribution:\n");
+               aot_printf (acfg, "GOT slot distribution:\n");
                for (i = 0; i < MONO_PATCH_INFO_NONE; ++i)
                        if (acfg->stats.got_slot_types [i])
-                               printf ("\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]);
+                               aot_printf (acfg, "\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]);
        }
 
-       printf ("JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000);
+       aot_printf (acfg, "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000);
 
        acfg_free (acfg);