This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Add VIEW_CONVERT_EXPR tree code
- From: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 19 Nov 01 15:38:22 EST
- Subject: Add VIEW_CONVERT_EXPR tree code
This adds a tree code that is, at this point, used only by Ada. I also
fixed two minor problems that came up while testing this.
Tested on alphaev56-dec-osfv4.0c.
Mon Nov 19 15:13:43 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* 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.
*** tree.def 2001/10/11 18:48:32 1.47
--- tree.def 2001/11/19 20:05:58
*************** DEFTREECODE (NOP_EXPR, "nop_expr", '1',
*** 692,695 ****
--- 692,702 ----
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
*** tree.h 2001/11/18 19:36:01 1.285
--- tree.h 2001/11/19 20:06:37
*************** extern tree get_inner_reference PARAMS
*** 2588,2591 ****
--- 2588,2595 ----
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. */
*** alias.c 2001/11/15 23:44:54 1.156
--- alias.c 2001/11/19 20:00:12
*************** static rtx find_base_term PARAMS ((rtx)
*** 96,100 ****
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));
--- 96,99 ----
*************** find_base_decl (t)
*** 394,422 ****
same, return it. Otherwise, return zero. */
return (d0 == d1 && d1 == d2) ? d0 : 0;
-
- default:
- return 0;
- }
- }
-
- /* 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:
--- 393,396 ----
*** dwarf2out.c 2001/11/15 23:44:56 1.330
--- dwarf2out.c 2001/11/19 20:02:09
*************** loc_descriptor_from_tree (loc, addressp)
*** 7930,7933 ****
--- 7930,7934 ----
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
*************** add_bound_info (subrange_die, bound_attr
*** 8850,8853 ****
--- 8851,8855 ----
case NOP_EXPR:
case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
break;
*** expr.c 2001/11/18 21:44:26 1.382
--- expr.c 2001/11/19 20:03:46
*************** is_zeros_p (exp)
*** 4361,4364 ****
--- 4361,4365 ----
case NOP_EXPR:
case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
return is_zeros_p (TREE_OPERAND (exp, 0));
*************** store_field (target, bitsize, bitpos, mo
*** 5152,5156 ****
PUT_MODE (blk_object, BLKmode);
- MEM_COPY_ATTRIBUTES (blk_object, object);
if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
--- 5153,5156 ----
*************** get_inner_reference (exp, pbitsize, pbit
*** 5452,5455 ****
--- 5452,5456 ----
}
else if (TREE_CODE (exp) != NON_LVALUE_EXPR
+ && TREE_CODE (exp) != VIEW_CONVERT_EXPR
&& ! ((TREE_CODE (exp) == NOP_EXPR
|| TREE_CODE (exp) == CONVERT_EXPR)
*************** get_inner_reference (exp, pbitsize, pbit
*** 5480,5483 ****
--- 5481,5510 ----
}
+ /* 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. */
*************** expand_expr (exp, target, tmode, modifie
*** 6288,6294 ****
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
{
layout_decl (exp, 0);
! PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
! set_mem_align (DECL_RTL (exp), DECL_ALIGN (exp));
}
--- 6315,6331 ----
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
{
+ rtx value = DECL_RTL_IF_SET (exp);
+
layout_decl (exp, 0);
!
! /* 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);
! }
}
*************** expand_expr (exp, target, tmode, modifie
*** 7501,7504 ****
--- 7538,7614 ----
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
*************** expand_expr (exp, target, tmode, modifie
*** 8669,8673 ****
if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
&& (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
! > MEM_ALIGN (op0)))
{
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
--- 8779,8784 ----
if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
&& (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
! > MEM_ALIGN (op0))
! && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
{
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
*** fold-const.c 2001/11/15 23:44:57 1.176
--- fold-const.c 2001/11/19 20:05:16
*************** fold (expr)
*** 5309,5312 ****
--- 5309,5318 ----
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:
*** varasm.c 2001/11/16 14:02:56 1.227
--- varasm.c 2001/11/19 20:07:11
*************** initializer_constant_valid_p (value, end
*** 4289,4292 ****
--- 4289,4293 ----
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);
*************** output_constant (exp, size, align)
*** 4443,4450 ****
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. */
if (lang_expand_constant)
{
--- 4444,4450 ----
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. */
if (lang_expand_constant)
{
*************** output_constant (exp, size, align)
*** 4463,4469 ****
&& (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)
{
exp = TREE_OPERAND (exp, 0);
--- 4463,4469 ----
&& (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) == VIEW_CONVERT_EXPR)
{
exp = TREE_OPERAND (exp, 0);