[interp] builtin types (#5339)
authorBernhard Urban <bernhard.urban@xamarin.com>
Wed, 9 Aug 2017 17:49:43 +0000 (19:49 +0200)
committerGitHub <noreply@github.com>
Wed, 9 Aug 2017 17:49:43 +0000 (19:49 +0200)
* [interp] support System.{nint,nuint,nfloat} (64bit only so far)

* [interp] 32bit support for System.{nint,nuint,nfloat}

* [fixup] explain mint_niy

mono/mini/interp/interp.c
mono/mini/interp/mintops.def
mono/mini/interp/transform.c
mono/mini/mini-native-types.c
mono/mini/mini.h

index f09df220599504afa287a8721f1038197b05da23..fccce6b3411211e47139f783249bb0032de10225 100644 (file)
@@ -390,8 +390,9 @@ get_virtual_method (InterpMethod *imethod, MonoObject *obj)
 }
 
 static void inline
-stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke)
+stackval_from_data (MonoType *type_, stackval *result, char *data, gboolean pinvoke)
 {
+       MonoType *type = mini_native_type_replace_type (type_);
        if (type->byref) {
                switch (type->type) {
                case MONO_TYPE_OBJECT:
@@ -479,8 +480,9 @@ stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvo
 }
 
 static void inline
-stackval_to_data (MonoType *type, stackval *val, char *data, gboolean pinvoke)
+stackval_to_data (MonoType *type_, stackval *val, char *data, gboolean pinvoke)
 {
+       MonoType *type = mini_native_type_replace_type (type_);
        if (type->byref) {
                gpointer *p = (gpointer*)data;
                *p = val->data.p;
@@ -2330,6 +2332,9 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
                MINT_IN_CASE(MINT_NOP)
                        ++ip;
                        MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_NIY)
+                       g_error ("mint_niy: instruction not implemented yet.  This shouldn't happen.");
+                       MINT_IN_BREAK;
                MINT_IN_CASE(MINT_BREAK)
                        ++ip;
                        do_debugger_tramp (mono_debugger_agent_user_break, frame);
@@ -3613,6 +3618,15 @@ array_constructed:
                        ++sp;
                        MINT_IN_BREAK;
                }
+               MINT_IN_CASE(MINT_NEWOBJ_MAGIC) {
+                       guint32 token;
+
+                       frame->ip = ip;
+                       token = * (guint16 *)(ip + 1);
+                       ip += 2;
+
+                       MINT_IN_BREAK;
+               }
                MINT_IN_CASE(MINT_CASTCLASS)
                        c = rtm->data_items [*(guint16 *)(ip + 1)];
                        if ((o = sp [-1].data.p)) {
@@ -3958,7 +3972,7 @@ array_constructed:
                        c = rtm->data_items [* (guint16 *)(ip + 1)];
                        guint16 offset = * (guint16 *)(ip + 2);
 
-                       if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
+                       if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype && !(mono_class_is_magic_int (c) || mono_class_is_magic_float (c))) {
                                int size = mono_class_value_size (c, NULL);
                                sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, sp [-1 - offset].data.p, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
@@ -4594,6 +4608,15 @@ array_constructed:
        --sp; \
        sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
        ++ip;
+
+#define RELOP_FP(datamem, op, noorder) \
+       --sp; \
+       if (isunordered (sp [-1].data.datamem, sp [0].data.datamem)) \
+               sp [-1].data.i = noorder; \
+       else \
+               sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
+       ++ip;
+
                MINT_IN_CASE(MINT_CEQ_I4)
                        RELOP(i, ==);
                        MINT_IN_BREAK;
@@ -4605,12 +4628,16 @@ array_constructed:
                        RELOP(l, ==);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CEQ_R8)
-                       --sp; 
-                       if (isunordered (sp [-1].data.f, sp [0].data.f))
-                               sp [-1].data.i = 0;
-                       else
-                               sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
-                       ++ip;
+                       RELOP_FP(f, ==, 0);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CNE_I4)
+                       RELOP(i, !=);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CNE_I8)
+                       RELOP(l, !=);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CNE_R8)
+                       RELOP_FP(f, !=, 0);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CGT_I4)
                        RELOP(i, >);
@@ -4619,12 +4646,16 @@ array_constructed:
                        RELOP(l, >);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CGT_R8)
-                       --sp; 
-                       if (isunordered (sp [-1].data.f, sp [0].data.f))
-                               sp [-1].data.i = 0;
-                       else
-                               sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
-                       ++ip;
+                       RELOP_FP(f, >, 0);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CGE_I4)
+                       RELOP(i, >=);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CGE_I8)
+                       RELOP(l, >=);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CGE_R8)
+                       RELOP_FP(f, >=, 0);
                        MINT_IN_BREAK;
 
 #define RELOP_CAST(datamem, op, type) \
@@ -4632,6 +4663,13 @@ array_constructed:
        sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
        ++ip;
 
+               MINT_IN_CASE(MINT_CGE_UN_I4)
+                       RELOP_CAST(l, >=, guint32);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CGE_UN_I8)
+                       RELOP_CAST(l, >=, guint64);
+                       MINT_IN_BREAK;
+
                MINT_IN_CASE(MINT_CGT_UN_I4)
                        RELOP_CAST(i, >, guint32);
                        MINT_IN_BREAK;
@@ -4639,12 +4677,7 @@ array_constructed:
                        RELOP_CAST(l, >, guint64);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CGT_UN_R8)
-                       --sp; 
-                       if (isunordered (sp [-1].data.f, sp [0].data.f))
-                               sp [-1].data.i = 1;
-                       else
-                               sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
-                       ++ip;
+                       RELOP_FP(f, >, 1);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CLT_I4)
                        RELOP(i, <);
@@ -4653,12 +4686,7 @@ array_constructed:
                        RELOP(l, <);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CLT_R8)
-                       --sp; 
-                       if (isunordered (sp [-1].data.f, sp [0].data.f))
-                               sp [-1].data.i = 0;
-                       else
-                               sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
-                       ++ip;
+                       RELOP_FP(f, <, 0);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CLT_UN_I4)
                        RELOP_CAST(i, <, guint32);
@@ -4667,13 +4695,28 @@ array_constructed:
                        RELOP_CAST(l, <, guint64);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CLT_UN_R8)
-                       --sp; 
-                       if (isunordered (sp [-1].data.f, sp [0].data.f))
-                               sp [-1].data.i = 1;
-                       else
-                               sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
-                       ++ip;
+                       RELOP_FP(f, <, 1);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CLE_I4)
+                       RELOP(i, <=);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CLE_I8)
+                       RELOP(l, <=);
                        MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CLE_UN_I4)
+                       RELOP_CAST(l, <=, guint32);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CLE_UN_I8)
+                       RELOP_CAST(l, <=, guint64);
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_CLE_R8)
+                       RELOP_FP(f, <=, 0);
+                       MINT_IN_BREAK;
+
+#undef RELOP
+#undef RELOP_FP
+#undef RELOP_CAST
+
                MINT_IN_CASE(MINT_LDFTN) {
                        sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
                        ++sp;
index 869c5f2df74e1102dce76f33694854b28f18719f..c98740a5d25a2577c3729828a74cfb7e83a82b01 100644 (file)
@@ -9,6 +9,7 @@
 /* OPDEF (opsymbol, opstring, oplength (in uint16s), optype) */
 
 OPDEF(MINT_NOP, "nop", 1, MintOpNoArgs)
+OPDEF(MINT_NIY, "niy", 1, MintOpNoArgs)
 OPDEF(MINT_BREAK, "break", 1, MintOpNoArgs)
 OPDEF(MINT_LDNULL, "ldnull", 1, MintOpNoArgs)
 OPDEF(MINT_DUP, "dup", 1, MintOpNoArgs)
@@ -269,6 +270,7 @@ OPDEF(MINT_CALLRUN, "callrun", 1, MintOpNoArgs)
 OPDEF(MINT_ENDFILTER, "endfilter", 1, MintOpNoArgs)
 
 OPDEF(MINT_NEWOBJ, "newobj", 2, MintOpMethodToken) 
+OPDEF(MINT_NEWOBJ_MAGIC, "newobj_magic", 2, MintOpMethodToken)
 OPDEF(MINT_INITOBJ, "initobj", 3, MintOpInt) 
 OPDEF(MINT_CASTCLASS, "castclass", 2, MintOpClassToken) 
 OPDEF(MINT_ISINST, "isinst", 2, MintOpClassToken) 
@@ -471,12 +473,23 @@ OPDEF(MINT_CEQ_I4, "ceq.i4", 1, MintOpNoArgs)
 OPDEF(MINT_CEQ_I8, "ceq.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CEQ_R8, "ceq.r8", 1, MintOpNoArgs)
 
+OPDEF(MINT_CNE_I4, "cne.i4", 1, MintOpNoArgs)
+OPDEF(MINT_CNE_I8, "cne.i8", 1, MintOpNoArgs)
+OPDEF(MINT_CNE_R8, "cne.r8", 1, MintOpNoArgs)
+
 OPDEF(MINT_CEQ0_I4, "ceq0.i4", 1, MintOpNoArgs)
 
 OPDEF(MINT_CGT_I4, "cgt.i4", 1, MintOpNoArgs)
 OPDEF(MINT_CGT_I8, "cgt.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CGT_R8, "cgt.r8", 1, MintOpNoArgs)
 
+OPDEF(MINT_CGE_I4, "cge.i4", 1, MintOpNoArgs)
+OPDEF(MINT_CGE_I8, "cge.i8", 1, MintOpNoArgs)
+OPDEF(MINT_CGE_R8, "cge.r8", 1, MintOpNoArgs)
+
+OPDEF(MINT_CGE_UN_I4, "cge.un.i4", 1, MintOpNoArgs)
+OPDEF(MINT_CGE_UN_I8, "cge.un.i8", 1, MintOpNoArgs)
+
 OPDEF(MINT_CGT_UN_I4, "cgt.un.i4", 1, MintOpNoArgs)
 OPDEF(MINT_CGT_UN_I8, "cgt.un.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CGT_UN_R8, "cgt.un.r8", 1, MintOpNoArgs)
@@ -485,6 +498,13 @@ OPDEF(MINT_CLT_I4, "clt.i4", 1, MintOpNoArgs)
 OPDEF(MINT_CLT_I8, "clt.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CLT_R8, "clt.r8", 1, MintOpNoArgs)
 
+OPDEF(MINT_CLE_I4, "cle.i4", 1, MintOpNoArgs)
+OPDEF(MINT_CLE_I8, "cle.i8", 1, MintOpNoArgs)
+OPDEF(MINT_CLE_R8, "cle.r8", 1, MintOpNoArgs)
+
+OPDEF(MINT_CLE_UN_I4, "cle.un.i4", 1, MintOpNoArgs)
+OPDEF(MINT_CLE_UN_I8, "cle.un.i8", 1, MintOpNoArgs)
+
 OPDEF(MINT_CLT_UN_I4, "clt.un.i4", 1, MintOpNoArgs)
 OPDEF(MINT_CLT_UN_I8, "clt.un.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CLT_UN_R8, "clt.un.r8", 1, MintOpNoArgs)
index f8144e1952ee2187b519ae719f1f8995dce8168b..8a072ce3c327bc9f27ca6ae1634ace3781328f21 100644 (file)
@@ -142,6 +142,132 @@ static int stack_type [] = {
        STACK_TYPE_VT
 };
 
+#if SIZEOF_VOID_P == 8
+#define MINT_NEG_P MINT_NEG_I8
+#define MINT_NOT_P MINT_NOT_I8
+
+#define MINT_NEG_FP MINT_NEG_R8
+
+#define MINT_ADD_P MINT_ADD_I8
+#define MINT_SUB_P MINT_SUB_I8
+#define MINT_MUL_P MINT_MUL_I8
+#define MINT_DIV_P MINT_DIV_I8
+#define MINT_DIV_UN_P MINT_DIV_UN_I8
+#define MINT_REM_P MINT_REM_I8
+#define MINT_REM_UN_P MINT_REM_UN_I8
+#define MINT_AND_P MINT_AND_I8
+#define MINT_OR_P MINT_OR_I8
+#define MINT_XOR_P MINT_XOR_I8
+#define MINT_SHL_P MINT_SHL_I8
+#define MINT_SHR_P MINT_SHR_I8
+#define MINT_SHR_UN_P MINT_SHR_UN_I8
+
+#define MINT_CEQ_P MINT_CEQ_I8
+#define MINT_CNE_P MINT_CNE_I8
+#define MINT_CLT_P MINT_CLT_I8
+#define MINT_CLT_UN_P MINT_CLT_UN_I8
+#define MINT_CGT_P MINT_CGT_I8
+#define MINT_CGT_UN_P MINT_CGT_UN_I8
+#define MINT_CLE_P MINT_CLE_I8
+#define MINT_CLE_UN_P MINT_CLE_UN_I8
+#define MINT_CGE_P MINT_CGE_I8
+#define MINT_CGE_UN_P MINT_CGE_UN_I8
+
+#define MINT_ADD_FP MINT_ADD_R8
+#define MINT_SUB_FP MINT_SUB_R8
+#define MINT_MUL_FP MINT_MUL_R8
+#define MINT_DIV_FP MINT_DIV_R8
+#define MINT_REM_FP MINT_REM_R8
+
+#define MINT_CNE_FP MINT_CNE_R8
+#define MINT_CEQ_FP MINT_CEQ_R8
+#define MINT_CGT_FP MINT_CGT_R8
+#define MINT_CGE_FP MINT_CGE_R8
+#define MINT_CLT_FP MINT_CLT_R8
+#define MINT_CLE_FP MINT_CLE_R8
+
+#else
+
+#define MINT_NEG_P MINT_NEG_I4
+#define MINT_NOT_P MINT_NOT_I4
+
+#define MINT_NEG_FP MINT_NEG_R8
+
+#define MINT_ADD_P MINT_ADD_I4
+#define MINT_SUB_P MINT_SUB_I4
+#define MINT_MUL_P MINT_MUL_I4
+#define MINT_DIV_P MINT_DIV_I4
+#define MINT_DIV_UN_P MINT_DIV_UN_I4
+#define MINT_REM_P MINT_REM_I4
+#define MINT_REM_UN_P MINT_REM_UN_I4
+#define MINT_AND_P MINT_AND_I4
+#define MINT_OR_P MINT_OR_I4
+#define MINT_XOR_P MINT_XOR_I4
+#define MINT_SHL_P MINT_SHL_I4
+#define MINT_SHR_P MINT_SHR_I4
+#define MINT_SHR_UN_P MINT_SHR_UN_I4
+
+#define MINT_CEQ_P MINT_CEQ_I4
+#define MINT_CNE_P MINT_CNE_I4
+#define MINT_CLT_P MINT_CLT_I4
+#define MINT_CLT_UN_P MINT_CLT_UN_I4
+#define MINT_CGT_P MINT_CGT_I4
+#define MINT_CGT_UN_P MINT_CGT_UN_I4
+#define MINT_CLE_P MINT_CLE_I4
+#define MINT_CLE_UN_P MINT_CLE_UN_I4
+#define MINT_CGE_P MINT_CGE_I4
+#define MINT_CGE_UN_P MINT_CGE_UN_I4
+
+#define MINT_ADD_FP MINT_ADD_R8
+#define MINT_SUB_FP MINT_SUB_R8
+#define MINT_MUL_FP MINT_MUL_R8
+#define MINT_DIV_FP MINT_DIV_R8
+#define MINT_REM_FP MINT_REM_R8
+
+#define MINT_CNE_FP MINT_CNE_R8
+#define MINT_CEQ_FP MINT_CEQ_R8
+#define MINT_CGT_FP MINT_CGT_R8
+#define MINT_CGE_FP MINT_CGE_R8
+#define MINT_CLT_FP MINT_CLT_R8
+#define MINT_CLE_FP MINT_CLE_R8
+
+#endif
+
+typedef struct {
+       const gchar *op_name;
+       guint16 insn [3];
+} MagicIntrinsic;
+
+// static const MagicIntrinsic int_binop[] = {
+
+static const MagicIntrinsic int_unnop[] = {
+       { "op_UnaryPlus", {MINT_NOP, MINT_NOP, MINT_NOP}},
+       { "op_UnaryNegation", {MINT_NEG_P, MINT_NEG_P, MINT_NEG_FP}},
+       { "op_OnesComplement", {MINT_NOT_P, MINT_NOT_P, MINT_NIY}}
+};
+
+static const MagicIntrinsic int_binop[] = {
+       { "op_Addition", {MINT_ADD_P, MINT_ADD_P, MINT_ADD_FP}},
+       { "op_Subtraction", {MINT_SUB_P, MINT_SUB_P, MINT_SUB_FP}},
+       { "op_Multiply", {MINT_MUL_P, MINT_MUL_P, MINT_MUL_FP}},
+       { "op_Division", {MINT_DIV_P, MINT_DIV_UN_P, MINT_DIV_FP}},
+       { "op_Modulus", {MINT_REM_P, MINT_REM_UN_P, MINT_REM_FP}},
+       { "op_BitwiseAnd", {MINT_AND_P, MINT_AND_P, MINT_NIY}},
+       { "op_BitwiseOr", {MINT_OR_P, MINT_OR_P, MINT_NIY}},
+       { "op_ExclusiveOr", {MINT_XOR_P, MINT_XOR_P, MINT_NIY}},
+       { "op_LeftShift", {MINT_SHL_P, MINT_SHL_P, MINT_NIY}},
+       { "op_RightShift", {MINT_SHR_P, MINT_SHR_UN_P, MINT_NIY}},
+};
+
+static const MagicIntrinsic int_cmpop[] = {
+       { "op_Inequality", {MINT_CNE_P, MINT_CNE_P, MINT_CNE_FP}},
+       { "op_Equality", {MINT_CEQ_P, MINT_CEQ_P, MINT_CEQ_FP}},
+       { "op_GreaterThan", {MINT_CGT_P, MINT_CGT_UN_P, MINT_CGT_FP}},
+       { "op_GreaterThanOrEqual", {MINT_CGE_P, MINT_CGE_UN_P, MINT_CGE_FP}},
+       { "op_LessThan", {MINT_CLT_P, MINT_CLT_UN_P, MINT_CLT_FP}},
+       { "op_LessThanOrEqual", {MINT_CLE_P, MINT_CLE_UN_P, MINT_CLE_FP}}
+};
+
 static void
 grow_code (TransformData *td)
 {
@@ -315,8 +441,9 @@ shift_op(TransformData *td, int mint_op)
 }
 
 static int 
-mint_type(MonoType *type)
+mint_type(MonoType *type_)
 {
+       MonoType *type = mini_native_type_replace_type (type_);
        if (type->byref)
                return MINT_TYPE_P;
 enum_type:
@@ -700,6 +827,32 @@ jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
        return FALSE;
 }
 
+static inline gboolean
+type_size (MonoType *type)
+{
+       if (type->type == MONO_TYPE_I4 || type->type == MONO_TYPE_U4)
+               return 4;
+       else if (type->type == MONO_TYPE_I8 || type->type == MONO_TYPE_U8)
+               return 8;
+       else if (type->type == MONO_TYPE_R4 && !type->byref)
+               return 4;
+       else if (type->type == MONO_TYPE_R8 && !type->byref)
+               return 8;
+       return SIZEOF_VOID_P;
+}
+
+static int mono_class_get_magic_index (MonoClass *k)
+{
+       if (mono_class_is_magic_int (k))
+               return !strcmp ("nint", k->name) ? 0 : 1;
+
+       if (mono_class_is_magic_float (k))
+               return 2;
+
+       return -1;
+}
+
+
 static void
 interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset, MonoClass *constrained_class, gboolean readonly)
 {
@@ -761,30 +914,151 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
 
        /* Intrinsics */
        if (target_method) {
+               const char *tm = target_method->name;
+               int type_index = mono_class_get_magic_index (target_method->klass);
+
                if (target_method->klass == mono_defaults.string_class) {
-                       if (target_method->name [0] == 'g') {
-                               if (strcmp (target_method->name, "get_Chars") == 0)
+                       if (tm [0] == 'g') {
+                               if (strcmp (tm, "get_Chars") == 0)
                                        op = MINT_GETCHR;
-                               else if (strcmp (target_method->name, "get_Length") == 0)
+                               else if (strcmp (tm, "get_Length") == 0)
                                        op = MINT_STRLEN;
                        }
+               } else if (type_index >= 0) {
+                       MonoClass *magic_class = target_method->klass;
+
+                       const int mt = mint_type (&magic_class->byval_arg);
+                       if (!strcmp (".ctor", tm)) {
+                               MonoType *arg = csignature->params [0];
+                               /* depending on SIZEOF_VOID_P and the type of the value passed to the .ctor we either have to CONV it, or do nothing */
+                               int arg_size = type_size (arg);
+
+                               if (arg_size > SIZEOF_VOID_P) { // 8 -> 4
+                                       switch (type_index) {
+                                       case 0: case 1:
+                                               ADD_CODE (td, MINT_CONV_I8_I4);
+                                               break;
+                                       case 2:
+                                               // ADD_CODE (td, MINT_CONV_R8_R4);
+                                               break;
+                                       }
+                               }
+
+                               if (arg_size < SIZEOF_VOID_P) { // 4 -> 8
+                                       switch (type_index) {
+                                       case 0: case 1:
+                                               ADD_CODE (td, MINT_CONV_I4_I8);
+                                               break;
+                                       case 2:
+                                               ADD_CODE (td, MINT_CONV_R4_R8);
+                                               break;
+                                       }
+                               }
+
+                               switch (type_index) {
+                               case 0: case 1:
+#if SIZEOF_VOID_P == 4
+                                       ADD_CODE (td, MINT_STIND_I4);
+#else
+                                       ADD_CODE (td, MINT_STIND_I8);
+#endif
+                                       break;
+                               case 2:
+#if SIZEOF_VOID_P == 4
+                                       ADD_CODE (td, MINT_STIND_R4);
+#else
+                                       ADD_CODE (td, MINT_STIND_R8);
+#endif
+                                       break;
+                               }
+
+                               td->sp -= 2;
+                               td->ip += 5;
+                               return;
+                       } else if (!strcmp ("op_Implicit", tm ) || !strcmp ("op_Explicit", tm)) {
+                               int arg_size = type_size (csignature->params [0]);
+                               if (arg_size > SIZEOF_VOID_P) { // 8 -> 4
+                                       switch (type_index) {
+                                       case 0: case 1:
+                                               ADD_CODE (td, MINT_CONV_I8_I4);
+                                               break;
+                                       case 2:
+                                               // ADD_CODE (td, MINT_CONV_R4_R8);
+                                               break;
+                                       }
+                               }
+
+                               if (arg_size < SIZEOF_VOID_P) { // 4 -> 8
+                                       switch (type_index) {
+                                       case 0: case 1:
+                                               ADD_CODE (td, MINT_CONV_I4_I8);
+                                               break;
+                                       case 2:
+                                               ADD_CODE (td, MINT_CONV_R4_R8);
+                                               break;
+                                       }
+                               }
+
+                               SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
+                               td->ip += 5;
+                               return;
+                       } else if (!strcmp (".cctor", tm)) {
+                               /* white list */
+                               goto no_intrinsic;
+                       } else if (!strcmp ("Parse", tm)) {
+                               /* white list */
+                               goto no_intrinsic;
+                       }
+
+                       for (i = 0; i < sizeof (int_unnop) / sizeof  (MagicIntrinsic); ++i) {
+                               if (!strcmp (int_unnop [i].op_name, tm)) {
+                                       ADD_CODE (td, int_unnop [i].insn [type_index]);
+                                       SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
+                                       td->ip += 5;
+                                       return;
+                               }
+                       }
+
+                       for (i = 0; i < sizeof (int_binop) / sizeof  (MagicIntrinsic); ++i) {
+                               if (!strcmp (int_binop [i].op_name, tm)) {
+                                       ADD_CODE (td, int_binop [i].insn [type_index]);
+                                       td->sp -= 1;
+                                       SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
+                                       td->ip += 5;
+                                       return;
+                               }
+                       }
+
+                       for (i = 0; i < sizeof (int_cmpop) / sizeof  (MagicIntrinsic); ++i) {
+                               if (!strcmp (int_cmpop [i].op_name, tm)) {
+                                       MonoClass *k = mono_defaults.boolean_class;
+                                       ADD_CODE (td, int_cmpop [i].insn [type_index]);
+                                       td->sp -= 1;
+                                       SET_TYPE (td->sp - 1, stack_type [mint_type (&k->byval_arg)], k);
+                                       td->ip += 5;
+                                       return;
+                               }
+                       }
+
+                       g_error ("TODO: %s", tm);
                } else if (mono_class_is_subclass_of (target_method->klass, mono_defaults.array_class, FALSE)) {
-                       if (!strcmp (target_method->name, "get_Rank")) {
+                       if (!strcmp (tm, "get_Rank")) {
                                op = MINT_ARRAY_RANK;
-                       } else if (!strcmp (target_method->name, "get_Length")) {
+                       } else if (!strcmp (tm, "get_Length")) {
                                op = MINT_LDLEN;
-                       } else if (!strcmp (target_method->name, "Address")) {
+                       } else if (!strcmp (tm, "Address")) {
                                op = readonly ? MINT_LDELEMA : MINT_LDELEMA_TC;
                        }
                } else if (target_method->klass->image == mono_defaults.corlib &&
                                   (strcmp (target_method->klass->name_space, "System.Diagnostics") == 0) &&
                                   (strcmp (target_method->klass->name, "Debugger") == 0)) {
-                       if (!strcmp (target_method->name, "Break") && csignature->param_count == 0) {
+                       if (!strcmp (tm, "Break") && csignature->param_count == 0) {
                                if (mini_should_insert_breakpoint (method))
                                        op = MINT_BREAK;
                        }
                }
        }
+no_intrinsic:
 
        if (constrained_class) {
                if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
@@ -2457,31 +2731,38 @@ generate (MonoMethod *method, InterpMethod *rtm, unsigned char *is_bb_start, Mon
 
                        csignature = mono_method_signature (m);
                        klass = m->klass;
+
                        td->sp -= csignature->param_count;
-                       ADD_CODE(td, MINT_NEWOBJ);
-                       ADD_CODE(td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
-                       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+                       if (mono_class_is_magic_int (klass) || mono_class_is_magic_float (klass)) {
+                               ADD_CODE (td, MINT_NEWOBJ_MAGIC);
+                               ADD_CODE (td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
+                               PUSH_TYPE (td, stack_type [mint_type (&klass->byval_arg)], klass);
+                       } else {
+                               ADD_CODE(td, MINT_NEWOBJ);
+                               ADD_CODE(td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
+                               mono_error_cleanup (&error); /* FIXME: don't swallow the error */
 
-                       if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
-                               vt_res_size = mono_class_value_size (klass, NULL);
-                               PUSH_VT (td, vt_res_size);
-                       }
-                       for (i = 0; i < csignature->param_count; ++i) {
-                               int mt = mint_type(csignature->params [i]);
-                               if (mt == MINT_TYPE_VT) {
-                                       MonoClass *k = mono_class_from_mono_type (csignature->params [i]);
-                                       gint32 size = mono_class_value_size (k, NULL);
-                                       size = (size + 7) & ~7;
-                                       vt_stack_used += size;
+                               if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
+                                       vt_res_size = mono_class_value_size (klass, NULL);
+                                       PUSH_VT (td, vt_res_size);
                                }
+                               for (i = 0; i < csignature->param_count; ++i) {
+                                       int mt = mint_type(csignature->params [i]);
+                                       if (mt == MINT_TYPE_VT) {
+                                               MonoClass *k = mono_class_from_mono_type (csignature->params [i]);
+                                               gint32 size = mono_class_value_size (k, NULL);
+                                               size = (size + 7) & ~7;
+                                               vt_stack_used += size;
+                                       }
+                               }
+                               if (vt_stack_used != 0 || vt_res_size != 0) {
+                                       ADD_CODE(td, MINT_VTRESULT);
+                                       ADD_CODE(td, vt_res_size);
+                                       WRITE32(td, &vt_stack_used);
+                                       td->vt_sp -= vt_stack_used;
+                               }
+                               PUSH_TYPE (td, stack_type [mint_type (&klass->byval_arg)], klass);
                        }
-                       if (vt_stack_used != 0 || vt_res_size != 0) {
-                               ADD_CODE(td, MINT_VTRESULT);
-                               ADD_CODE(td, vt_res_size);
-                               WRITE32(td, &vt_stack_used);
-                               td->vt_sp -= vt_stack_used;
-                       }
-                       PUSH_TYPE (td, stack_type [mint_type (&klass->byval_arg)], klass);
                        break;
                }
                case CEE_CASTCLASS:
index 91917664ae38c7b25e3702756543020ee9aef3e1..88efb61d67b9a587edd702b6c4f0741a10bc048c 100644 (file)
@@ -126,9 +126,6 @@ static const MagicTypeInfo type_info[] = {
        { 2, STACK_R8, STACK_R8, STACK_R8, OP_FCONV_TO_R8, OP_FCONV_TO_R4, OP_FMOVE, 0, 0, OP_PT_STORE_FP_MEMBASE_REG, 0 },
 };
 
-static inline gboolean mono_class_is_magic_int (MonoClass *klass);
-static inline gboolean mono_class_is_magic_float (MonoClass *klass);
-
 
 static inline gboolean
 type_size (MonoCompile *cfg, MonoType *type)
@@ -358,7 +355,7 @@ mono_class_is_magic_assembly (MonoClass *klass)
        return FALSE;
 }
 
-static inline gboolean
+gboolean
 mono_class_is_magic_int (MonoClass *klass)
 {
        static MonoClass *magic_nint_class;
@@ -391,7 +388,7 @@ mono_class_is_magic_int (MonoClass *klass)
        return FALSE;
 }
 
-static inline gboolean
+gboolean
 mono_class_is_magic_float (MonoClass *klass)
 {
        static MonoClass *magic_nfloat_class;
index 7629cef31299838bdd6836cdd7751bf2b01bd4f5..4a019761f7e0dbe970ddd84ffc385e84f0700804 100644 (file)
@@ -3202,6 +3202,8 @@ MonoInst*   mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field,
 guint32     mono_arch_cpu_enumerate_simd_versions (void);
 void        mono_simd_intrinsics_init (void);
 
+gboolean    mono_class_is_magic_int (MonoClass *klass);
+gboolean    mono_class_is_magic_float (MonoClass *klass);
 MonoInst*   mono_emit_native_types_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
 MonoType*   mini_native_type_replace_type (MonoType *type) MONO_LLVM_INTERNAL;