*/
static int
handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int count) {
- int i;
+ int i, bindex;
MonoBasicBlock *outb;
MonoInst *inst, **locals;
+ gboolean found;
if (!count)
return 0;
if (cfg->verbose_level > 3)
g_print ("%d item(s) on exit from B%d\n", count, bb->block_num);
if (!bb->out_scount) {
- int found = 0;
bb->out_scount = count;
//g_print ("bblock %d has out:", bb->block_num);
+ found = FALSE;
for (i = 0; i < bb->out_count; ++i) {
outb = bb->out_bb [i];
//g_print (" %d", outb->block_num);
if (outb->in_stack) {
- found = 1;
+ found = TRUE;
bb->out_stack = outb->in_stack;
break;
}
if (!found) {
bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count);
for (i = 0; i < count; ++i) {
-/* see bug#58863, but removing this code causes regressions in gtk-sharp build
- * (SEGV running Method::Initialize() in gapi_codegen.exe)
- */
-#if 1
- /* try to reuse temps already allocated for this purpouse, if they occupy the same
- * stack slot and if they are of the same type. */
- bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
-#else
- bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
-#endif
+ /*
+ * try to reuse temps already allocated for this purpouse, if they occupy the same
+ * stack slot and if they are of the same type.
+ * This won't cause conflicts since if 'local' is used to
+ * store one of the values in the in_stack of a bblock, then
+ * the same variable will be used for the same outgoing stack
+ * slot as well.
+ * This doesn't work when inlining methods, since the bblocks
+ * in the inlined methods do not inherit their in_stack from
+ * the bblock they are inlined to. See bug #58863 for an
+ * example.
+ */
+ if (cfg->inlined_method)
+ bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
+ else
+ bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
}
}
}
+
+ for (i = 0; i < bb->out_count; ++i) {
+ outb = bb->out_bb [i];
+ if (outb->in_scount)
+ continue; /* check they are the same locals */
+ outb->in_scount = count;
+ outb->in_stack = bb->out_stack;
+ }
+
locals = bb->out_stack;
for (i = 0; i < count; ++i) {
/* add store ops at the end of the bb, before the branch */
if (cfg->verbose_level > 3)
g_print ("storing %d to temp %d\n", i, locals [i]->inst_c0);
}
-
- for (i = 0; i < bb->out_count; ++i) {
- outb = bb->out_bb [i];
- if (outb->in_scount)
- continue; /* check they are the same locals */
- outb->in_scount = count;
- outb->in_stack = locals;
+
+ /*
+ * It is possible that the out bblocks already have in_stack assigned, and
+ * the in_stacks differ. In this case, we will store to all the different
+ * in_stacks.
+ */
+
+ found = TRUE;
+ bindex = 0;
+ while (found) {
+ /* Find a bblock which has a different in_stack */
+ found = FALSE;
+ while (bindex < bb->out_count) {
+ outb = bb->out_bb [bindex];
+ if (outb->in_stack != locals) {
+ /*
+ * Instead of storing sp [i] to locals [i], we need to store
+ * locals [i] to <new locals>[i], since the sp [i] tree can't
+ * be shared between trees.
+ */
+ for (i = 0; i < count; ++i)
+ mono_add_varcopy_to_end (cfg, bb, locals [i]->inst_c0, outb->in_stack [i]->inst_c0);
+ locals = outb->in_stack;
+ found = TRUE;
+ break;
+ }
+ bindex ++;
+ }
}
+
return 0;
}
* We have the `constrained.' prefix opcode.
*/
if (constrained_call->valuetype && !cmethod->klass->valuetype) {
+ MonoInst *load;
/*
* The type parameter is instantiated as a valuetype,
* but that type doesn't override the method we're
* calling, so we need to box `this'.
+ * sp [0] is a pointer to the data: we need the value
+ * in handle_box (), so load it here.
*/
- sp [0] = handle_box (cfg, bblock, sp [0], ip, constrained_call);
+ MONO_INST_NEW (cfg, load, mono_type_to_ldind (&constrained_call->byval_arg));
+ type_to_eval_stack_type (&constrained_call->byval_arg, load);
+ load->cil_code = ip;
+ load->inst_left = sp [0];
+ sp [0] = handle_box (cfg, bblock, load, ip, constrained_call);
} else if (!constrained_call->valuetype) {
MonoInst *ins;
klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoMethod* helper = mono_marshal_get_stelemref ();
MonoInst *iargs [3];
handle_loaded_temps (cfg, bblock, stack_start, sp);
iargs [2] = sp [2];
iargs [1] = sp [1];
iargs [0] = sp [0];
-
- mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+
+ mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
} else {
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
}
case CEE_STELEM_REF: {
MonoInst *iargs [3];
+ MonoMethod* helper = mono_marshal_get_stelemref ();
CHECK_STACK (3);
sp -= 3;
iargs [1] = sp [1];
iargs [0] = sp [0];
- mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+ mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
/*
MonoInst *group;
for (i = 0; i < cfg->num_bblocks; ++i) {
bb = cfg->bblocks [i];
- if (bb->cil_code) {
+ /*if (bb->cil_code) {
char* code1, *code2;
code1 = mono_disasm_code_one (NULL, cfg->method, bb->cil_code, NULL);
if (bb->last_ins->cil_code)
code = g_strdup_printf ("%s -> %s", code1, code2);
g_free (code1);
g_free (code2);
- } else
+ } else*/
code = g_strdup ("\n");
g_print ("\nBB%d DFN%d (len: %d): %s", bb->block_num, i, bb->cil_length, code);
if (bb->code) {