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]

[PATCH][match-and-simplify] Cleanup operator arity related diagnostics


The following removes a bunch of code dealing with "late" verifying
of operator presence and matching arity.  This can now all be
verified at parsing, giving proper locations and operator names.

Bootstrap pending.

Richard.

2014-09-24  Richard Biener  <rguenther@suse.de>

	* genmatch.c (struct id_base): Move nargs member here.
	(check_operator): Remove.
	(check_no_user_id): Likewise.
	(parse_operation): Fix error locations, handle convert0/2
	properly.
	(parse_expr): Error on non-matching arity.
	(parse_for): Compute arity of user-ids and complain for
	inconsistent substitutions.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 215550)
+++ gcc/genmatch.c	(working copy)
@@ -157,9 +157,10 @@ struct id_base : typed_noop_remove<id_ba
 {
   enum id_kind { CODE, FN, PREDICATE, USER_DEFINED } kind;
 
-  id_base (id_kind, const char *);
+  id_base (id_kind, const char *, int = -1);
 
   hashval_t hashval;
+  int nargs;
   const char *id;
 
   /* hash_table support.  */
@@ -185,10 +186,11 @@ id_base::equal (const value_type *op1,
 
 static hash_table<id_base> *operators;
 
-id_base::id_base (id_kind kind_, const char *id_)
+id_base::id_base (id_kind kind_, const char *id_, int nargs_)
 {
   kind = kind_;
   id = id_;
+  nargs = nargs_;
   hashval = htab_hash_string (id);
 }
 
@@ -196,11 +198,8 @@ struct operator_id : public id_base
 {
   operator_id (enum tree_code code_, const char *id_, unsigned nargs_,
 	       const char *tcc_)
-      : id_base (id_base::CODE, id_),
-      code (code_), nargs (nargs_), tcc (tcc_) {}
-  unsigned get_required_nargs () const { return nargs; }
+      : id_base (id_base::CODE, id_, nargs_), code (code_), tcc (tcc_) {}
   enum tree_code code;
-  unsigned nargs;
   const char *tcc;
 };
 
@@ -216,17 +215,15 @@ struct simplify;
 struct predicate_id : public id_base
 {
   predicate_id (const char *id_)
-    : id_base (id_base::PREDICATE, id_), matchers (vNULL), nargs(-1) {}
+    : id_base (id_base::PREDICATE, id_), matchers (vNULL) {}
   vec<simplify *> matchers;
-  int nargs;
 };
 
 struct user_id : public id_base
 {
   user_id (const char *id_)
-    : id_base (id_base::USER_DEFINED, id_), substitutes (vNULL), nargs(-1) {}
+    : id_base (id_base::USER_DEFINED, id_), substitutes (vNULL) {}
   vec<id_base *> substitutes;
-  int nargs;
 };
 
 template<>
@@ -830,36 +827,27 @@ lower_opt_convert (simplify *s, vec<simp
     }
 }
 
-void
-check_operator (id_base *op, unsigned n_ops, const cpp_token *token = 0)
-{
-  if (!op)
-    return;
-
-  if (op->kind != id_base::CODE)
-    return;
-
-  operator_id *opr = static_cast<operator_id *> (op);
-  if (opr->get_required_nargs () == n_ops)
-    return;
-
-  if (token)
-    fatal_at (token, "%s expects %u operands, got %u operands", opr->id, opr->get_required_nargs (), n_ops);
-  else
-    fatal ("%s expects %u operands, got %u operands", opr->id, opr->get_required_nargs (), n_ops);
-}
-
 /* In AST operand O replace operator ID with operator WITH.  */
 
 operand *
 replace_id (operand *o, user_id *id, id_base *with)
 {
+  /* Deep-copy captures and expressions, replacing operations as
+     needed.  */
   if (capture *c = dyn_cast<capture *> (o))
     {
       if (!c->what)
 	return c;
       return new capture (c->where, replace_id (c->what, id, with));
     }
+  else if (expr *e = dyn_cast<expr *> (o))
+    {
+      expr *ne = new expr (e->operation == id ? with : e->operation,
+			   e->is_commutative);
+      for (unsigned i = 0; i < e->ops.length (); ++i)
+	ne->append_op (replace_id (e->ops[i], id, with));
+      return ne;
+    }
 
   /* For c_expr we simply record a string replacement table which is
      applied at code-generation time.  */
@@ -870,23 +858,7 @@ replace_id (operand *o, user_id *id, id_
       return new c_expr (ce->r, ce->code, ce->nr_stmts, ids);
     }
 
-  expr *e = dyn_cast<expr *> (o);
-  if (!e)
-    return o;
-
-  expr *ne;
-  if (e->operation == id)
-    {
-      ne = new expr (with, e->is_commutative);
-      check_operator (ne->operation, e->ops.length ());
-    }
-  else
-    ne = new expr (e->operation, e->is_commutative);
-
-  for (unsigned i = 0; i < e->ops.length (); ++i)
-    ne->append_op (replace_id (e->ops[i], id, with));
-
-  return ne;
+  return o;
 }
 
 /* Lower recorded fors for SIN and output to SIMPLIFIERS.  */
@@ -947,40 +919,6 @@ lower_for (simplify *sin, vec<simplify *
     simplifiers.safe_push (worklist[i]);
 }
 
-void
-check_no_user_id (operand *o)
-{
-  if (o->type == operand::OP_CAPTURE)
-    {
-      capture *c = static_cast<capture *> (o);
-      if (c->what && c->what->type == operand::OP_EXPR)
-	{
-	  o = c->what;
-	  goto check_expr; 
-	}
-      return; 
-    }
-
-  if (o->type != operand::OP_EXPR)
-    return;
-
-check_expr:
-  expr *e = static_cast<expr *> (o);
-  if (e->operation->kind == id_base::USER_DEFINED)
-    fatal ("%s is not defined in for", e->operation->id);
-
-  for (unsigned i = 0; i < e->ops.length (); ++i)
-    check_no_user_id (e->ops[i]);
-}
-
-void
-check_no_user_id (simplify *s)
-{
-  check_no_user_id (s->match);
-  if (s->result)
-    check_no_user_id (s->result);
-}
-
 bool
 is_conversion (id_base *op)
 {
@@ -2395,30 +2333,36 @@ get_number (cpp_reader *r)
 
 /* Parsing.  */
 
+/* Parse the operator ID, special-casing convert?, convert1? and
+   convert2?  */
+
 static id_base *
 parse_operation (cpp_reader *r)
 {
+  const cpp_token *id_tok = peek (r);
   const char *id = get_ident (r);
   const cpp_token *token = peek (r);
+  if (strcmp (id, "convert0") == 0)
+    fatal_at (id_tok, "use 'convert?' here");
   if (token->type == CPP_QUERY
       && !(token->flags & PREV_WHITE))
     {
       if (strcmp (id, "convert") == 0)
 	id = "convert0";
-      else if (strcmp  (id, "convert0") == 0)
-	;
       else if (strcmp  (id, "convert1") == 0)
 	;
+      else if (strcmp  (id, "convert2") == 0)
+	;
       else
-	fatal_at (token, "non-convert operator conditionalized");
+	fatal_at (id_tok, "non-convert operator conditionalized");
       eat_token (r, CPP_QUERY);
     }
-  else if (strcmp  (id, "convert0") == 0
-	   || strcmp  (id, "convert1") == 0)
-    fatal_at (token, "expected '?' after conditional operator");
+  else if (strcmp  (id, "convert1") == 0
+	   || strcmp  (id, "convert2") == 0)
+    fatal_at (id_tok, "expected '?' after conditional operator");
   id_base *op = get_operator (id);
   if (!op)
-    fatal_at (token, "unknown operator %s", id);
+    fatal_at (id_tok, "unknown operator %s", id);
   return op;
 }
 
@@ -2474,7 +2418,10 @@ parse_expr (cpp_reader *r)
       const cpp_token *token = peek (r);
       if (token->type == CPP_CLOSE_PAREN)
 	{
-	  check_operator (e->operation, e->ops.length (), token);
+	  if (e->operation->nargs != -1
+	      && e->operation->nargs != (int) e->ops.length ())
+	    fatal_at (token, "'%s' expects %u operands, not %u",
+		      e->operation->id, e->operation->nargs, e->ops.length ());
 	  if (is_commutative)
 	    {
 	      if (e->ops.length () == 2)
@@ -2753,17 +2700,27 @@ parse_for (cpp_reader *r, source_locatio
 
       eat_token (r, CPP_OPEN_PAREN);
 
+      int arity = -1;
       while ((token = peek_ident (r)) != 0)
 	{
 	  const char *oper = get_ident (r);
 	  id_base *idb = get_operator (oper);
 	  if (idb == NULL)
-	    fatal_at (token, "no such operator %s", oper);
+	    fatal_at (token, "no such operator '%s'", oper);
 	  if (*idb == CONVERT0 || *idb == CONVERT1 || *idb == CONVERT2)
 	    fatal_at (token, "conditional operators cannot be used inside for");
-	  
+
+	  if (arity == -1)
+	    arity = idb->nargs;
+	  else if (idb->nargs == -1)
+	    ;
+	  else if (idb->nargs != arity)
+	    fatal_at (token, "operator '%s' with arity %d does not match "
+		      "others with arity %d", oper, idb->nargs, arity);
+
 	  op->substitutes.safe_push (idb);
 	}
+      op->nargs = arity;
       token = expect (r, CPP_CLOSE_PAREN);
 
       unsigned nsubstitutes = op->substitutes.length ();
@@ -2913,9 +2870,6 @@ lower (vec<simplify *> simplifiers)
   for (unsigned i = 0; i < out_simplifiers1.length (); ++i)
     lower_for (out_simplifiers1[i], out_simplifiers);
 
-  for (unsigned i = 0; i < out_simplifiers.length (); ++i)
-    check_no_user_id (out_simplifiers[i]);
-
   return out_simplifiers;
 }
 


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