This is a first cleanup step towards lowering for late, not during parsing.
This intermediate step removes the e_operation indirection and makes parse_for temporarily insert operators it defines so we can avoid lazily accepting anything as user-defined and thus report proper error locations. Bootstrap scheduled (gimple-match.c/generic-match.c is unchanged - always a good test) Richard. 2014-09-23 Richard Biener <rguent...@suse.de> * genmatch.c (struct e_operation): Remove. (struct expr): Replace e_operation operation with id_base. Add is_commutative member. (<everywhere>): Remove indirections through e_operation, move is_commutative handling to expr objects. (parse_for): Temporarily insert user-defined operators into the operator identifier hash. Index: match-and-simplify/gcc/genmatch.c =================================================================== *** match-and-simplify.orig/gcc/genmatch.c 2014-09-23 15:08:06.634446450 +0200 --- match-and-simplify/gcc/genmatch.c 2014-09-23 15:34:48.805336143 +0200 *************** struct predicate : public operand *** 292,313 **** { gcc_unreachable (); } }; - struct e_operation { - e_operation (const char *id, bool is_commutative_ = false, bool add_new_id = true); - id_base *op; - bool is_commutative; - }; - struct expr : public operand { ! expr (e_operation *operation_) : operand (OP_EXPR), operation (operation_), ! ops (vNULL), expr_type (NULL) {} void append_op (operand *op) { ops.safe_push (op); } ! e_operation *operation; vec<operand *> ops; const char *expr_type; virtual void gen_transform (FILE *f, const char *, bool, int, const char *, dt_operand ** = 0); }; --- 292,308 ---- { gcc_unreachable (); } }; struct expr : public operand { ! expr (id_base *operation_, bool is_commutative_ = false) : operand (OP_EXPR), operation (operation_), ! ops (vNULL), expr_type (NULL), is_commutative (is_commutative_) {} void append_op (operand *op) { ops.safe_push (op); } ! id_base *operation; vec<operand *> ops; const char *expr_type; + bool is_commutative; virtual void gen_transform (FILE *f, const char *, bool, int, const char *, dt_operand ** = 0); }; *************** get_operator (const char *id) *** 411,430 **** return 0; } - e_operation::e_operation (const char *id, bool is_commutative_, bool add_new_id) - { - is_commutative = is_commutative_; - op = get_operator (id); - if (op) - return; - - if (add_new_id == false) - fatal ("%s is not an operator/built-in function", id); - - op = new id_base (id_base::USER_DEFINED, id); - operators->find_slot_with_hash (op, op->hashval, INSERT); - } - struct if_or_with { if_or_with (operand *cexpr_, source_location location_, bool is_with_) : location (location_), cexpr (cexpr_), is_with (is_with_) {} --- 406,411 ---- *************** print_operand (operand *o, FILE *f = std *** 559,565 **** else if (expr *e = dyn_cast<expr *> (o)) { ! fprintf (f, "(%s", e->operation->op->id); if (flattened == false) { --- 540,546 ---- else if (expr *e = dyn_cast<expr *> (o)) { ! fprintf (f, "(%s", e->operation->id); if (flattened == false) { *************** commutate (operand *op) *** 660,666 **** ret.safe_push (ne); } ! if (!e->operation->is_commutative) return ret; for (unsigned i = 0; i < result.length (); ++i) --- 641,647 ---- ret.safe_push (ne); } ! if (!e->is_commutative) return ret; for (unsigned i = 0; i < result.length (); ++i) *************** lower_opt_convert (operand *o, enum tree *** 702,715 **** return o; expr *e = as_a<expr *> (o); ! if (*e->operation->op == oper) { ! expr *ne = new expr (new e_operation ("CONVERT_EXPR")); ne->append_op (lower_opt_convert (e->ops[0], oper)); return ne; } ! expr *ne = new expr (e->operation); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (lower_opt_convert (e->ops[i], oper)); --- 683,696 ---- return o; expr *e = as_a<expr *> (o); ! if (*e->operation == oper) { ! expr *ne = new expr (get_operator ("CONVERT_EXPR")); ne->append_op (lower_opt_convert (e->ops[0], oper)); return ne; } ! expr *ne = new expr (e->operation, e->is_commutative); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (lower_opt_convert (e->ops[i], oper)); *************** remove_opt_convert (operand *o, enum tre *** 731,740 **** return o; expr *e = as_a<expr *> (o); ! if (*e->operation->op == oper) return remove_opt_convert (e->ops[0], oper); ! expr *ne = new expr (e->operation); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (remove_opt_convert (e->ops[i], oper)); --- 712,721 ---- return o; expr *e = as_a<expr *> (o); ! if (*e->operation == oper) return remove_opt_convert (e->ops[0], oper); ! expr *ne = new expr (e->operation, e->is_commutative); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (remove_opt_convert (e->ops[i], oper)); *************** has_opt_convert (operand *o, enum tree_c *** 757,763 **** expr *e = as_a<expr *> (o); ! if (*e->operation->op == oper) return true; for (unsigned i = 0; i < e->ops.length (); ++i) --- 738,744 ---- expr *e = as_a<expr *> (o); ! if (*e->operation == oper) return true; for (unsigned i = 0; i < e->ops.length (); ++i) *************** replace_id (operand *o, const char *user *** 860,873 **** expr *e = static_cast<expr *> (o); expr *ne; ! if (e->operation->op->kind == id_base::USER_DEFINED && strcmp (e->operation->op->id, user_id) == 0) { ! struct e_operation *operation = new e_operation (oper, e->operation->is_commutative, false); ! check_operator (operation->op, e->ops.length ()); ! ne = new expr (operation); } else ! ne = new expr (e->operation); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (replace_id (e->ops[i], user_id, oper)); --- 841,854 ---- expr *e = static_cast<expr *> (o); expr *ne; ! if (e->operation->kind == id_base::USER_DEFINED ! && strcmp (e->operation->id, user_id) == 0) { ! ne = new expr (get_operator (oper), 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], user_id, oper)); *************** check_no_user_id (operand *o) *** 894,901 **** check_expr: expr *e = static_cast<expr *> (o); ! if (e->operation->op->kind == id_base::USER_DEFINED) ! fatal ("%s is not defined in for", e->operation->op->id); for (unsigned i = 0; i < e->ops.length (); ++i) check_no_user_id (e->ops[i]); --- 875,882 ---- 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 *** 957,963 **** expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth, const char *in_type, dt_operand **indexes) { ! bool conversion_p = is_conversion (operation->op); const char *type = expr_type; char optype[64]; if (type) --- 938,944 ---- expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth, const char *in_type, dt_operand **indexes) { ! bool conversion_p = is_conversion (operation); const char *type = expr_type; char optype[64]; if (type) *************** expr::gen_transform (FILE *f, const char *** 967,981 **** /* For conversions we need to build the expression using the outer type passed in. */ type = in_type; ! else if (*operation->op == REALPART_EXPR ! || *operation->op == IMAGPART_EXPR) { /* __real and __imag use the component type of its operand. */ sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth); type = optype; } ! else if (is_a <operator_id *> (operation->op) ! && strcmp (as_a <operator_id *> (operation->op)->tcc, "tcc_comparison") == 0) { /* comparisons use boolean_type_node (or what gets in), but their operands need to figure out the types themselves. */ --- 948,962 ---- /* For conversions we need to build the expression using the outer type passed in. */ type = in_type; ! else if (*operation == REALPART_EXPR ! || *operation == IMAGPART_EXPR) { /* __real and __imag use the component type of its operand. */ sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth); type = optype; } ! else if (is_a <operator_id *> (operation) ! && strcmp (as_a <operator_id *> (operation)->tcc, "tcc_comparison") == 0) { /* comparisons use boolean_type_node (or what gets in), but their operands need to figure out the types themselves. */ *************** expr::gen_transform (FILE *f, const char *** 1000,1006 **** char dest[32]; snprintf (dest, 32, " ops%d[%u]", depth, i); const char *optype ! = get_operand_type (operation->op, in_type, expr_type, i == 0 ? NULL : op0type); ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes); } --- 981,987 ---- char dest[32]; snprintf (dest, 32, " ops%d[%u]", depth, i); const char *optype ! = get_operand_type (operation, in_type, expr_type, i == 0 ? NULL : op0type); ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes); } *************** expr::gen_transform (FILE *f, const char *** 1012,1018 **** fprintf (f, " if (!seq)\n" " {\n" " res = gimple_simplify (%s, %s", ! operation->op->id, type); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ", seq, valueize);\n"); --- 993,999 ---- fprintf (f, " if (!seq)\n" " {\n" " res = gimple_simplify (%s, %s", ! operation->id, type); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ", seq, valueize);\n"); *************** expr::gen_transform (FILE *f, const char *** 1020,1038 **** fprintf (f, " }\n"); fprintf (f, " else\n"); fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, %s", ! operation->op->id, type); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ", valueize);\n"); } else { ! if (operation->op->kind == id_base::CODE) fprintf (f, " res = fold_build%d (%s, %s", ! ops.length(), operation->op->id, type); else fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d", ! operation->op->id, ops.length()); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ");\n"); --- 1001,1019 ---- fprintf (f, " }\n"); fprintf (f, " else\n"); fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, %s", ! operation->id, type); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ", valueize);\n"); } else { ! if (operation->kind == id_base::CODE) fprintf (f, " res = fold_build%d (%s, %s", ! ops.length(), operation->id, type); else fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d", ! operation->id, ops.length()); for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ");\n"); *************** cmp_operand (operand *o1, operand *o2) *** 1152,1158 **** { expr *e1 = static_cast<expr *>(o1); expr *e2 = static_cast<expr *>(o2); ! return strcmp (e1->operation->op->id, e2->operation->op->id) == 0; } else return false; --- 1133,1139 ---- { expr *e1 = static_cast<expr *>(o1); expr *e2 = static_cast<expr *>(o2); ! return strcmp (e1->operation->id, e2->operation->id) == 0; } else return false; *************** unsigned *** 1446,1452 **** dt_operand::gen_gimple_expr (FILE *f) { expr *e = static_cast<expr *> (op); ! id_base *id = e->operation->op; unsigned n_ops = e->ops.length (); for (unsigned i = 0; i < n_ops; ++i) --- 1427,1433 ---- dt_operand::gen_gimple_expr (FILE *f) { expr *e = static_cast<expr *> (op); ! id_base *id = e->operation; unsigned n_ops = e->ops.length (); for (unsigned i = 0; i < n_ops; ++i) *************** dt_operand::gen_generic_expr (FILE *f, c *** 1497,1503 **** char child_opname[20]; gen_opname (child_opname, i); ! if (e->operation->op->kind == id_base::CODE) fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n", child_opname, opname, i); else --- 1478,1484 ---- char child_opname[20]; gen_opname (child_opname, i); ! if (e->operation->kind == id_base::CODE) fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n", child_opname, opname, i); else *************** dt_node::gen_gimple_kids (FILE *f) *** 1525,1533 **** { if (e->ops.length () == 0) generic_exprs.safe_push (op); ! else if (e->operation->op->kind == id_base::FN) fns.safe_push (op); ! else if (e->operation->op->kind == id_base::PREDICATE) preds.safe_push (op); else gimple_exprs.safe_push (op); --- 1506,1514 ---- { if (e->ops.length () == 0) generic_exprs.safe_push (op); ! else if (e->operation->kind == id_base::FN) fns.safe_push (op); ! else if (e->operation->kind == id_base::PREDICATE) preds.safe_push (op); else gimple_exprs.safe_push (op); *************** dt_node::gen_gimple_kids (FILE *f) *** 1580,1586 **** for (unsigned i = 0; i < exprs_len; ++i) { expr *e = as_a <expr *> (gimple_exprs[i]->op); ! id_base *op = e->operation->op; if (*op == CONVERT_EXPR || *op == NOP_EXPR) fprintf (f, "CASE_CONVERT:\n"); else --- 1561,1567 ---- for (unsigned i = 0; i < exprs_len; ++i) { expr *e = as_a <expr *> (gimple_exprs[i]->op); ! id_base *op = e->operation; if (*op == CONVERT_EXPR || *op == NOP_EXPR) fprintf (f, "CASE_CONVERT:\n"); else *************** dt_node::gen_gimple_kids (FILE *f) *** 1609,1615 **** { expr *e = as_a <expr *>(fns[i]->op); fprintf (f, "case %s:\n" ! "{\n", e->operation->op->id); fns[i]->gen_gimple (f); fprintf (f, "break;\n" "}\n"); --- 1590,1596 ---- { expr *e = as_a <expr *>(fns[i]->op); fprintf (f, "case %s:\n" ! "{\n", e->operation->id); fns[i]->gen_gimple (f); fprintf (f, "break;\n" "}\n"); *************** dt_node::gen_gimple_kids (FILE *f) *** 1628,1634 **** { expr *e = as_a <expr *>(generic_exprs[i]->op); fprintf (f, "case %s:\n" ! "{\n", e->operation->op->id); generic_exprs[i]->gen_gimple (f); fprintf (f, "break;\n" --- 1609,1615 ---- { expr *e = as_a <expr *>(generic_exprs[i]->op); fprintf (f, "case %s:\n" ! "{\n", e->operation->id); generic_exprs[i]->gen_gimple (f); fprintf (f, "break;\n" *************** dt_node::gen_gimple_kids (FILE *f) *** 1643,1649 **** for (unsigned i = 0; i < preds.length (); ++i) { expr *e = as_a <expr *> (preds[i]->op); ! predicate_id *p = as_a <predicate_id *> (e->operation->op); preds[i]->get_name (kid_opname); fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs); fprintf (f, "if (gimple_%s (%s, %s_pops, valueize))\n", p->id, --- 1624,1630 ---- for (unsigned i = 0; i < preds.length (); ++i) { expr *e = as_a <expr *> (preds[i]->op); ! predicate_id *p = as_a <predicate_id *> (e->operation); preds[i]->get_name (kid_opname); fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs); fprintf (f, "if (gimple_%s (%s, %s_pops, valueize))\n", p->id, *************** dt_node::gen_generic_kids (FILE *f) *** 1756,1772 **** if (kid->op->type == operand::OP_EXPR) { expr *e = as_a <expr *> (kid->op); ! if (e->operation->op->kind == id_base::CODE) { generic_exprs.safe_push (kid); any = true; } ! else if (e->operation->op->kind == id_base::FN) { fns.safe_push (kid); any = true; } ! else if (e->operation->op->kind == id_base::PREDICATE) preds.safe_push (kid); else gcc_unreachable (); --- 1737,1753 ---- if (kid->op->type == operand::OP_EXPR) { expr *e = as_a <expr *> (kid->op); ! if (e->operation->kind == id_base::CODE) { generic_exprs.safe_push (kid); any = true; } ! else if (e->operation->kind == id_base::FN) { fns.safe_push (kid); any = true; } ! else if (e->operation->kind == id_base::PREDICATE) preds.safe_push (kid); else gcc_unreachable (); *************** dt_node::gen_generic_kids (FILE *f) *** 1784,1794 **** { dt_operand *kid = generic_exprs[j]; expr *e = as_a <expr *>(kid->op); ! gcc_assert (e->operation->op->kind == id_base::CODE); /* ??? CONVERT */ fprintf (f, "case %s:\n" ! "{\n", e->operation->op->id); kid->gen_generic (f); fprintf (f, "break;\n" "}\n"); --- 1765,1775 ---- { dt_operand *kid = generic_exprs[j]; expr *e = as_a <expr *>(kid->op); ! gcc_assert (e->operation->kind == id_base::CODE); /* ??? CONVERT */ fprintf (f, "case %s:\n" ! "{\n", e->operation->id); kid->gen_generic (f); fprintf (f, "break;\n" "}\n"); *************** dt_node::gen_generic_kids (FILE *f) *** 1799,1805 **** { dt_operand *kid = fns[j]; expr *e = as_a <expr *>(kid->op); ! gcc_assert (e->operation->op->kind == id_base::FN); if (first) fprintf (f, "case CALL_EXPR:\n" --- 1780,1786 ---- { dt_operand *kid = fns[j]; expr *e = as_a <expr *>(kid->op); ! gcc_assert (e->operation->kind == id_base::FN); if (first) fprintf (f, "case CALL_EXPR:\n" *************** dt_node::gen_generic_kids (FILE *f) *** 1811,1817 **** first = false; fprintf (f, "case %s:\n" ! "{\n", e->operation->op->id); kid->gen_generic (f); fprintf (f, "break;\n" "}\n"); --- 1792,1798 ---- first = false; fprintf (f, "case %s:\n" ! "{\n", e->operation->id); kid->gen_generic (f); fprintf (f, "break;\n" "}\n"); *************** dt_node::gen_generic_kids (FILE *f) *** 1829,1835 **** for (unsigned i = 0; i < preds.length (); ++i) { expr *e = as_a <expr *> (preds[i]->op); ! predicate_id *p = as_a <predicate_id *> (e->operation->op); char kid_opname[128]; preds[i]->get_name (kid_opname); fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs); --- 1810,1816 ---- for (unsigned i = 0; i < preds.length (); ++i) { expr *e = as_a <expr *> (preds[i]->op); ! predicate_id *p = as_a <predicate_id *> (e->operation); char kid_opname[128]; preds[i]->get_name (kid_opname); fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs); *************** dt_simplify::gen (FILE *f, bool gimple) *** 1938,1952 **** if (s->result->type == operand::OP_EXPR) { expr *e = as_a <expr *> (s->result); ! bool is_predicate = is_a <predicate_id *> (e->operation->op); if (!is_predicate) ! fprintf (f, "*res_code = %s;\n", e->operation->op->id); for (unsigned j = 0; j < e->ops.length (); ++j) { char dest[32]; snprintf (dest, 32, " res_ops[%d]", j); const char *optype ! = get_operand_type (e->operation->op, "type", e->expr_type, j == 0 ? NULL : "TREE_TYPE (res_ops[0])"); --- 1919,1933 ---- if (s->result->type == operand::OP_EXPR) { expr *e = as_a <expr *> (s->result); ! bool is_predicate = is_a <predicate_id *> (e->operation); if (!is_predicate) ! fprintf (f, "*res_code = %s;\n", e->operation->id); for (unsigned j = 0; j < e->ops.length (); ++j) { char dest[32]; snprintf (dest, 32, " res_ops[%d]", j); const char *optype ! = get_operand_type (e->operation, "type", e->expr_type, j == 0 ? NULL : "TREE_TYPE (res_ops[0])"); *************** dt_simplify::gen (FILE *f, bool gimple) *** 1974,1980 **** if (s->result->type == operand::OP_EXPR) { expr *e = as_a <expr *> (s->result); ! bool is_predicate = is_a <predicate_id *> (e->operation->op); for (unsigned j = 0; j < e->ops.length (); ++j) { char dest[32]; --- 1955,1961 ---- if (s->result->type == operand::OP_EXPR) { expr *e = as_a <expr *> (s->result); ! bool is_predicate = is_a <predicate_id *> (e->operation); for (unsigned j = 0; j < e->ops.length (); ++j) { char dest[32]; *************** dt_simplify::gen (FILE *f, bool gimple) *** 1986,2008 **** snprintf (dest, 32, " res_op%d", j); } const char *optype ! = get_operand_type (e->operation->op, "type", e->expr_type, j == 0 ? NULL : "TREE_TYPE (res_op0)"); e->ops[j]->gen_transform (f, dest, false, 1, optype, indexes); } ! if (is_a <predicate_id *> (e->operation->op)) fprintf (f, "return true;\n"); else { /* Re-fold the toplevel result. */ ! if (e->operation->op->kind == id_base::CODE) fprintf (f, " return fold_build%d (%s, type", ! e->ops.length (), e->operation->op->id); else fprintf (f, " return build_call_expr (builtin_decl_implicit (%s), %d", ! e->operation->op->id, e->ops.length()); for (unsigned j = 0; j < e->ops.length (); ++j) fprintf (f, ", res_op%d", j); fprintf (f, ");\n"); --- 1967,1989 ---- snprintf (dest, 32, " res_op%d", j); } const char *optype ! = get_operand_type (e->operation, "type", e->expr_type, j == 0 ? NULL : "TREE_TYPE (res_op0)"); e->ops[j]->gen_transform (f, dest, false, 1, optype, indexes); } ! if (is_a <predicate_id *> (e->operation)) fprintf (f, "return true;\n"); else { /* Re-fold the toplevel result. */ ! if (e->operation->kind == id_base::CODE) fprintf (f, " return fold_build%d (%s, type", ! e->ops.length (), e->operation->id); else fprintf (f, " return build_call_expr (builtin_decl_implicit (%s), %d", ! e->operation->id, e->ops.length()); for (unsigned j = 0; j < e->ops.length (); ++j) fprintf (f, ", res_op%d", j); fprintf (f, ");\n"); *************** decision_tree::gen_gimple (FILE *f) *** 2049,2061 **** if (e->ops.length () != n) continue; ! if (*e->operation->op == CONVERT_EXPR ! || *e->operation->op == NOP_EXPR) fprintf (f, "CASE_CONVERT:\n"); else fprintf (f, "case %s%s:\n", ! is_a <fn_id *> (e->operation->op) ? "-" : "", ! e->operation->op->id); fprintf (f, "{\n"); dop->gen_gimple_kids (f); fprintf (f, "break;\n"); --- 2030,2042 ---- if (e->ops.length () != n) continue; ! if (*e->operation == CONVERT_EXPR ! || *e->operation == NOP_EXPR) fprintf (f, "CASE_CONVERT:\n"); else fprintf (f, "case %s%s:\n", ! is_a <fn_id *> (e->operation) ? "-" : "", ! e->operation->id); fprintf (f, "{\n"); dop->gen_gimple_kids (f); fprintf (f, "break;\n"); *************** decision_tree::gen_generic (FILE *f) *** 2105,2118 **** GENERIC. The following drops patterns with outermost calls. It's easy to emit overloads for function code though if necessary. */ ! || e->operation->op->kind != id_base::CODE) continue; ! operator_id *op_id = static_cast <operator_id *> (e->operation->op); if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR) fprintf (f, "CASE_CONVERT:\n"); else ! fprintf (f, "case %s:\n", e->operation->op->id); fprintf (f, "{\n"); dop->gen_generic_kids (f); fprintf (f, "break;\n" --- 2086,2099 ---- GENERIC. The following drops patterns with outermost calls. It's easy to emit overloads for function code though if necessary. */ ! || e->operation->kind != id_base::CODE) continue; ! operator_id *op_id = static_cast <operator_id *> (e->operation); if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR) fprintf (f, "CASE_CONVERT:\n"); else ! fprintf (f, "case %s:\n", e->operation->id); fprintf (f, "{\n"); dop->gen_generic_kids (f); fprintf (f, "break;\n" *************** get_number (cpp_reader *r) *** 2323,2329 **** /* Parsing. */ ! static e_operation * parse_operation (cpp_reader *r) { const char *id = get_ident (r); --- 2304,2310 ---- /* Parsing. */ ! static id_base * parse_operation (cpp_reader *r) { const char *id = get_ident (r); *************** parse_operation (cpp_reader *r) *** 2344,2350 **** else if (strcmp (id, "convert0") == 0 || strcmp (id, "convert1") == 0) fatal_at (token, "expected '?' after conditional operator"); ! return new e_operation (id); } static struct operand * parse_op (cpp_reader *r); --- 2325,2334 ---- else if (strcmp (id, "convert0") == 0 || strcmp (id, "convert1") == 0) fatal_at (token, "expected '?' after conditional operator"); ! id_base *op = get_operator (id); ! if (!op) ! fatal_at (token, "unknown operator %s", id); ! return op; } static struct operand * parse_op (cpp_reader *r); *************** parse_expr (cpp_reader *r) *** 2399,2409 **** const cpp_token *token = peek (r); if (token->type == CPP_CLOSE_PAREN) { ! check_operator (e->operation->op, e->ops.length (), token); if (is_commutative) { if (e->ops.length () == 2) ! e->operation->is_commutative = true; else fatal_at (token, "only binary operators or function with two arguments can be marked commutative"); } --- 2383,2393 ---- const cpp_token *token = peek (r); if (token->type == CPP_CLOSE_PAREN) { ! check_operator (e->operation, e->ops.length (), token); if (is_commutative) { if (e->ops.length () == 2) ! e->is_commutative = true; else fatal_at (token, "only binary operators or function with two arguments can be marked commutative"); } *************** parse_op (cpp_reader *r) *** 2489,2495 **** fatal_at (token, "using an operator with operands as predicate"); /* Parse the zero-operand operator "predicates" as expression. */ ! op = new expr (new e_operation (id)); } else if (predicate_id *p = dyn_cast <predicate_id *> (opr)) op = new predicate (p); --- 2473,2479 ---- fatal_at (token, "using an operator with operands as predicate"); /* Parse the zero-operand operator "predicates" as expression. */ ! op = new expr (opr); } else if (predicate_id *p = dyn_cast <predicate_id *> (opr)) op = new predicate (p); *************** parse_simplify (cpp_reader *r, source_lo *** 2530,2536 **** if (match->type == operand::OP_CAPTURE && !matcher) fatal_at (loc, "outermost expression cannot be captured"); if (match->type == operand::OP_EXPR ! && is_a <predicate_id *> (as_a <expr *> (match)->operation->op)) fatal_at (loc, "outermost expression cannot be a predicate"); const cpp_token *token = peek (r); --- 2514,2520 ---- if (match->type == operand::OP_CAPTURE && !matcher) fatal_at (loc, "outermost expression cannot be captured"); if (match->type == operand::OP_EXPR ! && is_a <predicate_id *> (as_a <expr *> (match)->operation)) fatal_at (loc, "outermost expression cannot be a predicate"); const cpp_token *token = peek (r); *************** void *** 2653,2659 **** parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers, vec<if_or_with>& active_ifs) { ! vec<const char *> user_ids = vNULL; vec< vec<const char *> > opers_vec = vNULL; const cpp_token *token; unsigned min_n_opers = 0, max_n_opers = 0; --- 2637,2643 ---- parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers, vec<if_or_with>& active_ifs) { ! vec<id_base *> user_ids = vNULL; vec< vec<const char *> > opers_vec = vNULL; const cpp_token *token; unsigned min_n_opers = 0, max_n_opers = 0; *************** parse_for (cpp_reader *r, source_locatio *** 2664,2675 **** if (token == 0) break; ! const char *id = (const char *) NODE_NAME (token->val.node.node); ! if (get_operator (id)) ! fatal_at (token, "built-in operators cannot be user defined identifiers in for"); ! ! user_ids.safe_push (id); ! eat_token (r, CPP_NAME); eat_token (r, CPP_OPEN_PAREN); --- 2648,2661 ---- if (token == 0) break; ! /* Insert the user defined operators into the operator hash. */ ! const char *id = get_ident (r); ! id_base *op = new id_base (id_base::USER_DEFINED, 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); eat_token (r, CPP_OPEN_PAREN); *************** parse_for (cpp_reader *r, source_locatio *** 2677,2686 **** while ((token = peek_ident (r)) != 0) { ! eat_token (r, CPP_NAME); ! const char *oper = (const char *) NODE_NAME (token->val.node.node); id_base *idb = get_operator (oper); ! if (idb == 0) 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"); --- 2663,2671 ---- 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); if (*idb == CONVERT0 || *idb == CONVERT1 || *idb == CONVERT2) fatal_at (token, "conditional operators cannot be used inside for"); *************** parse_for (cpp_reader *r, source_locatio *** 2689,2695 **** } token = expect (r, CPP_CLOSE_PAREN); if (opers.length () == 0) ! fatal_at (token, "A user-defined identifier must have at least one substitution"); if (opers_vec.length () == 0) { min_n_opers = opers.length (); --- 2674,2680 ---- } token = expect (r, CPP_CLOSE_PAREN); if (opers.length () == 0) ! fatal_at (token, "A user-defined operator must have at least one substitution"); if (opers_vec.length () == 0) { min_n_opers = opers.length (); *************** parse_for (cpp_reader *r, source_locatio *** 2740,2757 **** for (unsigned i = 0; i < n_ids; ++i) { const char *oper = opers_vec[i][j % opers_vec[i].length ()]; ! match_op = replace_id (match_op, user_ids[i], oper); ! result_op = replace_id (result_op, user_ids[i], oper); for (unsigned k = 0; k < s->ifexpr_vec.length (); ++k) ! ifexpr_vec[k].cexpr = replace_id (ifexpr_vec[k].cexpr, user_ids[i], oper); } simplify *ns = new simplify (match_op, s->match_location, result_op, s->result_location, ifexpr_vec); simplifiers.safe_push (ns); } } } void --- 2725,2747 ---- for (unsigned i = 0; i < n_ids; ++i) { + const char *op = user_ids[i]->id; const char *oper = opers_vec[i][j % opers_vec[i].length ()]; ! match_op = replace_id (match_op, op, oper); ! result_op = replace_id (result_op, op, oper); for (unsigned k = 0; k < s->ifexpr_vec.length (); ++k) ! ifexpr_vec[k].cexpr = replace_id (ifexpr_vec[k].cexpr, op, oper); } simplify *ns = new simplify (match_op, s->match_location, result_op, s->result_location, ifexpr_vec); simplifiers.safe_push (ns); } } + + /* Remove user-defined operators from the hash again. */ + for (unsigned i = 0; i < user_ids.length (); ++i) + operators->remove_elt (user_ids[i]); } void