Don't register the LLVM SSE intrinsics on arm.
[mono.git] / mono / mini / mini-llvm.c
index 3474e0d7bbc0c7a4950b1d438da9b59021d215bd..0c49d35dd6a5e39b17cdb780987271d009e48c20 100644 (file)
@@ -205,6 +205,12 @@ IntPtrType (void)
        return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
 }
 
+static LLVMTypeRef
+ObjRefType (void)
+{
+       return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
+}
+
 /*
  * get_vtype_size:
  *
@@ -217,7 +223,7 @@ get_vtype_size (MonoType *t)
 
        size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
 
-       while (size < sizeof (gpointer) && mono_is_power_of_two (size) == -1)
+       while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
                size ++;
 
        return size;
@@ -326,14 +332,14 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
-               return IntPtrType ();
+               return ObjRefType ();
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* Because of generic sharing */
-               return IntPtrType ();
+               return ObjRefType ();
        case MONO_TYPE_GENERICINST:
                if (!mono_type_generic_inst_is_valuetype (t))
-                       return IntPtrType ();
+                       return ObjRefType ();
                /* Fall through */
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_TYPEDBYREF: {
@@ -1274,12 +1280,26 @@ set_metadata_flag (LLVMValueRef v, const char *flag_name)
 {
        LLVMValueRef md_arg;
        int md_kind;
-       
+
        md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
        md_arg = LLVMMDString ("mono", 4);
        LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
 }
 
+static void
+set_invariant_load_flag (LLVMValueRef v)
+{
+       LLVMValueRef md_arg;
+       int md_kind;
+       const char *flag_name;
+
+       // FIXME: Cache this
+       flag_name = "invariant.load";
+       md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
+       md_arg = LLVMMDString ("<index>", strlen ("<index>"));
+       LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
+}
+
 /*
  * emit_call:
  *
@@ -1865,6 +1885,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                LLVMAddGlobalMapping (ee, callee, target);
                        }
                }
+
+               if (call->method && strstr (call->method->klass->name, "AsyncVoidMethodBuilder"))
+                       /* LLVM miscompiles async methods */
+                       LLVM_FAILURE (ctx, "#13734");
        } else if (calli) {
        } else {
                MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
@@ -2021,7 +2045,6 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
 
        lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
 
-#ifdef LLVM_MONO_BRANCH
        /*
         * Modify cconv and parameter attributes to pass rgctx/imt correctly.
         */
@@ -2037,7 +2060,6 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                LLVMAddInstrAttribute (lcall, 1 + sinfo.rgctx_arg_pindex, LLVMInRegAttribute);
        if (call->imt_arg_reg)
                LLVMAddInstrAttribute (lcall, 1 + sinfo.imt_arg_pindex, LLVMInRegAttribute);
-#endif
 
        /* Add byval attributes if needed */
        for (i = 0; i < sig->param_count; ++i) {
@@ -2681,7 +2703,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_AND_IMM:
                case OP_MUL_IMM:
                case OP_SHL_IMM:
-               case OP_SHR_IMM: {
+               case OP_SHR_IMM:
+               case OP_SHR_UN_IMM: {
                        LLVMValueRef imm;
 
                        if (spec [MONO_INST_SRC1] == 'l') {
@@ -2757,6 +2780,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
                                break;
                        case OP_LSHR_UN_IMM:
+                       case OP_SHR_UN_IMM:
                                values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
                                break;
                        default:
@@ -2968,12 +2992,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        values [ins->dreg] = emit_load (ctx, bb, &builder, size, addr, dname, is_volatile);
 
-                       if (!is_volatile && (ins->flags & MONO_INST_CONSTANT_LOAD)) {
+                       if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
                                /*
                                 * These will signal LLVM that these loads do not alias any stores, and
                                 * they can't fail, allowing them to be hoisted out of loops.
                                 */
-                               set_metadata_flag (values [ins->dreg], "mono.noalias");
+                               set_invariant_load_flag (values [ins->dreg]);
                                set_metadata_flag (values [ins->dreg], "mono.nofail.load");
                        }
 
@@ -3091,23 +3115,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
                        got_entry_addr = LLVMBuildGEP (builder, ctx->lmodule->got_var, indexes, 2, "");
 
-                       // FIXME: This doesn't work right now, because it must be
-                       // paired with an invariant.end, and even then, its only in effect
-                       // inside its basic block
-#if 0
-                       {
-                               LLVMValueRef args [3];
-                               LLVMValueRef ptr, val;
-
-                               ptr = LLVMBuildBitCast (builder, got_entry_addr, LLVMPointerType (LLVMInt8Type (), 0), "ptr");
-
-                               args [0] = LLVMConstInt (LLVMInt64Type (), sizeof (gpointer), FALSE);
-                               args [1] = ptr;
-                               val = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.invariant.start"), args, 2, "");
-                       }
-#endif
-
                        values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, dname);
+                       set_invariant_load_flag (values [ins->dreg]);
                        break;
                }
                case OP_NOT_REACHED:
@@ -3206,44 +3215,38 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
                        break;
                }
-               case OP_ATOMIC_EXCHANGE_I4: {
-                       LLVMValueRef args [2];
-
-                       g_assert (ins->inst_offset == 0);
-
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
-                       args [1] = rhs;
-
-                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
-                       break;
-               }
+               case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_EXCHANGE_I8: {
                        LLVMValueRef args [2];
+                       LLVMTypeRef t;
+                               
+                       if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
+                               t = LLVMInt32Type ();
+                       else
+                               t = LLVMInt64Type ();
 
                        g_assert (ins->inst_offset == 0);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
-                       args [1] = convert (ctx, rhs, LLVMInt64Type ());
-                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
-                       break;
-               }
-               case OP_ATOMIC_ADD_NEW_I4: {
-                       LLVMValueRef args [2];
-
-                       g_assert (ins->inst_offset == 0);
+                       args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+                       args [1] = convert (ctx, rhs, t);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
-                       args [1] = rhs;
-                       values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
+                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
                        break;
                }
+               case OP_ATOMIC_ADD_NEW_I4:
                case OP_ATOMIC_ADD_NEW_I8: {
                        LLVMValueRef args [2];
+                       LLVMTypeRef t;
+                               
+                       if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+                               t = LLVMInt32Type ();
+                       else
+                               t = LLVMInt64Type ();
 
                        g_assert (ins->inst_offset == 0);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
-                       args [1] = convert (ctx, rhs, LLVMInt64Type ());
+                       args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+                       args [1] = convert (ctx, rhs, t);
                        values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
                        break;
                }
@@ -3252,11 +3255,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        LLVMValueRef args [3];
                        LLVMTypeRef t;
                                
-                       if (ins->opcode == OP_ATOMIC_CAS_I4) {
+                       if (ins->opcode == OP_ATOMIC_CAS_I4)
                                t = LLVMInt32Type ();
-                       } else {
+                       else
                                t = LLVMInt64Type ();
-                       }
 
                        args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
                        /* comparand */
@@ -3287,9 +3289,15 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        // 256 == GS segment register
                        LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
 #endif
-
                        // FIXME: XEN
                        values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
+#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
+                       /* See mono_amd64_emit_tls_get () */
+                       int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
+
+                       // 256 == GS segment register
+                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
 #else
                        LLVM_FAILURE (ctx, "opcode tls-get");
 #endif
@@ -4237,13 +4245,13 @@ mono_llvm_emit_method (MonoCompile *cfg)
                static int count = 0;
                count ++;
 
-               if (getenv ("LLVM_COUNT")) {
-                       if (count == atoi (getenv ("LLVM_COUNT"))) {
+               if (g_getenv ("LLVM_COUNT")) {
+                       if (count == atoi (g_getenv ("LLVM_COUNT"))) {
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
                                fflush (stdout);
                                last = TRUE;
                        }
-                       if (count > atoi (getenv ("LLVM_COUNT")))
+                       if (count > atoi (g_getenv ("LLVM_COUNT")))
                                LLVM_FAILURE (ctx, "");
                }
        }
@@ -4270,9 +4278,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        method = LLVMAddFunction (module, method_name, method_type);
        ctx->lmethod = method;
 
-#ifdef LLVM_MONO_BRANCH
        LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
-#endif
        LLVMSetLinkage (method, LLVMPrivateLinkage);
 
        LLVMAddFunctionAttr (method, LLVMUWTable);
@@ -4334,19 +4340,6 @@ mono_llvm_emit_method (MonoCompile *cfg)
        }
        g_free (names);
 
-       if (cfg->compile_aot) {
-               LLVMValueRef md_args [16];
-               LLVMValueRef md_node;
-               int method_index;
-
-               method_index = mono_aot_get_method_index (cfg->orig_method);
-               md_args [0] = LLVMMDString (method_name, strlen (method_name));
-               md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
-               md_node = LLVMMDNode (md_args, 2);
-               LLVMAddNamedMetadataOperand (module, "mono.function_indexes", md_node);
-               //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
-       }
-
        max_block_num = 0;
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
                max_block_num = MAX (max_block_num, bb->block_num);
@@ -4520,6 +4513,19 @@ mono_llvm_emit_method (MonoCompile *cfg)
 
        mark_as_used (module, method);
 
+       if (cfg->compile_aot) {
+               LLVMValueRef md_args [16];
+               LLVMValueRef md_node;
+               int method_index;
+
+               method_index = mono_aot_get_method_index (cfg->orig_method);
+               md_args [0] = LLVMMDString (method_name, strlen (method_name));
+               md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
+               md_node = LLVMMDNode (md_args, 2);
+               LLVMAddNamedMetadataOperand (module, "mono.function_indexes", md_node);
+               //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
+       }
+
        if (cfg->compile_aot) {
                /* Don't generate native code, keep the LLVM IR */
                if (cfg->compile_aot && cfg->verbose_level)
@@ -4865,16 +4871,6 @@ add_intrinsics (LLVMModuleRef module)
                LLVMAddFunction (module, "llvm.umul.with.overflow.i64", LLVMFunctionType (LLVMStructType (ovf_res_i64, 2, FALSE), ovf_params_i64, 2, FALSE));
        }
 
-       {
-               LLVMTypeRef struct_ptr = LLVMPointerType (LLVMStructType (NULL, 0, FALSE), 0);
-               LLVMTypeRef invariant_start_params [] = { LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
-               LLVMTypeRef invariant_end_params [] = { struct_ptr, LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
-
-               LLVMAddFunction (module, "llvm.invariant.start", LLVMFunctionType (struct_ptr, invariant_start_params, 2, FALSE));
-
-               LLVMAddFunction (module, "llvm.invariant.end", LLVMFunctionType (LLVMVoidType (), invariant_end_params, 3, FALSE));
-       }
-
        /* EH intrinsics */
        {
                LLVMTypeRef arg_types [2];
@@ -4890,6 +4886,7 @@ add_intrinsics (LLVMModuleRef module)
        }
 
        /* SSE intrinsics */
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
        {
                LLVMTypeRef ret_type, arg_types [16];
 
@@ -5034,6 +5031,7 @@ add_intrinsics (LLVMModuleRef module)
        }
 
        AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
+#endif
 
        /* Load/Store intrinsics */
        {