📄 genop.cc
字号:
continue; var_sym *the_var = first_destination.symbol(); assert(the_var != NULL); sym_node_list_e *the_list_e = read_once->lookup(the_var); if (the_list_e == NULL) continue; if (!instr_uses_var(second_instr, the_var)) continue; first_instr_node->remove_instr(first_instr); node_list->remove(first_instr_node->list_e()); delete first_instr_node->list_e(); delete first_instr_node; first_instr->set_dst(operand()); operand new_operand(first_instr); if (first_instr->opcode() == io_cpy) { in_rrr *first_rrr = (in_rrr *)first_instr; new_operand = first_rrr->src_op(); new_operand.remove(); delete first_rrr; } replace_operand(second_instr, operand(the_var), new_operand); read_once->remove(the_list_e); delete the_list_e; the_var->parent()->remove_sym(the_var); delete the_var; } }static boolean instr_uses_var(instruction *the_instr, var_sym *the_var) { assert(the_instr != NULL); unsigned num_srcs = the_instr->num_srcs(); for (unsigned src_num = 0; src_num < num_srcs; ++src_num) { operand this_source = the_instr->src_op(src_num); if (this_source == operand(the_var)) return TRUE; if (this_source.is_expr()) { if (instr_uses_var(this_source.instr(), the_var)) return TRUE; } } return FALSE; }static void replace_operand(instruction *the_instr, operand old_operand, operand new_operand) { assert(the_instr != NULL); unsigned num_srcs = the_instr->num_srcs(); for (unsigned src_num = 0; src_num < num_srcs; ++src_num) { operand this_source = the_instr->src_op(src_num); if (this_source == old_operand) { the_instr->set_src_op(src_num, new_operand); return; } if (this_source.is_expr()) replace_operand(this_source.instr(), old_operand, new_operand); } }static void prune_out_reads(sym_node_list *sym_list, instruction *the_instr) { assert(sym_list != NULL); assert(the_instr != NULL); if (sym_list->is_empty()) return; int num_srcs = the_instr->num_srcs(); for (int src_num = 0; src_num < num_srcs; ++src_num) { operand this_op = the_instr->src_op(src_num); if (this_op.is_symbol()) { sym_node *this_symbol = this_op.symbol(); assert(this_symbol != NULL); sym_node_list_e *this_element; sym_node_list_e *next_element = sym_list->head(); while (next_element != NULL) { this_element = next_element; next_element = this_element->next(); sym_node *test_sym = this_element->contents; if (test_sym == this_symbol) { sym_list->remove(this_element); delete this_element; } } if (sym_list->is_empty()) return; } else if (this_op.is_expr()) { instruction *this_instr = this_op.instr(); assert(this_instr != NULL); prune_out_reads(sym_list, this_instr); if (this_instr->opcode() == io_ldc) { in_ldc *this_ldc = (in_ldc *)this_instr; immed value = this_ldc->value(); if (value.is_symbol()) { sym_node_list_e *this_element = sym_list->lookup(value.symbol()); if (this_element != NULL) { sym_list->remove(this_element); delete this_element; } } } } } }static void remove_writes(sym_node_list *sym_list, tree_node_list *node_list) { assert(sym_list != NULL); if (node_list == NULL) return; if (sym_list->is_empty()) return; tree_node_list_iter the_iter(node_list); while (!the_iter.is_empty()) { tree_node *this_node = the_iter.step(); switch (this_node->kind()) { case TREE_INSTR: { tree_instr *this_tree_instr = (tree_instr *)this_node; instruction *this_instr = this_tree_instr->instr(); assert(this_instr != NULL); operand destination = this_instr->dst_op(); if (!destination.is_symbol()) break; sym_node *this_symbol = destination.symbol(); assert(this_symbol != NULL); if (!symbol_in_list(sym_list, this_symbol)) break; eliminate_write(this_tree_instr); break; } case TREE_IF: { tree_if *the_if = (tree_if *)this_node; remove_writes(sym_list, the_if->header()); remove_writes(sym_list, the_if->then_part()); remove_writes(sym_list, the_if->else_part()); break; } default: /* * This should never happen since this function should only be * called on lists of instructions and tree_if's. */ assert(FALSE); } } }static boolean symbol_in_list(sym_node_list *sym_list, sym_node *the_symbol) { return (sym_list->lookup(the_symbol) != NULL); }static void eliminate_write(tree_instr *writer) { tree_node_list_e *the_element = writer->list_e(); assert(the_element != NULL); tree_node_list *the_list = writer->parent(); assert(the_list != NULL); instruction *the_instr = writer->instr(); assert(the_instr != NULL); writer->remove_instr(the_instr); the_instr->set_dst(operand()); side_effect_list(the_list, the_element, operand(the_instr)); the_list->remove(the_element); delete writer; delete the_element; }static void remove_symbols(sym_node_list *sym_list) { assert(sym_list != NULL); sym_node_list_e *this_element; sym_node_list_e *next_element = sym_list->head(); while (next_element != NULL) { this_element = next_element; next_element = this_element->next(); sym_node *the_symbol = this_element->contents; assert(the_symbol != NULL); the_symbol->parent()->remove_sym(the_symbol); delete the_symbol; sym_list->remove(this_element); delete this_element; } assert(sym_list->is_empty()); }static void clean_field_refs_on_tree_node(tree_node *the_node, void *) { assert(the_node != NULL); if (!the_node->is_instr()) return; tree_instr *the_tree_instr = (tree_instr *)the_node; instruction *old_instr = the_tree_instr->instr(); assert(old_instr != NULL); the_tree_instr->remove_instr(old_instr); instruction *new_instr = clean_field_refs_on_instr(old_instr); the_tree_instr->set_instr(new_instr); }static operand clean_field_refs_on_operand(operand to_clean) { if (!to_clean.is_expr()) return to_clean; return operand(clean_field_refs_on_instr(to_clean.instr())); }static instruction *clean_field_refs_on_instr(instruction *to_clean) { operand destination = to_clean->dst_op(); unsigned num_srcs = to_clean->num_srcs(); for (unsigned src_num = 0; src_num < num_srcs; ++src_num) { operand old_operand = to_clean->src_op(src_num); old_operand.remove(); to_clean->set_src_op(src_num, clean_field_refs_on_operand(old_operand)); } if (instr_is_bit_field_ref(to_clean)) { operand new_operand = expand_bit_field_ref(to_clean); instruction *new_instr; if (new_operand.is_expr()) { new_instr = new_operand.instr(); } else { new_instr = new in_rrr(io_cpy, new_operand.type(), operand(), new_operand); } if (destination.is_symbol()) { new_instr->set_dst(destination); } return new_instr; } else { return to_clean; } }static operand expand_bit_field_ref(instruction *to_undo) { unsigned short bit_field_from; unsigned short bit_field_to; type_node *result_type; operand address = undo_bit_field_on_instr(to_undo, &bit_field_from, &bit_field_to, &result_type); int right_amount = result_type->size() - (bit_field_to - bit_field_from); int left_amount = right_amount - field_right; in_rrr *the_load = new in_rrr(io_lod, unsignedtype, operand(), address); in_rrr *the_lsl = new in_rrr(io_lsl, unsignedtype, operand(), operand(the_load), operand(new in_ldc(unsignedtype, operand(), immed(left_amount)))); in_rrr *pre_asr; if_ops right_shift_op; if (result_type == unsignedtype) { pre_asr = the_lsl; right_shift_op = io_lsr; } else { pre_asr = new in_rrr(io_cvt, result_type, operand(), operand(the_lsl)); right_shift_op = io_asr; } in_rrr *the_asr = new in_rrr(right_shift_op, result_type, operand(), operand(pre_asr), operand(new in_ldc(unsignedtype, operand(), immed(right_amount)))); return operand(the_asr); }static operand undo_bit_field_on_instr(instruction *to_undo, unsigned short *from, unsigned short *to, type_node **result_type) { assert(to_undo != NULL); assert(to_undo->opcode() == io_cal); in_cal *the_call = (in_cal *)to_undo; operand result = the_call->argument(0); result.remove(); operand from_operand = the_call->argument(1); assert(from_operand.is_expr()); instruction *from_instr = from_operand.instr(); assert(from_instr != NULL); assert(from_instr->opcode() == io_ldc); in_ldc *from_ldc = (in_ldc *)from_instr; immed from_value = from_ldc->value(); assert(from_value.is_integer()); *from = from_value.integer(); operand to_operand = the_call->argument(2); assert(to_operand.is_expr()); instruction *to_instr = to_operand.instr(); assert(to_instr != NULL); assert(to_instr->opcode() == io_ldc); in_ldc *to_ldc = (in_ldc *)to_instr; immed to_value = to_ldc->value(); assert(to_value.is_integer()); *to = to_value.integer(); *result_type = the_call->result_type(); delete to_undo; return result; }static boolean instr_is_bit_field_ref(instruction *to_test) { assert(to_test != NULL); if (to_test->opcode() != io_cal) return FALSE; in_cal *the_call = (in_cal *)to_test; operand address = the_call->addr_op(); if (!address.is_expr()) return FALSE; instruction *addr_instr = address.instr(); assert(addr_instr != NULL); if (addr_instr->opcode() != io_ldc) return FALSE; in_ldc *the_ldc = (in_ldc *)addr_instr; immed value = the_ldc->value(); if (!value.is_symbol()) return FALSE; return (value.symbol() == bit_ref_symbol); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -