2010-02-10 Geoff Norton <gnorton@novell.com>
[mono.git] / mono / mini / ir-emit.h
old mode 100644 (file)
new mode 100755 (executable)
index 7d85305..83bab8d
@@ -135,6 +135,15 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
         (dest)->type = STACK_I4; \
        } while (0)
 
+#define NEW_LOAD_MEMBASE_FLAGS(cfg,dest,op,dr,base,offset,ins_flags) do {      \
+        MONO_INST_NEW ((cfg), (dest), (op)); \
+        (dest)->dreg = (dr); \
+        (dest)->inst_basereg = (base); \
+        (dest)->inst_offset = (offset); \
+        (dest)->type = STACK_I4; \
+               (dest)->flags = (ins_flags); \
+       } while (0)
+
 #define NEW_LOAD_MEM(cfg,dest,op,dr,mem) do { \
         MONO_INST_NEW ((cfg), (dest), (op)); \
         (dest)->dreg = (dr); \
@@ -359,6 +368,12 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
         (dest)->klass = mono_class_from_mono_type (ltype); \
        } while (0)
 
+#define NEW_SEQ_POINT(cfg,dest,il_offset,ss_loc) do {   \
+       MONO_INST_NEW ((cfg), (dest), OP_SEQ_POINT); \
+       (dest)->inst_imm = (il_offset); \
+       (dest)->flags = ss_loc ? MONO_INST_SINGLE_STEP_LOC : 0; \
+       } while (0)
+
 /*
  * Variants which do an emit as well.
  */
@@ -411,7 +426,7 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
  */
 
 #define EMIT_NEW_VARLOAD_SFLOAT(cfg,dest,var,vartype) do { \
-        if (!(vartype)->byref && (vartype)->type == MONO_TYPE_R4) { \
+               if (COMPILE_SOFT_FLOAT ((cfg)) && !(vartype)->byref && (vartype)->type == MONO_TYPE_R4) { \
              MonoInst *iargs [1]; \
              EMIT_NEW_VARLOADA (cfg, iargs [0], (var), (vartype)); \
              (dest) = mono_emit_jit_icall (cfg, mono_fload_r4, iargs); \
@@ -421,7 +436,7 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
     } while (0)
 
 #define EMIT_NEW_VARSTORE_SFLOAT(cfg,dest,var,vartype,inst) do {       \
-        if (!(vartype)->byref && (vartype)->type == MONO_TYPE_R4) { \
+               if (COMPILE_SOFT_FLOAT ((cfg)) && !(vartype)->byref && (vartype)->type == MONO_TYPE_R4) { \
              MonoInst *iargs [2]; \
              iargs [0] = (inst); \
              EMIT_NEW_VARLOADA (cfg, iargs [1], (var), (vartype)); \
@@ -576,7 +591,7 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
 
 #define        MONO_EMIT_NEW_ICOMPARE_IMM(cfg,sr1,imm) do { \
         MonoInst *inst; \
-        MONO_INST_NEW ((cfg), (inst), sizeof (void*) == 8 ? OP_ICOMPARE_IMM : OP_COMPARE_IMM); \
+        MONO_INST_NEW ((cfg), (inst), sizeof (mgreg_t) == 8 ? OP_ICOMPARE_IMM : OP_COMPARE_IMM); \
         inst->sreg1 = sr1; \
         inst->inst_imm = (imm);                         \
            MONO_ADD_INS ((cfg)->cbb, inst); \
@@ -593,6 +608,16 @@ alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
 
 #define MONO_EMIT_NEW_LOAD_MEMBASE(cfg,dr,base,offset) MONO_EMIT_NEW_LOAD_MEMBASE_OP ((cfg), (OP_LOAD_MEMBASE), (dr), (base), (offset))
 
+#define MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS(cfg,op,dr,base,offset,ins_flags) do { \
+        MonoInst *inst; \
+        MONO_INST_NEW ((cfg), (inst), (op)); \
+        inst->dreg = dr; \
+        inst->inst_basereg = base; \
+        inst->inst_offset = offset; \
+               inst->flags = (ins_flags); \
+           MONO_ADD_INS (cfg->cbb, inst); \
+    } while (0)
+
 #define MONO_EMIT_NEW_STORE_MEMBASE(cfg,op,base,offset,sr) do { \
         MonoInst *inst; \
         MONO_INST_NEW ((cfg), (inst), (op)); \
@@ -719,6 +744,53 @@ static int ccount = 0;
            (cfg)->cbb = (bblock); \
     } while (0)
 
+/* This marks a place in code where an implicit exception could be thrown */
+#define MONO_EMIT_NEW_IMPLICIT_EXCEPTION(cfg) do { \
+               if (COMPILE_LLVM ((cfg))) {                                                                     \
+                       MONO_EMIT_NEW_UNALU (cfg, OP_IMPLICIT_EXCEPTION, -1, -1);       \
+               } \
+       } while (0)
+
+/* Emit an explicit null check which doesn't depend on SIGSEGV signal handling */
+#define MONO_EMIT_NULL_CHECK(cfg, reg) do { \
+               if (cfg->explicit_null_checks) {                                                          \
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, (reg), 0); \
+                       MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); \
+               } else {                                                                                                                \
+                       MONO_EMIT_NEW_IMPLICIT_EXCEPTION (cfg);                                         \
+               }                                                                                                                               \
+       } while (0)
+
+#define MONO_EMIT_NEW_CHECK_THIS(cfg, sreg) do { \
+       cfg->flags |= MONO_CFG_HAS_CHECK_THIS; \
+       if (cfg->explicit_null_checks) {           \
+               MONO_EMIT_NULL_CHECK (cfg, sreg); \
+       } else {                                                                                                \
+               MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_THIS, -1, sreg); \
+               MONO_EMIT_NEW_IMPLICIT_EXCEPTION (cfg);                         \
+               } \
+       MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, sreg);       \
+       } while (0)
+
+/* A load which can cause a nullref */
+#define NEW_LOAD_MEMBASE_FAULT(cfg,dest,op,dr,base,offset) do { \
+               MONO_EMIT_NULL_CHECK ((cfg), (base));                                                   \
+               NEW_LOAD_MEMBASE_FLAGS ((cfg), (dest), (op), (dr), (base), (offset), MONO_INST_FAULT); \
+       } while (0)
+
+#define EMIT_NEW_LOAD_MEMBASE_FAULT(cfg,dest,op,dr,base,offset) do { \
+               MONO_EMIT_NULL_CHECK ((cfg), (base));                                                   \
+               NEW_LOAD_MEMBASE_FLAGS ((cfg), (dest), (op), (dr), (base), (offset), MONO_INST_FAULT); \
+               MONO_ADD_INS ((cfg)->cbb, (dest)); \
+       } while (0)
+
+#define MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT(cfg,op,dr,base,offset) do { \
+               MONO_EMIT_NULL_CHECK (cfg, base);                                                               \
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS ((cfg), (op), (dr), (base), (offset), MONO_INST_FAULT); \
+       } while (0)
+
+#define MONO_EMIT_NEW_LOAD_MEMBASE_FAULT(cfg,dr,base,offset) MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT ((cfg), (OP_LOAD_MEMBASE), (dr), (base), (offset))
+
 /*Object Model related macros*/
 
 #ifndef MONO_ARCH_EMIT_BOUNDS_CHECK
@@ -737,18 +809,19 @@ static int ccount = 0;
  * index_reg is the vreg holding the index
  */
 #define MONO_EMIT_BOUNDS_CHECK(cfg, array_reg, array_type, array_length_field, index_reg) do { \
-            if (!(cfg->opt & MONO_OPT_ABCREM)) { \
-                MONO_ARCH_EMIT_BOUNDS_CHECK ((cfg), (array_reg), G_STRUCT_OFFSET (array_type, array_length_field), (index_reg)); \
-            } else { \
-                MonoInst *ins; \
-                MONO_INST_NEW ((cfg), ins, OP_BOUNDS_CHECK); \
-                ins->sreg1 = array_reg; \
-                ins->sreg2 = index_reg; \
-                ins->inst_imm = G_STRUCT_OFFSET (array_type, array_length_field); \
-                MONO_ADD_INS ((cfg)->cbb, ins); \
-                           (cfg)->flags |= MONO_CFG_HAS_ARRAY_ACCESS; \
-                (cfg)->cbb->has_array_access = TRUE; \
-            } \
+               if (!(cfg->opt & MONO_OPT_ABCREM)) {                                                    \
+                       MONO_EMIT_NULL_CHECK (cfg, array_reg);                                          \
+                       MONO_ARCH_EMIT_BOUNDS_CHECK ((cfg), (array_reg), G_STRUCT_OFFSET (array_type, array_length_field), (index_reg)); \
+               } else {                                                                                                                \
+                       MonoInst *ins;                                                                                          \
+                       MONO_INST_NEW ((cfg), ins, OP_BOUNDS_CHECK);                            \
+                       ins->sreg1 = array_reg;                                                                         \
+                       ins->sreg2 = index_reg;                                                                         \
+                       ins->inst_imm = G_STRUCT_OFFSET (array_type, array_length_field); \
+                       MONO_ADD_INS ((cfg)->cbb, ins);                                                         \
+                       (cfg)->flags |= MONO_CFG_HAS_ARRAY_ACCESS;                                      \
+                       (cfg)->cbb->has_array_access = TRUE;                                            \
+               }                                                                                                                               \
     } while (0)
 
 G_END_DECLS