📄 gen.cc
字号:
the_def->annotes()->append(a); }// initialize current global symbol with ``size'' bits of empty spacevoid space(var_def *the_def, int size) { if (the_def == NULL) return; annote *a = new annote(k_fill); a->immeds()->append(immed(size)); a->immeds()->append(immed(0)); the_def->annotes()->append(a); }/******************************************************************** * MISCELLANOUS OTHER LCC BACK-END FUNCTIONS * ********************************************************************/// stabline - file and line number markervoid stabline(Coordinate *coord) { if (curr_list != NULL) { instruction *mrk = new in_rrr(io_mrk); mrk->annotes()->append(make_line_annote(coord)); append_instr(mrk); } }/******************************************************************** * ACCESSORY FUNCTIONS FOR CODE GENERATION * ********************************************************************/void append_instr(instruction *instr) { curr_list->append(new tree_instr(instr)); }/* New stuff */extern void current_list_append_node(tree_node *the_node) { assert(curr_list != NULL); curr_list->append(the_node); }extern void current_list_append_list(tree_node_list *the_list) { assert(curr_list != NULL); curr_list->append(the_list); delete the_list; }/* * This procedure is called on the suif procedure just before it is written * out. It acts as a final pass to figure out symbols that have their * addresses taken; replace load-store combinations with memcpy's; change one * step conversions between integers that change both the the size and sign to * two different conversions; and replace a series of array reference * instructions into a single multi-dimensional array reference instruction. * Then it makes all the substitutions specified by global_replacements to * merge types that are really the same in SUIF. */static void finalize_suif_proc(proc_sym *the_proc) { assert(the_proc != NULL); tree_block *the_block = the_proc->block(); assert(the_block != NULL); the_block->map(&finalize_suif_node, NULL); (void)(the_block->clone_helper(global_replacements, TRUE)); }static void finalize_suif_node(tree_node *the_node, void *) { assert(the_node != NULL); if (the_node->is_instr()) { tree_instr *the_tree_instr = (tree_instr *)the_node; the_tree_instr->instr_map(&finalize_suif_instr, NULL, FALSE); } }static void finalize_suif_instr(instruction *the_instr, void *) { assert(the_instr != NULL); if (the_instr->opcode() == io_ldc) { in_ldc *the_ldc = (in_ldc *)the_instr; immed value = the_ldc->value(); if (value.is_symbol()) { sym_node *symbol = value.symbol(); assert(symbol != NULL); if (symbol->is_var()) { var_sym *the_var = (var_sym *)symbol; the_var->set_addr_taken(); } } } else if (the_instr->opcode() == io_str) { in_rrr *the_store = (in_rrr *)the_instr; operand data_op = the_store->src2_op(); if (data_op.is_expr() && (data_op.instr()->opcode() == io_lod)) { in_rrr *the_load = (in_rrr *)(data_op.instr()); operand source_address = the_load->src_addr_op(); source_address.remove(); data_op.remove(); the_store->set_opcode(io_memcpy); the_store->set_src2(source_address); delete the_load; } } else if (the_instr->opcode() == io_cvt) { in_rrr *the_cvt = (in_rrr *)the_instr; type_node *old_type = the_cvt->src_op().type()->unqual(); type_node *new_type = the_cvt->result_type()->unqual(); /* * If there is a convert from an int or pointer type to an int or * pointer type of a different size and one is signed but the other * isn't (pointers are treated as unsigned), SUIF needs two separate * convert instructions, one to change the size and one to change * between signed and unsigned. It matters which order this * conversion is done: * * - Going from an unsigned to a larger signed, everything * representable in the original type is representable in the new * type, so we just have to make sure it's representable in the * intermediate type. It is representable in the larger * unsigned, so we can do that conversion first. The other order * would not work; for example, converting 255 from an unsigned * char to a signed char would give -1, and converting that to a * signed int would give -1, not the correct 255. So in this * case we must do the size conversion first. * * - Going from a signed to a larger unsigned, 6.2.1.2, paragraph 2 * of ANSI/ISO 9899-1990 clearly states that the value is first * promoted to the signed type of the larger size. So we need to * do the size conversion first in this case, too. * * - Going from a signed to a smaller unsigned, 6.2.1.2, * paragraph 3, sentence 1 or ANSI/ISO 9899-1990 defines the * result: it must be the remainder on division of the number of * values representable by the target type. Converting first to * an unsigned type of the larger size and then to the smaller * size guarantees this will happen: it is the remainder on * division by the number of values representable by the smaller * unsigned of the remainder on division by the number of values * representable by the larger unsigned of the original value. * Since both numbers of values are powers of two, the larger is * a multiple of the smaller, so the result is what we needed. * So no matter how conversion to a smaller integer is defined * (the second sentence of paragraph 3 of 6.2.1.2 of * ANSI/ISO 9899-1990 makes it implementation defined), the result * is correct if we first do the sign conversion in this case. * * - Going from an unsigned to a smaller signed is a bit more * problematic because the standard leaves this implementation * defined. Anything representable in both types would also be * representable in the intermediate type either way the * conversion is done. And most of the time we're in 2's * complement and changing between unsigned and signed leaves the * same bits and changing to a smaller size just throws away the * higher order bits, whether we are seeing it as a signed or * unsigned. So it really doesn't matter much which way we * define it. * A reasonable assumption to make would be that any conversion * from a type A to a type B followed by a conversion from B to A * always gives back the original value if B has at least as many * bits as B. Lets assume this is true of the conversion between * a signed and an unsigned with the same number of bits. Then * we can guarantee this holds all the time if and only if we * choose to do the sign conversion first for the case of an * unsigned to a smaller signed. So we'll do the sign conversion * first in this case. * * The net result is that we want to do the size conversion first * when going to a larger size and the sign conversion first when * going to a smaller size. */ if (((old_type->op() == TYPE_INT) || old_type->is_enum() || old_type->is_ptr()) && ((new_type->op() == TYPE_INT) || new_type->is_enum() || new_type->is_ptr())) { boolean old_signed = !non_negative(old_type); boolean new_signed = !non_negative(new_type); if ((new_signed != old_signed) && (new_type->size() != old_type->size())) { type_node *intermediate_type; if (new_type->size() > old_type->size()) { intermediate_type = new base_type(TYPE_INT, new_type->size(), old_signed); } else { intermediate_type = new base_type(TYPE_INT, old_type->size(), new_signed); } intermediate_type = fileset->globals()->install_type(intermediate_type); operand old_op = the_cvt->src_op(); old_op.remove(); instruction *new_instr = new in_rrr(io_cvt, intermediate_type, operand(), old_op); the_cvt->set_src(operand(new_instr)); } } /* * Mgen also can't handle direct converts between floating point and * integers of any size other than word size. So we need to go * through that size first. */ else if (((old_type->op() == TYPE_FLOAT) && ((new_type->op() == TYPE_INT) || new_type->is_enum()) && (new_type->size() != type_signed->size())) || ((new_type->op() == TYPE_FLOAT) && ((old_type->op() == TYPE_INT) || old_type->is_enum()) && (old_type->size() != type_signed->size()))) { type_node *intermediate_type; if ((old_type->op() == TYPE_INT) || old_type->is_enum()) { if (non_negative(old_type)) intermediate_type = type_unsigned; else intermediate_type = type_signed; } else { if (non_negative(new_type)) intermediate_type = type_unsigned; else intermediate_type = type_signed; } operand old_op = the_cvt->src_op(); old_op.remove(); instruction *new_instr = new in_rrr(io_cvt, intermediate_type, operand(), old_op); the_cvt->set_src(operand(new_instr)); } } else if (the_instr->opcode() == io_array) { in_array *the_array = (in_array *)the_instr; operand base_operand = the_array->base_op(); if (base_operand.is_expr() && (base_operand.instr()->opcode() == io_array) && (base_operand.instr()->peek_annote(k_fields) == NULL)) { /* * Collapse adjacent array references into a single array * reference instruction with multiple dimensions. */ in_array *second_array = (in_array *)(base_operand.instr()); second_array->remove(); assert(the_array->dims() == 1); unsigned new_num_dims = 1 + second_array->dims(); the_array->set_dims(new_num_dims); assert(second_array->offset_op() == operand()); assert(second_array->offset() == 0); operand last_index = the_array->index(0); operand last_bound = the_array->bound(0); last_index.remove(); last_bound.remove(); the_array->set_index(new_num_dims - 1, last_index); the_array->set_bound(new_num_dims - 1, last_bound); for (unsigned dim_num = 0; dim_num < new_num_dims - 1; ++dim_num) { operand this_index = second_array->index(dim_num); operand this_bound = second_array->bound(dim_num); this_index.remove(); this_bound.remove(); the_array->set_index(dim_num, this_index); the_array->set_bound(dim_num, this_bound); } operand second_base = second_array->base_op(); second_base.remove(); the_array->set_base_op(second_base); delete second_array; } } }static annote *make_line_annote(Coordinate *location) { annote *result = new annote(k_line); result->immeds()->append(immed((int)location->y)); result->immeds()->append(immed(location->file ? location->file : (char *)"")); return result; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -