* [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).