On Mon, Aug 4, 2014 at 2:13 PM, Richard Biener
<[email protected]> wrote:
> On Sun, Aug 3, 2014 at 6:58 PM, Prathamesh Kulkarni
> <[email protected]> wrote:
>> On Tue, Jul 29, 2014 at 4:29 PM, Richard Biener
>> <[email protected]> wrote:
>>> On Mon, Jul 28, 2014 at 10:02 PM, Prathamesh Kulkarni
>>> <[email protected]> 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
* 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 213756)
+++ genmatch.c (working copy)
@@ -239,11 +239,20 @@ struct expr : public operand
struct c_expr : public operand
{
- c_expr (cpp_reader *r_, vec<cpp_token> code_, unsigned nr_stmts_)
+ struct elem: public cpp_token
+ {
+ enum elem_type { TOKEN, ID };
+ enum elem_type type;
+ const char *id;
+
+ elem (enum elem_type type_ = TOKEN, const char *id_ = 0): type (type_), id (id_) {}
+ };
+
+ c_expr (cpp_reader *r_, vec<elem> code_, unsigned nr_stmts_)
: operand (OP_C_EXPR), r (r_), code (code_),
nr_stmts (nr_stmts_), fname (NULL) {}
cpp_reader *r;
- vec<cpp_token> code;
+ vec<elem> code;
unsigned nr_stmts;
char *fname;
virtual void gen_transform (FILE *f, const char *, bool, int);
@@ -620,6 +629,31 @@ check_operator (id_base *op, unsigned n_
}
operand *
+replace_op_in_c_expr (operand *o, const char *user_id, const char *oper)
+{
+ gcc_assert (is_a<c_expr *> (o));
+ c_expr *ce = as_a<c_expr *> (o);
+
+ vec<c_expr::elem> code = vNULL;
+
+ for (unsigned i = 0; i < ce->code.length (); ++i)
+ {
+ cpp_token token = ce->code[i];
+ if (token.type == CPP_NAME
+ && strcmp ((const char *) NODE_NAME (token.val.node.node), user_id) == 0)
+ {
+ e_operation operation (oper);
+ c_expr::elem elm (c_expr::elem::ID, operation.op->id);
+ code.safe_push (elm);
+ }
+ else
+ code.safe_push (ce->code[i]);
+ }
+
+ return new c_expr (ce->r, code, ce->nr_stmts);
+}
+
+operand *
replace_id (operand *o, const char *user_id, const char *oper)
{
if (o->type == operand::OP_CAPTURE)
@@ -631,10 +665,13 @@ replace_id (operand *o, const char *user
return nc;
}
- if (o->type != operand::OP_EXPR)
+ if (is_a<c_expr *> (o))
+ return replace_op_in_c_expr (o, user_id, oper);
+
+ if (!is_a<expr *> (o))
return o;
- expr *e = static_cast<expr *> (o);
+ expr *e = as_a<expr *> (o);
expr *ne;
if (e->operation->op->kind == id_base::USER_DEFINED && strcmp (e->operation->op->id, user_id) == 0)
@@ -651,6 +688,7 @@ replace_id (operand *o, const char *user
return ne;
}
+
void
check_no_user_id (operand *o)
@@ -752,6 +790,11 @@ c_expr::gen_transform (FILE *f, const ch
for (unsigned i = 0; i < code.length (); ++i)
{
+ if (code[i].type == elem::ID)
+ {
+ fputs (code[i].id, f);
+ continue;
+ }
const cpp_token *token = &code[i];
/* Replace captures for code-gen. */
@@ -1727,6 +1770,11 @@ outline_c_exprs (FILE *f, struct operand
unsigned stmt_nr = 1;
for (unsigned i = 0; i < e->code.length (); ++i)
{
+ if (e->code[i].type == c_expr::elem::ID)
+ {
+ fputs (e->code[i].id, f);
+ continue;
+ }
const cpp_token *token = &e->code[i];
/* Replace captures for code-gen. */
@@ -1982,7 +2030,7 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
const cpp_token *token;
cpp_ttype end;
unsigned opencnt;
- vec<cpp_token> code = vNULL;
+ vec<c_expr::elem> code = vNULL;
unsigned nr_stmts = 0;
eat_token (r, start);
if (start == CPP_OPEN_PAREN)
@@ -2007,7 +2055,7 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
nr_stmts++;
/* Record the token. */
- code.safe_push (*token);
+ code.safe_push (*(c_expr::elem *) token);
}
while (1);
return new c_expr (r, code, nr_stmts);
@@ -2147,10 +2195,20 @@ parse_for (cpp_reader *r, source_locatio
{
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]);
+
+ 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]);
+
+
+ vec<operand *> ifexpr_vec = vNULL;
+ for (unsigned k = 0; k < s->ifexpr_vec.length (); ++k)
+ ifexpr_vec.safe_push (replace_op_in_c_expr (s->ifexpr_vec[k], user_id, opers[i]));
simplify *ns = new simplify (s->name, match_op, s->match_location,
- result_op, s->result_location, s->ifexpr_vec);
+ result_op, s->result_location, ifexpr_vec);
simplifiers.safe_push (ns);
}