Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / mini-llvm.c
index bf27a3629862f2de220565184b045da383d6b7c2..0b996be7f1838ee8a684725105b03d1d60afe7b5 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * mini-llvm.c: llvm "Backend" for the mono JIT
+/**
+ * \file
+ * llvm "Backend" for the mono JIT
  *
  * Copyright 2009-2011 Novell Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
@@ -9,7 +10,7 @@
 #include "config.h"
 
 #include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/debug-internals.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/object-internals.h>
@@ -434,6 +435,9 @@ create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
                 * This is needed on arm64 where HFAs are returned in
                 * registers.
                 */
+               /* SIMD types have size 16 in mono_class_value_size () */
+               if (klass->simd_type)
+                       nfields = 16/ esize;
                size = nfields;
                eltypes = g_new (LLVMTypeRef, size);
                for (i = 0; i < size; ++i)
@@ -463,6 +467,9 @@ create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
 static LLVMTypeRef
 type_to_llvm_type (EmitContext *ctx, MonoType *t)
 {
+       if (t->byref)
+               return ThisType ();
+
        t = mini_get_underlying_type (t);
 
        switch (t->type) {
@@ -480,13 +487,9 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
                return LLVMInt16Type ();
        case MONO_TYPE_U4:
                return LLVMInt32Type ();
-       case MONO_TYPE_BOOLEAN:
-               return LLVMInt8Type ();
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
                return LLVMInt64Type ();
-       case MONO_TYPE_CHAR:
-               return LLVMInt16Type ();
        case MONO_TYPE_R4:
                return LLVMFloatType ();
        case MONO_TYPE_R8:
@@ -495,10 +498,6 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
        case MONO_TYPE_U:
                return IntPtrType ();
        case MONO_TYPE_OBJECT:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_ARRAY:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
                return ObjRefType ();
        case MONO_TYPE_VAR:
@@ -1230,10 +1229,10 @@ sig_to_llvm_sig_no_cinfo (EmitContext *ctx, MonoMethodSignature *sig)
        int i, pindex;
        MonoType *rtype;
 
-       rtype = mini_get_underlying_type (sig->ret);
-       ret_type = type_to_llvm_type (ctx, rtype);
+       ret_type = type_to_llvm_type (ctx, sig->ret);
        if (!ctx_ok (ctx))
                return NULL;
+       rtype = mini_get_underlying_type (sig->ret);
 
        param_types = g_new0 (LLVMTypeRef, (sig->param_count * 8) + 3);
        pindex = 0;
@@ -1273,10 +1272,10 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
        if (!cinfo)
                return sig_to_llvm_sig_no_cinfo (ctx, sig);
 
-       rtype = mini_get_underlying_type (sig->ret);
-       ret_type = type_to_llvm_type (ctx, rtype);
+       ret_type = type_to_llvm_type (ctx, sig->ret);
        if (!ctx_ok (ctx))
                return NULL;
+       rtype = mini_get_underlying_type (sig->ret);
 
        switch (cinfo->ret.storage) {
        case LLVMArgVtypeInReg:
@@ -1428,7 +1427,10 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                        pindex ++;
                        break;
                case LLVMArgAsIArgs:
-                       param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
+                       if (ainfo->esize == 8)
+                               param_types [pindex] = LLVMArrayType (LLVMInt64Type (), ainfo->nslots);
+                       else
+                               param_types [pindex] = LLVMArrayType (IntPtrType (), ainfo->nslots);
                        pindex ++;
                        break;
                case LLVMArgVtypeByRef:
@@ -1833,7 +1835,7 @@ emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LL
                clause = get_most_deep_clause (cfg, ctx, bb);
 
                if (clause) {
-                       g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+                       g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT);
 
                        /*
                         * Have to use an invoke instead of a call, branching to the
@@ -1872,7 +1874,7 @@ emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LL
                         * handler bblock of the clause containing this bblock.
                         */
 
-                       g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+                       g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY || ec->flags == MONO_EXCEPTION_CLAUSE_FAULT);
 
                        tblock = cfg->cil_offset_to_bb [ec->handler_offset];
                        g_assert (tblock);
@@ -2466,7 +2468,7 @@ emit_get_method (MonoLLVMModule *module)
        func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
        LLVMSetLinkage (func, LLVMExternalLinkage);
        LLVMSetVisibility (func, LLVMHiddenVisibility);
-       LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+       mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
        module->get_method = func;
 
        entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
@@ -2546,7 +2548,7 @@ emit_get_unbox_tramp (MonoLLVMModule *module)
        func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
        LLVMSetLinkage (func, LLVMExternalLinkage);
        LLVMSetVisibility (func, LLVMHiddenVisibility);
-       LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+       mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
        module->get_unbox_tramp = func;
 
        entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
@@ -2597,7 +2599,7 @@ emit_llvm_code_start (MonoLLVMModule *module)
 
        func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
        LLVMSetLinkage (func, LLVMInternalLinkage);
-       LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+       mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
        module->code_start = func;
        entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
        builder = LLVMCreateBuilder ();
@@ -2636,7 +2638,7 @@ emit_init_icall_wrapper (MonoLLVMModule *module, const char *name, const char *i
                g_assert_not_reached ();
        }
        LLVMSetLinkage (func, LLVMInternalLinkage);
-       LLVMAddFunctionAttr (func, LLVMNoInlineAttribute);
+       mono_llvm_add_func_attr (func, LLVM_ATTR_NO_INLINE);
        mono_llvm_set_preserveall_cc (func);
        entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
        builder = LLVMCreateBuilder ();
@@ -2705,7 +2707,7 @@ emit_llvm_code_end (MonoLLVMModule *module)
 
        func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
        LLVMSetLinkage (func, LLVMInternalLinkage);
-       LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+       mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
        module->code_end = func;
        entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
        builder = LLVMCreateBuilder ();
@@ -2858,17 +2860,17 @@ emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_
        tramp_name = g_strdup_printf ("ut_%s", method_name);
        tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
        LLVMSetLinkage (tramp, LLVMInternalLinkage);
-       LLVMAddFunctionAttr (tramp, LLVMOptimizeForSizeAttribute);
-       //LLVMAddFunctionAttr (tramp, LLVMNoUnwindAttribute);
+       mono_llvm_add_func_attr (tramp, LLVM_ATTR_OPTIMIZE_FOR_SIZE);
+       //mono_llvm_add_func_attr (tramp, LLVM_ATTR_NO_UNWIND);
        linfo = ctx->linfo;
        // FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
        if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
-               LLVMAddAttribute (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVMInRegAttribute);
+               mono_llvm_add_param_attr (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVM_ATTR_IN_REG);
        if (ctx->cfg->vret_addr) {
                LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
                if (linfo->ret.storage == LLVMArgVtypeByRef) {
-                       LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMStructRetAttribute);
-                       LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
+                       mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
+                       mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
                }
        }
 
@@ -2890,9 +2892,9 @@ emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_
        }
        call = LLVMBuildCall (builder, method, args, nargs, "");
        if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
-               LLVMAddInstrAttribute (call, 1 + ctx->rgctx_arg_pindex, LLVMInRegAttribute);
+               mono_llvm_add_instr_attr (call, 1 + ctx->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
        if (linfo->ret.storage == LLVMArgVtypeByRef)
-               LLVMAddInstrAttribute (call, 1 + linfo->vret_arg_pindex, LLVMStructRetAttribute);
+               mono_llvm_add_instr_attr (call, 1 + linfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
 
        // FIXME: This causes assertions in clang
        //mono_llvm_set_must_tail (call);
@@ -3487,7 +3489,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                }
                case LLVMArgAsIArgs:
                        g_assert (addresses [reg]);
-                       args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
+                       if (ainfo->esize == 8)
+                               args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (LLVMInt64Type (), ainfo->nslots), 0)), "");
+                       else
+                               args [pindex] = LLVMBuildLoad (ctx->builder, convert (ctx, addresses [reg], LLVMPointerType (LLVMArrayType (IntPtrType (), ainfo->nslots), 0)), "");
                        break;
                case LLVMArgVtypeAsScalar:
                        g_assert_not_reached ();
@@ -3539,18 +3544,18 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                mono_llvm_set_call_preserveall_cc (lcall);
 
        if (cinfo->ret.storage == LLVMArgVtypeByRef)
-               LLVMAddInstrAttribute (lcall, 1 + cinfo->vret_arg_pindex, LLVMStructRetAttribute);
+               mono_llvm_add_instr_attr (lcall, 1 + cinfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
        if (!ctx->llvm_only && call->rgctx_arg_reg)
-               LLVMAddInstrAttribute (lcall, 1 + cinfo->rgctx_arg_pindex, LLVMInRegAttribute);
+               mono_llvm_add_instr_attr (lcall, 1 + cinfo->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
        if (call->imt_arg_reg)
-               LLVMAddInstrAttribute (lcall, 1 + cinfo->imt_arg_pindex, LLVMInRegAttribute);
+               mono_llvm_add_instr_attr (lcall, 1 + cinfo->imt_arg_pindex, LLVM_ATTR_IN_REG);
 
        /* Add byval attributes if needed */
        for (i = 0; i < sig->param_count; ++i) {
                LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
 
                if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
-                       LLVMAddInstrAttribute (lcall, 1 + ainfo->pindex, LLVMByValAttribute);
+                       mono_llvm_add_instr_attr (lcall, 1 + ainfo->pindex, LLVM_ATTR_BY_VAL);
        }
 
        /*
@@ -3909,7 +3914,7 @@ emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
        MonoExceptionClause *group_cursor = group_start;
 
        for (int i = 0; i < group_size; i ++) {
-               if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
+               if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY || group_cursor->flags & MONO_EXCEPTION_CLAUSE_FAULT))
                        finally_only = FALSE;
 
                group_cursor++;
@@ -3929,7 +3934,7 @@ emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
                LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
 
                // else move to that target bb
-               for (int i=0; i < group_size; i++) {
+               for (int i = 0; i < group_size; i++) {
                        MonoExceptionClause *clause = group_start + i;
                        int clause_index = clause - cfg->header->clauses;
                        MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
@@ -3958,7 +3963,7 @@ emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBloc
        MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
 
        // Make exception available to catch blocks
-       if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
+       if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
                LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
 
                g_assert (ctx->ex_var);
@@ -4009,18 +4014,15 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
                g_assert (personality);
        } else {
 #if LLVM_API_VERSION > 100
-               personality = ctx->module->personality;
-               if (!personality) {
-                       LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
-                       personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
-                       LLVMAddFunctionAttr (personality, LLVMNoUnwindAttribute);
-                       LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
-                       LLVMBuilderRef builder2 = LLVMCreateBuilder ();
-                       LLVMPositionBuilderAtEnd (builder2, entry_bb);
-                       LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
-                       ctx->module->personality = personality;
-                       LLVMDisposeBuilder (builder2);
-               }
+               /* Can't cache this as each method is in its own llvm module */
+               LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
+               personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
+               mono_llvm_add_func_attr (personality, LLVM_ATTR_NO_UNWIND);
+               LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
+               LLVMBuilderRef builder2 = LLVMCreateBuilder ();
+               LLVMPositionBuilderAtEnd (builder2, entry_bb);
+               LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
+               LLVMDisposeBuilder (builder2);
 #else
                static gint32 mapping_inited;
 
@@ -4115,26 +4117,26 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
        }
 
        /* Start a new bblock which CALL_HANDLER can branch to */
-       target_bb = bblocks [bb->block_num].call_handler_target_bb;
-       if (target_bb) {
-               ctx->builder = builder = create_builder (ctx);
-               LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
+       ctx->builder = builder = create_builder (ctx);
+       LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
 
-               ctx->bblocks [bb->block_num].end_bblock = target_bb;
+       ctx->bblocks [bb->block_num].end_bblock = target_bb;
 
-               /* Store the exception into the IL level exvar */
-               if (bb->in_scount == 1) {
-                       g_assert (bb->in_scount == 1);
-                       exvar = bb->in_stack [0];
+       /* Store the exception into the IL level exvar */
+       if (bb->in_scount == 1) {
+               g_assert (bb->in_scount == 1);
+               exvar = bb->in_stack [0];
 
-                       // FIXME: This is shared with filter clauses ?
-                       g_assert (!values [exvar->dreg]);
+               // FIXME: This is shared with filter clauses ?
+               g_assert (!values [exvar->dreg]);
 
-                       g_assert (ctx->ex_var);
-                       values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
-                       emit_volatile_store (ctx, exvar->dreg);
-               }
+               g_assert (ctx->ex_var);
+               values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
+               emit_volatile_store (ctx, exvar->dreg);
        }
+
+       /* Make normal branches to the start of the clause branch to the new bblock */
+       bblocks [bb->block_num].bblock = target_bb;
 }
 
 static void
@@ -4983,6 +4985,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_X86_LEA: {
                        LLVMValueRef v1, v2;
 
+                       rhs = LLVMBuildSExt (builder, convert (ctx, rhs, LLVMInt32Type ()), LLVMInt64Type (), "");
+
                        v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
                        v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
                        values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
@@ -5636,35 +5640,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        break;
                }
-               case OP_TLS_GET_REG: {
-#if defined(TARGET_AMD64) && defined(__linux__)
-                       // 257 == FS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
-                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt64Type ()), ptrtype, ""), "");
-#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
-                       /* See emit_tls_get_reg () */
-                       // 256 == GS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
-                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
-#else
-                       set_failure (ctx, "opcode tls-get");
-                       break;
-#endif
-                       break;
-               }
-
-               case OP_TLS_SET_REG: {
-#if defined(TARGET_AMD64) && defined(TARGET_OSX)
-                       /* See emit_tls_get_reg () */
-                       // 256 == GS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
-                       LLVMBuildStore (builder, convert (ctx, lhs, IntPtrType ()), LLVMBuildIntToPtr (builder, convert (ctx, rhs, LLVMInt32Type ()), ptrtype, ""));
-#else
-                       set_failure (ctx, "opcode tls-set-reg");
-                       break;
-#endif
-                       break;
-               }
                case OP_GC_SAFE_POINT: {
                        LLVMValueRef val, cmp, callee;
                        LLVMBasicBlockRef poll_bb, cont_bb;
@@ -5871,8 +5846,19 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        const char *name = (const char*)ins->inst_p0;
                        LLVMValueRef var;
 
-                       if (!ctx->module->objc_selector_to_var)
+                       if (!ctx->module->objc_selector_to_var) {
                                ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+                               LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), 8), "@OBJC_IMAGE_INFO");
+                               int32_t objc_imageinfo [] = { 0, 16 };
+                               LLVMSetInitializer (info_var, mono_llvm_create_constant_data_array ((uint8_t *) &objc_imageinfo, 8));
+                               LLVMSetLinkage (info_var, LLVMPrivateLinkage);
+                               LLVMSetExternallyInitialized (info_var, TRUE);
+                               LLVMSetSection (info_var, "__DATA, __objc_imageinfo,regular,no_dead_strip");
+                               LLVMSetAlignment (info_var, sizeof (mgreg_t));
+                               mark_as_used (ctx->module, info_var);
+                       }
+
                        var = g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
                        if (!var) {
                                LLVMValueRef indexes [16];
@@ -6162,8 +6148,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
                        break;
 
-#if 0
-                       // Requires a later llvm version
+#if LLVM_API_VERSION > 100
                case OP_CVTDQ2PD: {
                        LLVMValueRef indexes [16];
 
@@ -6189,14 +6174,16 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        break;
 #endif
 
+#if LLVM_API_VERSION <= 100
                case OP_CVTDQ2PD:
+               case OP_CVTPS2PD:
+               case OP_CVTTPS2DQ:
+#endif
                case OP_CVTDQ2PS:
                case OP_CVTPD2DQ:
                case OP_CVTPS2DQ:
                case OP_CVTPD2PS:
-               case OP_CVTPS2PD:
                case OP_CVTTPD2DQ:
-               case OP_CVTTPS2DQ:
                case OP_EXTRACT_MASK:
                case OP_SQRTPS:
                case OP_SQRTPD:
@@ -6479,7 +6466,11 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [0] = lhs;
                        args [1] = rhs;
                        /* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
+#if LLVM_API_VERSION >= 500
+                       args [2] = LLVMConstInt (LLVMInt8Type (), 0xf1, FALSE);
+#else
                        args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
+#endif
 
                        values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
                        break;
@@ -6550,33 +6541,39 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        LLVMValueRef val, switch_ins, callee;
                        GSList *bb_list;
                        BBInfo *info;
+                       gboolean is_fault = MONO_REGION_FLAGS (bb->region) == MONO_EXCEPTION_CLAUSE_FAULT;
 
-                       handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
-                       g_assert (handler_bb);
-                       info = &bblocks [handler_bb->block_num];
-                       lhs = info->finally_ind;
-                       g_assert (lhs);
+                       /*
+                        * Fault clauses are like finally clauses, but they are only called if an exception is thrown.
+                        */
+                       if (!is_fault) {
+                               handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
+                               g_assert (handler_bb);
+                               info = &bblocks [handler_bb->block_num];
+                               lhs = info->finally_ind;
+                               g_assert (lhs);
 
-                       bb_list = info->call_handler_return_bbs;
+                               bb_list = info->call_handler_return_bbs;
 
-                       resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
+                               resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
 
-                       /* Load the finally variable */
-                       val = LLVMBuildLoad (builder, lhs, "");
+                               /* Load the finally variable */
+                               val = LLVMBuildLoad (builder, lhs, "");
 
-                       /* Reset the variable */
-                       LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
+                               /* Reset the variable */
+                               LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
 
-                       /* Branch to either resume_bb, or to the bblocks in bb_list */
-                       switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
-                       /* 
-                        * The other targets are added at the end to handle OP_CALL_HANDLER
-                        * opcodes processed later.
-                        */
-                       info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
+                               /* Branch to either resume_bb, or to the bblocks in bb_list */
+                               switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
+                               /*
+                                * The other targets are added at the end to handle OP_CALL_HANDLER
+                                * opcodes processed later.
+                                */
+                               info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
 
-                       builder = ctx->builder = create_builder (ctx);
-                       LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+                               builder = ctx->builder = create_builder (ctx);
+                               LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+                       }
 
                        if (ctx->llvm_only) {
                                emit_resume_eh (ctx, bb);
@@ -6882,7 +6879,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        if (cfg->compile_aot)
                ctx->lmodule = ctx->module->lmodule;
        else
-               ctx->lmodule = LLVMModuleCreateWithName ("jit-module");
+               ctx->lmodule = LLVMModuleCreateWithName (g_strdup_printf ("jit-module-%s", cfg->method->name));
 #else
        ctx->lmodule = ctx->module->lmodule;
 #endif
@@ -6945,13 +6942,16 @@ emit_method_inner (EmitContext *ctx)
                static int count = 0;
                count ++;
 
-               if (g_getenv ("LLVM_COUNT")) {
-                       if (count == atoi (g_getenv ("LLVM_COUNT"))) {
+               char *llvm_count_str = g_getenv ("LLVM_COUNT");
+               if (llvm_count_str) {
+                       int lcount = atoi (llvm_count_str);
+                       g_free (llvm_count_str);
+                       if (count == lcount) {
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
                                fflush (stdout);
                                last = TRUE;
                        }
-                       if (count > atoi (g_getenv ("LLVM_COUNT"))) {
+                       if (count > lcount) {
                                set_failure (ctx, "count");
                                return;
                        }
@@ -6980,7 +6980,7 @@ emit_method_inner (EmitContext *ctx)
                LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
        LLVMSetLinkage (method, LLVMPrivateLinkage);
 
-       LLVMAddFunctionAttr (method, LLVMUWTable);
+       mono_llvm_add_func_attr (method, LLVM_ATTR_UW_TABLE);
 
        if (cfg->compile_aot) {
                LLVMSetLinkage (method, LLVMInternalLinkage);
@@ -7013,14 +7013,14 @@ emit_method_inner (EmitContext *ctx)
        header = cfg->header;
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
-               if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
-                   set_failure (ctx, "non-finally/catch clause.");
+               if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
+                   set_failure (ctx, "non-finally/catch/fault clause.");
                        return;
                }
        }
        if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
                /* We can't handle inlined methods with clauses */
-               LLVMAddFunctionAttr (method, LLVMNoInlineAttribute);
+               mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
 
        if (linfo->rgctx_arg) {
                ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
@@ -7031,7 +7031,7 @@ emit_method_inner (EmitContext *ctx)
                 * CC_X86_64_Mono in X86CallingConv.td.
                 */
                if (!ctx->llvm_only)
-                       LLVMAddAttribute (ctx->rgctx_arg, LLVMInRegAttribute);
+                       mono_llvm_add_param_attr (ctx->rgctx_arg, LLVM_ATTR_IN_REG);
                LLVMSetValueName (ctx->rgctx_arg, "rgctx");
        } else {
                ctx->rgctx_arg_pindex = -1;
@@ -7040,8 +7040,8 @@ emit_method_inner (EmitContext *ctx)
                values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
                LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
                if (linfo->ret.storage == LLVMArgVtypeByRef) {
-                       LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMStructRetAttribute);
-                       LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
+                       mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
+                       mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
                }
        }
 
@@ -7086,7 +7086,7 @@ emit_method_inner (EmitContext *ctx)
                LLVMSetValueName (values [cfg->args [i + sig->hasthis]->dreg], name);
                g_free (name);
                if (ainfo->storage == LLVMArgVtypeByVal)
-                       LLVMAddAttribute (LLVMGetParam (method, pindex), LLVMByValAttribute);
+                       mono_llvm_add_param_attr (LLVMGetParam (method, pindex), LLVM_ATTR_BY_VAL);
 
                if (ainfo->storage == LLVMArgVtypeByRef) {
                        /* For OP_LDADDR */
@@ -7117,19 +7117,6 @@ emit_method_inner (EmitContext *ctx)
                }
        }
 
-       /*
-        * The INDIRECT flag added by OP_LDADDR inhibits optimizations, even if the LDADDR
-        * was later optimized away, so clear these flags, and add them back for the still
-        * present OP_LDADDR instructions.
-        */
-       for (i = 0; i < cfg->next_vreg; ++i) {
-               MonoInst *ins;
-
-               ins = get_vreg_to_inst (cfg, i);
-               if (ins && ins != cfg->rgctx_var)
-                       ins->flags &= ~MONO_INST_INDIRECT;
-       }
-
        /*
         * Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
         */
@@ -7331,8 +7318,10 @@ emit_method_inner (EmitContext *ctx)
                        GSList *bb_list = info->call_handler_return_bbs;
 
                        GSList *bb_list_iter;
+                       i = 0;
                        for (bb_list_iter = bb_list; bb_list_iter; bb_list_iter = g_slist_next (bb_list_iter)) {
                                LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)bb_list_iter->data);
+                               i ++;
                        }
                }
        }
@@ -7727,6 +7716,7 @@ decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
        guint32 ei_len, i, nested_len;
        gpointer *type_info;
        gint32 *table;
+       guint8 *unw_info;
 
        /*
         * Decode the one element EH table emitted by the MonoException class
@@ -7759,9 +7749,16 @@ decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
        fde = (guint8*)eh_frame + fde_offset;
        cie = (guint8*)table;
 
-       mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info);
+       /* Compute lengths */
+       mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, NULL, NULL, NULL);
 
-       cfg->encoded_unwind_ops = info.unw_info;
+       ei = (MonoJitExceptionInfo *)g_malloc0 (info.ex_info_len * sizeof (MonoJitExceptionInfo));
+       type_info = (gpointer *)g_malloc0 (info.ex_info_len * sizeof (gpointer));
+       unw_info = (guint8*)g_malloc0 (info.unw_info_len);
+
+       mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info, ei, type_info, unw_info);
+
+       cfg->encoded_unwind_ops = unw_info;
        cfg->encoded_unwind_ops_len = info.unw_info_len;
        if (cfg->verbose_level > 1)
                mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
@@ -7770,9 +7767,7 @@ decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
                cfg->llvm_this_offset = info.this_offset;
        }
 
-       ei = info.ex_info;
        ei_len = info.ex_info_len;
-       type_info = info.type_info;
 
        // Nested clauses are currently disabled
        nested_len = 0;
@@ -8224,7 +8219,11 @@ add_intrinsic (LLVMModuleRef module, int id)
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
                arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
+#if LLVM_API_VERSION >= 500
+               arg_types [2] = LLVMInt8Type ();
+#else
                arg_types [2] = LLVMInt32Type ();
+#endif
                AddFunc (module, name, ret_type, arg_types, 3);
                break;
 #endif
@@ -8425,7 +8424,7 @@ mono_llvm_free_domain_info (MonoDomain *domain)
 }
 
 void
-mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
+mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
 {
        MonoLLVMModule *module = &aot_module;
 
@@ -8449,7 +8448,7 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
        module->static_link = static_link;
        module->llvm_only = llvm_only;
        /* The first few entries are reserved */
-       module->max_got_offset = 16;
+       module->max_got_offset = initial_got_size;
        module->context = LLVMGetGlobalContext ();
 
        if (llvm_only)
@@ -8589,6 +8588,7 @@ mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
        LLVMSetVisibility (d, LLVMHiddenVisibility);
        LLVMSetLinkage (d, LLVMInternalLinkage);
        LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
+       LLVMSetAlignment (d, 8);
        mono_llvm_set_is_constant (d);
 }
 
@@ -9026,7 +9026,7 @@ emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, co
        if (!minfo)
                return NULL;
 
-       mono_debug_symfile_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
+       mono_debug_get_seq_points (minfo, &source_file, NULL, NULL, &sym_seq_points, &n_seq_points);
        if (!source_file)
                source_file = g_strdup ("<unknown>");
        dir = g_path_get_dirname (source_file);
@@ -9122,7 +9122,7 @@ emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil
                MonoDebugSourceLocation *loc;
                LLVMValueRef loc_md;
 
-               loc = mono_debug_symfile_lookup_location (ctx->minfo, cil_code - cfg->header->code);
+               loc = mono_debug_method_lookup_location (ctx->minfo, cil_code - cfg->header->code);
 
                if (loc) {
 #if LLVM_API_VERSION > 100
@@ -9140,7 +9140,7 @@ emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsigned char *cil
                        loc_md = LLVMMDNode (md_args, nmd_args);
                        LLVMSetCurrentDebugLocation (builder, loc_md);
 #endif
-                       mono_debug_symfile_free_location (loc);
+                       mono_debug_free_source_location (loc);
                }
        }
 }
@@ -9240,7 +9240,7 @@ default_mono_llvm_unhandled_exception (void)
     The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
     typed registers, so we have to keep track of the precise LLVM type of each vreg.
     This is made easier because the IR is already in SSA form.
-    An additional problem is that our IR is not consistent with types, i.e. i32/ia64 
+    An additional problem is that our IR is not consistent with types, i.e. i32/i64 
        types are frequently used incorrectly.
 */