From patchwork Wed Sep 24 10:50:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 392868 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B289140085 for ; Wed, 24 Sep 2014 20:54:02 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=lqugypUowOX/cHfQFDrX+PHB0qLlKukq8k2I1o5/MmukFBknmnxCz Blx1A7JChvPlHNlSU7/ejSE19fV3KLabAll73dhLd3Zx6H4AaWCCBwBKIBuYc+M1 M00fJTG7ZOA2B4+jfnbuTzCJJ8o3QjXtdlFbH+WZ6MxuiTmOnhleT4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=d6gPchjoyeYqD3iz2NsXj3VDN54=; b=AvC6TBNdbmgxy/M4L1c4 Pk8wfLwr6qXQmQShbNfiK7ZLV/nW5JTh1eylJuM1ek4hII/eOesitj7C/mnTSSV0 BLw+BVvpAnql68z/XFIhKLiDGEVA0QXuKZN3DVp9yenWj61qqOdklrgW9zODHL5H PA16Im+9bPNJRYmWaT8UyxI= Received: (qmail 32232 invoked by alias); 24 Sep 2014 10:53:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 32219 invoked by uid 89); 24 Sep 2014 10:53:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx2.suse.de Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Wed, 24 Sep 2014 10:53:51 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 53ED5ACD2 for ; Wed, 24 Sep 2014 10:53:48 +0000 (UTC) Date: Wed, 24 Sep 2014 12:50:06 +0200 (CEST) From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH][match-and-simplify] Cleanup operator arity related diagnostics Message-ID: User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 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 * 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 *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 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 substitutes; - int nargs; }; template<> @@ -830,36 +827,27 @@ lower_opt_convert (simplify *s, veckind != id_base::CODE) - return; - - operator_id *opr = static_cast (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 (o)) { if (!c->what) return c; return new capture (c->where, replace_id (c->what, id, with)); } + else if (expr *e = dyn_cast (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 (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, vectype == operand::OP_CAPTURE) - { - capture *c = static_cast (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 (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 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; }