public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][RFC] Sanitize POINTER_PLUS_EXPR offset operand requirements
@ 2011-06-17 10:42 Richard Guenther
  0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2011-06-17 10:42 UTC (permalink / raw)
  To: gcc-patches


This implements my idea of how POINTER_PLUS_EXPR should end up being
changed.  This addresses two things, 1) reduce the use of sizetype
nodes, 2) properly handle targets where sizeof (void *) != sizeof 
(sizetype).  Especially 2) is important as currently we lose information
about the signedness of the offset and thus have no idea on whether
to sign- or zero-extend.

The following patch just implements the different checking and
handles the desired semantics during expansion.  It does not yet
touch the various places that build POINTER_PLUS_EXPRs (in fact,
a sizetype offset operand is still valid).  A final transition
will be as tedious as the original patch introducing POINTER_PLUS_EXPRs,
but the obvious starting points are the frontends and fold.  Partial
transitions will of course also eventually expose issues with
this new design.  Like, how do we fold (p + short a) + unsigned int b.
Straight-forward answer: as p + ((uintptr_t)a + (uintptr_t)b).  Which
we eventually can narrow again if we know sth about the value-ranges
of a and b (remember, overflow in ptr + offset is undefined).

Comments?

Thanks,
Richard.

2011-06-17  Richard Guenther  <rguenther@suse.de>

	* expr.c (expand_expr_real_2): Extend the POINTER_PLUS_EXPR offset
	operand to pointer precision.
	* tree-cfg.c (verify_expr): Allow arbitrary integral types
	for the POINTER_PLUS_EXPR offset operand.
	(verify_gimple_assign_binary): Likewise.
	* tree.c (build2_stat): Likewise.
	* tree.def (POINTER_PLUS_EXPR): Adjust documentation.

Index: trunk/gcc/expr.c
===================================================================
*** trunk.orig/gcc/expr.c	2011-06-16 16:56:02.000000000 +0200
--- trunk/gcc/expr.c	2011-06-17 11:33:52.000000000 +0200
*************** expand_expr_real_2 (sepops ops, rtx targ
*** 7422,7436 ****
        }
  
      case POINTER_PLUS_EXPR:
!       /* Even though the sizetype mode and the pointer's mode can be different
!          expand is able to handle this correctly and get the correct result out
!          of the PLUS_EXPR code.  */
!       /* Make sure to sign-extend the sizetype offset in a POINTER_PLUS_EXPR
!          if sizetype precision is smaller than pointer precision.  */
!       if (TYPE_PRECISION (sizetype) < TYPE_PRECISION (type))
! 	treeop1 = fold_convert_loc (loc, type,
! 				    fold_convert_loc (loc, ssizetype,
! 						      treeop1));
      case PLUS_EXPR:
        /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
  	 something else, make sure we add the register to the constant and
--- 7422,7433 ----
        }
  
      case POINTER_PLUS_EXPR:
!       /* Extend/truncate the offset operand to pointer width according
!          to its signedness.  */
!       if (TYPE_PRECISION (type) != TYPE_PRECISION (treeop1))
! 	treeop1 = fold_convert_loc (loc, type, treeop1);
! 
!       /* Fallthru.  */
      case PLUS_EXPR:
        /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
  	 something else, make sure we add the register to the constant and
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c	2011-06-16 16:55:45.000000000 +0200
--- trunk/gcc/tree-cfg.c	2011-06-17 11:35:17.000000000 +0200
*************** verify_expr (tree *tp, int *walk_subtree
*** 2845,2857 ****
  	  error ("invalid operand to pointer plus, first operand is not a pointer");
  	  return t;
  	}
!       /* Check to make sure the second operand is an integer with type of
! 	 sizetype.  */
!       if (!useless_type_conversion_p (sizetype,
! 				     TREE_TYPE (TREE_OPERAND (t, 1))))
  	{
  	  error ("invalid operand to pointer plus, second operand is not an "
! 		 "integer with type of sizetype");
  	  return t;
  	}
        /* FALLTHROUGH */
--- 2845,2855 ----
  	  error ("invalid operand to pointer plus, first operand is not a pointer");
  	  return t;
  	}
!       /* Check to make sure the second operand is an integer.  */
!       if (!INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
  	{
  	  error ("invalid operand to pointer plus, second operand is not an "
! 		 "integer type");
  	  return t;
  	}
        /* FALLTHROUGH */
*************** verify_gimple_assign_binary (gimple stmt
*** 3609,3615 ****
  do_pointer_plus_expr_check:
  	if (!POINTER_TYPE_P (rhs1_type)
  	    || !useless_type_conversion_p (lhs_type, rhs1_type)
! 	    || !useless_type_conversion_p (sizetype, rhs2_type))
  	  {
  	    error ("type mismatch in pointer plus expression");
  	    debug_generic_stmt (lhs_type);
--- 3607,3613 ----
  do_pointer_plus_expr_check:
  	if (!POINTER_TYPE_P (rhs1_type)
  	    || !useless_type_conversion_p (lhs_type, rhs1_type)
! 	    || !INTEGRAL_TYPE_P (rhs2_type))
  	  {
  	    error ("type mismatch in pointer plus expression");
  	    debug_generic_stmt (lhs_type);
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c	2011-06-16 16:55:45.000000000 +0200
--- trunk/gcc/tree.c	2011-06-17 11:29:35.000000000 +0200
*************** build2_stat (enum tree_code code, tree t
*** 3779,3786 ****
  
    if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
      gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
! 		&& INTEGRAL_TYPE_P (TREE_TYPE (arg1))
! 		&& useless_type_conversion_p (sizetype, TREE_TYPE (arg1)));
  
    t = make_node_stat (code PASS_MEM_STAT);
    TREE_TYPE (t) = tt;
--- 3779,3785 ----
  
    if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
      gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
! 		&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)));
  
    t = make_node_stat (code PASS_MEM_STAT);
    TREE_TYPE (t) = tt;
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def	2011-06-16 14:49:31.000000000 +0200
--- trunk/gcc/tree.def	2011-06-17 11:41:04.000000000 +0200
*************** DEFTREECODE (MINUS_EXPR, "minus_expr", t
*** 610,616 ****
  DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
  
  /* Pointer addition.  The first operand is always a pointer and the
!    second operand is an integer of type sizetype.  */
  DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)
  
  /* Division for integer result that rounds the quotient toward zero.  */
--- 610,617 ----
  DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
  
  /* Pointer addition.  The first operand is always a pointer and the
!    second operand is an integer.  The second operand is implicitly
!    extended to the width of the first operand.  */
  DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)
  
  /* Division for integer result that rounds the quotient toward zero.  */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-06-17  9:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-17 10:42 [PATCH][RFC] Sanitize POINTER_PLUS_EXPR offset operand requirements Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).