[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