[llvm] Load rgctx/imt arguments using a volatile load on arm to prevent LLVM from...
[mono.git] / mono / mini / decompose.c
index 2beeb9e59d57475fa500935d05262777fd834b91..88097b2257897627e388ca8babc88c40cddb2a88 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef DISABLE_JIT
 
 /* FIXME: This conflicts with the definition in mini.c, so it cannot be moved to mini.h */
-MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
+MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
 void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
 void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
 
@@ -1361,6 +1361,71 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
        }
 }
 
+void
+mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
+{
+       MonoBasicBlock *bb, *first_bb;
+
+       /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
+
+       cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+       first_bb = cfg->cbb;
+
+       for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+               MonoInst *ins;
+               MonoInst *prev = NULL;
+               MonoInst *src_var, *src, *dest;
+               gboolean restart;
+               int dreg;
+
+               if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
+
+               cfg->cbb->code = cfg->cbb->last_ins = NULL;
+               restart = TRUE;
+
+               while (restart) {
+                       restart = FALSE;
+
+                       for (ins = bb->code; ins; ins = ins->next) {
+                               switch (ins->opcode) {
+                               case OP_STOREV_MEMBASE: {
+                                       src_var = get_vreg_to_inst (cfg, ins->sreg1);
+
+                                       if (!src_var) {
+                                               g_assert (ins->klass);
+                                               src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
+                                       }
+
+                                       EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
+
+                                       dreg = alloc_preg (cfg);
+                                       EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
+                                       mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
+                                       break;
+                               }
+                               default:
+                                       break;
+                               }
+
+                               g_assert (cfg->cbb == first_bb);
+
+                               if (cfg->cbb->code || (cfg->cbb != first_bb)) {
+                                       /* Replace the original instruction with the new code sequence */
+
+                                       mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
+                                       first_bb->code = first_bb->last_ins = NULL;
+                                       first_bb->in_count = first_bb->out_count = 0;
+                                       cfg->cbb = first_bb;
+                               }
+                               else
+                                       prev = ins;
+                       }
+               }
+
+               if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
+       }
+}
+
 inline static MonoInst *
 mono_get_domainvar (MonoCompile *cfg)
 {
@@ -1413,7 +1478,7 @@ mono_decompose_array_access_opts (MonoCompile *cfg)
                                switch (ins->opcode) {
                                case OP_LDLEN:
                                        NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
-                                                                                       G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_CONSTANT_LOAD);
+                                                                                       G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
                                        MONO_ADD_INS (cfg->cbb, dest);
                                        break;
                                case OP_BOUNDS_CHECK:
@@ -1452,7 +1517,7 @@ mono_decompose_array_access_opts (MonoCompile *cfg)
                                        break;
                                case OP_STRLEN:
                                        MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
-                                                                                                                ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_CONSTANT_LOAD);
+                                                                                                                ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
                                        break;
                                default:
                                        break;