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; } } }
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; } } }
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); } }