[RFC] Verify type correctness in fold_buildN
Richard Guenther
rguenth@tat.physik.uni-tuebingen.de
Wed Jun 1 12:07:00 GMT 2005
As a start towards defining and enforcing a middle-end type-system
this instruments (with fatal results) the fold entry points
fold_buildN. Avoiding recursive checks for now we only verify the
about to be created tree has the correct types and that folding
doesn't return a different topmost type than told to.
Of course it fails miserably. The first offender is
#1 0x08316056 in fold_build2 (code=MULT_EXPR, type=0x403b3288,
op0=0x403ac8e8, op1=0x403ac8d0)
at /home/rguenth/src/gcc/cvs/gcc-4.1/gcc/fold-const.c:10582
#2 0x081d33c3 in idx_find_step (base=0x403b24c0, idx=0x403b24dc,
data=0xbfffee60)
at /home/rguenth/src/gcc/cvs/gcc-4.1/gcc/tree-ssa-loop-ivopts.c:1459
At least the checking infrastructure is reasonably clean now.
Richard.
2005Jun01 Richard Guenther <rguenth@gcc.gnu.org>
* tree.c (verify_tree_type, verify_tree_type1,
verify_tree_type2, verify_tree_type3, verify_tree_types_1,
verify_tree_types): New functions.
* tree.h (verify_tree_type, verify_tree_type1,
verify_tree_type2, verify_tree_type3, verify_tree_types): Export.
* fold-const.c (fold_build1, fold_build2, fold_build3): Instrument.
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.731
diff -c -3 -p -r1.731 tree.h
*** tree.h 1 Jun 2005 00:39:46 -0000 1.731
--- tree.h 1 Jun 2005 11:57:59 -0000
*************** extern tree get_base_address (tree t);
*** 3988,3991 ****
--- 3988,4003 ----
/* In tree-vectorizer.c. */
extern void vect_set_verbosity_level (const char *);
+ /* Verify type of a tree without recursing into operands. */
+ extern bool verify_tree_type1 (enum tree_code code, tree type,
+ tree op0);
+ extern bool verify_tree_type2 (enum tree_code code, tree type,
+ tree op0, tree op1);
+ extern bool verify_tree_type3 (enum tree_code code, tree type,
+ tree op0, tree op1, tree op2);
+ extern bool verify_tree_type (tree t);
+
+ /* Verify type of a tree recursively. */
+ extern bool verify_tree_types (tree t);
+
#endif /* GCC_TREE_H */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.483
diff -c -3 -p -r1.483 tree.c
*** tree.c 1 Jun 2005 00:39:45 -0000 1.483
--- tree.c 1 Jun 2005 11:57:59 -0000
*************** walk_tree_without_duplicates (tree *tp,
*** 6781,6784 ****
--- 6781,6974 ----
return result;
}
+
+ /* Exchange this with __asm__("int3") to trap on ia32. */
+ /*#define TREE_TYPE_ERROR gcc_unreachable () */
+ #define TREE_TYPE_ERROR return false
+
+ /* Verify that the unary tree composed of CODE, TYPE and OP0
+ has the correct type. */
+
+ bool
+ verify_tree_type1 (enum tree_code code, tree type, tree op0)
+ {
+ switch (code)
+ {
+ /* Trees with one operand. */
+
+ case ADDR_EXPR:
+ if (TREE_CODE (TREE_TYPE (op0)) != ARRAY_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (type))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (op0)))
+ TREE_TYPE_ERROR;
+ break;
+
+ case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ if (op0
+ && type != TREE_TYPE (TREE_TYPE (op0)))
+ TREE_TYPE_ERROR;
+ break;
+
+ case FIX_TRUNC_EXPR:
+ case FIX_CEIL_EXPR:
+ case FIX_FLOOR_EXPR:
+ case FIX_ROUND_EXPR:
+ if (TREE_CODE (type) != INTEGER_TYPE
+ || ! SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)))
+ TREE_TYPE_ERROR;
+ break;
+
+ case FLOAT_EXPR:
+ if (! SCALAR_FLOAT_TYPE_P (type)
+ || TREE_CODE (TREE_TYPE (op0)) != INTEGER_TYPE)
+ TREE_TYPE_ERROR;
+ break;
+
+ case ABS_EXPR:
+ if (TREE_CODE (type) != INTEGER_TYPE
+ && TREE_CODE (type) != REAL_TYPE)
+ TREE_TYPE_ERROR;
+ /* Fall through. */
+ case NEGATE_EXPR:
+ if (type != TREE_TYPE (op0))
+ TREE_TYPE_ERROR;
+ break;
+
+ case BIT_NOT_EXPR:
+ if (TYPE_MODE (type) != TYPE_MODE (TREE_TYPE (op0)))
+ TREE_TYPE_ERROR;
+ break;
+
+ default:
+ ;
+ }
+
+ return true;
+ }
+
+ /* Verify that the binary tree composed of CODE, TYPE, OP0 and OP1
+ has the correct type. */
+
+ bool
+ verify_tree_type2 (enum tree_code code, tree type, tree op0, tree op1)
+ {
+ switch (code)
+ {
+ /* tcc_binary */
+
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ if (type != TREE_TYPE (op0))
+ TREE_TYPE_ERROR;
+ break;
+
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ if (TYPE_MODE (type) != TYPE_MODE (TREE_TYPE (op0))
+ || TYPE_MODE (type) != TYPE_MODE (TREE_TYPE (op1)))
+ TREE_TYPE_ERROR;
+ break;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case RDIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ if (type != TREE_TYPE (op0)
+ || type != TREE_TYPE (op1))
+ TREE_TYPE_ERROR;
+ break;
+
+ /* tcc_reference */
+ case MISALIGNED_INDIRECT_REF:
+ if (type != TREE_TYPE (TREE_TYPE (op0))
+ || TREE_CODE (op1) != INTEGER_CST)
+ TREE_TYPE_ERROR;
+
+ default:
+ ;
+ }
+
+ return true;
+ }
+
+ /* Verify that the ternary tree composed of CODE, TYPE, OP0, OP1 and OP2
+ has the correct type. */
+
+ bool
+ verify_tree_type3 (enum tree_code code, tree type, tree op0, tree op1, tree op2)
+ {
+ switch (code)
+ {
+ case COMPONENT_REF:
+ if ((TREE_CODE (TREE_TYPE (op0)) != RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (op0)) != UNION_TYPE
+ && TREE_CODE (TREE_TYPE (op0)) != QUAL_UNION_TYPE)
+ || TREE_CODE (op1) != FIELD_DECL
+ || type != TREE_TYPE (op1))
+ TREE_TYPE_ERROR;
+ break;
+
+ default:
+ ;
+ }
+
+ return true;
+ }
+ #undef TREE_TYPE_ERROR
+
+ /* Verify type correctness of the tree T without recursing into the
+ tree operands. */
+
+ bool
+ verify_tree_type (tree t)
+ {
+ if (TREE_CODE_LENGTH (TREE_CODE (t)) == 1)
+ return verify_tree_type1 (TREE_CODE (t), TREE_TYPE (t),
+ TREE_OPERAND (t, 0));
+ else if (TREE_CODE_LENGTH (TREE_CODE (t)) == 2)
+ return verify_tree_type2 (TREE_CODE (t), TREE_TYPE (t),
+ TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+ else if (TREE_CODE_LENGTH (TREE_CODE (t)) == 3)
+ return verify_tree_type3 (TREE_CODE (t), TREE_TYPE (t),
+ TREE_OPERAND (t, 0), TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 2));
+ return true;
+ }
+
+ /* Helper for verify_tree_types. */
+
+ static tree
+ verify_tree_types_1 (tree *t, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *res)
+ {
+ if (! verify_tree_type (*t))
+ *(int *)res = 0;
+ return *t;
+ }
+
+ /* Verify type correctness of the tree T recursively. */
+
+ bool
+ verify_tree_types (tree t)
+ {
+ int res = 1;
+ walk_tree_without_duplicates (&t, verify_tree_types_1, &res);
+ return res == 1;
+ }
+
#include "gt-tree.h"
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.586
diff -c -3 -p -r1.586 fold-const.c
*** fold-const.c 1 Jun 2005 09:34:15 -0000 1.586
--- fold-const.c 1 Jun 2005 11:58:00 -0000
*************** recursive_label:
*** 10558,10566 ****
tree
fold_build1 (enum tree_code code, tree type, tree op0)
{
! tree tem = fold_unary (code, type, op0);
if (tem)
! return tem;
return build1 (code, type, op0);
}
--- 10558,10571 ----
tree
fold_build1 (enum tree_code code, tree type, tree op0)
{
! tree tem;
! gcc_assert (verify_tree_type1 (code, type, op0));
! tem = fold_unary (code, type, op0);
if (tem)
! {
! gcc_assert (TREE_TYPE (tem) == type);
! return tem;
! }
return build1 (code, type, op0);
}
*************** fold_build1 (enum tree_code code, tree t
*** 10573,10581 ****
tree
fold_build2 (enum tree_code code, tree type, tree op0, tree op1)
{
! tree tem = fold_binary (code, type, op0, op1);
if (tem)
! return tem;
return build2 (code, type, op0, op1);
}
--- 10578,10591 ----
tree
fold_build2 (enum tree_code code, tree type, tree op0, tree op1)
{
! tree tem;
! gcc_assert (verify_tree_type2 (code, type, op0, op1));
! tem = fold_binary (code, type, op0, op1);
if (tem)
! {
! gcc_assert (TREE_TYPE (tem) == type);
! return tem;
! }
return build2 (code, type, op0, op1);
}
*************** fold_build2 (enum tree_code code, tree t
*** 10588,10596 ****
tree
fold_build3 (enum tree_code code, tree type, tree op0, tree op1, tree op2)
{
! tree tem = fold_ternary (code, type, op0, op1, op2);
if (tem)
! return tem;
return build3 (code, type, op0, op1, op2);
}
--- 10598,10611 ----
tree
fold_build3 (enum tree_code code, tree type, tree op0, tree op1, tree op2)
{
! tree tem;
! gcc_assert (verify_tree_type3 (code, type, op0, op1, op2));
! tem = fold_ternary (code, type, op0, op1, op2);
if (tem)
! {
! gcc_assert (TREE_TYPE (tem) == type);
! return tem;
! }
return build3 (code, type, op0, op1, op2);
}
More information about the Gcc-patches
mailing list