Merge pull request #2820 from kumpera/license-change-rebased
[mono.git] / mono / mini / method-to-ir.c
index b2dbc6faf867b8bf452707852869c0d6c38f55a2..aed8309edf6ef795d06aca1840712df51809916c 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2010 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 <config.h>
@@ -60,6 +61,7 @@
 #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>
 #include <mono/metadata/reflection-internals.h>
 
@@ -2186,6 +2188,9 @@ handle_enum:
        return -1;
 }
 
+//XXX this ignores if t is byref
+#define MONO_TYPE_IS_PRIMITIVE_SCALAR(t) ((((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_U8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))
+
 /*
  * target_type_is_incompatible:
  * @cfg: MonoCompile context
@@ -2206,10 +2211,20 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg)
        if (target->byref) {
                /* FIXME: check that the pointed to types match */
                if (arg->type == STACK_MP) {
-                       MonoClass *base_class = mono_class_from_mono_type (target);
-                       /* This is needed to handle gshared types + ldaddr */
-                       simple_type = mini_get_underlying_type (&base_class->byval_arg);
-                       return target->type != MONO_TYPE_I && arg->klass != base_class && arg->klass != mono_class_from_mono_type (simple_type);
+                       if (cfg->verbose_level) printf ("ok\n");
+                       /* This is needed to handle gshared types + ldaddr. We lower the types so we can handle enums and other typedef-like types. */
+                       MonoClass *target_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&mono_class_from_mono_type (target)->byval_arg));
+                       MonoClass *source_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&arg->klass->byval_arg));
+
+                       /* if the target is native int& or same type */
+                       if (target->type == MONO_TYPE_I || target_class_lowered == source_class_lowered)
+                               return 0;
+
+                       /* Both are primitive type byrefs and the source points to a larger type that the destination */
+                       if (MONO_TYPE_IS_PRIMITIVE_SCALAR (&target_class_lowered->byval_arg) && MONO_TYPE_IS_PRIMITIVE_SCALAR (&source_class_lowered->byval_arg) &&
+                               mono_class_instance_size (target_class_lowered) <= mono_class_instance_size (source_class_lowered))
+                               return 0;
+                       return 1;
                }
                if (arg->type == STACK_PTR)
                        return 0;
@@ -7100,7 +7115,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        if (!cheader) {
                if (inline_always) {
                        mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                       cfg->error = error; //XXX is this a good or bad idea?
+                       mono_error_move (&cfg->error, &error);
                } else {
                        mono_error_cleanup (&error);
                }
@@ -8564,7 +8579,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
        skip_dead_blocks = !dont_verify;
        if (skip_dead_blocks) {
-               original_bb = bb = mono_basic_block_split (method, &cfg->error);
+               original_bb = bb = mono_basic_block_split (method, &cfg->error, header);
                CHECK_CFG_ERROR;
                g_assert (bb);
        }
@@ -9142,7 +9157,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        info_data = addr->inst_right->inst_left;
                                }
 
-                               if (info_type == MONO_PATCH_INFO_ICALL_ADDR || info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+                               if (info_type == MONO_PATCH_INFO_ICALL_ADDR) {
+                                       ins = (MonoInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_ICALL_ADDR_CALL, info_data, fsig, sp);
+                                       NULLIFY_INS (addr);
+                                       goto calli_end;
+                               } else if (info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
                                        ins = (MonoInst*)mono_emit_abs_call (cfg, info_type, info_data, fsig, sp);
                                        NULLIFY_INS (addr);
                                        goto calli_end;
@@ -9239,15 +9258,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
                                        
-                       if (!cmethod || mono_loader_get_last_error ()) {
-                               if (mono_loader_get_last_error ()) {
-                                       mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                                       mono_error_set_from_loader_error (&cfg->error);
-                                       CHECK_CFG_ERROR;
-                               } else {
-                                       LOAD_ERROR;
-                               }
-                       }
                        if (!dont_verify && !cfg->skip_visibility) {
                                MonoMethod *target_method = cil_method;
                                if (method->is_inflated) {
@@ -11493,8 +11503,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* STATIC CASE */
                        context_used = mini_class_check_context_used (cfg, klass);
 
-                       if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL)
-                               UNVERIFIED;
+                       if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL) {
+                               mono_error_set_field_load (&cfg->error, field->parent, field->name, "Using static instructions with literal field");
+                               CHECK_CFG_ERROR;
+                       }
 
                        /* The special_static_fields field is init'd in mono_class_vtable, so it needs
                         * to be called here.
@@ -11638,7 +11650,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                                INLINE_FAILURE ("class init");
                                                        if (!mono_runtime_class_init_full (vtable, &cfg->error)) {
                                                                mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                                                               g_assert_not_reached ();
                                                                goto exception_exit;
                                                        }
                                                }