Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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, ")");
}