Merge pull request #4433 from kumpera/android-fixes
[mono.git] / mono / mini / method-to-ir.c
index 94f28af96851df12d827fe14e038a306ee572652..5982e0c200851a771b00e243d5a71586c450c074 100644 (file)
@@ -60,7 +60,6 @@
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/debug-mono-symfile.h>
-#include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/metadata/mono-basic-block.h>
@@ -164,8 +163,8 @@ static MonoMethodSignature *helper_sig_get_tls_tramp;
 static MonoMethodSignature *helper_sig_set_tls_tramp;
 
 /* type loading helpers */
-static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, System.Diagnostics, DebuggableAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, "System.Runtime.CompilerServices", "RuntimeHelpers")
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, "System.Diagnostics", "DebuggableAttribute")
 
 /*
  * Instruction metadata
@@ -208,12 +207,6 @@ const gint8 ins_sreg_counts[] = {
 #undef MINI_OP
 #undef MINI_OP3
 
-#define MONO_INIT_VARINFO(vi,id) do { \
-       (vi)->range.first_use.pos.bid = 0xffff; \
-       (vi)->reg = -1; \
-       (vi)->idx = (id); \
-} while (0)
-
 guint32
 mono_alloc_ireg (MonoCompile *cfg)
 {
@@ -355,14 +348,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);
 }
@@ -4457,7 +4455,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
         * pack the arguments into an array, and do the rest of the work in in an icall.
         */
        if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
-               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
+               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret)) || mini_is_gsharedvt_type (fsig->ret)) &&
                (fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
                MonoInst *args [16];
 
@@ -4509,7 +4507,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
 
                if (mini_is_gsharedvt_type (fsig->ret)) {
                        ins = handle_unbox_gsharedvt (cfg, mono_class_from_mono_type (fsig->ret), ins);
-               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret)) {
+               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret))) {
                        MonoInst *add;
 
                        /* Unbox */
@@ -6506,7 +6504,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                 * Get rid of the begin and end bblocks if possible to aid local
                 * optimizations.
                 */
-               mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
+               if (prev_cbb->out_count == 1)
+                       mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
 
                if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] != ebblock))
                        mono_merge_basic_blocks (cfg, prev_cbb, prev_cbb->out_bb [0]);
@@ -6714,7 +6713,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);
@@ -6771,7 +6770,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 {
@@ -7546,6 +7545,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
                        }
                        g_free (sps);
+
+                       MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
+                       if (asyncMethod) {
+                               for (i = 0; asyncMethod != NULL && i < asyncMethod->num_awaits; i++)
+                               {
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->resume_offsets[i]);
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->yield_offsets[i]);
+                               }
+                               mono_debug_free_method_async_debug_info (asyncMethod);
+                       }
                } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
                        /* Methods without line number info like auto-generated property accessors */
                        seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
@@ -8581,6 +8590,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                CHECK_CFG_ERROR;
                                        }
                                }
+
+                               if (constrained_class->enumtype && !strcmp (cmethod->name, "GetHashCode")) {
+                                       /* Use the corresponding method from the base type to avoid boxing */
+                                       MonoType *base_type = mono_class_enum_basetype (constrained_class);
+                                       g_assert (base_type);
+                                       constrained_class = mono_class_from_mono_type (base_type);
+                                       cmethod = mono_class_get_method_from_name (constrained_class, cmethod->name, 0);
+                                       g_assert (cmethod);
+                               }
                        }
                                        
                        if (!dont_verify && !cfg->skip_visibility) {
@@ -11572,7 +11590,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);