This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [tree-ssa] verify cond_expr condition type


> > On Sat, 17 Jan 2004 23:53:32 +0100, Jan Hubicka <hubicka@ucw.cz> wrote:
> > 
> > >> As discussed re one of law's dominator changes.  Fortunately my fears
> > >> were unfounded and bootstrap and check passes with this installed.
> > >
> > > Nice, but would be perhaps better to go for my verify_gimple_grammar
> > > patch?  That should be place for such a checks to go
> > > (it don't do this check in current incarnation)
> > 
> > It makes sense for me to keep the logic about what is or is not fully
> > simplified all in the same place, i.e. the gimplifier.  I've had a patch to
> > add a speculative mode to the gimplifier in the works for a while now;
> > sorry I haven't finished it yet.  I'll definitely finish it up this week.
> 
> How this is different from verify_gimple_grammar idea?  It basically
> implements what the grammar specify in separate function.
To be more specific, there is my patch.
I didn't updated it for current tree and re-tested but unless you have
something better to replace it, I will do so today.

Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.63
diff -c -3 -p -r1.1.4.63 tree-simple.c
*** tree-simple.c	4 Dec 2003 02:22:01 -0000	1.1.4.63
--- tree-simple.c	12 Dec 2003 01:26:52 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,35 ----
  #include "output.h"
  #include "rtl.h"
  #include "expr.h"
+ #include "toplev.h"
  
  /* GCC GIMPLE structure
  
*************** is_gimple_stmt (tree t)
*** 371,383 ****
      }
  }
  
  /* Return nonzero if T is a variable.  */
  
  bool
  is_gimple_variable (tree t)
  {
    return (TREE_CODE (t) == VAR_DECL
- 	  || TREE_CODE (t) == PARM_DECL
  	  || TREE_CODE (t) == RESULT_DECL
  	  || TREE_CODE (t) == SSA_NAME);
  }
--- 372,732 ----
      }
  }
  
+ /* Verify that T is valid arugment of addr_expr.  */
+ static bool
+ verify_addr_expr_arg (tree t)
+ {
+   enum tree_code code;
+   bool found = false;
+   bool min_lval = false;
+ 
+   code = TREE_CODE (t);
+   while (code == ARRAY_REF
+          || code == COMPONENT_REF
+ 	 || code == REALPART_EXPR
+ 	 || code == IMAGPART_EXPR)
+     {
+       if (code == ARRAY_REF
+ 	  && !is_gimple_val (TREE_OPERAND (t, 1)))
+ 	  {
+ 	    error ("called function is not ID nor &ID");
+ 	    found = true;
+ 	  }
+       if (code == ARRAY_REF || code == COMPONENT_REF)
+ 	min_lval = true;
+       else
+ 	min_lval = false;
+       t = TREE_OPERAND (t, 0);
+       code = TREE_CODE (t);
+     }
+   if (min_lval)
+     {
+       if (!is_gimple_min_lval (t))
+ 	{
+ 	  error ("COMPONENT_REF/ARRAY_REF arg is not min_lval");
+ 	  found = true;
+ 	}
+     }
+   else
+     {
+       if (!is_gimple_min_lval (t))
+ 	{
+ 	  error ("addr-expr arg is not ID");
+ 	  found = true;
+ 	}
+     }
+   return found;
+ }
+ 
+ /* Verify that T is valid gimple call_expr.  */
+ static bool
+ verify_call_expr (tree t)
+ {
+   bool found = false;
+   tree op;
+   int i = 1;
+ 
+   if (TREE_CODE (t) != CALL_EXPR)
+     abort ();
+ 
+   if (!is_gimple_id (TREE_OPERAND (t, 0))
+       && TREE_CODE (TREE_OPERAND (t, 0)) != INTEGER_CST
+       && (TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
+ 	  || !is_gimple_id (TREE_OPERAND (TREE_OPERAND (t, 0), 0))))
+     {
+       error ("called function is not ID nor &ID");
+       found = true;
+     }
+   for (op = TREE_OPERAND (t, 1); op; op = TREE_CHAIN (op), i++)
+     {
+       if (!is_gimple_val (TREE_VALUE (op))
+ 	  /* A hack to get mark_decls_volatile_r hack working.
+ 	     Once mark_decls_volatile_r goes out, this should go too.  */
+ 	  && ((TREE_CODE (TREE_VALUE (op)) != PARM_DECL
+ 	       && TREE_CODE (TREE_VALUE (op)) != VAR_DECL)
+ 	      || !TREE_THIS_VOLATILE (TREE_VALUE (op))))
+ 	{
+ 	  error ("Operand %i is not val", i);
+ 	  found = true;
+ 	}
+     }
+   return found;
+ }
+ 
+ /* Verify that T is valid gimple modify_expr.  */
+ static bool
+ verify_modify_expr (tree t)
+ {
+   bool found = false;
+   tree lhs = TREE_OPERAND (t, 0);
+   tree rhs = TREE_OPERAND (t, 1);
+   if (TREE_CODE (t) != MODIFY_EXPR)
+     abort ();
+   if (!is_gimple_rhs (rhs))
+     {
+       error ("right hand side of modify_expr is not rhs");
+       found = true;
+     }
+   if (!is_gimple_min_lval (lhs)
+       && verify_addr_expr_arg (lhs))
+     {
+       error ("left hand side of modify_expr is not gimple lval");
+       found = true;
+     }
+ 
+   if (is_gimple_min_invariant (rhs))
+     return found;
+ 
+   /* ??? Probably not valid.  We are producing real/imag part exprs containing
+      array refs and similar.  */
+   if (TREE_CODE (rhs) == REALPART_EXPR
+       || TREE_CODE (rhs) == IMAGPART_EXPR)
+     return found;
+ 
+   switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
+     {
+     case '1':
+       if (!is_gimple_val (TREE_OPERAND (rhs, 0)))
+ 	{
+ 	  error ("operand of unary expression is not val");
+ 	  found = true;
+ 	}
+       break;
+     case '2':
+     case '<':
+       if (!is_gimple_val (TREE_OPERAND (rhs, 0)))
+ 	{
+ 	  error ("operand of binary expression is not val");
+ 	  found = true;
+ 	}
+       if (!is_gimple_val (TREE_OPERAND (rhs, 1)))
+ 	{
+ 	  error ("operand of binarry expression is not val");
+ 	  found = true;
+ 	}
+       break;
+ 
+     default:
+       break;
+     }
+   switch (TREE_CODE (rhs))
+     {
+       case CALL_EXPR:
+ 	found |= verify_call_expr (rhs);
+ 	break;
+       case COND_EXPR:
+ 	/* These are only valid if they're void.  */
+ 	if (VOID_TYPE_P (TREE_TYPE (rhs)))
+ 	  {
+ 	    error ("left hand side cond_expr must not be VOIDmode");
+ 	    found = true;
+ 	  }
+ 	if (TREE_CODE (COND_EXPR_THEN (rhs)) == GOTO_EXPR
+ 	    || TREE_CODE (COND_EXPR_ELSE (rhs)) == GOTO_EXPR)
+ 	  {
+ 	    error ("left hand side cond_expr must contain not goto_expr.");
+ 	    found = true;
+ 	  }
+ 	if (!is_gimple_condexpr (TREE_OPERAND (rhs, 0)))
+ 	  {
+ 	    error ("cond_expr condition is not condexpr");
+ 	    found = true;
+ 	  }
+ 	break;
+       case VA_ARG_EXPR:
+ 	/* FIXME refuse later.  */
+ 	break;
+ 	/* ??? More expression codes to refuse?  */
+       case TRUTH_NOT_EXPR:
+       case TRUTH_AND_EXPR:
+       case TRUTH_OR_EXPR:
+       case TRUTH_XOR_EXPR:
+ 	if (!is_gimple_val (TREE_OPERAND (rhs, 0)))
+ 	  {
+ 	    error ("Non-gimple truth_* expression");
+ 	    found = true;
+ 	  }
+ 	break;
+       case ADDR_EXPR:
+ 	found |= verify_addr_expr_arg (TREE_OPERAND (rhs, 0));
+ 	break;
+       default:
+ 	break;
+     }
+   return found;
+ }
+ 
+ /* Verify that T is valid gimple statement according to the grammar specified
+    above.  */
+ bool
+ verify_gimple_grammar_in_stmt (tree t)
+ {
+   enum tree_code code = TREE_CODE (t);
+   bool found = false;
+ 
+   if (IS_EMPTY_STMT (t))
+     return false;
+ 
+   switch (code)
+     {
+     case BIND_EXPR:
+       /* These are only valid if they're void.  */
+       if (!VOID_TYPE_P (TREE_TYPE (t)))
+ 	{
+ 	  error ("bind_expr shall not appear in low level gimple");
+ 	  found = true;
+ 	}
+       break;
+     case COND_EXPR:
+       /* These are only valid if they're void.  */
+       if (!VOID_TYPE_P (TREE_TYPE (t)))
+ 	{
+ 	  error ("statement level cond_expr must be VOIDmode");
+ 	  found = true;
+ 	}
+       if (TREE_CODE (COND_EXPR_THEN (t)) != GOTO_EXPR
+ 	  || TREE_CODE (COND_EXPR_ELSE (t)) != GOTO_EXPR)
+ 	{
+ 	  error ("statement level cond_expr must contain goto_expr in both arms.");
+ 	  found = true;
+ 	}
+       if (!is_gimple_condexpr (TREE_OPERAND (t, 0)))
+ 	{
+ 	  error ("cond_expr condition is not condexpr");
+ 	  found = true;
+ 	}
+       /* Verify goto expr to have label operand? */
+       break;
+ 
+     case SWITCH_EXPR:
+       {
+ 	tree op = TREE_OPERAND (t, 0);
+ 
+ 	/* ??? As a hack in gimplifier we allow nop to get warnings right.
+ 	   Fix this. */
+ 	if (TREE_CODE (op) == NOP_EXPR)
+ 	  op = TREE_OPERAND (op, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("switch_expr oprand is not value");
+ 	    found = true;
+ 	  }
+       }
+       if (TREE_OPERAND (t, 1))
+ 	{
+ 	  error ("switch_expr statement list is nonempty");
+ 	  found = true;
+ 	}
+       /* Verify label list? */
+       break;
+     case GOTO_EXPR:
+       if (TREE_CODE (TREE_OPERAND (t, 0)) != LABEL_DECL
+ 	  && !is_gimple_val (TREE_OPERAND (t, 0)))
+ 	{
+ 	  error ("goto_expr is not label nor value");
+ 	  found = true;
+ 	}
+       break;
+     case RETURN_EXPR:
+       if (TREE_OPERAND (t, 0))
+ 	{
+ 	  if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR)
+ 	    found |= verify_modify_expr (TREE_OPERAND (t, 0));
+ 	  else
+ 	    {
+ 	      error ("return_expr operand is not gimple value nor modify_expr");
+ 	      found = true;
+ 	    }
+ 	}
+       break;
+     case LABEL_EXPR:
+     case CASE_LABEL_EXPR:
+       break;
+     case PHI_NODE:
+       /* Phi nodes are sanity checked by verify_ssa.  */
+       break;
+     case TRY_CATCH_EXPR:
+     case TRY_FINALLY_EXPR:
+     case EH_FILTER_EXPR:
+     case CATCH_EXPR:
+     case RESX_EXPR:
+     case VA_ARG_EXPR:
+       /* ??? What shall be here?  */
+       break;
+     case STATEMENT_LIST:
+       /* There should be no need to verify statement_list ad we are always
+ 	 called to inner operands only.  */
+       abort ();
+       break;
+     case ASM_EXPR:
+       {
+ 	int i;
+ 	tree link;
+         bool allows_mem, allows_reg, is_inout;
+ 	const char *constraint;
+ 	int noutputs = list_length (ASM_OUTPUTS (t));
+ 	const char **oconstraints
+ 	  = (const char **) alloca ((noutputs) * sizeof (const char *));
+ 
+ 	for (i=0, link = ASM_OUTPUTS (t); link;
+ 	     ++i, link = TREE_CHAIN (link))
+ 	  {
+ 	    noutputs++;
+ 	    oconstraints[i] = constraint
+ 	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ 	    parse_output_constraint (&constraint, i, 0, 0,
+ 				     &allows_mem, &allows_reg, &is_inout);
+ 	    if ((allows_reg && !is_gimple_min_lval (TREE_VALUE (link)))
+ 		&& (allows_mem && verify_addr_expr_arg (TREE_VALUE (link))))
+ 	      {
+ 		error ("output operand %i is not gimple lval", i);
+ 		found = true;
+ 	      }
+ 	  }
+ 	for (i=0, link = ASM_INPUTS (t); link;
+ 	     ++i, link = TREE_CHAIN (link))
+ 	  {
+ 	    constraint
+ 	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ 	    parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ 				    oconstraints, &allows_mem, &allows_reg);
+ 	    if ((allows_reg && !is_gimple_val (TREE_VALUE (link)))
+ 		&& (allows_mem && verify_addr_expr_arg (TREE_VALUE (link))))
+ 	      {
+ 		error ("output operand %i is not gimple val", i);
+ 		found = true;
+ 	      }
+ 	  }
+       }
+       break;
+ 
+     case CALL_EXPR:
+       found |= verify_call_expr (t);
+       break;
+     case MODIFY_EXPR:
+       found |= verify_modify_expr (t);
+       break;
+ 
+     default:
+       error ("Invalid statement expression");
+       found = true;
+       break;
+     }
+   return found;
+ }
+ 
  /* Return nonzero if T is a variable.  */
  
  bool
  is_gimple_variable (tree t)
  {
+   /* Disqualify arguments passed by invisible reference.  These are de-facto
+      INDIRECT_REFs.  */
+   if (TREE_CODE (t) == PARM_DECL)
+     return (DECL_ARG_TYPE (t) == TREE_TYPE (t)
+ 	    || !POINTER_TYPE_P (DECL_ARG_TYPE (t))
+ 	    || TREE_TYPE (DECL_ARG_TYPE (t)) != TREE_TYPE (t));
    return (TREE_CODE (t) == VAR_DECL
  	  || TREE_CODE (t) == RESULT_DECL
  	  || TREE_CODE (t) == SSA_NAME);
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]