public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add GIMPLE type verifier enabled for stage1
@ 2007-07-25 16:02 Richard Guenther
  2007-07-25 16:59 ` Diego Novillo
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Guenther @ 2007-07-25 16:02 UTC (permalink / raw)
  To: gcc-patches


This adds the GIMPLE type verifier and enables it as an extra checking
target named 'types' which gets enabled for stage1 only at the moment.

Bootstrapped and tested on x86_64-unknown-linux-gnu.  Ok for mainline?

I verified that the stage1_checking flags are sane with various
combinations of enable/disable{-stage1}-checking options.

Thanks,
Richard.


2007-07-13  Richard Guenther  <rguenther@suse.de>

	toplev/
	* configure.ac: Add types checking to stage1 checking flags.
	* configure: Regenerate.

	* tree-cfg.c (verify_gimple_unary_expr, verify_gimple_binary_expr,
	verify_gimple_min_lval, verify_gimple_reference, verify_gimple_expr,
	verify_gimple_modify_stmt, verify_gimple_stmt, verify_gimple_1,
	verify_gimple): New functions.
	* tree-flow.h (verify_gimple): Declare.
	(verify_gimple_1): Declare.
	* gimplify.c (cpt_same_type): Remove.
	(gimplify_addr_expr): Remove checking code.
	(check_pointer_types_r): Remove.
	(gimplify_body): Call verify_gimple_1 instead of check_pointer_types_r.
	Only verify if there were no errors.
	* configure.ac: Add types checking flag.
	* configure: Regenerate.
	* config.in: Regenerate.

Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/tree-cfg.c	2007-07-25 14:49:32.000000000 +0200
*************** verify_expr (tree *tp, int *walk_subtree
*** 3346,3351 ****
--- 3346,4056 ----
  #undef CHECK_OP
  }
  
+ /* Verifies if EXPR is a valid GIMPLE unary expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_unary_expr (tree expr)
+ {
+   tree op = TREE_OPERAND (expr, 0);
+   tree type = TREE_TYPE (expr);
+ 
+   if (!is_gimple_val (op))
+     {
+       error ("invalid operand in unary expression");
+       return true;
+     }
+ 
+   /* For general unary expressions we have the operantions type
+      as the effective type the operation is carried out on.  So all
+      we need to require is that the operand is trivially convertible
+      to that type.  */
+   if (!useless_type_conversion_p (type, TREE_TYPE (op)))
+     {
+       error ("type mismatch in unary expression");
+       debug_generic_expr (type);
+       debug_generic_expr (TREE_TYPE (op));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verifies if EXPR is a valid GIMPLE binary expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_binary_expr (tree expr)
+ {
+   tree op0 = TREE_OPERAND (expr, 0);
+   tree op1 = TREE_OPERAND (expr, 1);
+   tree type = TREE_TYPE (expr);
+ 
+   if (!is_gimple_val (op0) || !is_gimple_val (op1))
+     {
+       error ("invalid operands in binary expression");
+       return true;
+     }
+ 
+   /* For general binary expressions we have the operantions type
+      as the effective type the operation is carried out on.  So all
+      we need to require is that both operands are trivially convertible
+      to that type.  */
+   if (!useless_type_conversion_p (type, TREE_TYPE (op0))
+       || !useless_type_conversion_p (type, TREE_TYPE (op1)))
+     {
+       error ("type mismatch in binary expression");
+       debug_generic_stmt (type);
+       debug_generic_stmt (TREE_TYPE (op0));
+       debug_generic_stmt (TREE_TYPE (op1));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify if EXPR is either a GIMPLE ID or a GIMPLE indirect reference.
+    Returns true if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_min_lval (tree expr)
+ {
+   tree op;
+ 
+   if (is_gimple_id (expr))
+     return false;
+ 
+   if (TREE_CODE (expr) != INDIRECT_REF
+       && TREE_CODE (expr) != ALIGN_INDIRECT_REF
+       && TREE_CODE (expr) != MISALIGNED_INDIRECT_REF)
+     {
+       error ("invalid expression for min lvalue");
+       return true;
+     }
+ 
+   op = TREE_OPERAND (expr, 0);
+   if (!is_gimple_val (op))
+     {
+       error ("invalid operand in indirect reference");
+       debug_generic_stmt (op);
+       return true;
+     }
+   if (!useless_type_conversion_p (TREE_TYPE (expr),
+ 				  TREE_TYPE (TREE_TYPE (op))))
+     {
+       error ("type mismatch in indirect reference");
+       debug_generic_stmt (TREE_TYPE (expr));
+       debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify if EXPR is a valid GIMPLE reference expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_reference (tree expr)
+ {
+   while (handled_component_p (expr))
+     {
+       tree op = TREE_OPERAND (expr, 0);
+ 
+       if (TREE_CODE (expr) == ARRAY_REF
+ 	  || TREE_CODE (expr) == ARRAY_RANGE_REF)
+ 	{
+ 	  if (!is_gimple_val (TREE_OPERAND (expr, 1))
+ 	      || (TREE_OPERAND (expr, 2)
+ 		  && !is_gimple_val (TREE_OPERAND (expr, 2)))
+ 	      || (TREE_OPERAND (expr, 3)
+ 		  && !is_gimple_val (TREE_OPERAND (expr, 3))))
+ 	    {
+ 	      error ("invalid operands to array reference");
+ 	      debug_generic_stmt (expr);
+ 	      return true;
+ 	    }
+ 	}
+ 
+       /* Verify if the reference array element types are compatible.  */
+       if (TREE_CODE (expr) == ARRAY_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in array reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+       if (TREE_CODE (expr) == ARRAY_RANGE_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (expr)),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in array range reference");
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (expr)));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+ 
+       if ((TREE_CODE (expr) == REALPART_EXPR
+ 	   || TREE_CODE (expr) == IMAGPART_EXPR)
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in real/imagpart reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+ 
+       if (TREE_CODE (expr) == COMPONENT_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_OPERAND (expr, 1))))
+ 	{
+ 	  error ("type mismatch in component reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1)));
+ 	  return true;
+ 	}
+ 
+       /* For VIEW_CONVERT_EXPRs which are allowed here, too, there
+ 	 is nothing to verify.  Gross mismatches at most invoke
+ 	 undefined behavior.  */
+ 
+       expr = op;
+     }
+ 
+   return verify_gimple_min_lval (expr);
+ }
+ 
+ /* Verify the GIMPLE expression EXPR.  Returns true if there is an
+    error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_expr (tree expr)
+ {
+   tree type = TREE_TYPE (expr);
+ 
+   if (is_gimple_val (expr))
+     return false;
+ 
+   /* Special codes we cannot handle via their class.  */
+   switch (TREE_CODE (expr))
+     {
+     case NOP_EXPR:
+     case CONVERT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in conversion");
+ 	    return true;
+ 	  }
+ 
+ 	/* Allow conversions between integral types.  */
+         if (INTEGRAL_TYPE_P (type) == INTEGRAL_TYPE_P (TREE_TYPE (op)))
+ 	  return false;
+ 
+ 	/* Allow conversions between integral types and pointers only if
+ 	   there is no sign or zero extension involved.  */
+ 	if (((POINTER_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (op)))
+ 	     || (POINTER_TYPE_P (TREE_TYPE (op)) && INTEGRAL_TYPE_P (type)))
+ 	    && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op)))
+ 	  return false;
+ 
+ 	/* Allow conversion from integer to offset type and vice versa.  */
+ 	if ((TREE_CODE (type) == OFFSET_TYPE
+ 	     && TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE)
+ 	    || (TREE_CODE (type) == INTEGER_TYPE
+ 		&& TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE))
+ 	  return false;
+ 
+ 	/* Otherwise assert we are converting between types of the
+ 	   same kind.  */
+ 	if (TREE_CODE (type) != TREE_CODE (TREE_TYPE (op)))
+ 	  {
+ 	    error ("invalid types in nop conversion");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case FLOAT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in int to float conversion");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op))
+ 	    || !SCALAR_FLOAT_TYPE_P (type))
+ 	  {
+ 	    error ("invalid types in conversion to floating point");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+         return false;
+       }
+ 
+     case FIX_TRUNC_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in float to int conversion");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (type)
+ 	    || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
+ 	  {
+ 	    error ("invalid types in conversion to integer");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+         return false;
+       }
+ 
+     case COMPLEX_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in complex expression");
+ 	    return true;
+ 	  }
+ 	if (!TREE_CODE (type) == COMPLEX_TYPE
+ 	    || !(TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+ 	         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)))
+ 	    || !(TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE
+ 	         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (op1)))
+ 	    || !useless_type_conversion_p (TREE_TYPE (type),
+ 					   TREE_TYPE (op0))
+ 	    || !useless_type_conversion_p (TREE_TYPE (type),
+ 					   TREE_TYPE (op1)))
+ 	  {
+ 	    error ("type mismatch in complex expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case CONSTRUCTOR:
+       {
+ 	/* This is used like COMPLEX_EXPR but for vectors.  */
+ 	if (TREE_CODE (type) != VECTOR_TYPE)
+ 	  {
+ 	    error ("constructor not allowed for non-vector types");
+ 	    debug_generic_stmt (type);
+ 	    return true;
+ 	  }
+ 	/* FIXME: verify constructor arguments.  */
+ 	return false;
+       }
+ 
+     case LSHIFT_EXPR:
+     case RSHIFT_EXPR:
+     case LROTATE_EXPR:
+     case RROTATE_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in shift expression");
+ 	    return true;
+ 	  }
+ 	if (!TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE
+ 	    || !useless_type_conversion_p (type, TREE_TYPE (op0)))
+ 	  {
+ 	    error ("type mismatch in shift expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case PLUS_EXPR:
+     case MINUS_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (POINTER_TYPE_P (type)
+ 	    || POINTER_TYPE_P (TREE_TYPE (op0))
+ 	    || POINTER_TYPE_P (TREE_TYPE (op1)))
+ 	  {
+ 	    error ("invalid (pointer) operands to plus/minus");
+ 	    return true;
+ 	  }
+ 	/* Continue with generic binary expression handling.  */
+ 	break;
+       }
+ 
+     case POINTER_PLUS_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+       	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in pointer plus expression");
+ 	    return true;
+ 	  }
+ 	if (!POINTER_TYPE_P (TREE_TYPE (op0))
+ 	    || TREE_CODE (TREE_TYPE (op1)) != INTEGER_TYPE
+ 	    || !useless_type_conversion_p (type, TREE_TYPE (op0))
+ 	    || !useless_type_conversion_p (sizetype, TREE_TYPE (op1)))
+ 	  {
+ 	    error ("type mismatch in pointer plus expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case COND_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	tree op2 = TREE_OPERAND (expr, 2);
+ 	if ((!is_gimple_val (op1)
+ 	     && TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
+ 	    || (!is_gimple_val (op2)
+ 		&& TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE))
+ 	  {
+ 	    error ("invalid operands in conditional expression");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ 	    || (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE
+ 	        && !useless_type_conversion_p (type, TREE_TYPE (op1)))
+ 	    || (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE
+ 	        && !useless_type_conversion_p (type, TREE_TYPE (op2))))
+ 	  {
+ 	    error ("type mismatch in conditional expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    debug_generic_stmt (TREE_TYPE (op2));
+ 	    return true;
+ 	  }
+ 	return verify_gimple_expr (op0);
+       }
+ 
+     case ADDR_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	tree ptr_type;
+ 	if (!is_gimple_addressable (op))
+ 	  {
+ 	    error ("invalid operand in unary expression");
+ 	    return true;
+ 	  }
+ 	ptr_type = build_pointer_type (TREE_TYPE (op));
+ 	if (!useless_type_conversion_p (type, ptr_type)
+ 	    /* FIXME: a longstanding wart, &a == &a[0].  */
+ 	    && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
+ 		|| !useless_type_conversion_p (type,
+ 			build_pointer_type (TREE_TYPE (TREE_TYPE (op))))))
+ 	  {
+ 	    error ("type mismatch in address expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (ptr_type);
+ 	    return true;
+ 	  }
+ 
+ 	return verify_gimple_reference (op);
+       }
+ 
+     case TRUTH_ANDIF_EXPR:
+     case TRUTH_ORIF_EXPR:
+     case TRUTH_AND_EXPR:
+     case TRUTH_OR_EXPR:
+     case TRUTH_XOR_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 
+       	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in truth expression");
+ 	    return true;
+ 	  }
+ 
+ 	/* We allow any kind of integral typed argument and result.  */
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ 	    || !INTEGRAL_TYPE_P (TREE_TYPE (op1))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in binary truth expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case TRUTH_NOT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in unary not");
+ 	    return true;
+ 	  }
+ 
+ 	/* For TRUTH_NOT_EXPR we can have any kind of integral
+ 	   typed arguments and results.  */
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in not expression");
+ 	    debug_generic_expr (TREE_TYPE (expr));
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case CALL_EXPR:
+       /* FIXME.  This is going to be difficult with non-unit-at-a-time
+ 	 gimplifying.  */
+       return false;
+ 
+     default:;
+     }
+ 
+   /* Generic handling via classes.  */
+   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
+     {
+     case tcc_unary:
+       return verify_gimple_unary_expr (expr);
+ 
+     case tcc_binary:
+       return verify_gimple_binary_expr (expr);
+ 
+     case tcc_reference:
+       return verify_gimple_reference (expr);
+ 
+     case tcc_comparison:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in comparison expression");
+ 	    return true;
+ 	  }
+ 	/* For comparisons we do not have the operations type as the
+ 	   effective type the comparison is carried out in.  Instead
+ 	   we require that either the first operand is trivially
+ 	   convertible into the second, or the other way around.
+ 	   The resulting type of a comparison may be any integral type.
+ 	   Because we special-case pointers to void we allow
+ 	   comparisons of pointers with the same mode as well.  */
+ 	if ((!useless_type_conversion_p (TREE_TYPE (op0), TREE_TYPE (op1))
+ 	     && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))
+ 	     && (!POINTER_TYPE_P (TREE_TYPE (op0))
+ 		 || !POINTER_TYPE_P (TREE_TYPE (op1))
+ 		 || TYPE_MODE (TREE_TYPE (op0)) != TYPE_MODE (TREE_TYPE (op1))))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in comparison expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+         break;
+       }
+ 
+     default:
+       gcc_unreachable ();
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify the GIMPLE assignment statement STMT.  Returns true if there
+    is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_modify_stmt (tree stmt)
+ {
+   tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+   tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+ 
+   gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
+ 
+   if (!useless_type_conversion_p (TREE_TYPE (lhs),
+ 				  TREE_TYPE (rhs)))
+     {
+       error ("non-trivial conversion at assignment");
+       debug_generic_expr (TREE_TYPE (lhs));
+       debug_generic_expr (TREE_TYPE (rhs));
+       return true;
+     }
+ 
+   /* Loads/stores from/to a variable are ok.  */
+   if ((is_gimple_val (lhs)
+        && is_gimple_variable (rhs))
+       || (is_gimple_val (rhs)
+ 	  && is_gimple_variable (lhs)))
+     return false;
+ 
+   /* Aggregate copies are ok.  */
+   if (!is_gimple_reg_type (TREE_TYPE (lhs))
+       && !is_gimple_reg_type (TREE_TYPE (rhs)))
+     return false;
+ 
+   /* We might get 'loads' from a parameter which is not a gimple value.  */
+   if (TREE_CODE (rhs) == PARM_DECL)
+     return verify_gimple_expr (lhs);
+ 
+   if (!is_gimple_variable (lhs)
+       && verify_gimple_expr (lhs))
+     return true;
+ 
+   if (!is_gimple_variable (rhs)
+       && verify_gimple_expr (rhs))
+     return true;
+ 
+   return false;
+   /*return verify_gimple_expr (rhs) || verify_gimple_expr (lhs);*/
+ }
+ 
+ /* Verify the GIMPLE statement STMT.  Returns true if there is an
+    error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_stmt (tree stmt)
+ {
+   if (!is_gimple_stmt (stmt))
+     {
+       error ("is not a valid GIMPLE statement");
+       return true;
+     }
+ 
+   if (OMP_DIRECTIVE_P (stmt))
+     {
+       /* OpenMP directives are validated by the FE and never operated
+ 	 on by the optimizers.  Furthermore, OMP_FOR may contain
+ 	 non-gimple expressions when the main index variable has had
+ 	 its address taken.  This does not affect the loop itself
+ 	 because the header of an OMP_FOR is merely used to determine
+ 	 how to setup the parallel iteration.  */
+       return false;
+     }
+ 
+   switch (TREE_CODE (stmt))
+     {
+     case GIMPLE_MODIFY_STMT:
+       return verify_gimple_modify_stmt (stmt);
+ 
+     case GOTO_EXPR:
+     case LABEL_EXPR:
+       return false;
+ 
+     case SWITCH_EXPR:
+       if (!is_gimple_val (TREE_OPERAND (stmt, 0)))
+ 	{
+ 	  error ("invalid operand to switch statement");
+ 	  debug_generic_expr (TREE_OPERAND (stmt, 0));
+ 	}
+       return false;
+ 
+     case RETURN_EXPR:
+       {
+ 	tree op = TREE_OPERAND (stmt, 0);
+ 
+ 	if (TREE_CODE (TREE_TYPE (stmt)) != VOID_TYPE)
+ 	  {
+ 	    error ("type error in return expression");
+ 	    return true;
+ 	  }
+ 
+ 	if (op == NULL_TREE
+ 	    || TREE_CODE (op) == RESULT_DECL)
+ 	  return false;
+ 
+ 	return verify_gimple_modify_stmt (op);
+       }
+ 
+     case CALL_EXPR:
+     case COND_EXPR:
+       return verify_gimple_expr (stmt);
+ 
+     case NOP_EXPR:
+     case CHANGE_DYNAMIC_TYPE_EXPR:
+     case ASM_EXPR:
+       return false;
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ /* Verify the GIMPLE statements inside the statement list STMTS.  */
+ 
+ void
+ verify_gimple_1 (tree stmts)
+ {
+   tree_stmt_iterator tsi;
+ 
+   for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
+     {
+       tree stmt = tsi_stmt (tsi);
+ 
+       switch (TREE_CODE (stmt))
+ 	{
+ 	case BIND_EXPR:
+ 	  verify_gimple_1 (BIND_EXPR_BODY (stmt));
+ 	  break;
+ 
+ 	case TRY_CATCH_EXPR:
+ 	case TRY_FINALLY_EXPR:
+ 	  verify_gimple_1 (TREE_OPERAND (stmt, 0));
+ 	  verify_gimple_1 (TREE_OPERAND (stmt, 1));
+ 	  break;
+ 
+ 	case CATCH_EXPR:
+ 	  verify_gimple_1 (CATCH_BODY (stmt));
+ 	  break;
+ 
+ 	case EH_FILTER_EXPR:
+ 	  verify_gimple_1 (EH_FILTER_FAILURE (stmt));
+ 	  break;
+ 
+ 	default:
+ 	  if (verify_gimple_stmt (stmt))
+ 	    debug_generic_expr (stmt);
+ 	}
+     }
+ }
+ 
+ /* Verify the GIMPLE statements inside the current function.  */
+ 
+ void
+ verify_gimple (void)
+ {
+   verify_gimple_1 (BIND_EXPR_BODY (DECL_SAVED_TREE (cfun->decl)));
+ }
  
  /* Verify STMT, return true if STMT is not in GIMPLE form.
     TODO: Implement type checking.  */
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/tree-flow.h	2007-07-25 14:49:32.000000000 +0200
*************** extern void bsi_commit_edge_inserts (voi
*** 753,758 ****
--- 753,760 ----
  extern void notice_special_calls (tree);
  extern void clear_special_calls (void);
  extern void verify_stmts (void);
+ extern void verify_gimple (void);
+ extern void verify_gimple_1 (tree);
  extern tree tree_block_label (basic_block);
  extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
  extern bool tree_duplicate_sese_region (edge, edge, basic_block *, unsigned,
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/gimplify.c	2007-07-25 14:49:32.000000000 +0200
*************** typedef struct gimple_temp_hash_elt
*** 113,121 ****
  
  /* Forward declarations.  */
  static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
- #ifdef ENABLE_CHECKING
- static bool cpt_same_type (tree a, tree b);
- #endif
  
  /* Mark X addressable.  Unlike the langhook we expect X to be in gimple
     form and we don't do any syntax checking.  */
--- 113,118 ----
*************** gimplify_addr_expr (tree *expr_p, tree *
*** 3986,4004 ****
  	tree t_op00 = TREE_TYPE (op00);
  
          if (!useless_type_conversion_p (t_expr, t_op00))
! 	  {
! #ifdef ENABLE_CHECKING
! 	    tree t_op0 = TREE_TYPE (op0);
! 	    gcc_assert (POINTER_TYPE_P (t_expr)
! 			&& (cpt_same_type (TREE_TYPE (t_expr), t_op0)
! 			    || (TREE_CODE (t_op0) == ARRAY_TYPE
! 				&& cpt_same_type (TREE_TYPE (t_expr),
! 						  TREE_TYPE (t_op0))))
! 			&& POINTER_TYPE_P (t_op00)
! 			&& cpt_same_type (t_op0, TREE_TYPE (t_op00)));
! #endif
! 	    op00 = fold_convert (TREE_TYPE (expr), op00);
! 	  }
          *expr_p = op00;
          ret = GS_OK;
        }
--- 3983,3989 ----
  	tree t_op00 = TREE_TYPE (op00);
  
          if (!useless_type_conversion_p (t_expr, t_op00))
! 	  op00 = fold_convert (TREE_TYPE (expr), op00);
          *expr_p = op00;
          ret = GS_OK;
        }
*************** gimplify_one_sizepos (tree *expr_p, tree
*** 6394,6477 ****
      }
  }
  \f
- #ifdef ENABLE_CHECKING
- /* Compare types A and B for a "close enough" match.  */
- 
- static bool
- cpt_same_type (tree a, tree b)
- {
-   if (useless_type_conversion_p (a, b))
-     return true;
- 
-   /* ??? The C++ FE decomposes METHOD_TYPES to FUNCTION_TYPES and doesn't
-      link them together.  This routine is intended to catch type errors
-      that will affect the optimizers, and the optimizers don't add new
-      dereferences of function pointers, so ignore it.  */
-   if ((TREE_CODE (a) == FUNCTION_TYPE || TREE_CODE (a) == METHOD_TYPE)
-       && (TREE_CODE (b) == FUNCTION_TYPE || TREE_CODE (b) == METHOD_TYPE))
-     return true;
- 
-   /* ??? The C FE pushes type qualifiers after the fact into the type of
-      the element from the type of the array.  See build_unary_op's handling
-      of ADDR_EXPR.  This seems wrong -- if we were going to do this, we
-      should have done it when creating the variable in the first place.
-      Alternately, why aren't the two array types made variants?  */
-   if (TREE_CODE (a) == ARRAY_TYPE && TREE_CODE (b) == ARRAY_TYPE)
-     return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b));
- 
-   /* And because of those, we have to recurse down through pointers.  */
-   if (POINTER_TYPE_P (a) && POINTER_TYPE_P (b))
-     return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b));
- 
-   return false;
- }
- 
- /* Check for some cases of the front end missing cast expressions.
-    The type of a dereference should correspond to the pointer type;
-    similarly the type of an address should match its object.  */
- 
- static tree
- check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- 		       void *data ATTRIBUTE_UNUSED)
- {
-   tree t = *tp;
-   tree ptype, otype, dtype;
- 
-   switch (TREE_CODE (t))
-     {
-     case INDIRECT_REF:
-     case ARRAY_REF:
-       otype = TREE_TYPE (t);
-       ptype = TREE_TYPE (TREE_OPERAND (t, 0));
-       dtype = TREE_TYPE (ptype);
-       gcc_assert (cpt_same_type (otype, dtype));
-       break;
- 
-     case ADDR_EXPR:
-       ptype = TREE_TYPE (t);
-       otype = TREE_TYPE (TREE_OPERAND (t, 0));
-       dtype = TREE_TYPE (ptype);
-       if (!cpt_same_type (dtype, otype))
- 	{
- 	  /* &array is allowed to produce a pointer to the element, rather than
- 	     a pointer to the array type.  We must allow this in order to
- 	     properly represent assigning the address of an array in C into
- 	     pointer to the element type.  */
- 	  gcc_assert (TREE_CODE (otype) == ARRAY_TYPE
- 		      && POINTER_TYPE_P (ptype)
- 		      && cpt_same_type (dtype, TREE_TYPE (otype)));
- 	  break;
- 	}
-       break;
- 
-     default:
-       return NULL_TREE;
-     }
- 
- 
-   return NULL_TREE;
- }
- #endif
  
  /* Gimplify the body of statements pointed to by BODY_P.  FNDECL is the
     function decl containing BODY.  */
--- 6379,6384 ----
*************** gimplify_body (tree *body_p, tree fndecl
*** 6540,6547 ****
    pop_gimplify_context (body);
    gcc_assert (gimplify_ctxp == NULL);
  
! #ifdef ENABLE_CHECKING
!   walk_tree (body_p, check_pointer_types_r, NULL, NULL);
  #endif
  
    timevar_pop (TV_TREE_GIMPLIFY);
--- 6447,6455 ----
    pop_gimplify_context (body);
    gcc_assert (gimplify_ctxp == NULL);
  
! #ifdef ENABLE_TYPES_CHECKING
!   if (!errorcount && !sorrycount)
!     verify_gimple_1 (BIND_EXPR_BODY (*body_p));
  #endif
  
    timevar_pop (TV_TREE_GIMPLIFY);
Index: gcc/config.in
===================================================================
*** gcc/config.in.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/config.in	2007-07-25 14:49:32.000000000 +0200
***************
*** 121,126 ****
--- 121,132 ----
  #endif
  
  
+ /* Define if you want all gimple types to be verified after gimplifiation. */
+ #ifndef USED_FOR_TARGET
+ #undef ENABLE_TYPES_CHECKING
+ #endif
+ 
+ 
  /* Define if you want to run subprograms and generated programs through
     valgrind (a memory checker). This is extremely expensive. */
  #ifndef USED_FOR_TARGET
Index: gcc/configure
===================================================================
*** gcc/configure.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/configure	2007-07-25 14:49:32.000000000 +0200
*************** Optional Features:
*** 868,874 ****
  			  enable only specific categories of checks.
  			  Categories are: yes,no,all,none,release.
  			  Flags are: assert,df,fold,gc,gcac,misc,
! 			  rtlflag,rtl,runtime,tree,valgrind.
    --enable-mapped-location   location_t is fileline integer cookie
    --enable-coverage=LEVEL
  			  enable compiler's code coverage collection.
--- 868,874 ----
  			  enable only specific categories of checks.
  			  Categories are: yes,no,all,none,release.
  			  Flags are: assert,df,fold,gc,gcac,misc,
! 			  rtlflag,rtl,runtime,tree,valgrind,types.
    --enable-mapped-location   location_t is fileline integer cookie
    --enable-coverage=LEVEL
  			  enable compiler's code coverage collection.
*************** do
*** 6429,6450 ****
  			ac_fold_checking= ; ac_gc_checking=1 ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;;
  	no|none)	ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking= ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;;
  	all)		ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
  			ac_fold_checking=1 ; ac_gc_checking=1 ;
  			ac_gc_always_collect=1 ; ac_rtl_checking=1 ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;;
  	release)	ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking=1 ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;;
  	# these enable particular checks
  	assert) 	ac_assert_checking=1 ;;
  	df)	 	ac_df_checking=1 ;;
--- 6429,6454 ----
  			ac_fold_checking= ; ac_gc_checking=1 ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	no|none)	ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking= ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	all)		ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
  			ac_fold_checking=1 ; ac_gc_checking=1 ;
  			ac_gc_always_collect=1 ; ac_rtl_checking=1 ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;
! 			ac_types_checking=1 ;;
  	release)	ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking=1 ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	# these enable particular checks
  	assert) 	ac_assert_checking=1 ;;
  	df)	 	ac_df_checking=1 ;;
*************** do
*** 6456,6461 ****
--- 6460,6466 ----
  	rtlflag)	ac_rtlflag_checking=1 ;;
  	runtime)	ac_runtime_checking=1 ;;
  	tree)		ac_tree_checking=1 ;;
+ 	types)		ac_types_checking=1 ;;
  	valgrind)	ac_valgrind_checking=1 ;;
  	*)	{ { echo "$as_me:$LINENO: error: unknown check category $check" >&5
  echo "$as_me: error: unknown check category $check" >&2;}
*************** _ACEOF
*** 6504,6509 ****
--- 6509,6521 ----
  
    TREEBROWSER=tree-browser.o
  fi
+ if test x$ac_types_checking != x ; then
+ 
+ cat >>confdefs.h <<\_ACEOF
+ #define ENABLE_TYPES_CHECKING 1
+ _ACEOF
+ 
+ fi
  
  if test x$ac_rtl_checking != x ; then
  
Index: gcc/configure.ac
===================================================================
*** gcc/configure.ac.orig	2007-07-25 14:46:45.000000000 +0200
--- gcc/configure.ac	2007-07-25 14:49:32.000000000 +0200
*************** AC_ARG_ENABLE(checking,
*** 347,353 ****
  			  enable only specific categories of checks.
  			  Categories are: yes,no,all,none,release.
  			  Flags are: assert,df,fold,gc,gcac,misc,
! 			  rtlflag,rtl,runtime,tree,valgrind.],
  [ac_checking_flags="${enableval}"],[
  # Determine the default checks.
  if test x$is_release = x ; then
--- 347,353 ----
  			  enable only specific categories of checks.
  			  Categories are: yes,no,all,none,release.
  			  Flags are: assert,df,fold,gc,gcac,misc,
! 			  rtlflag,rtl,runtime,tree,valgrind,types.],
  [ac_checking_flags="${enableval}"],[
  # Determine the default checks.
  if test x$is_release = x ; then
*************** do
*** 364,385 ****
  			ac_fold_checking= ; ac_gc_checking=1 ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;;
  	no|none)	ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking= ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;;
  	all)		ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
  			ac_fold_checking=1 ; ac_gc_checking=1 ;
  			ac_gc_always_collect=1 ; ac_rtl_checking=1 ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;;
  	release)	ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking=1 ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;;
  	# these enable particular checks
  	assert) 	ac_assert_checking=1 ;;
  	df)	 	ac_df_checking=1 ;;
--- 364,389 ----
  			ac_fold_checking= ; ac_gc_checking=1 ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	no|none)	ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking= ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	all)		ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
  			ac_fold_checking=1 ; ac_gc_checking=1 ;
  			ac_gc_always_collect=1 ; ac_rtl_checking=1 ;
  			ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
! 			ac_tree_checking=1 ; ac_valgrind_checking= ;
! 			ac_types_checking=1 ;;
  	release)	ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
  			ac_fold_checking= ; ac_gc_checking= ;
  			ac_gc_always_collect= ; ac_rtl_checking= ;
  			ac_rtlflag_checking= ; ac_runtime_checking=1 ;
! 			ac_tree_checking= ; ac_valgrind_checking= ;
! 			ac_types_checking= ;;
  	# these enable particular checks
  	assert) 	ac_assert_checking=1 ;;
  	df)	 	ac_df_checking=1 ;;
*************** do
*** 391,396 ****
--- 395,401 ----
  	rtlflag)	ac_rtlflag_checking=1 ;;
  	runtime)	ac_runtime_checking=1 ;;
  	tree)		ac_tree_checking=1 ;;
+ 	types)		ac_types_checking=1 ;;
  	valgrind)	ac_valgrind_checking=1 ;;
  	*)	AC_MSG_ERROR(unknown check category $check) ;;
  	esac
*************** if test x$ac_tree_checking != x ; then
*** 427,432 ****
--- 432,443 ----
     ])
    TREEBROWSER=tree-browser.o
  fi
+ if test x$ac_types_checking != x ; then
+   AC_DEFINE(ENABLE_TYPES_CHECKING, 1,
+ [Define if you want all gimple types to be verified after gimplifiation.
+    This is cheap.
+    ])
+ fi
  AC_SUBST(TREEBROWSER)
  if test x$ac_rtl_checking != x ; then
    AC_DEFINE(ENABLE_RTL_CHECKING, 1,
Index: configure
===================================================================
*** configure.orig	2007-07-25 14:46:45.000000000 +0200
--- configure	2007-07-25 14:49:32.000000000 +0200
*************** if test "${enable_stage1_checking+set}" 
*** 11967,11975 ****
    stage1_checking=--enable-checking=${enable_stage1_checking}
  else
    if test "x$enable_checking" = xno; then
!   stage1_checking=--enable-checking
  else
!   stage1_checking=--enable-checking${enable_checking+=}$enable_checking
  fi
  fi;
  
--- 11967,11975 ----
    stage1_checking=--enable-checking=${enable_stage1_checking}
  else
    if test "x$enable_checking" = xno; then
!   stage1_checking=--enable-checking=yes,types
  else
!   stage1_checking=--enable-checking=types${enable_checking+,}$enable_checking
  fi
  fi;
  
Index: configure.ac
===================================================================
*** configure.ac.orig	2007-07-25 14:46:45.000000000 +0200
--- configure.ac	2007-07-25 14:49:32.000000000 +0200
*************** AC_ARG_ENABLE(stage1-checking,
*** 2593,2601 ****
                            of the compiler],
  [stage1_checking=--enable-checking=${enable_stage1_checking}],
  [if test "x$enable_checking" = xno; then
!   stage1_checking=--enable-checking
  else
!   stage1_checking=--enable-checking${enable_checking+=}$enable_checking
  fi])
  AC_SUBST(stage1_checking)
  
--- 2593,2601 ----
                            of the compiler],
  [stage1_checking=--enable-checking=${enable_stage1_checking}],
  [if test "x$enable_checking" = xno; then
!   stage1_checking=--enable-checking=yes,types
  else
!   stage1_checking=--enable-checking=types${enable_checking+,}$enable_checking
  fi])
  AC_SUBST(stage1_checking)
  

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add GIMPLE type verifier enabled for stage1
  2007-07-25 16:02 [PATCH] Add GIMPLE type verifier enabled for stage1 Richard Guenther
@ 2007-07-25 16:59 ` Diego Novillo
  2007-07-26  9:26   ` Richard Guenther
  0 siblings, 1 reply; 3+ messages in thread
From: Diego Novillo @ 2007-07-25 16:59 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On 7/25/07 12:04 PM, Richard Guenther wrote:

> 	toplev/
> 	* configure.ac: Add types checking to stage1 checking flags.
> 	* configure: Regenerate.
> 
> 	* tree-cfg.c (verify_gimple_unary_expr, verify_gimple_binary_expr,
> 	verify_gimple_min_lval, verify_gimple_reference, verify_gimple_expr,
> 	verify_gimple_modify_stmt, verify_gimple_stmt, verify_gimple_1,
> 	verify_gimple): New functions.
> 	* tree-flow.h (verify_gimple): Declare.
> 	(verify_gimple_1): Declare.
> 	* gimplify.c (cpt_same_type): Remove.
> 	(gimplify_addr_expr): Remove checking code.
> 	(check_pointer_types_r): Remove.
> 	(gimplify_body): Call verify_gimple_1 instead of check_pointer_types_r.
> 	Only verify if there were no errors.
> 	* configure.ac: Add types checking flag.
> 	* configure: Regenerate.
> 	* config.in: Regenerate.

Good stuff.  OK with:


> +     case CALL_EXPR:
> +       /* FIXME.  This is going to be difficult with non-unit-at-a-time
> + 	 gimplifying.  */
> +       return false;

Why?  The comment is not too clear.

> +   return false;
> +   /*return verify_gimple_expr (rhs) || verify_gimple_expr (lhs);*/
> + }

Remove the commented code.  Or at most add a FIXME note stating why we
can't do the recursion.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add GIMPLE type verifier enabled for stage1
  2007-07-25 16:59 ` Diego Novillo
@ 2007-07-26  9:26   ` Richard Guenther
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Guenther @ 2007-07-26  9:26 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches

On Wed, 25 Jul 2007, Diego Novillo wrote:

> On 7/25/07 12:04 PM, Richard Guenther wrote:
> 
> > 	toplev/
> > 	* configure.ac: Add types checking to stage1 checking flags.
> > 	* configure: Regenerate.
> > 
> > 	* tree-cfg.c (verify_gimple_unary_expr, verify_gimple_binary_expr,
> > 	verify_gimple_min_lval, verify_gimple_reference, verify_gimple_expr,
> > 	verify_gimple_modify_stmt, verify_gimple_stmt, verify_gimple_1,
> > 	verify_gimple): New functions.
> > 	* tree-flow.h (verify_gimple): Declare.
> > 	(verify_gimple_1): Declare.
> > 	* gimplify.c (cpt_same_type): Remove.
> > 	(gimplify_addr_expr): Remove checking code.
> > 	(check_pointer_types_r): Remove.
> > 	(gimplify_body): Call verify_gimple_1 instead of check_pointer_types_r.
> > 	Only verify if there were no errors.
> > 	* configure.ac: Add types checking flag.
> > 	* configure: Regenerate.
> > 	* config.in: Regenerate.
> 
> Good stuff.  OK with:
> 
> 
> > +     case CALL_EXPR:
> > +       /* FIXME.  This is going to be difficult with non-unit-at-a-time
> > + 	 gimplifying.  */
> > +       return false;
> 
> Why?  The comment is not too clear.

I'll extend/change it to

  /* FIXME.  The C frontend passes unpromoted arguments in case it
     didn't see a function declaration before the call.  */

which is the only problem I am aware of, but really I didn't try to
do any verification here yet.

> 
> > +   return false;
> > +   /*return verify_gimple_expr (rhs) || verify_gimple_expr (lhs);*/
> > + }
> 
> Remove the commented code.  Or at most add a FIXME note stating why we
> can't do the recursion.

I'll remove the commented code, the recursion is dealt with before.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-07-26  9:24 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-25 16:02 [PATCH] Add GIMPLE type verifier enabled for stage1 Richard Guenther
2007-07-25 16:59 ` Diego Novillo
2007-07-26  9:26   ` 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).