Merge pull request #3066 from alexanderkyte/pedump_sgen
[mono.git] / mono / mini / mini-llvm.c
index f8aa239061589f9c9092ff6b246e76eecfa98591..ca7a3ce12b2ba071c84d3b0c1583c0cc56bf09cc 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright 2009-2011 Novell Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mini.h"
@@ -1281,6 +1282,9 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                }
                break;
        }
+       case LLVMArgAsIArgs:
+               ret_type = LLVMArrayType (IntPtrType (), cinfo->ret.nslots);
+               break;
        case LLVMArgFpStruct: {
                /* Vtype returned as a fp struct */
                LLVMTypeRef members [16];
@@ -1743,26 +1747,14 @@ get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
 {
        // Since they're sorted by nesting we just need
        // the first one that the bb is a member of
-       MonoExceptionClause *last = NULL;
-
        for (int i = 0; i < cfg->header->num_clauses; i++) {
                MonoExceptionClause *curr = &cfg->header->clauses [i];
 
                if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset))
                        return curr;
-               /*
-               if (MONO_OFFSET_IN_CLAUSE (curr, bb->real_offset)) {
-                       if (last && CLAUSE_END(last) > CLAUSE_END(curr))
-                               last = curr;
-                       else
-                               last = curr;
-               } else if(last) {
-                       break;
-               }
-               */
        }
 
-       return last;
+       return NULL;
 }
        
 static void
@@ -3147,7 +3139,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        gboolean is_virtual, calli, preserveall;
        LLVMBuilderRef builder = *builder_ref;
 
-       if (call->signature->call_convention != MONO_CALL_DEFAULT) {
+       if ((call->signature->call_convention != MONO_CALL_DEFAULT) && !((call->signature->call_convention == MONO_CALL_C) && ctx->llvm_only)) {
                set_failure (ctx, "non-default callconv");
                return;
        }
@@ -3212,8 +3204,12 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                        target =
                                                mono_create_jit_trampoline (mono_domain_get (),
                                                                                                        call->method, &error);
-                                       if (!mono_error_ok (&error))
-                                               mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+                                       if (!is_ok (&error)) {
+                                               set_failure (ctx, mono_error_get_message (&error));
+                                               mono_error_cleanup (&error);
+                                               return;
+                                       }
+
                                        tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
                                        LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
                                        LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
@@ -3223,15 +3219,17 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
 #else
                                target =
                                        mono_create_jit_trampoline (mono_domain_get (),
-                                                                                               call->method, &error);
-                               if (!mono_error_ok (&error))
-                                       mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+                                                                   call->method, &error);
+                               if (!is_ok (&error)) {
+                                       g_free (name);
+                                       set_failure (ctx, mono_error_get_message (&error));
+                                       mono_error_cleanup (&error);
+                                       return;
+                               }
 
                                callee = LLVMAddFunction (ctx->lmodule, name, llvm_sig);
                                g_free (name);
 
-                               if (!mono_error_ok (&error))
-                                       mono_error_raise_exception (&error); /* FIXME: Don't raise here */
                                LLVMAddGlobalMapping (ctx->module->ee, callee, target);
 #endif
                        }
@@ -3537,6 +3535,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                        addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
                LLVMBuildStore (builder, lcall, addresses [call->inst.dreg]);
                break;
+       case LLVMArgAsIArgs:
        case LLVMArgFpStruct:
                if (!addresses [call->inst.dreg])
                        addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
@@ -4364,6 +4363,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                LLVMBuildRetVoid (builder);
                                break;
                        }
+                       case LLVMArgAsIArgs:
                        case LLVMArgFpStruct: {
                                LLVMTypeRef ret_type = LLVMGetReturnType (LLVMGetElementType (LLVMTypeOf (method)));
                                LLVMValueRef retval;
@@ -5235,6 +5235,19 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        ji = mono_aot_patch_info_dup (tmp_ji);
                        g_free (tmp_ji);
 
+                       if (ji->type == MONO_PATCH_INFO_ICALL_ADDR) {
+                               char *symbol = mono_aot_get_direct_call_symbol (MONO_PATCH_INFO_ICALL_ADDR_CALL, ji->data.target);
+                               if (symbol) {
+                                       /*
+                                        * Avoid emitting a got entry for these since the method is directly called, and it might not be
+                                        * resolvable at runtime using dlsym ().
+                                        */
+                                       g_free (symbol);
+                                       values [ins->dreg] = LLVMConstInt (IntPtrType (), 0, FALSE);
+                                       break;
+                               }
+                       }
+
                        ji->next = cfg->patch_info;
                        cfg->patch_info = ji;
                                   
@@ -5548,6 +5561,43 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 #endif
                        break;
                }
+               case OP_GC_SAFE_POINT: {
+                       LLVMValueRef val, cmp, callee;
+                       LLVMBasicBlockRef poll_bb, cont_bb;
+                       static LLVMTypeRef sig;
+                       const char *icall_name = "mono_threads_state_poll";
+
+                       if (!sig)
+                               sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
+
+                       /*
+                        * if (!*sreg1)
+                        *   mono_threads_state_poll ();
+                        * FIXME: Use a preserveall wrapper
+                        */
+                       val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE, LLVM_BARRIER_NONE);
+                       cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
+                       poll_bb = gen_bb (ctx, "POLL_BB");
+                       cont_bb = gen_bb (ctx, "CONT_BB");
+                       LLVMBuildCondBr (builder, cmp, cont_bb, poll_bb);
+
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, poll_bb);
+
+                       if (ctx->cfg->compile_aot) {
+                               callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
+                       } else {
+                               gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
+                               callee = emit_jit_callee (ctx, icall_name, sig, target);
+                       }
+                       LLVMBuildCall (builder, callee, NULL, 0, "");
+                       LLVMBuildBr (builder, cont_bb);
+
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, cont_bb);
+                       ctx->bblocks [bb->block_num].end_bblock = cont_bb;
+                       break;
+               }
 
                        /*
                         * Overflow opcodes.
@@ -5558,14 +5608,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_ISUB_OVF_UN:
                case OP_IMUL_OVF:
                case OP_IMUL_OVF_UN:
-#if SIZEOF_VOID_P == 8
                case OP_LADD_OVF:
                case OP_LADD_OVF_UN:
                case OP_LSUB_OVF:
                case OP_LSUB_OVF_UN:
                case OP_LMUL_OVF:
                case OP_LMUL_OVF_UN:
-#endif
                        {
                                LLVMValueRef args [2], val, ovf, func;
 
@@ -7061,6 +7109,12 @@ emit_method_inner (EmitContext *ctx)
 
                // FIXME: beforefieldinit
                if (ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) {
+                       /*
+                        * linkonce methods shouldn't have initialization,
+                        * because they might belong to assemblies which
+                        * haven't been loaded yet.
+                        */
+                       g_assert (!ctx->is_linkonce);
                        emit_init_method (ctx);
                } else {
                        LLVMBuildBr (ctx->builder, ctx->inited_bb);
@@ -7714,7 +7768,9 @@ static void
 add_intrinsic (LLVMModuleRef module, int id)
 {
        const char *name;
+#if defined(TARGET_AMD64) || defined(TARGET_X86)
        LLVMTypeRef ret_type, arg_types [16];
+#endif
 
        name = g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
        g_assert (name);