On Mon, Aug 11, 2014 at 4:58 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Sun, Aug 10, 2014 at 11:17 PM, Prathamesh Kulkarni > <bilbotheelffri...@gmail.com> wrote: >> On Mon, Aug 4, 2014 at 2:13 PM, Richard Biener >> <richard.guent...@gmail.com> wrote: >>> On Sun, Aug 3, 2014 at 6:58 PM, Prathamesh Kulkarni >>> <bilbotheelffri...@gmail.com> wrote: >>>> On Tue, Jul 29, 2014 at 4:29 PM, Richard Biener >>>> <richard.guent...@gmail.com> wrote: >>>>> On Mon, Jul 28, 2014 at 10:02 PM, Prathamesh Kulkarni >>>>> <bilbotheelffri...@gmail.com> wrote: >>>>>> I am having few issues replacing op in c_expr. >>>>>> I thought of following possibilities: >>>>>> >>>>>> a) create a new vec<cpp_token> vector new_code. >>>>>> for each token in code >>>>>> { >>>>>> if token.type is not CPP_NAME >>>>>> new_code.safe_push (token); >>>>>> else >>>>>> { >>>>>> cpp_token new_token = >>>>>> ??? create new token of type CPP_NAME >>>>>> with contents as name of operator ??? >>>>>> } >>>>>> } >>>>>> >>>>>> I tried to go this way, but am stuck with creating a new token type. >>>>>> i started by: >>>>>> cpp_token new_token = token; // get same attrs as token. >>>>>> CPP_HASHNODE (new_token.val.node.node)->ident.str = name of operator. >>>>>> CPP_HASHNODE (new_token.val.node.node)->ident.len = len of operator name. >>>>>> name of operator is obtained from opers[i] in parse_for. >>>>>> >>>>>> however this does not work because I guess >>>>>> new_token = token, shallow copies >>>>>> the token (default assignment operator, i didn't find an overloaded >>>>>> version). >>>>>> >>>>>> b) create new struct c_expr_elem and use >>>>>> vec<c_expr_elem> code, instead of vec<cpp_token> code; >>>>>> >>>>>> sth like: >>>>>> struct c_expr_elem >>>>>> { >>>>>> enum c_expr_elem_type { ID, TOKEN }; >>>>>> enum c_expr_elem_type type; >>>>>> >>>>>> union { >>>>>> cpp_token token; >>>>>> const char *id; >>>>>> }; >>>>>> }; >>>>>> >>>>>> while replacing op, compare token with op, and if it matches, >>>>>> create a new c_expr_elem with type = ID, and id = name of operator. >>>>>> This shall probably work, but shall require many changes to other parts >>>>>> since we change c_expr::code. >>>>>> >>>>>> I would like to hear any other suggestions. >>>>> >>>>> Together with the vector of tokens recorded at parse_c_expr time >>>>> record a vector of token mappings (op -> plus, op2 -> ...) and do >>>>> the replacement at code-generation time where we also special-case >>>>> captures. >>>>> >>>>> Yeah, it's a but unfortunate that c_expr parsing is done the way it >>>>> is done.... >>>> Thanks. I guess we would require a multi-map for this since there can >>>> be many operators >>>> (op -> [plus, minus], op2 -> [negate]) ? >>> >>> Well, it would be enough to attach the mapping to c_expr()s after the >>> AST lowering when there is at most one? Because obviously >>> code-generation cannot know which to replace. >>> >>>> Unfortunately, I somehow seem to have missed your response and ended up >>>> with a >>>> hackish way of doing it, although it works. I will soon change that to >>>> use token mappings. >>>> >>>> I mostly followed b), except i made it sub-class of cpp_token, so the >>>> other code using c_expr::code >>>> (outline_c_expr, c_expr::gen_transform) did not require changes except >>>> for special-casing op. >>> >>> Indeed not too ugly. Still at the point where you replace in the for() >>> processing >>> >>> - operand *result_op = replace_id (s->result, user_id, >>> opers[i]); >>> + >>> + operand *result_op; >>> + if (is_a<c_expr *> (s->result)) >>> + result_op = replace_op_in_c_expr (s->result, user_id, >>> opers[i]); >>> + else >>> + result_op = replace_id (s->result, user_id, opers[i]); >>> + >>> + >>> >>> it should be "easy" to attach a replacemet vector/map to the c_expr >>> and use that duing code-generation. >>> >>> Note that sub-expressions can also be c_exprs, thus >>> >>> (match-and-simplify >>> (....) >>> (plus { ... } @2)) >>> >>> I don't think your patch covers that. That is, you should add >>> c_expr handing to replace_id instead. >> Thanks, this patch covers that case. >> For now, I have still kept the old way, since the change was one-liner. >> I will change it after I am done with conditional convert > > I'll wait for that - the patch introduces extra warnings which will break > bootstrap. > Hi, This patch replaces op in c_expr, by using vector in c_expr to record <user_id, operator> mapping. Sorry for late response.
I needed to clone c_expr, so added clone member function to operand hierarchy. Ideally it should be a pure member function (= 0) in operand, however for simplicity I have put gcc_unreachable (), since I only want it used for c_expr (not required so far for other classes). Is that okay for now ? Eventually I will implement clone for other classes... * genmatch.c (operand): New member function clone. (c_expr): Override clone. (c_expr): New struct id_tab. (c_expr): New member ids. (simplify::simplify): Adjust to clone c_expr. (replace_id): New default parameter replace_c_expr. (c_expr::gen_transform): Adjust to replace user-defined identifier in c_expr. (outline_c_expr): Likewise. (parse_for): Likewise. Thanks, Prathamesh > Thanks, > Richard. > >> * genmatch.c (c_expr::elem): New struct. >> (c_expr::code): Change type to vec<c_expr::elem>. >> (replace_op_in_c_expr): New function. >> (replace_id): Call replace_op_in_c_expr. >> (c_expr::gen_transform): Adjust to changes in c_expr. >> (outline_c_expr): Likewise. >> (parse_c_expr): Likewise. >> (parse_for): Call replace_op_in_c_expr. >> Thanks, >> Prathamesh >>> >>> Richard. >>> >>>> * genmatch.c (c_expr::elem): New struct. >>>> (c_expr::code): Change type to vec<c_expr::elem>. >>>> (replace_op_in_c_expr): New function. >>>> (c_expr::gen_transform): Adjust to changes in c_expr. >>>> (outline_c_expr): Likewise. >>>> (parse_c_expr): Likewise. >>>> (parse_for): Call replace_op_in_c_expr. >>>> >>>> Thanks, >>>> Prathamesh >>>> >>>>> >>>>> Richard. >>>>> >>>>>> Thanks, >>>>>> Prathamesh.
Index: genmatch.c =================================================================== --- genmatch.c (revision 214020) +++ genmatch.c (working copy) @@ -222,6 +222,8 @@ struct operand { operand (enum op_type type_) : type (type_) {} enum op_type type; virtual void gen_transform (FILE *f, const char *, bool, int) = 0; + + virtual operand *clone() { gcc_unreachable (); } }; struct predicate : public operand @@ -251,14 +253,36 @@ struct expr : public operand struct c_expr : public operand { + struct id_tab { + const char *id; + const char *oper; + + id_tab (const char *id_, const char *oper_): id (id_), oper (oper_) {} + }; + + c_expr (cpp_reader *r_, vec<cpp_token> code_, unsigned nr_stmts_) : operand (OP_C_EXPR), r (r_), code (code_), - nr_stmts (nr_stmts_), fname (NULL) {} + nr_stmts (nr_stmts_), fname (NULL), ids (vNULL) {} cpp_reader *r; vec<cpp_token> code; unsigned nr_stmts; char *fname; + vec<id_tab> ids; + virtual void gen_transform (FILE *f, const char *, bool, int); + + operand *clone() + { + // we only want to copy ids + c_expr *ce = new c_expr (r, code, nr_stmts); + for (unsigned i = 0; i < ids.length (); ++i) + { + id_tab temp (ids[i].id, ids[i].oper); + ce->ids.safe_push (temp); + } + return ce; + } }; struct capture : public operand @@ -356,8 +380,17 @@ struct simplify { operand *match_, source_location match_location_, struct operand *result_, source_location result_location_, vec<operand *> ifexpr_vec_ = vNULL) : name (name_), match (match_), match_location (match_location_), - result (result_), result_location (result_location_), - ifexpr_vec (ifexpr_vec_) {} + result_location (result_location_) + { + ifexpr_vec = vNULL; + for (unsigned i = 0; i < ifexpr_vec_.length (); ++i) + ifexpr_vec.safe_push (ifexpr_vec_[i]->clone ()); + + if (is_a<c_expr *> (result_)) + result = result_->clone (); + else + result = result_; + } const char *name; operand *match; @@ -760,7 +793,7 @@ check_operator (id_base *op, unsigned n_ } operand * -replace_id (operand *o, const char *user_id, const char *oper) +replace_id (operand *o, const char *user_id, const char *oper, bool replace_c_expr = false) { if (o->type == operand::OP_CAPTURE) { @@ -771,6 +804,15 @@ replace_id (operand *o, const char *user return nc; } + c_expr *ce; + if ((ce = dyn_cast<c_expr *> (o)) != 0 && replace_c_expr == true) + { + id_base *idb = get_operator (oper); + c_expr::id_tab temp (user_id, idb->id); + ce->ids.safe_push (temp); + return ce; + } + if (o->type != operand::OP_EXPR) return o; @@ -909,6 +951,23 @@ c_expr::gen_transform (FILE *f, const ch } } + if (token->type == CPP_NAME) + { + const char *id = (const char *) NODE_NAME (token->val.node.node); + unsigned j; + for (j = 0; j < ids.length (); ++j) + { + if (strcmp (id, ids[j].id) == 0) + { + fprintf (f, "%s", ids[j].oper); + break; + } + } + if (j < ids.length ()) + continue; + } + + if (token->flags & PREV_WHITE) fputc (' ', f); @@ -1912,6 +1971,25 @@ outline_c_exprs (FILE *f, struct operand if (token->flags & PREV_WHITE) fputc (' ', f); + if (token->type == CPP_NAME) + { + const char *id = (const char *) NODE_NAME (token->val.node.node); + unsigned j; + + for (j = 0; j < e->ids.length (); ++j) + { + if (strcmp (id, e->ids[j].id) == 0) + { + fprintf (f, "%s", e->ids[j].oper); + break; + } + } + + if (j < e->ids.length ()) + continue; + } + + /* Output the token as string. */ char *tk = (char *)cpp_token_as_text (e->r, token); fputs (tk, f); @@ -2292,10 +2370,11 @@ parse_simplify (cpp_reader *r, source_lo void parse_pattern (cpp_reader *, vec<simplify *>&); void -parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers) +parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers_out) { const char *user_id = get_ident (r); eat_ident (r, "in"); + vec<const char *> replace_opers = vNULL; if (get_operator (user_id) != 0) fatal_at (peek (r), "%s is an operator, cannot be used as variable in for", user_id); @@ -2319,30 +2398,49 @@ parse_for (cpp_reader *r, source_locatio fatal_at (token, "no pattern defined in for"); + vec<simplify *> for_simplifiers = vNULL; + vec<simplify *> simplifiers = vNULL; + while (1) { const cpp_token *token = peek (r); if (token->type == CPP_CLOSE_PAREN) break; - vec<simplify *> for_simplifiers = vNULL; parse_pattern (r, for_simplifiers); - + } + for (unsigned i = 0; i < opers.length (); ++i) { + id_base *idb = get_operator (opers[i]); + gcc_assert (idb); + for (unsigned j = 0; j < for_simplifiers.length (); ++j) { simplify *s = for_simplifiers[j]; operand *match_op = replace_id (s->match, user_id, opers[i]); operand *result_op = replace_id (s->result, user_id, opers[i]); + replace_opers.safe_push (idb->id); simplify *ns = new simplify (s->name, match_op, s->match_location, result_op, s->result_location, s->ifexpr_vec); simplifiers.safe_push (ns); } } - } + + gcc_assert (replace_opers.length () == simplifiers.length ()); + + for (unsigned i = 0; i < simplifiers.length (); ++i) + { + simplify *s = simplifiers[i]; + for (unsigned j = 0; j < s->ifexpr_vec.length (); ++j) + s->ifexpr_vec[j] = replace_id (s->ifexpr_vec[j], user_id, replace_opers[i], true); + s->result = replace_id (s->result, user_id, replace_opers[i], true); + } + + for (unsigned i = 0; i < simplifiers.length (); ++i) + simplifiers_out.safe_push (simplifiers[i]); } void