Fix the build.
[mono.git] / mono / mini / mini-llvm.c
index 7b3b0e57f47b3c64926f10823b4abff8046228b3..af00dcd9841a504a4cfcc938128f3dbb4f0ba59e 100644 (file)
@@ -46,7 +46,6 @@ void bzero (void *to, size_t count) { memset (to, 0, count); }
 typedef struct {
        LLVMModuleRef module;
        LLVMValueRef throw, rethrow, throw_corlib_exception;
-       LLVMValueRef generic_class_init_tramp;
        GHashTable *llvm_types;
        LLVMValueRef got_var;
        const char *got_symbol;
@@ -65,11 +64,14 @@ typedef struct {
        int max_got_offset;
 
        /* For AOT */
+       MonoAssembly *assembly;
+       char *global_prefix;
        MonoAotFileInfo aot_info;
        const char *jit_got_symbol;
        const char *eh_frame_symbol;
        LLVMValueRef code_start, code_end;
        gboolean has_jitted_code;
+       gboolean static_link;
 } MonoLLVMModule;
 
 /*
@@ -279,6 +281,7 @@ get_vtype_size (MonoType *t)
 
        size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
 
+       /* LLVMArgAsIArgs depends on this since it stores whole words */
        while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
                size ++;
 
@@ -391,7 +394,7 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
        if (t->byref)
                return LLVMPointerType (LLVMInt8Type (), 0);
 
-       t = mini_get_underlying_type (ctx->cfg, t);
+       t = mini_get_underlying_type (t);
        switch (t->type) {
        case MONO_TYPE_VOID:
                return LLVMVoidType ();
@@ -1170,24 +1173,35 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
        if (sinfo)
                memset (sinfo, 0, sizeof (LLVMSigInfo));
 
-       rtype = mini_get_underlying_type (ctx->cfg, sig->ret);
+       rtype = mini_get_underlying_type (sig->ret);
        ret_type = type_to_llvm_type (ctx, rtype);
        CHECK_FAILURE (ctx);
 
        if (cinfo) {
-               if (cinfo->ret.storage == LLVMArgVtypeInReg) {
+               switch (cinfo->ret.storage) {
+               case LLVMArgVtypeInReg:
                        /* LLVM models this by returning an aggregate value */
                        if (cinfo->ret.pair_storage [0] == LLVMArgInIReg && cinfo->ret.pair_storage [1] == LLVMArgNone) {
                                LLVMTypeRef members [2];
 
                                members [0] = IntPtrType ();
                                ret_type = LLVMStructType (members, 1, FALSE);
+                       } else if (cinfo->ret.pair_storage [0] == LLVMArgNone && cinfo->ret.pair_storage [1] == LLVMArgNone) {
+                               /* Empty struct */
+                               ret_type = LLVMVoidType ();
                        } else {
                                g_assert_not_reached ();
                        }
-               } else if (cinfo->ret.storage == LLVMArgVtypeByVal) {
+                       break;
+               case LLVMArgVtypeByVal:
                        /* Vtype returned normally by val */
-               } else if (cinfo->ret.storage == LLVMArgFpStruct) {
+                       break;
+               case LLVMArgVtypeAsScalar:
+                       /* LLVM models this by returning an int */
+                       g_assert (cinfo->ret.nslots == 1 || cinfo->ret.nslots == 2);
+                       ret_type = LLVMIntType (cinfo->ret.nslots * sizeof (mgreg_t) * 8);
+                       break;
+               case LLVMArgFpStruct: {
                        /* Vtype returned as a fp struct */
                        LLVMTypeRef members [16];
 
@@ -1195,16 +1209,38 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                        for (i = 0; i < cinfo->ret.nslots; ++i)
                                members [i] = cinfo->ret.esize == 8 ? LLVMDoubleType () : LLVMFloatType ();
                        ret_type = LLVMStructType (members, cinfo->ret.nslots, FALSE);
-               } else if (mini_type_is_vtype (ctx->cfg, rtype)) {
-                       g_assert (cinfo->ret.storage == LLVMArgVtypeRetAddr);
-                       vretaddr = TRUE;
+                       break;
+               }
+               case LLVMArgVtypeByRef:
+                       /* Vtype returned using a hidden argument */
                        ret_type = LLVMVoidType ();
+                       break;
+               default:
+                       if (mini_type_is_vtype (rtype)) {
+                               g_assert (cinfo->ret.storage == LLVMArgVtypeRetAddr);
+                               vretaddr = TRUE;
+                               ret_type = LLVMVoidType ();
+                       }
+                       break;
                }
        }
 
        pindexes = g_new0 (int, sig->param_count);
        param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
        pindex = 0;
+       if (cinfo && cinfo->ret.storage == LLVMArgVtypeByRef) {
+               /*
+                * Has to be the first argument because of the sret argument attribute
+                * FIXME: This might conflict with passing 'this' as the first argument, but
+                * this is only used on arm64 which has a dedicated struct return register.
+                */
+               if (sinfo)
+                       sinfo->vret_arg_pindex = pindex;
+               param_types [pindex] = type_to_llvm_arg_type (ctx, sig->ret);
+               CHECK_FAILURE (ctx);
+               param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
+               pindex ++;
+       }
        if (cinfo && cinfo->rgctx_arg) {
                if (sinfo)
                        sinfo->rgctx_arg_pindex = pindex;
@@ -1284,6 +1320,12 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                        param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
                        pindex ++;
                        break;
+               case LLVMArgVtypeByRef:
+                       param_types [pindex] = type_to_llvm_arg_type (ctx, sig->params [i]);
+                       CHECK_FAILURE (ctx);
+                       param_types [pindex] = LLVMPointerType (param_types [pindex], 0);
+                       pindex ++;
+                       break;
                case LLVMArgAsFpArgs: {
                        int j;
 
@@ -1292,6 +1334,9 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                        pindex += ainfo->nslots;
                        break;
                }
+               case LLVMArgVtypeAsScalar:
+                       g_assert_not_reached ();
+                       break;
                default:
                        param_types [pindex ++] = type_to_llvm_arg_type (ctx, sig->params [i]);
                        break;
@@ -2044,7 +2089,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                MonoInst *var = cfg->varinfo [i];
                LLVMTypeRef vtype;
 
-               if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || mini_type_is_vtype (cfg, var->inst_vtype)) {
+               if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || mini_type_is_vtype (var->inst_vtype)) {
                        vtype = type_to_llvm_type (ctx, var->inst_vtype);
                        CHECK_FAILURE (ctx);
                        /* Could be already created by an OP_VPHI */
@@ -2095,6 +2140,11 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                        }
                        break;
                }
+               case LLVMArgVtypeByRef: {
+                       /* The argument is passed by ref */
+                       ctx->addresses [reg] = LLVMGetParam (ctx->lmethod, ctx->pindexes [i]);
+                       break;
+               }
                case LLVMArgAsIArgs: {
                        LLVMValueRef arg = LLVMGetParam (ctx->lmethod, ctx->pindexes [i]);
 
@@ -2104,6 +2154,9 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                        LLVMBuildStore (ctx->builder, arg, convert (ctx, ctx->addresses [reg], LLVMPointerType (LLVMTypeOf (arg), 0)));
                        break;
                }
+               case LLVMArgVtypeAsScalar:
+                       g_assert_not_reached ();
+                       break;
                default:
                        ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (cfg, type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i]));
                        break;
@@ -2115,10 +2168,10 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
        if (sig->hasthis)
                emit_volatile_store (ctx, cfg->args [0]->dreg);
        for (i = 0; i < sig->param_count; ++i)
-               if (!mini_type_is_vtype (cfg, sig->params [i]))
+               if (!mini_type_is_vtype (sig->params [i]))
                        emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
 
-       if (sig->hasthis && !cfg->rgctx_var && cfg->generic_sharing_context) {
+       if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) {
                LLVMValueRef this_alloc;
 
                /*
@@ -2202,14 +2255,6 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
        ;
 }
 
-/* Have to export this for AOT */
-void
-mono_personality (void)
-{
-       /* Not used */
-       g_assert_not_reached ();
-}
-
 static void
 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
 {
@@ -2240,7 +2285,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        if (call->imt_arg_reg)
                cinfo->imt_arg = TRUE;
 
-       vretaddr = cinfo && cinfo->ret.storage == LLVMArgVtypeRetAddr;
+       vretaddr = cinfo && (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef);
 
        llvm_sig = sig_to_llvm_sig_full (ctx, sig, cinfo, &sinfo);
        CHECK_FAILURE (ctx);
@@ -2385,12 +2430,14 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                args [sinfo.imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->lmodule->ptr_type);
 #endif
        }
-
        if (vretaddr) {
                if (!addresses [call->inst.dreg])
                        addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
                g_assert (sinfo.vret_arg_pindex < nargs);
-               args [sinfo.vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
+               if (cinfo && cinfo->ret.storage == LLVMArgVtypeByRef)
+                       args [sinfo.vret_arg_pindex] = addresses [call->inst.dreg];
+               else
+                       args [sinfo.vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
        }
 
        for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
@@ -2427,10 +2474,17 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                        g_assert (addresses [reg]);
                        args [pindex] = addresses [reg];
                        break;
+               case LLVMArgVtypeByRef:
+                       g_assert (addresses [reg]);
+                       args [pindex] = addresses [reg];
+                       break;
                case LLVMArgAsIArgs:
                        g_assert (addresses [reg]);
                        args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
                        break;
+               case LLVMArgVtypeAsScalar:
+                       g_assert_not_reached ();
+                       break;
                default:
                        g_assert (args [pindex]);
                        if (i == 0 && sig->hasthis)
@@ -2463,6 +2517,8 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        if (!sig->pinvoke)
                LLVMSetInstructionCallConv (lcall, LLVMMono1CallConv);
 
+       if (cinfo && cinfo->ret.storage == LLVMArgVtypeByRef)
+               LLVMAddInstrAttribute (lcall, 1 + sinfo.vret_arg_pindex, LLVMStructRetAttribute);
        if (call->rgctx_arg_reg)
                LLVMAddInstrAttribute (lcall, 1 + sinfo.rgctx_arg_pindex, LLVMInRegAttribute);
        if (call->imt_arg_reg)
@@ -2485,6 +2541,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                case LLVMArgVtypeInReg: {
                        LLVMValueRef regs [2];
 
+                       if (LLVMTypeOf (lcall) == LLVMVoidType ())
+                               /* Empty struct */
+                               break;
+
                        if (!addresses [ins->dreg])
                                addresses [ins->dreg] = build_alloca (ctx, sig->ret);
 
@@ -2504,6 +2564,11 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
                        LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
                        break;
+               case LLVMArgVtypeAsScalar:
+                       if (!addresses [call->inst.dreg])
+                               addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
+                       LLVMBuildStore (builder, lcall, convert_full (ctx, addresses [call->inst.dreg], LLVMPointerType (LLVMTypeOf (lcall), 0), FALSE));
+                       break;
                default:
                        if (sig->ret->type != MONO_TYPE_VOID && !vretaddr)
                                /* If the method returns an unsigned value, need to zext it */
@@ -2556,7 +2621,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
 
        if (cfg->compile_aot) {
                /* Use a dummy personality function */
-               personality = LLVMGetNamedFunction (module, "mono_aot_personality");
+               personality = LLVMGetNamedFunction (module, "mono_personality");
                g_assert (personality);
        } else {
                personality = LLVMGetNamedFunction (module, "mono_personality");
@@ -2693,11 +2758,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
        if (bb->flags & BB_EXCEPTION_HANDLER) {
                if (!bblocks [bb->block_num].invoke_target) {
-                       /*
-                        * LLVM asserts if llvm.eh.selector is called from a bblock which
-                        * doesn't have an invoke pointing at it.
-                        * Update: LLVM no longer asserts, but some tests in exceptions.exe now fail.
-                        */
                        LLVM_FAILURE (ctx, "handler without invokes");
                }
 
@@ -2830,7 +2890,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                }
 
                case OP_SETRET:
-                       if (linfo->ret.storage == LLVMArgVtypeInReg) {
+                       switch (linfo->ret.storage) {
+                       case LLVMArgVtypeInReg: {
                                LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
                                LLVMValueRef part1, retval;
                                int size;
@@ -2849,8 +2910,20 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                LLVMBuildRet (builder, retval);
                                break;
                        }
+                       case LLVMArgVtypeAsScalar: {
+                               LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
+                               LLVMValueRef retval;
+                               int size;
+
+                               size = get_vtype_size (sig->ret);
 
-                       if (linfo->ret.storage == LLVMArgVtypeByVal) {
+                               g_assert (addresses [ins->sreg1]);
+
+                               retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), "");
+                               LLVMBuildRet (builder, retval);
+                               break;
+                       }
+                       case LLVMArgVtypeByVal: {
                                LLVMValueRef retval;
 
                                g_assert (addresses [ins->sreg1]);
@@ -2858,13 +2931,15 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                LLVMBuildRet (builder, retval);
                                break;
                        }
-
-                       if (linfo->ret.storage == LLVMArgVtypeRetAddr) {
+                       case LLVMArgVtypeByRef: {
                                LLVMBuildRetVoid (builder);
                                break;
                        }
-
-                       if (linfo->ret.storage == LLVMArgFpStruct) {
+                       case LLVMArgVtypeRetAddr: {
+                               LLVMBuildRetVoid (builder);
+                               break;
+                       }
+                       case LLVMArgFpStruct: {
                                LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
                                LLVMValueRef retval;
 
@@ -2873,20 +2948,23 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                LLVMBuildRet (builder, retval);
                                break;
                        }
-
-                       if (!lhs || ctx->is_dead [ins->sreg1]) {
-                               /* 
-                                * The method did not set its return value, probably because it
-                                * ends with a throw.
-                                */
-                               if (cfg->vret_addr)
-                                       LLVMBuildRetVoid (builder);
-                               else
-                                       LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
-                       } else {
-                               LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
+                       default: {
+                               if (!lhs || ctx->is_dead [ins->sreg1]) {
+                                       /*
+                                        * The method did not set its return value, probably because it
+                                        * ends with a throw.
+                                        */
+                                       if (cfg->vret_addr)
+                                               LLVMBuildRetVoid (builder);
+                                       else
+                                               LLVMBuildRet (builder, LLVMConstNull (type_to_llvm_type (ctx, sig->ret)));
+                               } else {
+                                       LLVMBuildRet (builder, convert (ctx, lhs, type_to_llvm_type (ctx, sig->ret)));
+                               }
+                               has_terminator = TRUE;
+                               break;
+                       }
                        }
-                       has_terminator = TRUE;
                        break;
                case OP_ICOMPARE:
                case OP_FCOMPARE:
@@ -3456,6 +3534,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_LCONV_TO_R8:
                        values [ins->dreg] = LLVMBuildSIToFP (builder, lhs, LLVMDoubleType (), dname);
                        break;
+               case OP_ICONV_TO_R_UN:
                case OP_LCONV_TO_R_UN:
                        values [ins->dreg] = LLVMBuildUIToFP (builder, lhs, LLVMDoubleType (), dname);
                        break;
@@ -3736,7 +3815,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_LDADDR: {
                        MonoInst *var = ins->inst_p0;
 
-                       values [ins->dreg] = addresses [var->dreg];
+                       if (var->opcode == OP_VTARG_ADDR) {
+                               /* The variable contains the vtype address */
+                               values [ins->dreg] = values [var->dreg];
+                       } else {
+                               values [ins->dreg] = addresses [var->dreg];
+                       }
                        break;
                }
                case OP_SIN: {
@@ -4066,7 +4150,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                break;
                        }
 
-                       if (mini_is_gsharedvt_klass (cfg, klass)) {
+                       if (mini_is_gsharedvt_klass (klass)) {
                                // FIXME:
                                LLVM_FAILURE (ctx, "gsharedvt");
                                break;
@@ -5018,6 +5102,10 @@ mono_llvm_emit_method (MonoCompile *cfg)
        if (cfg->vret_addr) {
                values [cfg->vret_addr->dreg] = LLVMGetParam (method, sinfo.vret_arg_pindex);
                LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
+               if (linfo->ret.storage == LLVMArgVtypeByRef) {
+                       LLVMAddAttribute (LLVMGetParam (method, sinfo.vret_arg_pindex), LLVMStructRetAttribute);
+                       LLVMAddAttribute (LLVMGetParam (method, sinfo.vret_arg_pindex), LLVMNoAliasAttribute);
+               }
        }
        if (sig->hasthis) {
                values [cfg->args [0]->dreg] = LLVMGetParam (method, sinfo.this_arg_pindex);
@@ -5039,6 +5127,11 @@ mono_llvm_emit_method (MonoCompile *cfg)
                g_free (name);
                if (linfo->args [i + sig->hasthis].storage == LLVMArgVtypeByVal)
                        LLVMAddAttribute (LLVMGetParam (method, sinfo.pindexes [i]), LLVMByValAttribute);
+
+               if (linfo->args [i + sig->hasthis].storage == LLVMArgVtypeByRef) {
+                       /* For OP_LDADDR */
+                       cfg->args [i + sig->hasthis]->opcode = OP_VTARG_ADDR;
+               }
        }
        g_free (names);
 
@@ -5366,7 +5459,9 @@ mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        break;
                }
                case LLVMArgVtypeByVal:
+               case LLVMArgVtypeByRef:
                case LLVMArgVtypeInReg:
+               case LLVMArgVtypeAsScalar:
                case LLVMArgAsIArgs:
                case LLVMArgAsFpArgs:
                        MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
@@ -5438,10 +5533,11 @@ exception_cb (void *data)
        /* Count nested clauses */
        nested_len = 0;
        for (i = 0; i < ei_len; ++i) {
-               for (j = 0; j < ei_len; ++j) {
-                       gint32 cindex1 = *(gint32*)type_info [i];
-                       MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
-                       gint32 cindex2 = *(gint32*)type_info [j];
+               gint32 cindex1 = *(gint32*)type_info [i];
+               MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
+
+               for (j = 0; j < cfg->header->num_clauses; ++j) {
+                       int cindex2 = j;
                        MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
 
                        if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
@@ -5471,19 +5567,25 @@ exception_cb (void *data)
         */
        nindex = ei_len;
        for (i = 0; i < ei_len; ++i) {
-               for (j = 0; j < ei_len; ++j) {
-                       gint32 cindex1 = *(gint32*)type_info [i];
-                       MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
-                       gint32 cindex2 = *(gint32*)type_info [j];
+               gint32 cindex1 = *(gint32*)type_info [i];
+               MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];
+
+               for (j = 0; j < cfg->header->num_clauses; ++j) {
+                       int cindex2 = j;
                        MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
+                       MonoJitExceptionInfo *nesting_ei, *nested_ei;
 
                        if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
-                               memcpy (&cfg->llvm_ex_info [nindex], &cfg->llvm_ex_info [j], sizeof (MonoJitExceptionInfo));
-                               cfg->llvm_ex_info [nindex].try_start = cfg->llvm_ex_info [i].try_start;
-                               cfg->llvm_ex_info [nindex].try_end = cfg->llvm_ex_info [i].try_end;
-                               cfg->llvm_ex_info [nindex].handler_start = cfg->llvm_ex_info [i].handler_start;
-                               cfg->llvm_ex_info [nindex].exvar_offset = cfg->llvm_ex_info [i].exvar_offset;
+                               /* clause1 is the nested clause */
+                               nested_ei = &cfg->llvm_ex_info [i];
+                               nesting_ei = &cfg->llvm_ex_info [nindex];
                                nindex ++;
+
+                               memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));
+
+                               nesting_ei->flags = clause2->flags;
+                               nesting_ei->data.catch_class = clause2->data.catch_class;
+                               nesting_ei->clause_index = cindex2;
                        }
                }
        }
@@ -5872,26 +5974,31 @@ mono_llvm_free_domain_info (MonoDomain *domain)
 }
 
 void
-mono_llvm_create_aot_module (const char *global_prefix, gboolean emit_dwarf)
+mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link)
 {
-       /* Delete previous module */
-       if (aot_module.plt_entries)
-               g_hash_table_destroy (aot_module.plt_entries);
-       if (aot_module.module)
-               LLVMDisposeModule (aot_module.module);
-
-       memset (&aot_module, 0, sizeof (aot_module));
+       MonoLLVMModule *lmodule = &aot_module;
 
-       aot_module.module = LLVMModuleCreateWithName ("aot");
-       aot_module.got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
-       aot_module.eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
-       aot_module.external_symbols = TRUE;
-       aot_module.emit_dwarf = emit_dwarf;
+       /* Delete previous module */
+       if (lmodule->plt_entries)
+               g_hash_table_destroy (lmodule->plt_entries);
+       if (lmodule->module)
+               LLVMDisposeModule (lmodule->module);
+
+       memset (lmodule, 0, sizeof (aot_module));
+
+       lmodule->module = LLVMModuleCreateWithName ("aot");
+       lmodule->assembly = assembly;
+       lmodule->global_prefix = g_strdup (global_prefix);
+       lmodule->got_symbol = g_strdup_printf ("%s_llvm_got", global_prefix);
+       lmodule->eh_frame_symbol = g_strdup_printf ("%s_eh_frame", global_prefix);
+       lmodule->external_symbols = TRUE;
+       lmodule->emit_dwarf = emit_dwarf;
+       lmodule->static_link = static_link;
        /* The first few entries are reserved */
-       aot_module.max_got_offset = 16;
+       lmodule->max_got_offset = 16;
 
-       add_intrinsics (aot_module.module);
-       add_types (&aot_module);
+       add_intrinsics (lmodule->module);
+       add_types (lmodule);
 
        /* Add GOT */
        /*
@@ -5901,31 +6008,16 @@ mono_llvm_create_aot_module (const char *global_prefix, gboolean emit_dwarf)
         * its size is known in mono_llvm_emit_aot_module ().
         */
        {
-               LLVMTypeRef got_type = LLVMArrayType (aot_module.ptr_type, 0);
+               LLVMTypeRef got_type = LLVMArrayType (lmodule->ptr_type, 0);
 
-               aot_module.got_var = LLVMAddGlobal (aot_module.module, got_type, "mono_dummy_got");
-               LLVMSetInitializer (aot_module.got_var, LLVMConstNull (got_type));
+               aot_module.got_var = LLVMAddGlobal (lmodule->module, got_type, "mono_dummy_got");
+               LLVMSetInitializer (lmodule->got_var, LLVMConstNull (got_type));
        }
 
-       /* Add a dummy personality function */
-       {
-               LLVMBasicBlockRef lbb;
-               LLVMBuilderRef lbuilder;
-               LLVMValueRef personality;
-
-               personality = LLVMAddFunction (aot_module.module, "mono_aot_personality", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
-               LLVMSetLinkage (personality, LLVMInternalLinkage);
-               lbb = LLVMAppendBasicBlock (personality, "BB0");
-               lbuilder = LLVMCreateBuilder ();
-               LLVMPositionBuilderAtEnd (lbuilder, lbb);
-               LLVMBuildRetVoid (lbuilder);
-               mark_as_used (&aot_module, personality);
-       }
-
-       aot_module.llvm_types = g_hash_table_new (NULL, NULL);
-       aot_module.plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
-       aot_module.plt_entries_ji = g_hash_table_new (NULL, NULL);
-       aot_module.method_to_lmethod = g_hash_table_new (NULL, NULL);
+       lmodule->llvm_types = g_hash_table_new (NULL, NULL);
+       lmodule->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
+       lmodule->plt_entries_ji = g_hash_table_new (NULL, NULL);
+       lmodule->method_to_lmethod = g_hash_table_new (NULL, NULL);
 }
 
 static LLVMValueRef
@@ -5951,9 +6043,11 @@ llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
 void
 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
 {
+       MonoLLVMModule *lmodule = &aot_module;
+
        /* Save these for later */
-       memcpy (&aot_module.aot_info, info, sizeof (MonoAotFileInfo));
-       aot_module.has_jitted_code = has_jitted_code;
+       memcpy (&lmodule->aot_info, info, sizeof (MonoAotFileInfo));
+       lmodule->has_jitted_code = has_jitted_code;
 }
 
 /*
@@ -5970,7 +6064,23 @@ mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
 
        type = LLVMArrayType (LLVMInt8Type (), data_len);
        d = LLVMAddGlobal (lmodule->module, type, symbol);
+       LLVMSetVisibility (d, LLVMHiddenVisibility);
+       LLVMSetLinkage (d, LLVMInternalLinkage);
        LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
+       mono_llvm_set_is_constant (d);
+}
+
+/* Add a reference to a global defined in JITted code */
+static LLVMValueRef
+AddJitGlobal (MonoLLVMModule *lmodule, LLVMTypeRef type, const char *name)
+{
+       char *s;
+       LLVMValueRef v;
+
+       s = g_strdup_printf ("%s%s", lmodule->global_prefix, name);
+       v = LLVMAddGlobal (lmodule->module, LLVMInt8Type (), s);
+       g_free (s);
+       return v;
 }
 
 static void
@@ -6004,7 +6114,11 @@ emit_aot_file_info (MonoLLVMModule *lmodule)
        file_info_type = LLVMStructCreateNamed (LLVMGetGlobalContext (), "MonoAotFileInfo");
        LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
 
-       info_var = LLVMAddGlobal (aot_module.module, file_info_type, "mono_aot_file_info");
+       info_var = LLVMAddGlobal (lmodule->module, file_info_type, "mono_aot_file_info");
+       if (lmodule->static_link) {
+               LLVMSetVisibility (info_var, LLVMHiddenVisibility);
+               LLVMSetLinkage (info_var, LLVMInternalLinkage);
+       }
        fields = g_new (LLVMValueRef, nfields);
        tindex = 0;
        fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->version, FALSE);
@@ -6016,54 +6130,56 @@ emit_aot_file_info (MonoLLVMModule *lmodule)
         * for symbols defined in the .s file emitted by the aot compiler.
         */
        eltype = eltypes [tindex];
-       fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_got");
-       fields [tindex ++] = aot_module.got_var;
+       fields [tindex ++] = AddJitGlobal (lmodule, eltype, "jit_got");
+       fields [tindex ++] = lmodule->got_var;
        /* llc defines this directly */
-       fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, aot_module.eh_frame_symbol);
-       if (TRUE || aot_module.has_jitted_code) {
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_code_start");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "jit_code_end");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "method_addresses");
+       fields [tindex ++] = LLVMAddGlobal (lmodule->module, eltype, lmodule->eh_frame_symbol);
+       if (TRUE || lmodule->has_jitted_code) {
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "jit_code_start");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "jit_code_end");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "method_addresses");
        } else {
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
        }
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "blob");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "class_name_table");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "class_info_offsets");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "method_info_offsets");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "ex_info_offsets");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "extra_method_info_offsets");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "extra_method_table");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "got_info_offsets");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "llvm_got_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "blob");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "class_name_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "class_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "method_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "ex_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "extra_method_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "extra_method_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "got_info_offsets");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "llvm_got_info_offsets");
        /* Not needed (mem_end) */
        fields [tindex ++] = LLVMConstNull (eltype);
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "image_table");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "assembly_guid");
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "runtime_version");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "image_table");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "assembly_guid");
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "runtime_version");
        if (info->trampoline_size [0]) {
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "specific_trampolines");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "static_rgctx_trampolines");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "imt_thunks");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "gsharedvt_arg_trampolines");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "specific_trampolines");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "static_rgctx_trampolines");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "imt_thunks");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "gsharedvt_arg_trampolines");
        } else {
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
        }
-       // FIXME:
-       fields [tindex ++] = LLVMConstNull (eltype);
-       fields [tindex ++] = LLVMGetNamedGlobal (aot_module.module, "assembly_name");
-       if (TRUE || aot_module.has_jitted_code) {
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "plt");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "plt_end");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unwind_info");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampolines");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampolines_end");
-               fields [tindex ++] = LLVMAddGlobal (aot_module.module, eltype, "unbox_trampoline_addresses");
+       if (lmodule->static_link)
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "globals");
+       else
+               fields [tindex ++] = LLVMConstNull (eltype);
+       fields [tindex ++] = LLVMGetNamedGlobal (lmodule->module, "assembly_name");
+       if (TRUE || lmodule->has_jitted_code) {
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "plt");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "plt_end");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "unwind_info");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "unbox_trampolines");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "unbox_trampolines_end");
+               fields [tindex ++] = AddJitGlobal (lmodule, eltype, "unbox_trampoline_addresses");
        } else {
                fields [tindex ++] = LLVMConstNull (eltype);
                fields [tindex ++] = LLVMConstNull (eltype);
@@ -6073,6 +6189,9 @@ emit_aot_file_info (MonoLLVMModule *lmodule)
                fields [tindex ++] = LLVMConstNull (eltype);
        }
 
+       for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
+               fields [2 + i] = LLVMConstBitCast (fields [2 + i], eltype);
+
        /* Scalars */
        fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_got_offset_base, FALSE);
        fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
@@ -6095,6 +6214,23 @@ emit_aot_file_info (MonoLLVMModule *lmodule)
        g_assert (tindex == nfields);
 
        LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
+
+       if (lmodule->static_link) {
+               char *s, *p;
+               LLVMValueRef var;
+
+               s = g_strdup_printf ("mono_aot_module_%s_info", lmodule->assembly->aname.name);
+               /* Get rid of characters which cannot occur in symbols */
+               p = s;
+               for (p = s; *p; ++p) {
+                       if (!(isalnum (*p) || *p == '_'))
+                               *p = '_';
+               }
+               var = LLVMAddGlobal (lmodule->module, LLVMPointerType (LLVMInt8Type (), 0), s);
+               g_free (s);
+               LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (lmodule->module, "mono_aot_file_info"), LLVMPointerType (LLVMInt8Type (), 0)));
+               LLVMSetLinkage (var, LLVMExternalLinkage);
+       }
 }
 
 /*