diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 63bbd149ff0..6cae9dc73ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +Mon Nov 19 15:13:43 2001 Richard Kenner + + * tree.def (VIEW_CONVERT_EXPR): New tree code. + * tree.h (handled_component_p): New declaration. + * alias.c (handled_component_p): Move function from here ... + * expr.c (handled_component_p): ... to here and non longer static. + (is_zeros_p, case VIEW_CONVERT_EXPR): New case. + (store_field): Remove unneeded MEM_COPY_ATTRIBUTES call. + (get_inner_reference): Handle VIEW_CONVERT_EXPR. + (expand_expr, case VAR_DECL): Clean up handling of re-layout case. + (expand_expr, case VIEW_CONVERT_EXPR): New case. + (expand_expr, cse ADDR_EXPR): No need to copy if already + BIGGEST_ALIGNMENT. + * fold-const.c (fold, case VIEW_CONVERT_EXPR): New case. + * varasm.c (initializer_constant_value_p, case VIEW_CONVERT_EXPR): New. + (output_constant): Handle VIEW_CONVERT_EXPR. + * dwarf2out.c (loc-descriptor_from_tree, add_bound_info): + Add new case for VIEW_CONVERT_EXPR. + 2001-11-19 Kaveh R. Ghazi * a29k/unix.h (ASM_FILE_START): Const-ify. diff --git a/gcc/alias.c b/gcc/alias.c index 27e7e3903fd..a92cf857844 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -95,7 +95,6 @@ static void record_set PARAMS ((rtx, rtx, void *)); static rtx find_base_term PARAMS ((rtx)); static int base_alias_check PARAMS ((rtx, rtx, enum machine_mode, enum machine_mode)); -static int handled_component_p PARAMS ((tree)); static rtx find_base_value PARAMS ((rtx)); static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx)); static int insert_subset_children PARAMS ((splay_tree_node, void*)); @@ -399,31 +398,6 @@ find_base_decl (t) } } -/* Return 1 if T is an expression that get_inner_reference handles. */ - -static int -handled_component_p (t) - tree t; -{ - switch (TREE_CODE (t)) - { - case BIT_FIELD_REF: - case COMPONENT_REF: - case ARRAY_REF: - case ARRAY_RANGE_REF: - case NON_LVALUE_EXPR: - return 1; - - case NOP_EXPR: - case CONVERT_EXPR: - return (TYPE_MODE (TREE_TYPE (t)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))); - - default: - return 0; - } -} - /* Return 1 if all the nested component references handled by get_inner_reference in T are such that we can address the object in T. */ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 86a3a6a3961..164b0511281 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -7929,6 +7929,7 @@ loc_descriptor_from_tree (loc, addressp) case NOP_EXPR: case CONVERT_EXPR: case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: case SAVE_EXPR: return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); @@ -8849,6 +8850,7 @@ add_bound_info (subrange_die, bound_attr, bound) case CONVERT_EXPR: case NOP_EXPR: case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); break; diff --git a/gcc/expr.c b/gcc/expr.c index 324f5cd106c..0c5429ec187 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4360,6 +4360,7 @@ is_zeros_p (exp) case CONVERT_EXPR: case NOP_EXPR: case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: return is_zeros_p (TREE_OPERAND (exp, 0)); case INTEGER_CST: @@ -5151,7 +5152,6 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type, rtx blk_object = copy_rtx (object); PUT_MODE (blk_object, BLKmode); - MEM_COPY_ATTRIBUTES (blk_object, object); if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target))) emit_move_insn (object, target); @@ -5451,6 +5451,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, continue; } else if (TREE_CODE (exp) != NON_LVALUE_EXPR + && TREE_CODE (exp) != VIEW_CONVERT_EXPR && ! ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR) && (TYPE_MODE (TREE_TYPE (exp)) @@ -5479,6 +5480,32 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, return exp; } +/* Return 1 if T is an expression that get_inner_reference handles. */ + +int +handled_component_p (t) + tree t; +{ + switch (TREE_CODE (t)) + { + case BIT_FIELD_REF: + case COMPONENT_REF: + case ARRAY_REF: + case ARRAY_RANGE_REF: + case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: + return 1; + + case NOP_EXPR: + case CONVERT_EXPR: + return (TYPE_MODE (TREE_TYPE (t)) + == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))); + + default: + return 0; + } +} + /* Subroutine of expand_exp: compute memory_usage from modifier. */ static enum memory_use_mode @@ -6287,9 +6314,19 @@ expand_expr (exp, target, tmode, modifier) if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp)) && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) { + rtx value = DECL_RTL_IF_SET (exp); + layout_decl (exp, 0); - PUT_MODE (DECL_RTL (exp), DECL_MODE (exp)); - set_mem_align (DECL_RTL (exp), DECL_ALIGN (exp)); + + /* If the RTL was already set, update its mode and memory + attributes. */ + if (value != 0) + { + PUT_MODE (value, DECL_MODE (exp)); + SET_DECL_RTL (exp, 0); + set_mem_attributes (value, exp, 1); + SET_DECL_RTL (exp, value); + } } /* Although static-storage variables start off initialized, according to @@ -7500,6 +7537,79 @@ expand_expr (exp, target, tmode, modifier) TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); return target; + case VIEW_CONVERT_EXPR: + op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0); + + /* If the input and output modes are both the same, we are done. + Otherwise, if neither mode is BLKmode and both are within a word, we + can use gen_lowpart. If neither is true, store the operand into + memory and convert the MEM to the new mode. */ + if (TYPE_MODE (type) == GET_MODE (op0)) + ; + else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode + && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD + && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD) + op0 = gen_lowpart (TYPE_MODE (type), op0); + else + { + tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + enum machine_mode non_blkmode + = GET_MODE (op0) == BLKmode ? TYPE_MODE (type) : GET_MODE (op0); + + if (CONSTANT_P (op0)) + op0 = validize_mem (force_const_mem (TYPE_MODE (inner_type), op0)); + else + { + if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type)) + target + = assign_stack_temp_for_type (TYPE_MODE (inner_type), + GET_MODE_SIZE (non_blkmode), + 0, inner_type); + + if (GET_MODE (target) == BLKmode) + emit_block_move (target, op0, + expr_size (TREE_OPERAND (exp, 0))); + else + emit_move_insn (target, op0); + + op0 = target; + } + } + + if (GET_CODE (op0) == MEM) + { + op0 = copy_rtx (op0); + + /* If the output type is such that the operand is known to be + aligned, indicate that it is. Otherwise, we need only be + concerned about alignment for non-BLKmode results. */ + if (TYPE_ALIGN_OK (type)) + set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); + else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT + && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type))) + { + tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + HOST_WIDE_INT temp_size = MAX (int_size_in_bytes (inner_type), + GET_MODE_SIZE (TYPE_MODE (type))); + rtx new = assign_stack_temp_for_type (TYPE_MODE (type), + temp_size, 0, type); + rtx new_with_op0_mode = copy_rtx (new); + + PUT_MODE (new_with_op0_mode, GET_MODE (op0)); + if (GET_MODE (op0) == BLKmode) + emit_block_move (new_with_op0_mode, op0, + GEN_INT (GET_MODE_SIZE (TYPE_MODE (type)))); + else + emit_move_insn (new_with_op0_mode, op0); + + op0 = new; + } + + PUT_MODE (op0, TYPE_MODE (type)); + } + + return op0; + case PLUS_EXPR: /* We come here from MINUS_EXPR when the second operand is a constant. */ @@ -8668,7 +8778,8 @@ expand_expr (exp, target, tmode, modifier) strict alignment. */ if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))) - > MEM_ALIGN (op0))) + > MEM_ALIGN (op0)) + && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT) { tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); rtx new diff --git a/gcc/fold-const.c b/gcc/fold-const.c index f7cdc57d421..2083c55abfa 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -5308,6 +5308,12 @@ fold (expr) } return fold_convert (t, arg0); + case VIEW_CONVERT_EXPR: + if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR) + return build1 (VIEW_CONVERT_EXPR, type, + TREE_OPERAND (TREE_OPERAND (t, 0), 0)); + return t; + #if 0 /* This loses on &"foo"[0]. */ case ARRAY_REF: { diff --git a/gcc/tree.def b/gcc/tree.def index 8a02e5b2f60..c4f08cf5f0d 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -691,6 +691,13 @@ DEFTREECODE (NOP_EXPR, "nop_expr", '1', 1) /* Value is same as argument, but guaranteed not an lvalue. */ DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", '1', 1) +/* Represents viewing something of one type as being of a second type. + This corresponds to an "Unchecked Conversion" in Ada and roughly to + the idiom *(type2 *)&X in C. The only operand is the value to be + viewed as being of another type. It is undefined if the type of the + input and of the expression have different sizes. */ +DEFTREECODE (VIEW_CONVERT_EXPR, "view_convert_expr", '1', 1) + /* Represents something we computed once and will use multiple times. First operand is that expression. Second is the function decl in which the SAVE_EXPR was created. The third operand is the RTL, diff --git a/gcc/tree.h b/gcc/tree.h index 9c45fb851ad..c28edf12df6 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2587,6 +2587,10 @@ extern tree get_inner_reference PARAMS ((tree, HOST_WIDE_INT *, enum machine_mode *, int *, int *)); +/* Return 1 if T is an expression that get_inner_reference handles. */ + +extern int handled_component_p PARAMS ((tree)); + /* Given a DECL or TYPE, return the scope in which it was declared, or NUL_TREE if there is no containing scope. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 697276234b0..32dabe82d08 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -4288,6 +4288,7 @@ initializer_constant_valid_p (value, endtype) case FDESC_EXPR: return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0; + case VIEW_CONVERT_EXPR: case NON_LVALUE_EXPR: return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); @@ -4442,10 +4443,9 @@ output_constant (exp, size, align) { enum tree_code code = TREE_CODE (TREE_TYPE (exp)); - /* Some front-ends use constants other than the standard - language-indepdent varieties, but which may still be output - directly. Give the front-end a chance to convert EXP to a - language-independent representation. */ + /* Some front-ends use constants other than the standard language-indepdent + varieties, but which may still be output directly. Give the front-end a + chance to convert EXP to a language-independent representation. */ if (lang_expand_constant) { exp = (*lang_expand_constant) (exp); @@ -4462,9 +4462,9 @@ output_constant (exp, size, align) while ((TREE_CODE (exp) == NOP_EXPR && (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0)) || AGGREGATE_TYPE_P (TREE_TYPE (exp)))) - || (TREE_CODE (exp) == CONVERT_EXPR - && code == UNION_TYPE) - || TREE_CODE (exp) == NON_LVALUE_EXPR) + || (TREE_CODE (exp) == CONVERT_EXPR && code == UNION_TYPE) + || TREE_CODE (exp) == NON_LVALUE_EXPR + || TREE_CODE (exp) == VIEW_CONVERT_EXPR) { exp = TREE_OPERAND (exp, 0); code = TREE_CODE (TREE_TYPE (exp));