Merge pull request #1412 from esdrubal/stackframe
[mono.git] / mono / mini / aot-compiler.c
index 0697d0ba6bebb77f7ec510eea0af1d2bc9e2f5f1..283489f8d26dfafe23fa4ea3e3ba2906b7d57486 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>
@@ -64,6 +52,7 @@
 #include <mono/utils/mono-mmap.h>
 
 #include "mini.h"
+#include "seq-points.h"
 #include "image-writer.h"
 #include "dwarfwriter.h"
 #include "mini-gc.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 +113,7 @@ typedef struct MonoAotOptions {
        gboolean use_trampolines_page;
        gboolean no_instances;
        gboolean gnu_asm;
+       gboolean llvm;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -701,6 +679,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
@@ -1269,6 +1251,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
@@ -1936,14 +1923,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);
@@ -1954,18 +1941,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 */
@@ -3366,8 +3353,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
 
@@ -3539,14 +3527,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;
                }
 
@@ -3627,13 +3616,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;
                }
 
@@ -3810,13 +3800,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;
                }
 
@@ -3857,7 +3848,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;
@@ -4275,13 +4266,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;
                }
 
@@ -4869,13 +4861,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));
@@ -4998,7 +4991,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);
@@ -5328,7 +5323,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 {
        MonoMethod *method;
        int i, k, buf_size, method_index;
-       guint32 debug_info_size;
+       guint32 debug_info_size, seq_points_size;
        guint8 *code;
        MonoMethodHeader *header;
        guint8 *p, *buf, *debug_info;
@@ -5352,7 +5347,9 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        seq_points = cfg->seq_point_info;
 
-       buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 128) : 0) + cfg->gc_map_size;
+       seq_points_size = seq_point_info_get_write_size (seq_points);
+
+       buf_size = header->num_clauses * 256 + debug_info_size + 2048 + seq_points_size + cfg->gc_map_size;
        p = buf = g_malloc (buf_size);
 
        use_unwind_ops = cfg->unwind_ops != NULL;
@@ -5380,6 +5377,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) {
                /*
@@ -5549,27 +5555,9 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
        }
 
-       if (seq_points) {
-               int il_offset, native_offset, last_il_offset, last_native_offset, j;
-
-               encode_value (seq_points->len, p, &p);
-               last_il_offset = last_native_offset = 0;
-               for (i = 0; i < seq_points->len; ++i) {
-                       SeqPoint *sp = &seq_points->seq_points [i];
-                       il_offset = sp->il_offset;
-                       native_offset = sp->native_offset;
-                       encode_value (il_offset - last_il_offset, p, &p);
-                       encode_value (native_offset - last_native_offset, p, &p);
-                       last_il_offset = il_offset;
-                       last_native_offset = native_offset;
+       if (seq_points)
+               p += seq_point_info_write (seq_points, p);
 
-                       encode_value (sp->flags, p, &p);
-                       encode_value (sp->next_len, p, &p);
-                       for (j = 0; j < sp->next_len; ++j)
-                               encode_value (sp->next [j], p, &p);
-               }
-       }
-               
        g_assert (debug_info_size < buf_size);
 
        encode_value (debug_info_size, p, &p);
@@ -5602,14 +5590,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;
 
@@ -5763,41 +5752,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);
 
@@ -5837,9 +5801,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;
@@ -6393,6 +6354,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        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")) {
@@ -6450,9 +6413,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);
@@ -6580,6 +6544,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        gboolean skip;
        int index, depth;
        MonoMethod *wrapped;
+       JitFlags flags;
 
        if (acfg->aot_opts.metadata_only)
                return;
@@ -6624,7 +6589,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) {
@@ -6665,6 +6635,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.
@@ -7003,6 +6975,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)
 {
@@ -7098,7 +7085,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);
 
        /*
@@ -7837,10 +7824,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);
@@ -8635,7 +8623,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);
 
@@ -8655,7 +8643,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);*/
@@ -8720,7 +8708,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 ();
@@ -8852,7 +8840,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                MonoDebugOptions *opt = mini_get_debug_options ();
 
                opt->mdb_optimizations = TRUE;
-               opt->gen_seq_points = TRUE;
+               opt->gen_seq_points_debug_data = TRUE;
 
                if (!mono_debug_enabled ()) {
                        aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n");
@@ -8861,7 +8849,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                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;
@@ -8870,6 +8858,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        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)
@@ -8996,7 +8986,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
                res = emit_llvm_file (acfg);
                if (!res)
-                       return FALSE;
+                       return 1;
        }
 #endif
 
@@ -9004,7 +8994,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