+2014-11-12 Richard Biener <rguenther@suse.de>
+
+ Merge from match-and-simplify branch
+ 2014-11-04 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (user_id): Add new member is_oper_list.
+ (user_id::user_id): Add new default argument.
+ (parser::parse_operator_list): New function.
+ (parser::parse_for): Allow operator-list.
+ (parser::parse_pattern): Call parser::parse_operator_list.
+ (parser::parse_operation): Reject operator-list.
+ * match-builtin.pd: Define operator lists POWs, CBRTs and SQRTs.
+
+ 2014-10-31 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (parser::parse_c_expr): Mark user-defined ops as used.
+
+ 2014-10-30 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (parser::parse_op): Check if predicate is used in
+ result operand.
+
+ 2014-10-29 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (parser::parse_for): Make sure to have a valid
+ token to report errors at.
+
+ 2014-10-28 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (parser): Add new member parsing_match_operand.
+ (parser::parse_operation): Check for conditional convert in result
+ operand.
+ (parser::parse_expr): Check for commutative operator in result operand.
+ Check for :type in match operand.
+ (parser::parse_simplify): Set/unset parsing_match_operand.
+ (parser::parser): Initialize parsing_match_operand.
+
+ 2014-10-28 Richard Biener <rguenther@suse.de>
+
+ * genmatch.c (parser::parse_for): Properly check for already
+ defined operators.
+
+ 2014-10-28 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * genmatch.c (error_cb): Adjust for printing warnings.
+ (warning_at): New function.
+ (user_id): Add new member used.
+ (get_operator): Mark user_id as used.
+ (parse_for): Warn for unused operators.
+
2014-11-12 Richard Biener <rguenther@suse.de>
* match.pd: Implement simple complex operations cancelling.
#if GCC_VERSION >= 4001
__attribute__((format (printf, 6, 0)))
#endif
-error_cb (cpp_reader *, int, int, source_location location,
+error_cb (cpp_reader *, int errtype, int, source_location location,
unsigned int, const char *msg, va_list *ap)
{
const line_map *map;
linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map);
expanded_location loc = linemap_expand_location (line_table, map, location);
- fprintf (stderr, "%s:%d:%d error: ", loc.file, loc.line, loc.column);
+ fprintf (stderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column,
+ (errtype == CPP_DL_WARNING) ? "warning" : "error");
vfprintf (stderr, msg, *ap);
fprintf (stderr, "\n");
FILE *f = fopen (loc.file, "r");
notfound:
fclose (f);
}
- exit (1);
+
+ if (errtype == CPP_DL_FATAL)
+ exit (1);
+ return false;
}
static void
va_end (ap);
}
+static void
+#if GCC_VERSION >= 4001
+__attribute__((format (printf, 2, 3)))
+#endif
+warning_at (const cpp_token *tk, const char *msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ error_cb (NULL, CPP_DL_WARNING, 0, tk->src_loc, 0, msg, &ap);
+ va_end (ap);
+}
+
static void
output_line_directive (FILE *f, source_location location,
bool dumpfile = false)
struct user_id : public id_base
{
- user_id (const char *id_)
- : id_base (id_base::USER, id_), substitutes (vNULL) {}
+ user_id (const char *id_, bool is_oper_list_ = false)
+ : id_base (id_base::USER, id_), substitutes (vNULL),
+ used (false), is_oper_list (is_oper_list_) {}
vec<id_base *> substitutes;
+ bool used;
+ bool is_oper_list;
};
template<>
id_base *op = operators->find_with_hash (&tem, tem.hashval);
if (op)
- return op;
+ {
+ /* If this is a user-defined identifier track whether it was used. */
+ if (user_id *uid = dyn_cast<user_id *> (op))
+ uid->used = true;
+ return op;
+ }
/* Try all-uppercase. */
char *id2 = xstrdup (id);
void parse_for (source_location);
void parse_if (source_location);
void parse_predicates (source_location);
+ void parse_operator_list (source_location);
cpp_reader *r;
vec<if_or_with> active_ifs;
public:
vec<simplify *> simplifiers;
vec<predicate_id *> user_predicates;
+ bool parsing_match_operand;
};
/* Lexing helpers. */
;
else
fatal_at (id_tok, "non-convert operator conditionalized");
+
+ if (!parsing_match_operand)
+ fatal_at (id_tok, "conditional convert can only be used in "
+ "match expression");
eat_token (CPP_QUERY);
}
else if (strcmp (id, "convert1") == 0
id_base *op = get_operator (id);
if (!op)
fatal_at (id_tok, "unknown operator %s", id);
+
+ user_id *p = dyn_cast<user_id *> (op);
+ if (p && p->is_oper_list)
+ fatal_at (id_tok, "operator-list not allowed in expression");
+
return op;
}
{
eat_token (CPP_ATSIGN);
const cpp_token *token = peek ();
- const char *id;
+ const char *id = NULL;
if (token->type == CPP_NUMBER)
id = get_number ();
else if (token->type == CPP_NAME)
{
const char *s = get_ident ();
if (s[0] == 'c' && !s[1])
- is_commutative = true;
+ {
+ if (!parsing_match_operand)
+ fatal_at (token,
+ "flag 'c' can only be used in match expression");
+ is_commutative = true;
+ }
else if (s[1] != '\0')
- expr_type = s;
+ {
+ if (parsing_match_operand)
+ fatal_at (token, "type can only be used in result expression");
+ expr_type = s;
+ }
else
fatal_at (token, "flag %s not recognized", s);
+
token = peek ();
}
else
if (token->type == CPP_SEMICOLON)
nr_stmts++;
+ /* If this is possibly a user-defined identifier mark it used. */
+ if (token->type == CPP_NAME)
+ get_operator ((const char *)CPP_HASHNODE
+ (token->val.node.node)->ident.str);
+
/* Record the token. */
code.safe_push (*token);
}
op = new predicate (p);
else
fatal_at (token, "using an unsupported operator as predicate");
+ if (!parsing_match_operand)
+ fatal_at (token, "predicates are only allowed in match expression");
token = peek ();
if (token->flags & PREV_WHITE)
return op;
capture_ids = new cid_map_t;
const cpp_token *loc = peek ();
+ parsing_match_operand = true;
struct operand *match = parse_op ();
+ parsing_match_operand = false;
if (match->type == operand::OP_CAPTURE && !matcher)
fatal_at (loc, "outermost expression cannot be captured");
if (match->type == operand::OP_EXPR
void
parser::parse_for (source_location)
{
+ auto_vec<const cpp_token *> user_id_tokens;
vec<user_id *> user_ids = vNULL;
const cpp_token *token;
unsigned min_n_opers = 0, max_n_opers = 0;
while (1)
{
- token = peek_ident ();
- if (token == 0)
+ token = peek ();
+ if (token->type != CPP_NAME)
break;
/* Insert the user defined operators into the operator hash. */
const char *id = get_ident ();
+ if (get_operator (id) != NULL)
+ fatal_at (token, "operator already defined");
user_id *op = new user_id (id);
id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT);
- if (*slot)
- fatal_at (token, "operator already defined");
*slot = op;
user_ids.safe_push (op);
+ user_id_tokens.safe_push (token);
eat_token (CPP_OPEN_PAREN);
fatal_at (token, "operator '%s' with arity %d does not match "
"others with arity %d", oper, idb->nargs, arity);
- op->substitutes.safe_push (idb);
+ user_id *p = dyn_cast<user_id *> (idb);
+ if (p && p->is_oper_list)
+ op->substitutes.safe_splice (p->substitutes);
+ else
+ op->substitutes.safe_push (idb);
}
op->nargs = arity;
token = expect (CPP_CLOSE_PAREN);
/* Remove user-defined operators from the hash again. */
for (unsigned i = 0; i < user_ids.length (); ++i)
- operators->remove_elt (user_ids[i]);
+ {
+ if (!user_ids[i]->used)
+ warning_at (user_id_tokens[i],
+ "operator %s defined but not used", user_ids[i]->id);
+ operators->remove_elt (user_ids[i]);
+ }
+}
+
+/* Parse an identifier associated with a list of operators.
+ oprs = '(' 'define_operator_list' <ident> <ident>... ')' */
+
+void
+parser::parse_operator_list (source_location)
+{
+ const cpp_token *token = peek ();
+ const char *id = get_ident ();
+
+ if (get_operator (id) != 0)
+ fatal_at (token, "operator %s already defined", id);
+
+ user_id *op = new user_id (id, true);
+ int arity = -1;
+
+ while ((token = peek_ident ()) != 0)
+ {
+ token = peek ();
+ const char *oper = get_ident ();
+ id_base *idb = get_operator (oper);
+
+ if (idb == 0)
+ fatal_at (token, "no such operator '%s'", oper);
+
+ if (arity == -1)
+ arity = idb->nargs;
+ else if (idb->nargs == -1)
+ ;
+ else if (arity != idb->nargs)
+ fatal_at (token, "operator '%s' with arity %d does not match "
+ "others with arity %d", oper, idb->nargs, arity);
+
+ /* We allow composition of multiple operator lists. */
+ if (user_id *p = dyn_cast<user_id *> (idb))
+ op->substitutes.safe_splice (p->substitutes);
+ else
+ op->substitutes.safe_push (idb);
+ }
+
+ if (op->substitutes.length () == 0)
+ fatal_at (token, "operator-list cannot be empty");
+
+ op->nargs = arity;
+ id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT);
+ *slot = op;
}
/* Parse an outer if expression.
fatal_at (token, "define_predicates inside if or for is not supported");
parse_predicates (token->src_loc);
}
+ else if (strcmp (id, "define_operator_list") == 0)
+ {
+ if (active_ifs.length () > 0
+ || active_fors.length () > 0)
+ fatal_at (token, "operator-list inside if or for is not supported");
+ parse_operator_list (token->src_loc);
+ }
else
fatal_at (token, "expected %s'simplify', 'match', 'for' or 'if'",
active_ifs.length () == 0 && active_fors.length () == 0
active_fors = vNULL;
simplifiers = vNULL;
user_predicates = vNULL;
+ parsing_match_operand = false;
const cpp_token *token = next ();
while (token->type != CPP_EOF)