X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmethod-to-ir.c;h=62bc0f5fc52ad32eaa28fe5b38d88c038492544f;hb=f704d56c378b28e252572db4730a6e13edc14aa0;hp=09bab4683ef57335c2209792745f8b4ea6546db0;hpb=3ab1a56f73cac926676e24b58d07bf0c4e75d3eb;p=mono.git diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 09bab4683ef..62bc0f5fc52 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -1,5 +1,6 @@ -/* - * method-to-ir.c: Convert CIL to the JIT internal representation +/** + * \file + * Convert CIL to the JIT internal representation * * Author: * Paolo Molaro (lupus@ximian.com) @@ -13,6 +14,7 @@ #include #include +#include "mini.h" #ifndef DISABLE_JIT @@ -35,7 +37,6 @@ #endif #include -#include "mini.h" #include #include #include @@ -50,8 +51,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -144,8 +143,6 @@ static int stind_to_store_membase (int opcode); int mono_op_to_op_imm (int opcode); int mono_op_to_op_imm_noemul (int opcode); -MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args); - static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, guchar *ip, guint real_offset, gboolean inline_always); static MonoInst* @@ -348,14 +345,19 @@ mono_print_bb (MonoBasicBlock *bb, const char *msg) { int i; MonoInst *tree; + GString *str = g_string_new (""); - printf ("\n%s %d: [IN: ", msg, bb->block_num); + g_string_append_printf (str, "%s %d: [IN: ", msg, bb->block_num); for (i = 0; i < bb->in_count; ++i) - printf (" BB%d(%d)", bb->in_bb [i]->block_num, bb->in_bb [i]->dfn); - printf (", OUT: "); + g_string_append_printf (str, " BB%d(%d)", bb->in_bb [i]->block_num, bb->in_bb [i]->dfn); + g_string_append_printf (str, ", OUT: "); for (i = 0; i < bb->out_count; ++i) - printf (" BB%d(%d)", bb->out_bb [i]->block_num, bb->out_bb [i]->dfn); - printf (" ]\n"); + g_string_append_printf (str, " BB%d(%d)", bb->out_bb [i]->block_num, bb->out_bb [i]->dfn); + g_string_append_printf (str, " ]\n"); + + g_print ("%s", str->str); + g_string_free (str, TRUE); + for (tree = bb->code; tree; tree = tree->next) mono_print_ins_index (-1, tree); } @@ -1259,16 +1261,22 @@ mono_get_got_var (MonoCompile *cfg) return cfg->got_var; } -static MonoInst * -mono_get_vtable_var (MonoCompile *cfg) +static void +mono_create_rgctx_var (MonoCompile *cfg) { - g_assert (cfg->gshared); - if (!cfg->rgctx_var) { cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); /* force the var to be stack allocated */ cfg->rgctx_var->flags |= MONO_INST_VOLATILE; } +} + +static MonoInst * +mono_get_vtable_var (MonoCompile *cfg) +{ + g_assert (cfg->gshared); + + mono_create_rgctx_var (cfg); return cfg->rgctx_var; } @@ -1824,47 +1832,35 @@ emit_push_lmf (MonoCompile *cfg) if (!cfg->lmf_ir) return; - if (cfg->lmf_ir_mono_lmf) { - MonoInst *lmf_vara_ins, *lmf_ins; - /* Load current lmf */ - lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF); - g_assert (lmf_ins); - EMIT_NEW_VARLOADA (cfg, lmf_vara_ins, cfg->lmf_var, NULL); - /* Save previous_lmf */ - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_vara_ins->dreg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg); - /* Set new LMF */ - mono_create_tls_set (cfg, lmf_vara_ins, TLS_KEY_LMF); - } else { - int lmf_reg, prev_lmf_reg; - /* - * Store lmf_addr in a variable, so it can be allocated to a global register. - */ - if (!cfg->lmf_addr_var) - cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); + int lmf_reg, prev_lmf_reg; + /* + * Store lmf_addr in a variable, so it can be allocated to a global register. + */ + if (!cfg->lmf_addr_var) + cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); #ifdef HOST_WIN32 - ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS); - g_assert (ins); - int jit_tls_dreg = ins->dreg; + ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS); + g_assert (ins); + int jit_tls_dreg = ins->dreg; - lmf_reg = alloc_preg (cfg); - EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf)); + lmf_reg = alloc_preg (cfg); + EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf)); #else - lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR); - g_assert (lmf_ins); + lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR); + g_assert (lmf_ins); #endif - lmf_ins->dreg = cfg->lmf_addr_var->dreg; + lmf_ins->dreg = cfg->lmf_addr_var->dreg; - EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL); - lmf_reg = ins->dreg; + EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL); + lmf_reg = ins->dreg; - prev_lmf_reg = alloc_preg (cfg); - /* Save previous_lmf */ - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0); - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg); - /* Set new lmf */ - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg); - } + prev_lmf_reg = alloc_preg (cfg); + /* Save previous_lmf */ + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0); + EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg); + /* Set new lmf */ + EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg); } /* @@ -1884,26 +1880,19 @@ emit_pop_lmf (MonoCompile *cfg) EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL); lmf_reg = ins->dreg; - if (cfg->lmf_ir_mono_lmf) { - /* Load previous_lmf */ - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, alloc_preg (cfg), lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf)); - /* Set new LMF */ - mono_create_tls_set (cfg, ins, TLS_KEY_LMF); - } else { - int prev_lmf_reg; - /* - * Emit IR to pop the LMF: - * *(lmf->lmf_addr) = lmf->prev_lmf - */ - /* This could be called before emit_push_lmf () */ - if (!cfg->lmf_addr_var) - cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); - lmf_addr_reg = cfg->lmf_addr_var->dreg; + int prev_lmf_reg; + /* + * Emit IR to pop the LMF: + * *(lmf->lmf_addr) = lmf->prev_lmf + */ + /* This could be called before emit_push_lmf () */ + if (!cfg->lmf_addr_var) + cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); + lmf_addr_reg = cfg->lmf_addr_var->dreg; - prev_lmf_reg = alloc_preg (cfg); - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf)); - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg); - } + prev_lmf_reg = alloc_preg (cfg); + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf)); + EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg); } static void @@ -2856,6 +2845,8 @@ emit_llvmonly_calli (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **arg static gboolean direct_icalls_enabled (MonoCompile *cfg) { + return FALSE; + /* LLVM on amd64 can't handle calls to non-32 bit addresses */ #ifdef TARGET_AMD64 if (cfg->compile_llvm && !cfg->llvm_only) @@ -2948,12 +2939,12 @@ mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature * static void -emit_method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method) +emit_method_access_failure (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee) { MonoInst *args [16]; - args [0] = emit_get_rgctx_method (cfg, mono_method_check_context_used (method), method, MONO_RGCTX_INFO_METHOD); - args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (cil_method), cil_method, MONO_RGCTX_INFO_METHOD); + args [0] = emit_get_rgctx_method (cfg, mono_method_check_context_used (caller), caller, MONO_RGCTX_INFO_METHOD); + args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (callee), callee, MONO_RGCTX_INFO_METHOD); mono_emit_jit_icall (cfg, mono_throw_method_access, args); } @@ -4594,9 +4585,11 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method) /* also consider num_locals? */ /* Do the size check early to avoid creating vtables */ if (!inline_limit_inited) { - if (g_getenv ("MONO_INLINELIMIT")) - inline_limit = atoi (g_getenv ("MONO_INLINELIMIT")); - else + char *inlinelimit; + if ((inlinelimit = g_getenv ("MONO_INLINELIMIT"))) { + inline_limit = atoi (inlinelimit); + g_free (inlinelimit); + } else inline_limit = INLINE_LENGTH_LIMIT; inline_limit_inited = TRUE; } @@ -4896,18 +4889,18 @@ static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint; /** * mono_set_break_policy: - * policy_callback: the new callback function + * \param policy_callback the new callback function * * Allow embedders to decide wherther to actually obey breakpoint instructions - * (both break IL instructions and Debugger.Break () method calls), for example + * (both break IL instructions and \c Debugger.Break method calls), for example * to not allow an app to be aborted by a perfectly valid IL opcode when executing * untrusted or semi-trusted code. * - * @policy_callback will be called every time a break point instruction needs to - * be inserted with the method argument being the method that calls Debugger.Break() - * or has the IL break instruction. The callback should return #MONO_BREAK_POLICY_NEVER + * \p policy_callback will be called every time a break point instruction needs to + * be inserted with the method argument being the method that calls \c Debugger.Break + * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER * if it wants the breakpoint to not be effective in the given method. - * #MONO_BREAK_POLICY_ALWAYS is the default. + * \c MONO_BREAK_POLICY_ALWAYS is the default. */ void mono_set_break_policy (MonoBreakPolicyFunc policy_callback) @@ -5241,8 +5234,7 @@ static MonoInst* mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { MonoInst *ins = NULL; - - MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class (); + MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class (); if (cmethod->klass == mono_defaults.string_class) { if (strcmp (cmethod->name, "get_Chars") == 0 && fsig->param_count + fsig->hasthis == 2) { @@ -5388,6 +5380,37 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } else if (cmethod->klass == runtime_helpers_class) { if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) { EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars)); + return ins; + } else if (strcmp (cmethod->name, "IsReferenceOrContainsReferences") == 0 && fsig->param_count == 0) { + MonoGenericContext *ctx = mono_method_get_context (cmethod); + g_assert (ctx); + g_assert (ctx->method_inst); + g_assert (ctx->method_inst->type_argc == 1); + MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]); + MonoClass *klass = mono_class_from_mono_type (t); + + ins = NULL; + + mono_class_init (klass); + if (MONO_TYPE_IS_REFERENCE (t)) + EMIT_NEW_ICONST (cfg, ins, 1); + else if (MONO_TYPE_IS_PRIMITIVE (t)) + EMIT_NEW_ICONST (cfg, ins, 0); + else if (cfg->gshared && (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && !mini_type_var_is_vt (t)) + EMIT_NEW_ICONST (cfg, ins, 1); + else if (!cfg->gshared || !mini_class_check_context_used (cfg, klass)) + EMIT_NEW_ICONST (cfg, ins, klass->has_references ? 1 : 0); + else { + g_assert (cfg->gshared); + + int context_used = mini_class_check_context_used (cfg, klass); + + /* This returns 1 or 2 */ + MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS); + int dreg = alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1); + } + return ins; } else return NULL; @@ -6708,7 +6731,7 @@ mini_get_method_allow_open (MonoMethod *m, guint32 token, MonoClass *klass, Mono { MonoMethod *method; - mono_error_init (error); + error_init (error); if (m->wrapper_type != MONO_WRAPPER_NONE) { method = (MonoMethod *)mono_method_get_wrapper_data (m, token); @@ -6765,7 +6788,7 @@ mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *conte { MonoMethodSignature *fsig; - mono_error_init (error); + error_init (error); if (method->wrapper_type != MONO_WRAPPER_NONE) { fsig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token); } else { @@ -6875,14 +6898,12 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono return NULL; if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib) return NULL; - switch (mono_type_get_underlying_type (&klass->byval_arg)->type) { - case MONO_TYPE_BOOLEAN: + switch (mini_get_underlying_type (&klass->byval_arg)->type) { case MONO_TYPE_I1: case MONO_TYPE_U1: size = 1; break; /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */ #if TARGET_BYTE_ORDER == G_LITTLE_ENDIAN - case MONO_TYPE_CHAR: case MONO_TYPE_I2: case MONO_TYPE_U2: size = 2; break; @@ -11585,7 +11606,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b tclass, MONO_RGCTX_INFO_REFLECTION_TYPE); } else if (cfg->compile_aot) { if (method->wrapper_type) { - mono_error_init (&error); //got to do it since there are multiple conditionals below + error_init (&error); //got to do it since there are multiple conditionals below if (mono_class_get_checked (tclass->image, tclass->type_token, &error) == tclass && !generic_context) { /* Special case for static synchronized wrappers */ EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context); @@ -12327,6 +12348,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); + ip += 2; + *sp++ = ins; + break; + case CEE_MONO_GET_RGCTX_ARG: + CHECK_OPSIZE (2); + CHECK_STACK_OVF (1); + + mono_create_rgctx_var (cfg); + + MONO_INST_NEW (cfg, ins, OP_MOVE); + ins->dreg = alloc_dreg (cfg, STACK_PTR); + ins->sreg1 = cfg->rgctx_var->dreg; + ins->type = STACK_PTR; + MONO_ADD_INS (cfg->cbb, ins); + ip += 2; *sp++ = ins; break; @@ -14544,6 +14580,9 @@ NOTES #else /* !DISABLE_JIT */ -MONO_EMPTY_SOURCE_FILE (method_to_ir); +void +mono_set_break_policy (MonoBreakPolicyFunc policy_callback) +{ +} #endif /* !DISABLE_JIT */