Example #1
0
static void
replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) {
	MonoInst *ins;

#if defined(__native_client_codegen__)
	/* Need to maintain this flag for the new block because */
	/* we can't jump indirectly to a non-aligned block.     */
	if (orig->flags & BB_INDIRECT_JUMP_TARGET)
	{
		repl->flags |= BB_INDIRECT_JUMP_TARGET;
	}
#endif
	
	for (ins = bb->code; ins != NULL; ins = ins->next) {
		switch (ins->opcode) {
		case OP_BR:
			if (ins->inst_target_bb == orig)
				ins->inst_target_bb = repl;
			break;
		case OP_CALL_HANDLER:
			if (ins->inst_target_bb == orig)
				ins->inst_target_bb = repl;
			break;
		case OP_SWITCH: {
			int i;
			int n = GPOINTER_TO_INT (ins->klass);
			for (i = 0; i < n; i++ ) {
				if (ins->inst_many_bb [i] == orig)
					ins->inst_many_bb [i] = repl;
			}
			break;
		}
		default:
			if (MONO_IS_COND_BRANCH_OP (ins)) {
				if (ins->inst_true_bb == orig)
					ins->inst_true_bb = repl;
				if (ins->inst_false_bb == orig)
					ins->inst_false_bb = repl;
			} else if (MONO_IS_JUMP_TABLE (ins)) {
				int i;
				MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (ins);
				for (i = 0; i < table->table_size; i++ ) {
					if (table->table [i] == orig)
						table->table [i] = repl;
				}
			}

			break;
		}
	}
}
Example #2
0
static void
replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) {
	MonoInst *ins;
	
	for (ins = bb->code; ins != NULL; ins = ins->next) {
		switch (ins->opcode) {
		case OP_BR:
			if (ins->inst_target_bb == orig)
				ins->inst_target_bb = repl;
			break;
		case OP_CALL_HANDLER:
			if (ins->inst_target_bb == orig)
				ins->inst_target_bb = repl;
			break;
		case OP_SWITCH: {
			int i;
			int n = GPOINTER_TO_INT (ins->klass);
			for (i = 0; i < n; i++ ) {
				if (ins->inst_many_bb [i] == orig)
					ins->inst_many_bb [i] = repl;
			}
			break;
		}
		default:
			if (MONO_IS_COND_BRANCH_OP (ins)) {
				if (ins->inst_true_bb == orig)
					ins->inst_true_bb = repl;
				if (ins->inst_false_bb == orig)
					ins->inst_false_bb = repl;
			} else if (MONO_IS_JUMP_TABLE (ins)) {
				int i;
				MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (ins);
				for (i = 0; i < table->table_size; i++ ) {
					if (table->table [i] == orig)
						table->table [i] = repl;
				}
			}

			break;
		}
	}
}
Example #3
0
void
mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *bbn) 
{
	MonoInst *inst;
	MonoBasicBlock *prev_bb;
	int i;

	bb->has_array_access |= bbn->has_array_access;
	bb->extended |= bbn->extended;

	mono_unlink_bblock (cfg, bb, bbn);
	for (i = 0; i < bbn->out_count; ++i)
		mono_link_bblock (cfg, bb, bbn->out_bb [i]);
	while (bbn->out_count)
		mono_unlink_bblock (cfg, bbn, bbn->out_bb [0]);

	/* Handle the branch at the end of the bb */
	if (bb->has_call_handler) {
		for (inst = bb->code; inst != NULL; inst = inst->next) {
			if (inst->opcode == OP_CALL_HANDLER) {
				g_assert (inst->inst_target_bb == bbn);
				NULLIFY_INS (inst);
			}
		}
	}
	if (bb->has_jump_table) {
		for (inst = bb->code; inst != NULL; inst = inst->next) {
			if (MONO_IS_JUMP_TABLE (inst)) {
				int i;
				MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (inst);
				for (i = 0; i < table->table_size; i++ ) {
					/* Might be already NULL from a previous merge */
					if (table->table [i])
						g_assert (table->table [i] == bbn);
					table->table [i] = NULL;
				}
				/* Can't nullify this as later instructions depend on it */
			}
		}
	}
	if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins)) {
		g_assert (bb->last_ins->inst_false_bb == bbn);
		bb->last_ins->inst_false_bb = NULL;
		bb->extended = TRUE;
	} else if (bb->last_ins && MONO_IS_BRANCH_OP (bb->last_ins)) {
		NULLIFY_INS (bb->last_ins);
	}

	bb->has_call_handler |= bbn->has_call_handler;
	bb->has_jump_table |= bbn->has_jump_table;

	if (bb->last_ins) {
		if (bbn->code) {
			bb->last_ins->next = bbn->code;
			bbn->code->prev = bb->last_ins;
			bb->last_ins = bbn->last_ins;
		}
	} else {
		bb->code = bbn->code;
		bb->last_ins = bbn->last_ins;
	}

	for (prev_bb = cfg->bb_entry; prev_bb && prev_bb->next_bb != bbn; prev_bb = prev_bb->next_bb)
		;
	if (prev_bb) {
		prev_bb->next_bb = bbn->next_bb;
	} else {
		/* bbn might not be in the bb list yet */
		if (bb->next_bb == bbn)
			bb->next_bb = bbn->next_bb;
	}
	mono_nullify_basic_block (bbn);

	/* 
	 * If bbn fell through to its next bblock, have to add a branch, since bb
	 * will not fall though to the same bblock (#513931).
	 */
	if (bb->last_ins && bb->out_count == 1 && bb->out_bb [0] != bb->next_bb && !MONO_IS_BRANCH_OP (bb->last_ins)) {
		MONO_INST_NEW (cfg, inst, OP_BR);
		inst->inst_target_bb = bb->out_bb [0];
		MONO_ADD_INS (bb, inst);
	}
}