static gboolean lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr) { MonoInst *var = (MonoInst *)ldaddr->inst_p0; MonoType *type = &var->klass->byval_arg; int replaced_op = mono_type_to_store_membase (cfg, type); if (store->opcode == OP_STOREV_MEMBASE && store->klass != var->klass) { if (cfg->verbose_level > 2) printf ("Incompatible store_vtype classes %s x %s\n", store->klass->name, store->klass->name); return FALSE; } if (replaced_op != store->opcode) { if (cfg->verbose_level > 2) printf ("Incompatible store_reg type: expected %s but got %s\n", mono_inst_name (replaced_op), mono_inst_name (store->opcode)); return FALSE; } else { if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); } } store->opcode = mono_type_to_regmove (cfg, type); type_to_eval_stack_type (cfg, type, store); store->dreg = var->dreg; mono_jit_stats.stores_eliminated++; return TRUE; }
static gboolean lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr) { MonoInst *var = (MonoInst *)ldaddr->inst_p0; MonoType *type = &var->klass->byval_arg; int replaced_op = mono_type_to_load_membase (cfg, type); if (load->opcode == OP_LOADV_MEMBASE && load->klass != var->klass) { if (cfg->verbose_level > 2) printf ("Incompatible load_vtype classes %s x %s\n", load->klass->name, var->klass->name); return FALSE; } if (replaced_op != load->opcode) { if (cfg->verbose_level > 2) printf ("Incompatible load type: expected %s but got %s\n", mono_inst_name (replaced_op), mono_inst_name (load->opcode)); return FALSE; } else { if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (load); } } load->opcode = mono_type_to_regmove (cfg, type); type_to_eval_stack_type (cfg, type, load); load->sreg1 = var->dreg; mono_jit_stats.loads_eliminated++; return TRUE; }
static void add_pool_entry (MonoCompile *cfg, ConstantPoolEntry *entry) { int *cp_id= (int *) mono_mempool_alloc0 (cfg->mempool, sizeof (int)); *cp_id = cfg->gdump_ctx->next_cp_id; g_hash_table_insert (cfg->gdump_ctx->constant_pool, entry, cp_id); write_byte (cfg, POOL_NEW); write_short (cfg, cfg->gdump_ctx->next_cp_id++); switch (entry->pt) { case PT_STRING: write_byte (cfg, POOL_STRING); write_string (cfg, (char *) entry->data); break; case PT_METHOD: { MonoMethod *method = (MonoMethod *) entry->data; write_byte (cfg, POOL_METHOD); write_pool (cfg, create_cp_entry (cfg, (void *) method->klass, PT_KLASS)); write_pool (cfg, create_cp_entry (cfg, (void *) method->name, PT_STRING)); write_pool (cfg, create_cp_entry (cfg, (void *) method->signature, PT_SIGNATURE)); write_int (cfg, (int) method->flags); write_int (cfg, -1); // don't transmit bytecode. break; } case PT_KLASS: { MonoClass *klass = (MonoClass *) entry->data; write_byte (cfg, POOL_KLASS); write_string (cfg, m_class_get_name (klass)); write_byte (cfg, KLASS); break; } case PT_SIGNATURE: { write_byte (cfg, POOL_SIGNATURE); MonoMethodSignature *sig = (MonoMethodSignature *) entry->data; write_short (cfg, sig->param_count); for (int i = 0; i < sig->param_count; i++) { GString *sbuf = g_string_new (NULL); mono_type_get_desc (sbuf, sig->params [i], TRUE); write_pool (cfg, create_cp_entry (cfg, (void *) sbuf->str, PT_STRING)); g_string_free (sbuf, TRUE); } GString *sbuf = g_string_new (NULL); mono_type_get_desc (sbuf, sig->ret, TRUE); write_pool (cfg, create_cp_entry (cfg, (void *) sbuf->str, PT_STRING)); g_string_free (sbuf, TRUE); break; } case PT_OPTYPE: { MonoInst *insn = (MonoInst *) entry->data; write_byte (cfg, POOL_NODE_CLASS); write_string (cfg, mono_inst_name (insn->opcode)); GString *insndesc = mono_print_ins_index_strbuf (-1, insn); int len = strnlen (insndesc->str, 0x2000); #define CUTOFF 40 if (len > CUTOFF) { insndesc->str[CUTOFF] = '\0'; insndesc->str[CUTOFF - 1] = '.'; insndesc->str[CUTOFF - 2] = '.'; } write_string (cfg, insndesc->str); if (len > CUTOFF) insndesc->str[CUTOFF] = ' '; g_string_free (insndesc, TRUE); // one predecessor write_short (cfg, 1); write_byte (cfg, 0); write_pool (cfg, create_cp_entry (cfg, (void *) "predecessor", PT_STRING)); write_pool (cfg, create_cp_entry (cfg, (void *) NULL, PT_INPUTTYPE)); // make NUM_SUCCESSOR successor edges, not everyone will be used. #define NUM_SUCCESSOR 5 write_short (cfg, NUM_SUCCESSOR); for (int i = 0; i < NUM_SUCCESSOR; i++) { char *str = g_strdup ("successor1"); str[9] = '0' + i; write_byte (cfg, 0); write_pool (cfg, create_cp_entry (cfg, (void *) str, PT_STRING)); } break; } case PT_INPUTTYPE: { write_byte (cfg, POOL_ENUM); write_pool (cfg, create_cp_entry (cfg, (void *) NULL, PT_ENUMKLASS)); write_int (cfg, 0); break; } case PT_ENUMKLASS: { write_byte (cfg, POOL_KLASS); write_string (cfg, "InputType"); write_byte (cfg, ENUM_KLASS); write_int (cfg, 1); write_pool (cfg, create_cp_entry (cfg, (void *) "fixed", PT_STRING)); break; } } }
static void mono_print_label (FILE *fp, MonoInst *tree) { int arity; if (!tree) return; arity = mono_burg_arity [tree->opcode]; fprintf (fp, "\\ %s%s", arity? "(": "", mono_inst_name (tree->opcode)); switch (tree->opcode) { case OP_ICONST: fprintf (fp, "[%ld]", (long)tree->inst_c0); break; case OP_I8CONST: fprintf (fp, "[%lld]", (long long)tree->inst_l); break; case OP_R8CONST: fprintf (fp, "[%f]", *(double*)tree->inst_p0); break; case OP_R4CONST: fprintf (fp, "[%f]", *(float*)tree->inst_p0); break; case OP_ARG: case OP_LOCAL: fprintf (fp, "[%d]", (int)tree->inst_c0); break; case OP_REGOFFSET: fprintf (fp, "[0x%x(%s)]", (int)tree->inst_offset, mono_arch_regname (tree->inst_basereg)); break; case OP_REGVAR: fprintf (fp, "[%s]", mono_arch_regname (tree->dreg)); break; case CEE_NEWARR: fprintf (fp, "[%s]", tree->inst_newa_class->name); mono_print_label (fp, tree->inst_newa_len); break; case OP_CALL: case OP_CALL_MEMBASE: case OP_FCALL: case OP_FCALL_MEMBASE: case OP_LCALL: case OP_LCALL_MEMBASE: case OP_VCALL: case OP_VCALL_MEMBASE: case OP_VOIDCALL: case OP_VOIDCALL_MEMBASE: { MonoCallInst *call = (MonoCallInst*)tree; if (call->method) { if (mono_method_signature (call->method)->hasthis && tree->inst_left) { mono_print_label (fp, tree->inst_left); } fprintf (fp, "[%s]", call->method->name); } break; } case OP_PHI: { int i; fprintf (fp, "[%d\\ (", (int)tree->inst_c0); for (i = 0; i < tree->inst_phi_args [0]; i++) { if (i) fprintf (fp, ",\\ "); fprintf (fp, "%d", tree->inst_phi_args [i + 1]); } fprintf (fp, ")]"); break; } case OP_NOP: case OP_JMP: case OP_BREAK: break; case OP_BR: fprintf (fp, "[B%d]", tree->inst_target_bb->block_num); break; case OP_SWITCH: case CEE_ISINST: case CEE_CASTCLASS: case OP_CALL_REG: case OP_FCALL_REG: case OP_LCALL_REG: case OP_VCALL_REG: case OP_VOIDCALL_REG: mono_print_label (fp, tree->inst_left); break; case CEE_BNE_UN: case CEE_BEQ: case CEE_BLT: case CEE_BLT_UN: case CEE_BGT: case CEE_BGT_UN: case CEE_BGE: case CEE_BGE_UN: case CEE_BLE: case CEE_BLE_UN: fprintf (fp, "[B%dB%d]", tree->inst_true_bb->block_num, tree->inst_false_bb->block_num); mono_print_label (fp, tree->inst_left); break; default: if (arity) { mono_print_label (fp, tree->inst_left); if (arity > 1) mono_print_label (fp, tree->inst_right); } break; } if (arity) fprintf (fp, ")"); }