📄 main.cc
字号:
start_bj = (in_bj *)(start_instr); delete jumpto_info; tree_node *jumpto_lab_node = jumpto_lab_instr->owner(); tree_node_list_e *follow_back = jumpto_lab_node->list_e()->prev(); assert(follow_back != NULL); while (follow_back->contents->is_instr()) { tree_instr *back_tree_instr = (tree_instr *)(follow_back->contents); instruction *back_instr = back_tree_instr->instr(); if (back_instr->opcode() != io_mrk) break; follow_back = follow_back->prev(); assert(follow_back != NULL); destroy_node(back_tree_instr); } assert(follow_back->contents->is_instr()); tree_instr *goto_node = (tree_instr *)(follow_back->contents); instruction *goto_instr = goto_node->instr(); assert(goto_instr->opcode() == io_jmp); in_bj *goto_bj = (in_bj *)(goto_instr); end_label_instr = split_out(end_label_instr, goto_bj); end_node = end_label_instr->owner(); move_nodes(jumpto_lab_node, end_node, new_else); destroy_node(goto_node); destroy_node(jumpto_lab_node); force_same_list(start_bj->owner(), end_node); } else { start_bj = (in_bj *)(the_info->start_instr); end_label_instr = split_out(end_label_instr, start_bj); jumpto_sym = start_bj->target(); end_node = end_label_instr->owner(); } tree_node *start_node = start_bj->owner(); move_nodes(start_node, end_node, new_then); destroy_node(end_node); tree_if *new_if = new tree_if(jumpto_sym, new_header, new_then, new_else); tree_node_list_e *start_e = start_node->list_e(); parent_list->insert_after(new_if, start_e); parent_list->remove(start_e); new_header->append(start_e); remove_label_info(new_then); remove_label_info(new_else); }static void build_do(arc_info *the_info) { assert(!the_info->broken); assert(the_info->start_instr->opcode() == io_lab); assert(the_info->end_instr != NULL); assert((the_info->end_instr->opcode() == io_btrue) || (the_info->end_instr->opcode() == io_bfalse) || (the_info->end_instr->opcode() == io_jmp)); in_lab *top_label_instr = (in_lab *)(the_info->start_instr); in_bj *bottom_branch = (in_bj *)(the_info->end_instr); tree_node *bottom_node = bottom_branch->owner(); top_label_instr = split_out(top_label_instr, bottom_branch); tree_node *top_node = top_label_instr->owner(); tree_node_list *parent_list = top_node->parent(); label_sym *top_label_sym = top_label_instr->label(); assert(bottom_branch->target() == top_label_sym); base_symtab *base_scope = top_node->scope(); assert(base_scope->is_block()); block_symtab *block_scope = (block_symtab *)base_scope; tree_node_list_e *new_top_e = top_node->list_e()->next(); assert(new_top_e != NULL); destroy_node(top_node); top_node = new_top_e->contents; tree_node_list *new_body = new tree_node_list; tree_node_list *new_test = new tree_node_list; label_sym *continue_lab = block_scope->new_unique_label(); label_sym *break_lab = block_scope->new_unique_label(); tree_loop *new_loop = new tree_loop(new_body, new_test, continue_lab, break_lab, top_label_sym); parent_list->insert_before(new_loop, new_top_e); while (top_node != bottom_node) { tree_node_list_e *this_e = top_node->list_e(); tree_node_list_e *next_e = this_e->next(); assert(next_e != NULL); parent_list->remove(this_e); new_body->append(this_e); top_node = next_e->contents; } tree_node_list_e *bottom_e = bottom_node->list_e(); parent_list->remove(bottom_e); new_test->append(bottom_e); remove_label_info(new_body); }static in_lab *split_out(in_lab *target, in_bj *focus) { label_sym *lab_sym = target->label(); assert(lab_sym == focus->target()); force_same_list(target->owner(), focus->owner()); label_info *lab_info = get_lab_info(lab_sym); if (lab_info->backward_jumps.count() + lab_info->forward_jumps.count() == 1) { delete lab_info; return target; } tree_node *target_node = target->owner(); tree_node_list *parent_list = target_node->parent(); base_symtab *base_scope = target_node->scope(); assert(base_scope->is_block()); block_symtab *block_scope = (block_symtab *)base_scope; label_sym *new_lab_sym = block_scope->new_unique_label(lab_sym->name()); focus->set_target(new_lab_sym); in_lab *new_target = new in_lab(new_lab_sym); tree_instr *new_target_node = new tree_instr(new_target); if ((lab_info->forward_jumps.is_empty() && (lab_info->backward_jumps.tail()->contents == focus)) || ((!lab_info->forward_jumps.is_empty()) && (lab_info->forward_jumps.tail()->contents == focus))) { if (lab_info->forward_jumps.is_empty()) { instruction_list_e *last_e = lab_info->backward_jumps.tail(); lab_info->backward_jumps.remove(last_e); delete last_e; } else { instruction_list_e *last_e = lab_info->forward_jumps.tail(); lab_info->forward_jumps.remove(last_e); delete last_e; } parent_list->insert_before(new_target_node, target_node->list_e()); return new_target; } if ((lab_info->backward_jumps.is_empty() && (lab_info->forward_jumps.head()->contents == focus)) || ((!lab_info->backward_jumps.is_empty()) && (lab_info->backward_jumps.head()->contents == focus))) { if (lab_info->backward_jumps.is_empty()) lab_info->forward_jumps.pop(); else lab_info->backward_jumps.pop(); parent_list->insert_after(new_target_node, target_node->list_e()); return new_target; } label_sym *new_inner_sym = block_scope->new_unique_label(lab_sym->name()); in_lab *new_inner_target = new in_lab(new_inner_sym); tree_instr *new_inner_node = new tree_instr(new_inner_target); instruction_list_e *follow_forward = lab_info->forward_jumps.head(); while (follow_forward != NULL) { if (follow_forward->contents == focus) { parent_list->insert_before(new_target_node, target_node->list_e()); parent_list->insert_before(new_inner_node, new_target_node->list_e()); create_info_for_new_lab_instr(new_inner_target); rename_inners(&(lab_info->forward_jumps), follow_forward->next(), NULL, new_inner_sym, lab_sym); lab_info->forward_jumps.remove(follow_forward); delete follow_forward; return new_target; } follow_forward = follow_forward->next(); } parent_list->insert_after(new_target_node, target_node->list_e()); parent_list->insert_after(new_inner_node, new_target_node->list_e()); create_info_for_new_lab_instr(new_inner_target); rename_inners(&(lab_info->backward_jumps), lab_info->backward_jumps.head(), focus, new_inner_sym, lab_sym); instruction_list_e *follow_backward = lab_info->backward_jumps.head(); while (TRUE) { assert(follow_backward != NULL); if (follow_backward->contents == focus) break; follow_backward = follow_backward->next(); } lab_info->backward_jumps.remove(follow_backward); delete follow_backward; return new_target; }static void rename_inners(instruction_list *i_list, instruction_list_e *start, instruction *end, label_sym *new_label, label_sym *old_label) { label_info *inner_lab_info = get_lab_info(new_label); instruction_list_e *follow = start; do { instruction *this_instr = follow->contents; if (this_instr == end) return; switch (this_instr->opcode()) { case io_btrue: case io_bfalse: case io_jmp: { in_bj *the_bj = (in_bj *)this_instr; assert(the_bj->target() == old_label); the_bj->set_target(new_label); break; } case io_mbr: { in_mbr *the_mbr = (in_mbr *)this_instr; if (the_mbr->default_lab() == old_label) { the_mbr->set_default_lab(new_label); } else { unsigned num_labs = the_mbr->num_labs(); unsigned lab_num; for (lab_num = 0; lab_num < num_labs; ++lab_num) { if (the_mbr->label(lab_num) == old_label) { the_mbr->set_label(lab_num, new_label); break; } } assert(lab_num < num_labs); } break; } default: assert(FALSE); } instruction_list_e *next_e = follow->next(); i_list->remove(follow); inner_lab_info->backward_jumps.append(follow); follow = next_e; } while (follow != NULL); }static void move_nodes(tree_node *before, tree_node *after, tree_node_list *new_list) { tree_node_list_e *follow = before->list_e()->next(); tree_node_list *old_list = before->parent(); while (TRUE) { assert(follow != NULL); if (follow->contents == after) return; tree_node_list_e *next_e = follow->next(); old_list->remove(follow); new_list->append(follow); follow = next_e; } }static void destroy_node(tree_node *old_node) { tree_node_list *parent_list = old_node->parent(); tree_node_list_e *old_e = old_node->list_e(); parent_list->remove(old_e); delete old_e; delete old_node; }static boolean is_if_else_boundary(in_bj *the_bj, arc_info_list *arc_stack) { if (is_backward_branch(the_bj)) return FALSE; if (the_bj->opcode() != io_jmp) return FALSE; arc_info_list_e *stack_head = arc_stack->head(); if (stack_head == NULL) return FALSE; if (stack_head->contents.broken) return FALSE; instruction *end_instr = stack_head->contents.end_instr; if ((end_instr == NULL) || (end_instr->opcode() != io_lab)) return FALSE; in_lab *else_lab_instr = (in_lab *)end_instr; label_info *else_lab_info = get_lab_info(else_lab_instr->label()); if ((!else_lab_info->backward_jumps.is_empty()) || (else_lab_info->forward_jumps.count() != 1)) { return FALSE; } tree_node_list_e *end_list_e = end_instr->owner()->list_e(); tree_node_list_e *follow_e = the_bj->owner()->list_e()->next(); while (follow_e != end_list_e) { if (follow_e == NULL) return FALSE; tree_node *this_node = follow_e->contents; if (!this_node->is_instr()) return FALSE; tree_instr *this_tree_instr = (tree_instr *)this_node; instruction *this_instr = this_tree_instr->instr(); if (this_instr->opcode() != io_mrk) return FALSE; follow_e = follow_e->next(); } return TRUE; }/* * When we are looking at control flow, we ignore the beginnings and * endings of block scopes, so node1 and node2 might be in different * lists. However, having one in the body of a tree_for, for * example, while the other is not, cannot happen. Another way to * put the same statement is that by dismantling only tree_block * nodes we are guaranteed to be able to get the two nodes on the * same list. So that's what we do here -- we dismantle tree_block * nodes as necessary. */static void force_same_list(tree_node *node1, tree_node *node2) { tree_node_list *parent1 = node1->parent(); tree_node_list *parent2 = node2->parent(); if (parent1 == parent2) return; assert(parent1 != NULL); assert(parent2 != NULL); tree_node *grandparent1 = parent1->parent(); tree_node *grandparent2 = parent2->parent(); assert(grandparent1 != NULL); assert(grandparent2 != NULL); if (!grandparent1->is_block() || grandparent1->is_proc()) { while (node2->parent() != parent1) { tree_node_list *p2 = node2->parent(); assert(p2 != NULL); tree_node *gp2 = p2->parent(); assert(gp2 != NULL); assert(gp2->is_block() && !gp2->is_proc()); dismantle(gp2); } } else if (!grandparent2->is_block() || grandparent2->is_proc()) { while (node1->parent() != parent2) { tree_node_list *p1 = node1->parent(); assert(p1 != NULL); tree_node *gp1 = p1->parent(); assert(gp1 != NULL); assert(gp1->is_block() && !gp1->is_proc()); dismantle(gp1); } } else { tree_block *gptb1 = (tree_block *)grandparent1; tree_block *gptb2 = (tree_block *)grandparent2; base_symtab *nearest_symtab = common_symtab(gptb1->symtab(), gptb2->symtab()); assert(nearest_symtab->is_block()); block_symtab *nearest_block_symtab = (block_symtab *)nearest_symtab; tree_block *nearest_block = nearest_block_symtab->block(); tree_node_list *target_list = nearest_block->body(); while (node1->parent() != target_list) { tree_node_list *p1 = node1->parent(); assert(p1 != NULL); tree_node *gp1 = p1->parent(); assert(gp1 != NULL); assert(gp1->is_block() && !gp1->is_proc()); dismantle(gp1); } while (node2->parent() != target_list) { tree_node_list *p2 = node2->parent(); assert(p2 != NULL); tree_node *gp2 = p2->parent(); assert(gp2 != NULL); assert(gp2->is_block() && !gp2->is_proc()); dismantle(gp2); } } }/*----------------------------------------------------------------------* End Private Function Implementations *----------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -