This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]