Author: zoltan
Date: 2005-12-08 15:40:11 -0500 (Thu, 08 Dec 2005)
New Revision: 54119

Modified:
   branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
   branches/vargaz/mini-linear-il/mono/mono/mini/mini-ops.h
   branches/vargaz/mini-linear-il/mono/mono/mini/mini-x86.c
Log:
Continue adding support for object model opcodes

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c        
2005-12-08 18:17:48 UTC (rev 54118)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/method-to-ir.c        
2005-12-08 20:40:11 UTC (rev 54119)
@@ -112,6 +112,12 @@
 }
 
 static inline guint32
+alloc_preg (MonoCompile *cfg)
+{
+       return alloc_ireg (cfg);
+}
+
+static inline guint32
 alloc_freg (MonoCompile *cfg)
 {
        return cfg->next_vfreg ++;
@@ -270,6 +276,18 @@
        return -1;
 }
 
+G_GNUC_UNUSED
+static void
+mono_print_bb_code_new (MonoBasicBlock *bb) {
+       if (bb->code) {
+               MonoInst *c = bb->code;
+               while (c) {
+                       mono_print_ins (c);
+                       c = c->next;
+               }
+       }
+}
+
 /*
  * Basic blocks have two numeric identifiers:
  * dfn: Depth First Number
@@ -586,6 +604,51 @@
         MONO_ADD_INS ((cfg)->cbb, (dest)); \
     } while (0)
 
+#define EMIT_NEW_PCONST(cfg,dest,val) do {     \
+        NEW_PCONST ((cfg), (dest), (val)); \
+        MONO_ADD_INS ((cfg)->cbb, (dest)); \
+    } while (0)
+
+#define EMIT_NEW_AOTCONST(cfg,dest,patch_type,cons) do { \
+        NEW_AOTCONST ((cfg), (dest), (patch_type), (cons)); \
+        MONO_ADD_INS ((cfg)->cbb, (dest)); \
+    } while (0)
+
+#define EMIT_NEW_AOTCONST_TOKEN(cfg,dest,patch_type,image,token,stack_type) do 
{ \
+        NEW_AOTCONST_TOKEN ((cfg), (dest), (patch_type), (image), (token), 
(stack_type)); \
+        MONO_ADD_INS ((cfg)->cbb, (dest)); \
+    } while (0)
+
+#define EMIT_NEW_CLASSCONST(cfg,dest,val) EMIT_NEW_AOTCONST ((cfg), (dest), 
MONO_PATCH_INFO_CLASS, (val))
+
+#define EMIT_NEW_IMAGECONST(cfg,dest,val) EMIT_NEW_AOTCONST ((cfg), (dest), 
MONO_PATCH_INFO_IMAGE, (val))
+
+#define EMIT_NEW_FIELDCONST(cfg,dest,val) EMIT_NEW_AOTCONST ((cfg), (dest), 
MONO_PATCH_INFO_FIELD, (val))
+
+#define EMIT_NEW_METHODCONST(cfg,dest,val) EMIT_NEW_AOTCONST ((cfg), (dest), 
MONO_PATCH_INFO_METHODCONST, (val))
+
+#define EMIT_NEW_VTABLECONST(cfg,dest,vtable) EMIT_NEW_AOTCONST ((cfg), 
(dest), MONO_PATCH_INFO_VTABLE, cfg->compile_aot ? (gpointer)((vtable)->klass) 
: (vtable))
+
+#define EMIT_NEW_SFLDACONST(cfg,dest,val) EMIT_NEW_AOTCONST ((cfg), (dest), 
MONO_PATCH_INFO_SFLDA, (val))
+
+#define EMIT_NEW_LDSTRCONST(cfg,dest,image,token) EMIT_NEW_AOTCONST_TOKEN 
((cfg), (dest), MONO_PATCH_INFO_LDSTR, (image), (token), STACK_OBJ)
+
+#define EMIT_NEW_TYPE_FROM_HANDLE_CONST(cfg,dest,image,token) 
EMIT_NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_TYPE_FROM_HANDLE, 
(image), (token), STACK_OBJ)
+
+#define EMIT_NEW_LDTOKENCONST(cfg,dest,image,token) EMIT_NEW_AOTCONST_TOKEN 
((cfg), (dest), MONO_PATCH_INFO_LDTOKEN, (image), (token), STACK_PTR)
+
+#define EMIT_NEW_TEMPLOADA(cfg,dest,num) do { NEW_TEMPLOADA ((cfg), (dest), 
(num)); MONO_ADD_INS ((cfg)->cbb, (dest)); } while (0)
+
+#define EMIT_NEW_LOCLOADA(cfg,dest,num) do { NEW_LOCLOADA ((cfg), (dest), 
(num)); MONO_ADD_INS ((cfg)->cbb, (dest)); } while (0)
+
+#define EMIT_NEW_UNALU(cfg,dest,op,dr,sr1) do { \
+        MONO_INST_NEW ((cfg), (dest), (op)); \
+        (dest)->opcode = op; \
+        (dest)->dreg = dr; \
+        (dest)->sreg1 = sr1; \
+           MONO_ADD_INS (cfg->cbb, (dest)); \
+    } while (0)        
+
 /*
  * Variants which do not take an dest argument, but take a dreg argument.
  */
@@ -1961,7 +2024,7 @@
 mini_emit_load_intf_reg (MonoCompile *cfg, int intf_reg, int ioffset_reg, 
MonoClass *klass)
 {
        if (cfg->compile_aot) {
-               int iid_reg = alloc_dreg (cfg, STACK_PTR);
+               int iid_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, 
MONO_PATCH_INFO_IID);
 #if SIZEOF_VOID_P == 8
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, iid_reg, iid_reg, 3);
@@ -1979,16 +2042,180 @@
 static void
 mini_emit_load_intf_reg_vtable (MonoCompile *cfg, int intf_reg, int 
vtable_reg, MonoClass *klass)
 {
-       int ioffset_reg = alloc_dreg (cfg, STACK_PTR);
+       int ioffset_reg = alloc_preg (cfg);
 
        MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ioffset_reg, vtable_reg, 
G_STRUCT_OFFSET (MonoVTable, interface_offsets));
        mini_emit_load_intf_reg (cfg, intf_reg, ioffset_reg, klass);
 }
 
+/* Emit code which loads <klass_reg>->interface_offsets [klass->interface_id] 
*/
+static void
+mini_emit_load_intf_reg_class (MonoCompile *cfg, int intf_reg, int klass_reg, 
MonoClass *klass)
+{
+       int ioffset_reg = alloc_preg (cfg);
+
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ioffset_reg, klass_reg, 
G_STRUCT_OFFSET (MonoClass, interface_offsets));
+
+       if (cfg->compile_aot) {
+               int iid_reg = alloc_preg (cfg);
+               MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, 
MONO_PATCH_INFO_IID);
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, iid_reg, iid_reg, 2);
+               MONO_EMIT_NEW_BIALU (cfg, CEE_ADD, ioffset_reg, ioffset_reg, 
iid_reg);
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, 
intf_reg, ioffset_reg, 0);
+       }
+       else
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, 
intf_reg, ioffset_reg, klass->interface_id * sizeof (int));
+}
+
+/* 
+ * Emit code which checks whenever the interface id of @klass is smaller than
+ * than the value given by max_iid_reg.
+*/
+static void
+mini_emit_max_iid_check (MonoCompile *cfg, int max_iid_reg, MonoClass *klass,
+                                                MonoInst *false_target)
+{
+       if (cfg->compile_aot) {
+               int iid_reg = alloc_preg (cfg);
+               MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, 
MONO_PATCH_INFO_IID);
+               MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, max_iid_reg, iid_reg);
+       }
+       else
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, max_iid_reg, 
klass->interface_id);
+       if (false_target)
+               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BLT_UN, false_target);
+       else
+               MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException");
+}
+
+/* Same as above, but obtains max_iid from a vtable */
+static void
+mini_emit_max_iid_check_vtable (MonoCompile *cfg, int vtable_reg, MonoClass 
*klass,
+                                                                MonoInst 
*false_target)
+{
+       int max_iid_reg = alloc_preg (cfg);
+               
+       MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, 
vtable_reg, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
+       mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
+}
+
+/* Same as above, but obtains max_iid from a klass */
+static void
+mini_emit_max_iid_check_class (MonoCompile *cfg, int klass_reg, MonoClass 
*klass,
+                                                                MonoInst 
*false_target)
+{
+       int max_iid_reg = alloc_preg (cfg);
+
+       MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, 
klass_reg, G_STRUCT_OFFSET (MonoClass, max_interface_id));          
+       mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
+}
+
 static void 
+mini_emit_isninst_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, 
MonoInst *false_target, MonoInst *true_target)
+{
+       int idepth_reg = alloc_preg (cfg);
+       int stypes_reg = alloc_preg (cfg);
+       int stype = alloc_preg (cfg);
+
+       if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, 
idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, 
klass->idepth);
+               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BLT_UN, false_target);
+       }
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, G_STRUCT_OFFSET 
(MonoClass, supertypes));
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 
1) * SIZEOF_VOID_P));
+       if (cfg->compile_aot) {
+               int const_reg = alloc_preg (cfg);
+               MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
+               MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, const_reg);
+       } else {
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, stype, klass);
+       }
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, true_target);
+}
+
+static void 
+mini_emit_isninst_iface_cast (MonoCompile *cfg, int vtable_reg, MonoClass 
*klass, MonoInst *false_target, MonoInst *true_target)
+{
+       int intf_reg = alloc_preg (cfg);
+
+       mini_emit_max_iid_check_vtable (cfg, vtable_reg, klass, false_target);
+       mini_emit_load_intf_reg_vtable (cfg, intf_reg, vtable_reg, klass);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, 0);
+       /* the object_is_null target simply copies the input register to the 
output */
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BNE_UN, true_target);
+}
+
+/*
+ * Variant of the above that takes a register to the class, not the vtable.
+ * Note that inside interfaces_offsets the empty value is -1, not NULL, in 
this case.
+ */
+static void 
+mini_emit_isninst_iface_class_cast (MonoCompile *cfg, int klass_reg, MonoClass 
*klass, MonoInst *false_target, MonoInst *true_target)
+{
+       int intf_reg = alloc_preg (cfg);
+
+       mini_emit_max_iid_check_class (cfg, klass_reg, klass, false_target);
+       mini_emit_load_intf_reg_class (cfg, intf_reg, klass_reg, klass);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, -1);
+       /* the object_is_null target simply copies the input register to the 
output */
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BGE, true_target);
+}
+
+static void 
+mini_emit_castclass (MonoCompile *cfg, int klass_reg, MonoClass *klass)
+{
+       int idepth_reg = alloc_preg (cfg);
+       int stypes_reg = alloc_preg (cfg);
+       int stype = alloc_preg (cfg);
+
+       if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, 
idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, 
klass->idepth);
+               MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException");
+       }
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, G_STRUCT_OFFSET 
(MonoClass, supertypes));
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 
1) * SIZEOF_VOID_P));
+       if (cfg->compile_aot) {
+               int const_reg = alloc_preg (cfg);
+               MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
+               MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, const_reg);
+       } else {
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, stype, klass);
+       }
+       MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
+}
+
+static void 
+mini_emit_castclass_iface (MonoCompile *cfg, int vtable_reg, MonoClass *klass)
+{
+       int intf_reg = alloc_preg (cfg);
+
+       mini_emit_max_iid_check_vtable (cfg, vtable_reg, klass, NULL);
+       mini_emit_load_intf_reg_vtable (cfg, intf_reg, vtable_reg, klass);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, 0);
+       MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException");
+}
+
+/*
+ * Variant of the aboce that takes a register to the class, not the vtable.
+ * Note that inside interfaces_offsets the empty value is -1, not NULL, in 
this case.
+ */
+static void 
+mini_emit_castclass_iface_class (MonoCompile *cfg, int klass_reg, MonoClass 
*klass)
+{
+       int intf_reg = alloc_preg (cfg);
+
+       mini_emit_max_iid_check_class (cfg, klass_reg, klass, NULL);
+       mini_emit_load_intf_reg_class (cfg, intf_reg, klass_reg, klass);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, -1);
+       MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException");
+}
+
+static void 
 mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int 
val, int align)
 {
-       int val_reg = alloc_dreg (cfg, STACK_PTR);
+       int val_reg = alloc_preg (cfg);
 
        /* FIXME: Use STORE_MEMBASE_IMM */
 
@@ -2039,7 +2266,7 @@
 #if !NO_UNALIGNED_ACCESS
        if (sizeof (gpointer) == 8) {
                while (size >= 8) {
-                       cur_reg = alloc_dreg (cfg, STACK_PTR);
+                       cur_reg = alloc_preg (cfg);
                        MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI8_MEMBASE, 
cur_reg, srcreg, soffset);
                        MONO_EMIT_NEW_STORE_MEMBASE (cfg, 
OP_STOREI8_MEMBASE_REG, destreg, doffset, cur_reg);
                        doffset += 8;
@@ -2050,7 +2277,7 @@
 #endif
 
        while (size >= 4) {
-               cur_reg = alloc_dreg (cfg, STACK_PTR);
+               cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, cur_reg, 
srcreg, soffset);
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, 
destreg, doffset, cur_reg);
                doffset += 4;
@@ -2058,7 +2285,7 @@
                size -= 4;
        }
        while (size >= 2) {
-               cur_reg = alloc_dreg (cfg, STACK_PTR);
+               cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, cur_reg, 
srcreg, soffset);
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, 
destreg, doffset, cur_reg);
                doffset += 2;
@@ -2066,7 +2293,7 @@
                size -= 2;
        }
        while (size >= 1) {
-               cur_reg = alloc_dreg (cfg, STACK_PTR);
+               cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, cur_reg, 
srcreg, soffset);
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, 
destreg, doffset, cur_reg);
                doffset += 1;
@@ -2141,6 +2368,9 @@
 {
        MonoInst *load, *store, *temp, *ins;
 
+       /* Not needed */
+       return;
+
        while (stack < sp) {
                ins = *stack;
                /* handle also other constants */
@@ -2161,6 +2391,9 @@
                        } else
                                MONO_ADD_INS (cfg->cbb, store);
                        NEW_TEMPLOAD (cfg, load, temp->inst_c0);
+                       if (load->opcode == CEE_LDOBJ) {
+                               NOT_IMPLEMENTED;
+                       }
                        load->cil_code = ins->cil_code;
                        MONO_ADD_INS (cfg->cbb, load);
                        *stack = load;
@@ -2480,10 +2713,10 @@
                /* Initialize method->slot */
                mono_class_setup_vtable (method->klass);
 
-               vtable_reg = alloc_dreg (cfg, STACK_PTR);
+               vtable_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, 
G_STRUCT_OFFSET (MonoObject, vtable));
                if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-                       slot_reg = alloc_dreg (cfg, STACK_PTR);
+                       slot_reg = alloc_preg (cfg);
                        mini_emit_load_intf_reg_vtable (cfg, slot_reg, 
vtable_reg, method->klass);
                        call->inst.inst_offset = method->slot * SIZEOF_VOID_P;
                } else {
@@ -2727,10 +2960,8 @@
                        memset_method = get_memset_method ();
                        handle_loaded_temps (cfg, stack_start, sp);
                        iargs [0] = dest;
-                       NEW_ICONST (cfg, iargs [1], 0);
-                       MONO_ADD_INS (cfg->cbb, iargs [1]);
-                       NEW_ICONST (cfg, iargs [2], n);
-                       MONO_ADD_INS (cfg->cbb, iargs [2]);
+                       EMIT_NEW_ICONST (cfg, iargs [1], 0);
+                       EMIT_NEW_ICONST (cfg, iargs [2], n);
                        mono_emit_method_call_spilled (cfg, memset_method, 
memset_method->signature, iargs, ip, NULL);
                }
                break;
@@ -2759,12 +2990,10 @@
                        guint32 lw = vtable->klass->instance_size;
                        lw = ((lw + (sizeof (gpointer) - 1)) & ~(sizeof 
(gpointer) - 1)) / sizeof (gpointer);
                        EMIT_NEW_ICONST (cfg, iargs [0], lw);
-                       NEW_VTABLECONST (cfg, iargs [1], vtable);
-                       MONO_ADD_INS (cfg->cbb, iargs [1]);
+                       EMIT_NEW_VTABLECONST (cfg, iargs [1], vtable);
                }
                else {
-                       NEW_VTABLECONST (cfg, iargs [0], vtable);
-                       MONO_ADD_INS (cfg->cbb, iargs [0]);
+                       EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
                }
        }
 
@@ -2785,7 +3014,7 @@
        NEW_STORE_MEMBASE (cfg, vstore, mono_type_to_store_membase 
(&klass->byval_arg), alloc->dreg, sizeof (MonoObject), val->dreg);
 
        if (vstore->opcode == CEE_STOBJ) {
-               int dreg = alloc_dreg (cfg, STACK_PTR);
+               int dreg = alloc_preg (cfg);
                NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, alloc->dreg, sizeof 
(MonoObject));
                MONO_ADD_INS (cfg->cbb, dest);
                handle_stobj (cfg, dest, val, NULL, klass, FALSE, FALSE);
@@ -2799,15 +3028,241 @@
 static MonoInst*
 handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, unsigned 
char *ip)
 {
-       /* FIXME: */
+       MonoInst *object_is_null;
+       int obj_reg = src->dreg;
+       int vtable_reg = alloc_preg (cfg);
+
+       MONO_NEW_LABEL (cfg, object_is_null);
+
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, object_is_null);
+
+       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, 
G_STRUCT_OFFSET (MonoObject, vtable));
+               mini_emit_castclass_iface (cfg, vtable_reg, klass);
+       } else {
+               int klass_reg = alloc_preg (cfg);
+
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, 
G_STRUCT_OFFSET (MonoObject, vtable));
+
+               if (klass->rank) {
+                       int rank_reg = alloc_preg (cfg);
+                       int eclass_reg = alloc_preg (cfg);
+
+                       MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, 
rank_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, rank));
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, 
rank_reg, klass->rank);
+                       MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, 
G_STRUCT_OFFSET (MonoVTable, klass));
+                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, 
G_STRUCT_OFFSET (MonoClass, cast_class));
+                       if (klass->cast_class == mono_defaults.object_class) {
+                               int parent_reg = alloc_preg (cfg);
+                               int const_reg = -1;
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, 
eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
+                               if (cfg->compile_aot) {
+                                       const_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class->parent);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, parent_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BNE_UN, 
object_is_null);
+                               if (cfg->compile_aot) {
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       } else if (klass->cast_class == 
mono_defaults.enum_class->parent) {
+                               int const_reg = alloc_preg (cfg);
+                               if (cfg->compile_aot) {
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class->parent);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, 
object_is_null);
+                               if (cfg->compile_aot) {
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       } else if (klass->cast_class == 
mono_defaults.enum_class) {
+                               if (cfg->compile_aot) {
+                                       int const_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       } else if (klass->cast_class->flags & 
TYPE_ATTRIBUTE_INTERFACE) {
+                               mini_emit_castclass_iface_class (cfg, 
eclass_reg, klass->cast_class);
+                       } else {
+                               mini_emit_castclass (cfg, eclass_reg, 
klass->cast_class);
+                       }
+
+                       if ((klass->rank == 1) && (klass->byval_arg.type == 
MONO_TYPE_SZARRAY)) {
+                               /* Check that the object is a vector too */
+                               int bounds_reg = alloc_preg (cfg);
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, 
obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
+                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, 
-1, bounds_reg, 0);
+                               MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       }
+               } else {
+                       if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) 
&& (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+                               /* the remoting code is broken, access the 
class for now */
+                               if (0) {
+                                       MonoVTable *vt = mono_class_vtable 
(cfg->domain, klass);
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, vtable_reg, vt);
+                               } else {
+                                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, 
klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, klass_reg, klass);
+                               }
+                               MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, 
"InvalidCastException");
+                       } else {
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, 
vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+                               mini_emit_castclass (cfg, klass_reg, klass);
+                       }
+               }
+       }
+
+       mono_bblock_add_inst (cfg->cbb, object_is_null);
+
        return src;
 }
 
 static MonoInst*
 handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, unsigned 
char *ip)
 {
-       /* FIXME: */
-       return src;
+       MonoInst *object_is_null, *end_label, *false_label, *ins;
+       int obj_reg = src->dreg;
+       int vtable_reg = alloc_preg (cfg);
+       int res_reg = alloc_preg (cfg);
+
+       MONO_NEW_LABEL (cfg, object_is_null);
+       MONO_NEW_LABEL (cfg, end_label);
+       MONO_NEW_LABEL (cfg, false_label);
+
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, object_is_null);
+
+       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, 
G_STRUCT_OFFSET (MonoObject, vtable));
+               /* the object_is_null target simply copies the input register 
to the output */
+               mini_emit_isninst_iface_cast (cfg, vtable_reg, klass, 
false_label, object_is_null);
+       } else {
+               int klass_reg = alloc_preg (cfg);
+
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, 
G_STRUCT_OFFSET (MonoObject, vtable));
+
+               if (klass->rank) {
+                       int rank_reg = alloc_preg (cfg);
+                       int eclass_reg = alloc_preg (cfg);
+
+                       MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, 
rank_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, rank));
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, 
rank_reg, klass->rank);
+                       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BNE_UN, 
false_label);
+                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, 
G_STRUCT_OFFSET (MonoVTable, klass));
+                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, 
G_STRUCT_OFFSET (MonoClass, cast_class));
+                       if (klass->cast_class == mono_defaults.object_class) {
+                               int parent_reg = alloc_preg (cfg);
+                               int const_reg = -1;
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, 
eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
+                               if (cfg->compile_aot) {
+                                       const_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class->parent);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, parent_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BNE_UN, 
object_is_null);
+                               if (cfg->compile_aot) {
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, 
object_is_null);
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BR, 
false_label);
+                       } else if (klass->cast_class == 
mono_defaults.enum_class->parent) {
+                               int const_reg = -1;
+                               
+                               if (cfg->compile_aot) {
+                                       const_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class->parent);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, 
object_is_null);
+                               if (cfg->compile_aot) {
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, 
object_is_null);
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BR, 
false_label);
+                       } else if (klass->cast_class == 
mono_defaults.enum_class) {
+                               if (cfg->compile_aot) {
+                                       int const_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_CLASSCONST (cfg, 
const_reg, mono_defaults.enum_class);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, 
-1, eclass_reg, const_reg);
+                               } else {
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BEQ, 
object_is_null);
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BR, 
false_label);
+                       } else if (klass->cast_class->flags & 
TYPE_ATTRIBUTE_INTERFACE) {
+                               mini_emit_isninst_iface_class_cast (cfg, 
eclass_reg, klass->cast_class, false_label, object_is_null);
+                       } else {
+                               if ((klass->rank == 1) && 
(klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
+                                       /* Check that the object is a vector 
too */
+                                       int bounds_reg = alloc_preg (cfg);
+                                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, 
bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, bounds_reg, 0);
+                                       MONO_EMIT_NEW_BRANCH_LABEL (cfg, 
CEE_BNE_UN, false_label);
+                               }
+
+                               /* the object_is_null target simply copies the 
input register to the output */
+                               mini_emit_isninst_cast (cfg, eclass_reg, 
klass->cast_class, false_label, object_is_null);
+                       }
+               } else if (mono_class_is_nullable (klass)) {
+                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, 
G_STRUCT_OFFSET (MonoVTable, klass));
+                       /* the object_is_null target simply copies the input 
register to the output */
+                       mini_emit_isninst_cast (cfg, klass_reg, 
klass->cast_class, false_label, object_is_null);
+               } else {
+                       if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) 
&& (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+                               /* the remoting code is broken, access the 
class for now */
+                               if (0) {
+                                       MonoVTable *vt = mono_class_vtable 
(cfg->domain, klass);
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, vtable_reg, vt);
+                               } else {
+                                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, 
klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, 
OP_COMPARE_IMM, -1, klass_reg, klass);
+                               }
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BNE_UN, 
false_label);
+                               MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BR, 
object_is_null);
+                       } else {
+                               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, 
vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+                               /* the object_is_null target simply copies the 
input register to the output */
+                               mini_emit_isninst_cast (cfg, klass_reg, klass, 
false_label, object_is_null);
+                       }
+               }
+       }
+
+       mono_bblock_add_inst (cfg->cbb, false_label);
+       MONO_EMIT_NEW_ICONST (cfg, res_reg, 0);
+       MONO_EMIT_NEW_BRANCH_LABEL (cfg, CEE_BR, end_label);
+       mono_bblock_add_inst (cfg->cbb, object_is_null);
+       EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, obj_reg);
+       ins->type = STACK_PTR;
+       mono_bblock_add_inst (cfg->cbb, end_label);
+
+       return ins;
 }
 
 static MonoInst*
@@ -4599,17 +5054,13 @@
                                MonoInst *dest, *src, *temp;
 
                                temp = mono_compile_create_var (cfg, 
&ins->klass->byval_arg, OP_LOCAL);
-                               NEW_LOCLOADA (cfg, src, n);
-                               MONO_ADD_INS (cfg->cbb, src);
-                               NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
-                               MONO_ADD_INS (cfg->cbb, dest);
+                               EMIT_NEW_LOCLOADA (cfg, src, n);
+                               EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
                                handle_stobj (cfg, dest, src, ip, ins->klass, 
FALSE, FALSE);
 
-                               NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
-                               MONO_ADD_INS (cfg->cbb, dest);
+                               EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
                                dest->type = STACK_VTYPE;
                                dest->klass = ins->klass;
-                               MONO_ADD_INS (cfg->cbb, dest);
                                *sp++ = dest;
                        } else {
                                MONO_ADD_INS (bblock, ins);
@@ -4641,8 +5092,7 @@
                                ins->cil_code = ip;
 
                                if (ins->opcode == CEE_STOBJ) {
-                                       NEW_LOCLOADA (cfg, ins, n);
-                                       MONO_ADD_INS (cfg->cbb, ins);
+                                       EMIT_NEW_LOCLOADA (cfg, ins, n);
                                        handle_stobj (cfg, ins, *sp, ip, 
ins->klass, FALSE, FALSE);
                                } else
                                        MONO_ADD_INS (bblock, ins);
@@ -4699,16 +5149,13 @@
                                MonoInst *dest, *src, *temp;
 
                                temp = mono_compile_create_var (cfg, 
&ins->klass->byval_arg, OP_LOCAL);
-                               NEW_LOCLOADA (cfg, src, n);
-                               MONO_ADD_INS (cfg->cbb, src);
-                               NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
-                               MONO_ADD_INS (cfg->cbb, dest);
+                               EMIT_NEW_LOCLOADA (cfg, src, n);
+                               EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
                                handle_stobj (cfg, dest, src, ip, ins->klass, 
FALSE, FALSE);
 
-                               NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
+                               EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
                                dest->type = STACK_VTYPE;
                                dest->klass = ins->klass;
-                               MONO_ADD_INS (cfg->cbb, dest);
                                *sp++ = dest;
                        } else {
                                MONO_ADD_INS (bblock, ins);
@@ -4720,9 +5167,8 @@
                        CHECK_OPSIZE (2);
                        CHECK_STACK_OVF (1);
                        CHECK_LOCAL (ip [1]);
-                       NEW_LOCLOADA (cfg, ins, ip [1]);
+                       EMIT_NEW_LOCLOADA (cfg, ins, ip [1]);
                        ins->cil_code = ip;
-                       MONO_ADD_INS (bblock, ins);
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -4735,8 +5181,7 @@
                        NEW_LOCSTORE (cfg, ins, ip [1], *sp);
                        ins->cil_code = ip;
                        if (ins->opcode == CEE_STOBJ) {
-                               NEW_LOCLOADA (cfg, ins, ip [1]);
-                               MONO_ADD_INS (cfg->cbb, ins);
+                               EMIT_NEW_LOCLOADA (cfg, ins, ip [1]);
                                handle_stobj (cfg, ins, *sp, ip, ins->klass, 
FALSE, FALSE);
                        } else
                                MONO_ADD_INS (bblock, ins);
@@ -4745,8 +5190,7 @@
                        break;
                case CEE_LDNULL:
                        CHECK_STACK_OVF (1);
-                       NEW_PCONST (cfg, ins, NULL);
-                       MONO_ADD_INS (bblock, ins);
+                       EMIT_NEW_PCONST (cfg, ins, NULL);
                        ins->cil_code = ip;
                        ins->type = STACK_OBJ;
                        ++ip;
@@ -4754,8 +5198,7 @@
                        break;
                case CEE_LDC_I4_M1:
                        CHECK_STACK_OVF (1);
-                       NEW_ICONST (cfg, ins, -1);
-                       MONO_ADD_INS (bblock, ins);
+                       EMIT_NEW_ICONST (cfg, ins, -1);
                        ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
@@ -4770,8 +5213,7 @@
                case CEE_LDC_I4_7:
                case CEE_LDC_I4_8:
                        CHECK_STACK_OVF (1);
-                       NEW_ICONST (cfg, ins, (*ip) - CEE_LDC_I4_0);
-                       MONO_ADD_INS (bblock, ins);
+                       EMIT_NEW_ICONST (cfg, ins, (*ip) - CEE_LDC_I4_0);
                        ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
@@ -4780,8 +5222,7 @@
                        CHECK_OPSIZE (2);
                        CHECK_STACK_OVF (1);
                        ++ip;
-                       NEW_ICONST (cfg, ins, *((signed char*)ip));
-                       MONO_ADD_INS (bblock, ins);
+                       EMIT_NEW_ICONST (cfg, ins, *((signed char*)ip));
                        ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
@@ -4789,8 +5230,7 @@
                case CEE_LDC_I4:
                        CHECK_OPSIZE (5);
                        CHECK_STACK_OVF (1);
-                       NEW_ICONST (cfg, ins, (gint32)read32 (ip + 1));
-                       MONO_ADD_INS (bblock, ins);
+                       EMIT_NEW_ICONST (cfg, ins, (gint32)read32 (ip + 1));
                        ins->cil_code = ip;
                        ip += 5;
                        *sp++ = ins;
@@ -4868,14 +5308,44 @@
                                } else {
                                        MONO_ADD_INS (bblock, store);
                                }
+
                                NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
                                ins->cil_code = ip;
-                               MONO_ADD_INS (bblock, ins);
-                               *sp++ = ins;
+                               if (ins->opcode == CEE_LDOBJ) {
+                                       MonoInst *dest, *src, *temp2;
+
+                                       temp2 = mono_compile_create_var (cfg, 
&ins->klass->byval_arg, OP_LOCAL);
+                                       EMIT_NEW_TEMPLOADA (cfg, src, 
temp->inst_c0);
+                                       EMIT_NEW_TEMPLOADA (cfg, dest, 
temp2->inst_c0);
+                                       handle_stobj (cfg, dest, src, ip, 
ins->klass, FALSE, FALSE);
+                                       EMIT_NEW_TEMPLOADA (cfg, dest, 
temp2->inst_c0);
+                                       dest->type = STACK_VTYPE;
+                                       dest->klass = ins->klass;
+                                       *sp++ = dest;
+                               }
+                               else {
+                                       MONO_ADD_INS (bblock, ins);
+                                       *sp++ = ins;
+                               }
+
                                NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
                                ins->cil_code = ip;
-                               MONO_ADD_INS (bblock, ins);
-                               *sp++ = ins;
+                               if (ins->opcode == CEE_LDOBJ) {
+                                       MonoInst *dest, *src, *temp2;
+
+                                       temp2 = mono_compile_create_var (cfg, 
&ins->klass->byval_arg, OP_LOCAL);
+                                       EMIT_NEW_TEMPLOADA (cfg, src, 
temp->inst_c0);
+                                       EMIT_NEW_TEMPLOADA (cfg, dest, 
temp2->inst_c0);
+                                       handle_stobj (cfg, dest, src, ip, 
ins->klass, FALSE, FALSE);
+                                       EMIT_NEW_TEMPLOADA (cfg, dest, 
temp2->inst_c0);
+                                       dest->type = STACK_VTYPE;
+                                       dest->klass = ins->klass;
+                                       *sp++ = dest;
+                               }
+                               else {
+                                       MONO_ADD_INS (bblock, ins);
+                                       *sp++ = ins;
+                               }
                        }
                        ++ip;
                        inline_costs += 2;
@@ -5258,14 +5728,12 @@
                                                MonoInst *dest, *src, *temp;
 
                                                temp = mono_compile_create_var 
(cfg, &ins->klass->byval_arg, OP_LOCAL);
-                                               NEW_TEMPLOADA (cfg, dest, 
temp->inst_c0);
-                                               MONO_ADD_INS (cfg->cbb, dest);
+                                               EMIT_NEW_TEMPLOADA (cfg, dest, 
temp->inst_c0);
                                                handle_stobj (cfg, dest, addr, 
ip, ins->klass, FALSE, FALSE);
 
-                                               NEW_TEMPLOADA (cfg, dest, 
temp->inst_c0);
+                                               EMIT_NEW_TEMPLOADA (cfg, dest, 
temp->inst_c0);
                                                dest->type = STACK_VTYPE;
                                                dest->klass = ins->klass;
-                                               MONO_ADD_INS (cfg->cbb, dest);
 
                                                ins = dest;
                                        } else {
@@ -5504,8 +5972,8 @@
                        MonoInst *label, *src1;
                        MonoBasicBlock **targets;
                        MonoBasicBlock *default_bblock;
-                       int offset_reg = alloc_dreg (cfg, STACK_PTR);
-                       int target_reg = alloc_dreg (cfg, STACK_PTR);
+                       int offset_reg = alloc_preg (cfg);
+                       int target_reg = alloc_preg (cfg);
 
                        CHECK_OPSIZE (5);
                        CHECK_STACK (1);
@@ -5582,7 +6050,7 @@
                        case CEE_LDIND_I8:
                                NOT_IMPLEMENTED;
                        default:
-                               dreg = alloc_dreg (cfg, STACK_PTR);
+                               dreg = alloc_preg (cfg);
                        }
 
                        NEW_LOAD_MEMBASE (cfg, ins, ldind_to_load_membase 
(*ip), dreg, sp [0]->dreg, 0);
@@ -6034,30 +6502,29 @@
                        handle_loaded_temps (cfg, stack_start, sp);
 
                        if (mini_class_is_system_array (cmethod->klass)) {
-                               NEW_METHODCONST (cfg, *sp, cmethod);
-                               MONO_ADD_INS (cfg->cbb, *sp);
+                               EMIT_NEW_METHODCONST (cfg, *sp, cmethod);
                                alloc = handle_array_new (cfg, 
fsig->param_count, sp, ip);
                        } else if (cmethod->string_ctor) {
                                NOT_IMPLEMENTED;
                                /* we simply pass a null pointer */
-                               NEW_PCONST (cfg, *sp, NULL); 
+                               EMIT_NEW_PCONST (cfg, *sp, NULL); 
                                /* now call the string ctor */
                                temp = mono_emit_method_call_spilled (cfg, 
cmethod, fsig, sp, ip, NULL);
                        } else {
                                MonoInst* callvirt_this_arg = NULL;
                                
                                if (cmethod->klass->valuetype) {
-                                       NOT_IMPLEMENTED;
-
                                        iargs [0] = mono_compile_create_var 
(cfg, &cmethod->klass->byval_arg, OP_LOCAL);
                                        temp = iargs [0]->inst_c0;
 
-                                       NEW_TEMPLOADA (cfg, *sp, temp);
+                                       EMIT_NEW_TEMPLOADA (cfg, *sp, temp);
 
                                        handle_initobj (cfg, *sp, NULL, 
cmethod->klass, stack_start, sp);
 
-                                       NEW_TEMPLOADA (cfg, *sp, temp);
+                                       EMIT_NEW_TEMPLOADA (cfg, *sp, temp);
 
+                                       alloc = NULL;
+
                                        /* 
                                         * The code generated by 
mini_emit_virtual_call () expects
                                         * iargs [0] to be a boxed instance, 
but luckily the vcall
@@ -6109,8 +6576,15 @@
                                }
                        }
 
-                       *sp = alloc;
-                       sp++;
+                       if (alloc == NULL) {
+                               /* Valuetype */
+                               EMIT_NEW_TEMPLOADA (cfg, ins, iargs 
[0]->inst_c0);
+                               ins->type = STACK_VTYPE;
+                               ins->klass = ins->klass;
+                               *sp++= ins;
+                       }
+                       else
+                               *sp++ = alloc;
                        
                        ip += 5;
                        inline_costs += 5;
@@ -6375,7 +6849,7 @@
                        MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, 
G_STRUCT_OFFSET (MonoClass, element_class));
                        
                        if (cfg->compile_aot) {
-                               int const_reg = alloc_dreg (cfg, STACK_PTR);
+                               int const_reg = alloc_preg (cfg);
                                MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, 
klass->element_class);
                                MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, 
eclass_reg, const_reg);
                        } else {
@@ -6508,7 +6982,7 @@
                                        }
                                } else {
                                        if (*ip == CEE_LDFLDA) {
-                                               dreg = alloc_dreg (cfg, 
STACK_PTR);
+                                               dreg = alloc_preg (cfg);
 
                                                NEW_BIALU_IMM (cfg, ins, 
OP_PADD, dreg, sp [0]->dreg, foffset);
                                                MONO_ADD_INS (bblock, ins);
@@ -6713,6 +7187,7 @@
                        ip += 5;
                        break;
                }
+#endif
                case CEE_STOBJ:
                        CHECK_STACK (2);
                        sp -= 2;
@@ -6721,24 +7196,17 @@
                        klass = mini_get_class (method, token, generic_context);
                        if (!klass)
                                goto load_error;
-                       n = mono_type_to_stind (&klass->byval_arg);
-                       if (n == CEE_STOBJ) {
+                       /* FIXME: should check item at sp [1] is compatible 
with the type of the store. */
+                       NEW_STORE_MEMBASE (cfg, ins, mono_type_to_store_membase 
(&klass->byval_arg), sp [0]->dreg, 0, sp [1]->dreg);
+                       if (ins->opcode == CEE_STOBJ)
                                handle_stobj (cfg, sp [0], sp [1], ip, klass, 
FALSE, FALSE);
-                       } else {
-                               /* FIXME: should check item at sp [1] is 
compatible with the type of the store. */
-                               MonoInst *store;
-                               MONO_INST_NEW (cfg, store, n);
-                               store->cil_code = ip;
-                               store->inst_left = sp [0];
-                               store->inst_right = sp [1];
-                               store->flags |= ins_flag;
-                               MONO_ADD_INS (bblock, store);
-                       }
+                       else
+                               MONO_ADD_INS (cfg->cbb, ins);
                        ins_flag = 0;
                        ip += 5;
                        inline_costs += 1;
                        break;
-#endif
+
                        /*
                         * Array opcodes
                         */
@@ -6787,7 +7255,7 @@
                        CHECK_STACK (1);
                        --sp;
 
-                       dreg = alloc_dreg (cfg, STACK_PTR);
+                       dreg = alloc_preg (cfg);
                        NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg, sp 
[0]->dreg,
                                                          G_STRUCT_OFFSET 
(MonoArray, max_length));
                        MONO_ADD_INS (cfg->cbb, ins);
@@ -6812,17 +7280,17 @@
                         */
                        if (!klass->valuetype && method->wrapper_type == 
MONO_WRAPPER_NONE) {
                                MonoClass* array_class = mono_array_class_get 
(klass, 1);
-                               int vtable_reg = alloc_dreg (cfg, STACK_PTR);
+                               int vtable_reg = alloc_preg (cfg);
 
                                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, 
OP_LOAD_MEMBASE, vtable_reg, 
                                                                                
           sp [0]->dreg, G_STRUCT_OFFSET (MonoObject, vtable));
                                       
                                if (cfg->opt & MONO_OPT_SHARED) {
-                                       int class_reg = alloc_dreg (cfg, 
STACK_PTR);
+                                       int class_reg = alloc_preg (cfg);
                                        MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, 
OP_LOAD_MEMBASE, class_reg, 
                                                                                
                   vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
                                        if (cfg->compile_aot) {
-                                               int klass_reg = alloc_dreg 
(cfg, STACK_PTR);
+                                               int klass_reg = alloc_preg 
(cfg);
                                                MONO_EMIT_NEW_CLASSCONST (cfg, 
klass_reg, array_class);
                                                MONO_EMIT_NEW_BIALU (cfg, 
OP_COMPARE, -1, class_reg, klass_reg);
                                        } else {
@@ -6830,7 +7298,7 @@
                                        }
                                } else {
                                        if (cfg->compile_aot) {
-                                               int vt_reg = alloc_dreg (cfg, 
STACK_PTR);
+                                               int vt_reg = alloc_preg (cfg);
                                                MONO_EMIT_NEW_VTABLECONST (cfg, 
vt_reg, mono_class_vtable (cfg->domain, array_class));
                                                MONO_EMIT_NEW_BIALU (cfg, 
OP_COMPARE, -1, vtable_reg, vt_reg);
                                        } else {
@@ -6845,8 +7313,8 @@
                        mono_class_init (klass);
                        size = mono_class_array_element_size (klass);
 
-                       mult_reg = alloc_dreg (cfg, STACK_PTR);
-                       add_reg = alloc_dreg (cfg, STACK_PTR);
+                       mult_reg = alloc_preg (cfg);
+                       add_reg = alloc_preg (cfg);
                        array_reg = sp [0]->dreg;
                        index_reg = sp [1]->dreg;
 
@@ -6905,8 +7373,8 @@
                        klass = array_access_to_klass (*ip);
                        size = mono_class_array_element_size (klass);
 
-                       mult_reg = alloc_dreg (cfg, STACK_PTR);
-                       add_reg = alloc_dreg (cfg, STACK_PTR);
+                       mult_reg = alloc_preg (cfg);
+                       add_reg = alloc_preg (cfg);
                        array_reg = sp [0]->dreg;
                        index_reg = sp [1]->dreg;
 
@@ -6942,8 +7410,8 @@
                        /* FIXME: Add back the LDELEMA(reg,OP_ICONST) 
optimization */
                        /* FIXME: Add arch specific optimizations */
 
-                       mult_reg = alloc_dreg (cfg, STACK_PTR);
-                       add_reg = alloc_dreg (cfg, STACK_PTR);
+                       mult_reg = alloc_preg (cfg);
+                       add_reg = alloc_preg (cfg);
                        array_reg = sp [0]->dreg;
                        index_reg = sp [1]->dreg;
                        val_reg = sp [2]->dreg;
@@ -7092,6 +7560,7 @@
                        ip += 5;
                        break;
                }
+#endif
                case CEE_LDTOKEN: {
                        gpointer handle;
                        MonoClass *handle_class;
@@ -7118,13 +7587,15 @@
 
                                vtvar = mono_compile_create_var (cfg, 
&handle_class->byval_arg, OP_LOCAL); 
 
-                               NEW_IMAGECONST (cfg, iargs [0], image);
-                               NEW_ICONST (cfg, iargs [1], n);
-                               NEW_PCONST (cfg, iargs [2], generic_context);
-                               temp = mono_emit_jit_icall (cfg, 
mono_ldtoken_wrapper, iargs, ip);
-                               NEW_TEMPLOAD (cfg, res, temp);
-                               NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
-                               NEW_INDSTORE (cfg, store, addr, res, 
&mono_defaults.int_class->byval_arg);
+                               EMIT_NEW_IMAGECONST (cfg, iargs [0], image);
+                               EMIT_NEW_ICONST (cfg, iargs [1], n);
+                               EMIT_NEW_PCONST (cfg, iargs [2], 
generic_context);
+                               ins = mono_emit_jit_icall (cfg, 
mono_ldtoken_wrapper, iargs, ip);
+                               EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
+                               
+                               NOT_IMPLEMENTED;
+
+                               NEW_INDSTORE (cfg, store, addr, ins->dreg, 
&mono_defaults.int_class->byval_arg);
                                MONO_ADD_INS (bblock, store);
                                NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
                        } else {
@@ -7134,9 +7605,9 @@
                                        MonoClass *tclass = 
mono_class_from_mono_type (handle);
                                        mono_class_init (tclass);
                                        if (cfg->compile_aot)
-                                               NEW_TYPE_FROM_HANDLE_CONST 
(cfg, ins, image, n);
+                                               EMIT_NEW_TYPE_FROM_HANDLE_CONST 
(cfg, ins, image, n);
                                        else
-                                               NEW_PCONST (cfg, ins, 
mono_type_get_object (cfg->domain, handle));
+                                               EMIT_NEW_PCONST (cfg, ins, 
mono_type_get_object (cfg->domain, handle));
                                        ins->type = STACK_OBJ;
                                        ins->klass = cmethod->klass;
                                        ip += 5;
@@ -7144,13 +7615,15 @@
                                        MonoInst *store, *addr, *vtvar;
 
                                        if (cfg->compile_aot)
-                                               NEW_LDTOKENCONST (cfg, ins, 
image, n);
+                                               EMIT_NEW_LDTOKENCONST (cfg, 
ins, image, n);
                                        else
-                                               NEW_PCONST (cfg, ins, handle);
+                                               EMIT_NEW_PCONST (cfg, ins, 
handle);
                                        vtvar = mono_compile_create_var (cfg, 
&handle_class->byval_arg, OP_LOCAL);
-                                       NEW_TEMPLOADA (cfg, addr, 
vtvar->inst_c0);
-                                       NEW_INDSTORE (cfg, store, addr, ins, 
&mono_defaults.int_class->byval_arg);
-                                       MONO_ADD_INS (bblock, store);
+                                       EMIT_NEW_TEMPLOADA (cfg, addr, 
vtvar->inst_c0);
+
+                                       NOT_IMPLEMENTED;
+
+                                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, 
OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
                                        NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
                                }
                        }
@@ -7159,6 +7632,7 @@
                        ip += 5;
                        break;
                }
+#if 0
                case CEE_THROW:
                        CHECK_STACK (1);
                        MONO_INST_NEW (cfg, ins, *ip);
@@ -7525,10 +7999,8 @@
                                ip += 2;
                                break;
                        }
-#if 0
                        case CEE_LDFTN: {
                                MonoInst *argconst;
-                               int temp;
 
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
@@ -7544,18 +8016,18 @@
 
                                handle_loaded_temps (cfg, stack_start, sp);
 
-                               NEW_METHODCONST (cfg, argconst, cmethod);
+                               EMIT_NEW_METHODCONST (cfg, argconst, cmethod);
                                if (method->wrapper_type != 
MONO_WRAPPER_SYNCHRONIZED)
-                                       temp = mono_emit_jit_icall (cfg, 
mono_ldftn, &argconst, ip);
+                                       ins = mono_emit_jit_icall (cfg, 
mono_ldftn, &argconst, ip);
                                else
-                                       temp = mono_emit_jit_icall (cfg, 
mono_ldftn_nosync, &argconst, ip);
-                               NEW_TEMPLOAD (cfg, *sp, temp);
-                               sp ++;
+                                       ins = mono_emit_jit_icall (cfg, 
mono_ldftn_nosync, &argconst, ip);
+                               *sp++ = ins;
                                
                                ip += 6;
                                inline_costs += 10 * num_calls++;
                                break;
                        }
+#if 0
                        case CEE_LDVIRTFTN: {
                                MonoInst *args [2];
                                int temp;
@@ -8130,18 +8602,6 @@
        return -1;
 }
 
-G_GNUC_UNUSED
-static void
-mono_print_bb_code_new (MonoBasicBlock *bb) {
-       if (bb->code) {
-               MonoInst *c = bb->code;
-               while (c) {
-                       mono_print_ins (c);
-                       c = c->next;
-               }
-       }
-}
-
 #ifdef MINI_OP
 #undef MINI_OP
 #endif

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini-ops.h
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini-ops.h    2005-12-08 
18:17:48 UTC (rev 54118)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini-ops.h    2005-12-08 
20:40:11 UTC (rev 54119)
@@ -559,7 +559,7 @@
 MINI_OP(OP_X86_PUSH_IMM,           "x86_push_imm", NONE, NONE, NONE)
 MINI_OP(OP_X86_PUSH,               "x86_push", NONE, IREG, NONE)
 MINI_OP(OP_X86_PUSH_FP,            "x86_push_fp", NONE, NONE, NONE)
-MINI_OP(OP_X86_PUSH_OBJ,           "x86_push_obj", NONE, NONE, NONE)
+MINI_OP(OP_X86_PUSH_OBJ,           "x86_push_obj", NONE, IREG, NONE)
 MINI_OP(OP_X86_PUSH_GOT_ENTRY,     "x86_push_got_entry", NONE, NONE, NONE)
 MINI_OP(OP_X86_LEA,                "x86_lea", NONE, NONE, NONE)
 MINI_OP(OP_X86_LEA_MEMBASE,        "x86_lea_membase", NONE, NONE, NONE)

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini-x86.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini-x86.c    2005-12-08 
18:17:48 UTC (rev 54118)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini-x86.c    2005-12-08 
20:40:11 UTC (rev 54119)
@@ -1094,6 +1094,7 @@
                                arg->opcode = OP_X86_PUSH_OBJ;
                                arg->inst_basereg = in->dreg;
                                arg->inst_offset = 0;
+                               arg->inst_imm = size;
                                        
                                MONO_ADD_INS (cfg->cbb, arg);
                        }

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to