diff options
author | Josh Stone <jistone@redhat.com> | 2009-02-10 20:10:33 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-02-10 20:10:33 -0800 |
commit | 8040a4b42cd0fc66142d3ef2f905ea0267726b76 (patch) | |
tree | ca0d5d32c5f87dcb2803e5172d3d8ad471eaaf4d | |
parent | 098043c5f96ee58756342cfbe7b49c2572f79a15 (diff) | |
parent | 9f9873dfc0978ef3ce7b7b5aa7ae1e2b5b4909b9 (diff) | |
download | systemtap-steved-8040a4b42cd0fc66142d3ef2f905ea0267726b76.tar.gz systemtap-steved-8040a4b42cd0fc66142d3ef2f905ea0267726b76.tar.xz systemtap-steved-8040a4b42cd0fc66142d3ef2f905ea0267726b76.zip |
Merge branch 'update_visitor'
This brings a new update_visitor that makes it easier to traverse the
parse tree and modify parts of it as necessary. I wrote this as part of
my in-progress work to allow @cast() expansion, but I was able to apply
it to the dwarf/etc. target variable expanders and to the optimization
stages. I think the resulting code is more predictable and easier to
follow...
Conflicts:
ChangeLog (bumped my commit dates to push dates...)
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | elaborate.cxx | 376 | ||||
-rw-r--r-- | staptree.cxx | 547 | ||||
-rw-r--r-- | staptree.h | 101 | ||||
-rw-r--r-- | tapsets.cxx | 138 |
5 files changed, 595 insertions, 603 deletions
@@ -1,3 +1,39 @@ +2009-02-10 Josh Stone <jistone@redhat.com> + + * staptree.h (update_visitor::require): Add a clearok parameter for + optimizing traversers to signal that they're ready for NULL back. + * elaborate.cxx (dead_assignment_remover): Convert into an + update_visitor and remove its now-redundant traversal methods. + * elaborate.cxx (dead_stmtexpr_remover): Convert to an update_visitor. + * elaborate.cxx (void_statement_reducer): Convert to an update_visitor. + +2009-02-10 Josh Stone <jistone@redhat.com> + + * tapsets.cxx (var_expanding_copy_visitor): This struct becomes + var_expanding_visitor and inherits from update_visitor instead of + deep_copy_visitor. Each of the probe-type variants of this are also no + longer copiers. + +2009-02-10 Josh Stone <jistone@redhat.com> + + * staptree.h (update_visitor): A new visitor to make it easier to + rewrite parts of a probe or function without making a full copy. + * staptree.cxx (update_visitor::*): Each child is recursed with a + require() call, and then the parent returns itself with provide(). + * staptree.h (deep_copy_visitor): Inherit from update_visitor to get + the recursive descent while updating nodes. + * staptree.cxx (deep_copy_visitor::*): Use the implicit copy + constructors to copy all fields, then defer to update_visitor for the + recursion. Referents are still cleared from the copies of symbols and + function calls. + +2009-02-10 Josh Stone <jistone@redhat.com> + + * staptree.h (require, provide): Simplify stack operations with less + pointer magic, and move to be deep_copy_visitor members. + * staptree.h (deep_copy_visitor::deep_copy): Templatize + * staptree.cxx, tapsets.cxx: Refactor require/provide callers + 2009-02-10 Frank Ch. Eigler <fche@elastic.org> * tapsets.cxx (find_variable_and_frame_base): Tolerate -1 return diff --git a/elaborate.cxx b/elaborate.cxx index 5678e8a7..ba50defb 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2091,59 +2091,30 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati // ------------------------------------------------------------------------ -struct dead_assignment_remover: public traversing_visitor +struct dead_assignment_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; const varuse_collecting_visitor& vut; - expression** current_expr; dead_assignment_remover(systemtap_session& s, bool& r, const varuse_collecting_visitor& v): - session(s), relaxed_p(r), vut(v), current_expr(0) {} - - void visit_expr_statement (expr_statement* s); - // XXX: other places where an assignment may be nested should be - // handled too (e.g., loop/if conditionals, array indexes, function - // parameters). Until then, they result in visit_assignment() being - // called with null current_expr. + session(s), relaxed_p(r), vut(v) {} void visit_assignment (assignment* e); - void visit_binary_expression (binary_expression* e); - void visit_arrayindex (arrayindex* e); - void visit_functioncall (functioncall* e); - void visit_if_statement (if_statement* e); - void visit_for_loop (for_loop* e); }; void -dead_assignment_remover::visit_expr_statement (expr_statement* s) -{ - expression** last_expr = current_expr; - current_expr = & s->value; - s->value->visit (this); - s->tok = s->value->tok; // in case it was replaced - current_expr = last_expr; -} - - -void dead_assignment_remover::visit_assignment (assignment* e) { + e->left = require (e->left); + e->right = require (e->right); + symbol* left = get_symbol_within_expression (e->left); vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target - if (current_expr && // see XXX above: this case represents a missed - // optimization opportunity - *current_expr == e && // we're not nested any deeper than expected - leftvar) // not unresolved $target; intended sideeffect cannot be elided + if (leftvar) // not unresolved $target, so intended sideeffect may be elided { - expression** last_expr = current_expr; - e->left->visit (this); - current_expr = &e->right; - e->right->visit (this); - current_expr = last_expr; - if (vut.read.find(leftvar) == vut.read.end()) // var never read? { // NB: Not so fast! The left side could be an array whose @@ -2163,9 +2134,9 @@ dead_assignment_remover::visit_assignment (assignment* e) break; } - varuse_collecting_visitor vut; - e->left->visit (& vut); - if (vut.side_effect_free () && !is_global) // XXX: use _wrt() once we track focal_vars + varuse_collecting_visitor lvut; + e->left->visit (& lvut); + if (lvut.side_effect_free () && !is_global) // XXX: use _wrt() once we track focal_vars { /* PR 1119: NB: This is not necessary here. A write-only variable will also be elided soon at the next _opt2 iteration. @@ -2178,77 +2149,13 @@ dead_assignment_remover::visit_assignment (assignment* e) clog << "Eliding assignment to " << leftvar->name << " at " << *e->tok << endl; - *current_expr = e->right; // goodbye assignment* + provide (e->right); // goodbye assignment* relaxed_p = false; + return; } } } -} - -void -dead_assignment_remover::visit_binary_expression (binary_expression* e) -{ - expression** last_expr = current_expr; - current_expr = &e->left; - e->left->visit (this); - current_expr = &e->right; - e->right->visit (this); - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_arrayindex (arrayindex *e) -{ - symbol *array = NULL; - hist_op *hist = NULL; - classify_indexable(e->base, array, hist); - - if (array) - { - expression** last_expr = current_expr; - for (unsigned i=0; i < e->indexes.size(); i++) - { - current_expr = & e->indexes[i]; - e->indexes[i]->visit (this); - } - current_expr = last_expr; - } -} - -void -dead_assignment_remover::visit_functioncall (functioncall* e) -{ - expression** last_expr = current_expr; - for (unsigned i=0; i<e->args.size(); i++) - { - current_expr = & e->args[i]; - e->args[i]->visit (this); - } - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_if_statement (if_statement* s) -{ - expression** last_expr = current_expr; - current_expr = & s->condition; - s->condition->visit (this); - s->thenblock->visit (this); - if (s->elseblock) - s->elseblock->visit (this); - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_for_loop (for_loop* s) -{ - expression** last_expr = current_expr; - if (s->init) s->init->visit (this); - current_expr = & s->cond; - s->cond->visit (this); - if (s->incr) s->incr->visit (this); - s->block->visit (this); - current_expr = last_expr; + provide (e); } // Let's remove assignments to variables that are never read. We @@ -2268,9 +2175,10 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; i<s.probes.size(); i++) - s.probes[i]->body->visit (& dar); - for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body->visit (& dar); + s.probes[i]->body = dar.require (s.probes[i]->body); + for (map<string,functiondecl*>::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + it->second->body = dar.require (it->second->body); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here @@ -2279,15 +2187,14 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // ------------------------------------------------------------------------ -struct dead_stmtexpr_remover: public traversing_visitor +struct dead_stmtexpr_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; - statement** current_stmt; // pointer to current stmt* being iterated set<vardecl*> focal_vars; // vars considered subject to side-effects dead_stmtexpr_remover(systemtap_session& s, bool& r): - session(s), relaxed_p(r), current_stmt(0) {} + session(s), relaxed_p(r) {} void visit_block (block *s); void visit_null_statement (null_statement *s); @@ -2306,7 +2213,8 @@ dead_stmtexpr_remover::visit_null_statement (null_statement *s) // easy! if (session.verbose>2) clog << "Eliding side-effect-free null statement " << *s->tok << endl; - *current_stmt = 0; + s = 0; + provide (s); } @@ -2316,13 +2224,11 @@ dead_stmtexpr_remover::visit_block (block *s) vector<statement*> new_stmts; for (unsigned i=0; i<s->statements.size(); i++ ) { - statement** last_stmt = current_stmt; - current_stmt = & s->statements[i]; - s->statements[i]->visit (this); - if (*current_stmt != 0) + statement* new_stmt = require (s->statements[i], true); + if (new_stmt != 0) { // flatten nested blocks into this one - block *b = dynamic_cast<block *>(*current_stmt); + block *b = dynamic_cast<block *>(new_stmt); if (b) { if (session.verbose>2) @@ -2332,42 +2238,32 @@ dead_stmtexpr_remover::visit_block (block *s) relaxed_p = false; } else - new_stmts.push_back (*current_stmt); + new_stmts.push_back (new_stmt); } - current_stmt = last_stmt; } if (new_stmts.size() == 0) { if (session.verbose>2) clog << "Eliding side-effect-free empty block " << *s->tok << endl; - *current_stmt = 0; + s = 0; } else if (new_stmts.size() == 1) { if (session.verbose>2) clog << "Eliding side-effect-free singleton block " << *s->tok << endl; - *current_stmt = new_stmts[0]; + provide (new_stmts[0]); + return; } else - { - s->statements = new_stmts; - } + s->statements = new_stmts; + provide (s); } void dead_stmtexpr_remover::visit_if_statement (if_statement *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->thenblock; - s->thenblock->visit (this); - - if (s->elseblock) - { - current_stmt = & s->elseblock; - s->elseblock->visit (this); - // null *current_stmt is OK here. - } - current_stmt = last_stmt; + s->thenblock = require (s->thenblock, true); + s->elseblock = require (s->elseblock, true); if (s->thenblock == 0) { @@ -2382,7 +2278,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) if (session.verbose>2) clog << "Eliding side-effect-free if statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby + s = 0; // yeah, baby } else { @@ -2393,7 +2289,8 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) expr_statement *es = new expr_statement; es->value = s->condition; es->tok = es->value->tok; - *current_stmt = es; + provide (es); + return; } } else @@ -2412,31 +2309,27 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) s->elseblock = 0; } } + provide (s); } void dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + s->block = require(s->block, true); if (s->block == 0) { if (session.verbose>2) clog << "Eliding side-effect-free foreach statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby + s = 0; // yeah, baby } + provide (s); } void dead_stmtexpr_remover::visit_for_loop (for_loop *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + s->block = require(s->block, true); if (s->block == 0) { @@ -2450,14 +2343,16 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s) { if (session.verbose>2) clog << "Eliding side-effect-free for statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby - return; + s = 0; // yeah, baby + } + else + { + // Can't elide this whole statement; put a null in there. + s->block = new null_statement(); + s->block->tok = s->tok; } - - // Can't elide this whole statement; put a null in there. - s->block = new null_statement(); - s->block->tok = s->tok; } + provide (s); } @@ -2467,8 +2362,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) { // Run a varuse query against the operand expression. If it has no // side-effects, replace the entire statement expression by a null - // statement. This replacement is done by overwriting the - // current_stmt pointer. + // statement with the provide() call. // // Unlike many other visitors, we do *not* traverse this outermost // one into the expression subtrees. There is no need - no @@ -2481,8 +2375,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) varuse_collecting_visitor vut; s->value->visit (& vut); - if (vut.side_effect_free_wrt (focal_vars) && - *current_stmt == s) // we're not nested any deeper than expected + if (vut.side_effect_free_wrt (focal_vars)) { /* PR 1119: NB: this message is not a good idea here. It can name some arbitrary RHS expression of an assignment. @@ -2497,10 +2390,10 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) // NB: this 0 pointer is invalid to leave around for any length of // time, but the parent parse tree objects above handle it. - * current_stmt = 0; - + s = 0; relaxed_p = false; } + provide (s); } @@ -2525,8 +2418,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (p->locals.begin(), p->locals.end()); - duv.current_stmt = & p->body; - p->body->visit (& duv); + p->body = duv.require(p->body, true); if (p->body == 0) { if (! s.suppress_warnings) @@ -2551,8 +2443,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - duv.current_stmt = & fn->body; - fn->body->visit (& duv); + fn->body = duv.require(fn->body, true); if (fn->body == 0) { if (! s.suppress_warnings) @@ -2577,21 +2468,27 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) // into separate statements that evaluate each subcomponent of the expression. // The dead-statement-remover can later remove some parts if they have no side // effects. -struct void_statement_reducer: public traversing_visitor +// +// All expressions must be overridden here so we never visit their subexpressions +// accidentally. Thus, the only visited expressions should be value of an +// expr_statement. +// +// For an expression to replace its expr_statement with something else, it will +// let the new statement provide(), and then provide(0) for itself. The +// expr_statement will take this as a sign that it's been replaced. +struct void_statement_reducer: public update_visitor { systemtap_session& session; bool& relaxed_p; - statement** current_stmt; // pointer to current stmt* being iterated - expr_statement* current_expr; // pointer to current expr being iterated set<vardecl*> focal_vars; // vars considered subject to side-effects void_statement_reducer(systemtap_session& s, bool& r): - session(s), relaxed_p(r), current_stmt(0), current_expr(0) {} + session(s), relaxed_p(r) {} - // these just maintain current_stmt while recursing, but don't visit - // expressions in the conditional / loop controls. void visit_expr_statement (expr_statement* s); - void visit_block (block *s); + + // expressions in conditional / loop controls are definitely a side effect, + // but still recurse into the child statements void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); @@ -2611,72 +2508,54 @@ struct void_statement_reducer: public traversing_visitor // these are a bit hairy to grok due to the intricacies of indexables and // stats, so I'm chickening out and skipping them... - void visit_array_in (array_in* e) {} - void visit_arrayindex (arrayindex* e) {} - void visit_stat_op (stat_op* e) {} - void visit_hist_op (hist_op* e) {} + void visit_array_in (array_in* e) { provide (e); } + void visit_arrayindex (arrayindex* e) { provide (e); } + void visit_stat_op (stat_op* e) { provide (e); } + void visit_hist_op (hist_op* e) { provide (e); } // these can't be reduced because they always have an effect - void visit_return_statement (return_statement* s) {} - void visit_delete_statement (delete_statement* s) {} - void visit_pre_crement (pre_crement* e) {} - void visit_post_crement (post_crement* e) {} - void visit_assignment (assignment* e) {} + void visit_return_statement (return_statement* s) { provide (s); } + void visit_delete_statement (delete_statement* s) { provide (s); } + void visit_pre_crement (pre_crement* e) { provide (e); } + void visit_post_crement (post_crement* e) { provide (e); } + void visit_assignment (assignment* e) { provide (e); } }; void void_statement_reducer::visit_expr_statement (expr_statement* s) { - assert(!current_expr); // it shouldn't be possible to have nested expr's - current_expr = s; - s->value->visit (this); - current_expr = NULL; -} + s->value = require (s->value, true); -void -void_statement_reducer::visit_block (block *s) -{ - statement** last_stmt = current_stmt; - for (unsigned i=0; i<s->statements.size(); i++ ) - { - current_stmt = & s->statements[i]; - s->statements[i]->visit (this); - } - current_stmt = last_stmt; + // if the expression provides 0, that's our signal that a new + // statement has been provided, so we shouldn't provide this one. + if (s->value != 0) + provide(s); } void void_statement_reducer::visit_if_statement (if_statement* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->thenblock; - s->thenblock->visit (this); - - if (s->elseblock) - { - current_stmt = & s->elseblock; - s->elseblock->visit (this); - } - current_stmt = last_stmt; + // s->condition is never void + s->thenblock = require (s->thenblock); + s->elseblock = require (s->elseblock); + provide (s); } void void_statement_reducer::visit_for_loop (for_loop* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + // s->init/cond/incr are never void + s->block = require (s->block); + provide (s); } void void_statement_reducer::visit_foreach_loop (foreach_loop* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + // s->indexes/base/limit are never void + s->block = require (s->block); + provide (s); } void @@ -2685,8 +2564,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) // In void context, the evaluation of "a || b" is exactly like // "if (!a) b", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused logical-or " << *e->tok << endl; @@ -2694,8 +2571,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) if_statement *is = new if_statement; is->tok = e->tok; is->elseblock = 0; - *current_stmt = is; - current_expr = NULL; unary_expression *ue = new unary_expression; ue->operand = e->left; @@ -2710,6 +2585,8 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2718,8 +2595,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) // In void context, the evaluation of "a && b" is exactly like // "if (a) b", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused logical-and " << *e->tok << endl; @@ -2728,8 +2603,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) is->tok = e->tok; is->elseblock = 0; is->condition = e->left; - *current_stmt = is; - current_expr = NULL; expr_statement *es = new expr_statement; es->value = e->right; @@ -2738,6 +2611,8 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2746,8 +2621,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) // In void context, the evaluation of "a ? b : c" is exactly like // "if (a) b else c", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused ternary expression " << *e->tok << endl; @@ -2755,8 +2628,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) if_statement *is = new if_statement; is->tok = e->tok; is->condition = e->cond; - *current_stmt = is; - current_expr = NULL; expr_statement *es = new expr_statement; es->value = e->truevalue; @@ -2770,6 +2641,8 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2778,15 +2651,11 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) // When the result of a binary operation isn't needed, it's just as good to // evaluate the operands as sequential statements in a block. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Eliding unused binary " << *e->tok << endl; block *b = new block; - b->tok = current_expr->tok; - *current_stmt = b; - current_expr = NULL; + b->tok = e->tok; expr_statement *es = new expr_statement; es->value = e->left; @@ -2800,6 +2669,8 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2808,16 +2679,11 @@ void_statement_reducer::visit_unary_expression (unary_expression* e) // When the result of a unary operation isn't needed, it's just as good to // evaluate the operand directly - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Eliding unused unary " << *e->tok << endl; - current_expr->value = e->operand; - current_expr->tok = current_expr->value->tok; - current_expr->value->visit(this); - relaxed_p = false; + e->operand->visit(this); } void @@ -2839,24 +2705,26 @@ void_statement_reducer::visit_functioncall (functioncall* e) // and just evaluate the arguments in sequence if (!e->args.size()) - return; + { + provide (e); + return; + } varuse_collecting_visitor vut; vut.traversed.insert (e->referent); vut.current_function = e->referent; e->referent->body->visit (& vut); if (!vut.side_effect_free_wrt (focal_vars)) - return; - - assert(current_expr && current_expr->value == e); + { + provide (e); + return; + } if (session.verbose>2) clog << "Eliding side-effect-free function call " << *e->tok << endl; block *b = new block; b->tok = e->tok; - *current_stmt = b; - current_expr = NULL; for (unsigned i=0; i<e->args.size(); i++ ) { @@ -2868,6 +2736,8 @@ void_statement_reducer::visit_functioncall (functioncall* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2877,17 +2747,16 @@ void_statement_reducer::visit_print_format (print_format* e) // arguments in sequence if (e->print_to_stream || !e->args.size()) - return; - - assert(current_expr && current_expr->value == e); + { + provide (e); + return; + } if (session.verbose>2) clog << "Eliding unused print " << *e->tok << endl; block *b = new block; b->tok = e->tok; - *current_stmt = b; - current_expr = NULL; for (unsigned i=0; i<e->args.size(); i++ ) { @@ -2899,6 +2768,8 @@ void_statement_reducer::visit_print_format (print_format* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } @@ -2912,17 +2783,10 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) vuv.focal_vars.insert (s.globals.begin(), s.globals.end()); for (unsigned i=0; i<s.probes.size(); i++) - { - derived_probe* p = s.probes[i]; - vuv.current_stmt = & p->body; - p->body->visit (& vuv); - } - for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) - { - functiondecl* fn = it->second; - vuv.current_stmt = & fn->body; - fn->body->visit (& vuv); - } + s.probes[i]->body = vuv.require (s.probes[i]->body); + for (map<string,functiondecl*>::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + it->second->body = vuv.require (it->second->body); } diff --git a/staptree.cxx b/staptree.cxx index cc618111..9ffbaf09 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -2098,414 +2098,465 @@ throwing_visitor::visit_hist_op (hist_op* e) void -deep_copy_visitor::visit_block (block* s) +update_visitor::visit_block (block* s) { - block* n = new block; - n->tok = s->tok; for (unsigned i = 0; i < s->statements.size(); ++i) + s->statements[i] = require (s->statements[i]); + provide (s); +} + +void +update_visitor::visit_embeddedcode (embeddedcode* s) +{ + provide (s); +} + +void +update_visitor::visit_null_statement (null_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_expr_statement (expr_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_if_statement (if_statement* s) +{ + s->condition = require (s->condition); + s->thenblock = require (s->thenblock); + s->elseblock = require (s->elseblock); + provide (s); +} + +void +update_visitor::visit_for_loop (for_loop* s) +{ + s->init = require (s->init); + s->cond = require (s->cond); + s->incr = require (s->incr); + s->block = require (s->block); + provide (s); +} + +void +update_visitor::visit_foreach_loop (foreach_loop* s) +{ + for (unsigned i = 0; i < s->indexes.size(); ++i) + s->indexes[i] = require (s->indexes[i]); + s->base = require (s->base); + s->limit = require (s->limit); + s->block = require (s->block); + provide (s); +} + +void +update_visitor::visit_return_statement (return_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_delete_statement (delete_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_next_statement (next_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_break_statement (break_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_continue_statement (continue_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_literal_string (literal_string* e) +{ + provide (e); +} + +void +update_visitor::visit_literal_number (literal_number* e) +{ + provide (e); +} + +void +update_visitor::visit_binary_expression (binary_expression* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_unary_expression (unary_expression* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_pre_crement (pre_crement* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_post_crement (post_crement* e) +{ + e->operand = require (e->operand); + provide (e); +} + + +void +update_visitor::visit_logical_or_expr (logical_or_expr* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_logical_and_expr (logical_and_expr* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_array_in (array_in* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_comparison (comparison* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_concatenation (concatenation* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_ternary_expression (ternary_expression* e) +{ + e->cond = require (e->cond); + e->truevalue = require (e->truevalue); + e->falsevalue = require (e->falsevalue); + provide (e); +} + +void +update_visitor::visit_assignment (assignment* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_symbol (symbol* e) +{ + provide (e); +} + +void +update_visitor::visit_target_symbol (target_symbol* e) +{ + provide (e); +} + +void +update_visitor::visit_arrayindex (arrayindex* e) +{ + e->base = require (e->base); + for (unsigned i = 0; i < e->indexes.size(); ++i) + e->indexes[i] = require (e->indexes[i]); + provide (e); +} + +void +update_visitor::visit_functioncall (functioncall* e) +{ + for (unsigned i = 0; i < e->args.size(); ++i) + e->args[i] = require (e->args[i]); + provide (e); +} + +void +update_visitor::visit_print_format (print_format* e) +{ + for (unsigned i = 0; i < e->args.size(); ++i) + e->args[i] = require (e->args[i]); + e->hist = require (e->hist); + provide (e); +} + +void +update_visitor::visit_stat_op (stat_op* e) +{ + e->stat = require (e->stat); + provide (e); +} + +void +update_visitor::visit_hist_op (hist_op* e) +{ + e->stat = require (e->stat); + provide (e); +} + +template <> indexable* +update_visitor::require <indexable*> (indexable* src, bool clearok) +{ + indexable *dst = NULL; + if (src != NULL) { - statement* ns; - require <statement*> (this, &ns, s->statements[i]); - n->statements.push_back(ns); + symbol *array_src=NULL; + hist_op *hist_src=NULL; + + classify_indexable(src, array_src, hist_src); + + if (array_src) + dst = require (array_src); + else + dst = require (hist_src); + assert(clearok || dst); } - provide <block*> (this, n); + return dst; +} + + +// ------------------------------------------------------------------------ + + +void +deep_copy_visitor::visit_block (block* s) +{ + update_visitor::visit_block(new block(*s)); } void deep_copy_visitor::visit_embeddedcode (embeddedcode* s) { - embeddedcode* n = new embeddedcode; - n->tok = s->tok; - n->code = s->code; - provide <embeddedcode*> (this, n); + update_visitor::visit_embeddedcode(new embeddedcode(*s)); } void deep_copy_visitor::visit_null_statement (null_statement* s) { - null_statement* n = new null_statement; - n->tok = s->tok; - provide <null_statement*> (this, n); + update_visitor::visit_null_statement(new null_statement(*s)); } void deep_copy_visitor::visit_expr_statement (expr_statement* s) { - expr_statement* n = new expr_statement; - n->tok = s->tok; - require <expression*> (this, &(n->value), s->value); - provide <expr_statement*> (this, n); + update_visitor::visit_expr_statement(new expr_statement(*s)); } void deep_copy_visitor::visit_if_statement (if_statement* s) { - if_statement* n = new if_statement; - n->tok = s->tok; - require <expression*> (this, &(n->condition), s->condition); - require <statement*> (this, &(n->thenblock), s->thenblock); - require <statement*> (this, &(n->elseblock), s->elseblock); - provide <if_statement*> (this, n); + update_visitor::visit_if_statement(new if_statement(*s)); } void deep_copy_visitor::visit_for_loop (for_loop* s) { - for_loop* n = new for_loop; - n->tok = s->tok; - require <expr_statement*> (this, &(n->init), s->init); - require <expression*> (this, &(n->cond), s->cond); - require <expr_statement*> (this, &(n->incr), s->incr); - require <statement*> (this, &(n->block), s->block); - provide <for_loop*> (this, n); + update_visitor::visit_for_loop(new for_loop(*s)); } void deep_copy_visitor::visit_foreach_loop (foreach_loop* s) { - foreach_loop* n = new foreach_loop; - n->tok = s->tok; - for (unsigned i = 0; i < s->indexes.size(); ++i) - { - symbol* sym; - require <symbol*> (this, &sym, s->indexes[i]); - n->indexes.push_back(sym); - } - - require <indexable*> (this, &(n->base), s->base); - - n->sort_direction = s->sort_direction; - n->sort_column = s->sort_column; - require <expression*> (this, &(n->limit), s->limit); - - require <statement*> (this, &(n->block), s->block); - provide <foreach_loop*> (this, n); + update_visitor::visit_foreach_loop(new foreach_loop(*s)); } void deep_copy_visitor::visit_return_statement (return_statement* s) { - return_statement* n = new return_statement; - n->tok = s->tok; - require <expression*> (this, &(n->value), s->value); - provide <return_statement*> (this, n); + update_visitor::visit_return_statement(new return_statement(*s)); } void deep_copy_visitor::visit_delete_statement (delete_statement* s) { - delete_statement* n = new delete_statement; - n->tok = s->tok; - require <expression*> (this, &(n->value), s->value); - provide <delete_statement*> (this, n); + update_visitor::visit_delete_statement(new delete_statement(*s)); } void deep_copy_visitor::visit_next_statement (next_statement* s) { - next_statement* n = new next_statement; - n->tok = s->tok; - provide <next_statement*> (this, n); + update_visitor::visit_next_statement(new next_statement(*s)); } void deep_copy_visitor::visit_break_statement (break_statement* s) { - break_statement* n = new break_statement; - n->tok = s->tok; - provide <break_statement*> (this, n); + update_visitor::visit_break_statement(new break_statement(*s)); } void deep_copy_visitor::visit_continue_statement (continue_statement* s) { - continue_statement* n = new continue_statement; - n->tok = s->tok; - provide <continue_statement*> (this, n); + update_visitor::visit_continue_statement(new continue_statement(*s)); } void deep_copy_visitor::visit_literal_string (literal_string* e) { - literal_string* n = new literal_string(e->value); - n->tok = e->tok; - provide <literal_string*> (this, n); + update_visitor::visit_literal_string(new literal_string(*e)); } void deep_copy_visitor::visit_literal_number (literal_number* e) { - literal_number* n = new literal_number(e->value); - n->tok = e->tok; - provide <literal_number*> (this, n); + update_visitor::visit_literal_number(new literal_number(*e)); } void deep_copy_visitor::visit_binary_expression (binary_expression* e) { - binary_expression* n = new binary_expression; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <binary_expression*> (this, n); + update_visitor::visit_binary_expression(new binary_expression(*e)); } void deep_copy_visitor::visit_unary_expression (unary_expression* e) { - unary_expression* n = new unary_expression; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->operand), e->operand); - provide <unary_expression*> (this, n); + update_visitor::visit_unary_expression(new unary_expression(*e)); } void deep_copy_visitor::visit_pre_crement (pre_crement* e) { - pre_crement* n = new pre_crement; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->operand), e->operand); - provide <pre_crement*> (this, n); + update_visitor::visit_pre_crement(new pre_crement(*e)); } void deep_copy_visitor::visit_post_crement (post_crement* e) { - post_crement* n = new post_crement; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->operand), e->operand); - provide <post_crement*> (this, n); + update_visitor::visit_post_crement(new post_crement(*e)); } void deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) { - logical_or_expr* n = new logical_or_expr; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <logical_or_expr*> (this, n); + update_visitor::visit_logical_or_expr(new logical_or_expr(*e)); } void deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) { - logical_and_expr* n = new logical_and_expr; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <logical_and_expr*> (this, n); + update_visitor::visit_logical_and_expr(new logical_and_expr(*e)); } void deep_copy_visitor::visit_array_in (array_in* e) { - array_in* n = new array_in; - n->tok = e->tok; - require <arrayindex*> (this, &(n->operand), e->operand); - provide <array_in*> (this, n); + update_visitor::visit_array_in(new array_in(*e)); } void deep_copy_visitor::visit_comparison (comparison* e) { - comparison* n = new comparison; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <comparison*> (this, n); + update_visitor::visit_comparison(new comparison(*e)); } void deep_copy_visitor::visit_concatenation (concatenation* e) { - concatenation* n = new concatenation; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <concatenation*> (this, n); + update_visitor::visit_concatenation(new concatenation(*e)); } void deep_copy_visitor::visit_ternary_expression (ternary_expression* e) { - ternary_expression* n = new ternary_expression; - n->tok = e->tok; - require <expression*> (this, &(n->cond), e->cond); - require <expression*> (this, &(n->truevalue), e->truevalue); - require <expression*> (this, &(n->falsevalue), e->falsevalue); - provide <ternary_expression*> (this, n); + update_visitor::visit_ternary_expression(new ternary_expression(*e)); } void deep_copy_visitor::visit_assignment (assignment* e) { - assignment* n = new assignment; - n->op = e->op; - n->tok = e->tok; - require <expression*> (this, &(n->left), e->left); - require <expression*> (this, &(n->right), e->right); - provide <assignment*> (this, n); + update_visitor::visit_assignment(new assignment(*e)); } void deep_copy_visitor::visit_symbol (symbol* e) { - symbol* n = new symbol; - n->tok = e->tok; - n->name = e->name; - n->referent = NULL; - provide <symbol*> (this, n); + symbol* n = new symbol(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_symbol(n); } void deep_copy_visitor::visit_target_symbol (target_symbol* e) { - target_symbol* n = new target_symbol; - n->tok = e->tok; - n->base_name = e->base_name; - n->components = e->components; - provide <target_symbol*> (this, n); + target_symbol* n = new target_symbol(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_target_symbol(n); } void deep_copy_visitor::visit_arrayindex (arrayindex* e) { - arrayindex* n = new arrayindex; - n->tok = e->tok; - - require <indexable*> (this, &(n->base), e->base); - - for (unsigned i = 0; i < e->indexes.size(); ++i) - { - expression* ne; - require <expression*> (this, &ne, e->indexes[i]); - n->indexes.push_back(ne); - } - provide <arrayindex*> (this, n); + update_visitor::visit_arrayindex(new arrayindex(*e)); } void deep_copy_visitor::visit_functioncall (functioncall* e) { - functioncall* n = new functioncall; - n->tok = e->tok; - n->function = e->function; - n->referent = NULL; - for (unsigned i = 0; i < e->args.size(); ++i) - { - expression* na; - require <expression*> (this, &na, e->args[i]); - n->args.push_back(na); - } - provide <functioncall*> (this, n); + functioncall* n = new functioncall(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_functioncall(n); } void deep_copy_visitor::visit_print_format (print_format* e) { - print_format* n = new print_format; - n->tok = e->tok; - n->print_to_stream = e->print_to_stream; - n->print_with_format = e->print_with_format; - n->print_with_delim = e->print_with_delim; - n->print_with_newline = e->print_with_newline; - n->print_char = e->print_char; - n->raw_components = e->raw_components; - n->components = e->components; - n->delimiter = e->delimiter; - for (unsigned i = 0; i < e->args.size(); ++i) - { - expression* na; - require <expression*> (this, &na, e->args[i]); - n->args.push_back(na); - } - if (e->hist) - require <hist_op*> (this, &n->hist, e->hist); - provide <print_format*> (this, n); + update_visitor::visit_print_format(new print_format(*e)); } void deep_copy_visitor::visit_stat_op (stat_op* e) { - stat_op* n = new stat_op; - n->tok = e->tok; - n->ctype = e->ctype; - require <expression*> (this, &(n->stat), e->stat); - provide <stat_op*> (this, n); + update_visitor::visit_stat_op(new stat_op(*e)); } void deep_copy_visitor::visit_hist_op (hist_op* e) { - hist_op* n = new hist_op; - n->tok = e->tok; - n->htype = e->htype; - n->params = e->params; - require <expression*> (this, &(n->stat), e->stat); - provide <hist_op*> (this, n); -} - -block* -deep_copy_visitor::deep_copy (block* b) -{ - block* n; - deep_copy_visitor v; - require <block*> (&v, &n, b); - return n; -} - -statement* -deep_copy_visitor::deep_copy (statement* s) -{ - statement* n; - deep_copy_visitor v; - require <statement*> (&v, &n, s); - return n; -} - -expression* -deep_copy_visitor::deep_copy (expression* s) -{ - expression* n; - deep_copy_visitor v; - require <expression*> (&v, &n, s); - return n; -} - -template <> void -require <indexable *> (deep_copy_visitor* v, indexable** dst, indexable* src) -{ - if (src != NULL) - { - symbol *array_src=NULL, *array_dst=NULL; - hist_op *hist_src=NULL, *hist_dst=NULL; - - classify_indexable(src, array_src, hist_src); - - *dst = NULL; - - if (array_src) - { - require <symbol*> (v, &array_dst, array_src); - *dst = array_dst; - } - else - { - require <hist_op*> (v, &hist_dst, hist_src); - *dst = hist_dst; - } - assert (*dst); - } + update_visitor::visit_hist_op(new hist_op(*e)); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ @@ -810,19 +810,31 @@ struct throwing_visitor: public visitor void visit_hist_op (hist_op* e); }; -// A visitor which performs a deep copy of the root node it's applied -// to. NB: It does not copy any of the variable or function -// declarations; those fields are set to NULL, assuming you want to -// re-infer the declarations in a new context (the one you're copying -// to). +// A visitor similar to a traversing_visitor, but with the ability to rewrite +// parts of the tree through require/provide. -struct deep_copy_visitor: public visitor +struct update_visitor: public visitor { - std::stack<void *> targets; + template <typename T> T require (T src, bool clearok=false) + { + T dst = NULL; + if (src != NULL) + { + src->visit(this); + assert(!targets.empty()); + dst = static_cast<T>(targets.top()); + targets.pop(); + assert(clearok || dst); + } + return dst; + } + + template <typename T> void provide (T src) + { + targets.push(static_cast<void*>(src)); + } - static expression *deep_copy (expression *s); - static statement *deep_copy (statement *s); - static block *deep_copy (block *s); + virtual ~update_visitor() { assert(targets.empty()); } virtual void visit_block (block *s); virtual void visit_embeddedcode (embeddedcode *s); @@ -856,30 +868,61 @@ struct deep_copy_visitor: public visitor virtual void visit_print_format (print_format* e); virtual void visit_stat_op (stat_op* e); virtual void visit_hist_op (hist_op* e); + +private: + std::stack<void *> targets; }; -template <typename T> void -require (deep_copy_visitor* v, T* dst, T src) -{ - *dst = NULL; - if (src != NULL) - { - v->targets.push(static_cast<void* >(dst)); - src->visit(v); - v->targets.pop(); - assert(*dst); - } -} +template <> indexable* +update_visitor::require <indexable*> (indexable* src, bool clearok); -template <> void -require <indexable *> (deep_copy_visitor* v, indexable** dst, indexable* src); +// A visitor which performs a deep copy of the root node it's applied +// to. NB: It does not copy any of the variable or function +// declarations; those fields are set to NULL, assuming you want to +// re-infer the declarations in a new context (the one you're copying +// to). -template <typename T> void -provide (deep_copy_visitor* v, T src) +struct deep_copy_visitor: public update_visitor { - assert(!v->targets.empty()); - *(static_cast<T*>(v->targets.top())) = src; -} + template <typename T> static T deep_copy (T e) + { + deep_copy_visitor v; + return v.require (e); + } + + virtual void visit_block (block *s); + virtual void visit_embeddedcode (embeddedcode *s); + virtual void visit_null_statement (null_statement *s); + virtual void visit_expr_statement (expr_statement *s); + virtual void visit_if_statement (if_statement* s); + virtual void visit_for_loop (for_loop* s); + virtual void visit_foreach_loop (foreach_loop* s); + virtual void visit_return_statement (return_statement* s); + virtual void visit_delete_statement (delete_statement* s); + virtual void visit_next_statement (next_statement* s); + virtual void visit_break_statement (break_statement* s); + virtual void visit_continue_statement (continue_statement* s); + virtual void visit_literal_string (literal_string* e); + virtual void visit_literal_number (literal_number* e); + virtual void visit_binary_expression (binary_expression* e); + virtual void visit_unary_expression (unary_expression* e); + virtual void visit_pre_crement (pre_crement* e); + virtual void visit_post_crement (post_crement* e); + virtual void visit_logical_or_expr (logical_or_expr* e); + virtual void visit_logical_and_expr (logical_and_expr* e); + virtual void visit_array_in (array_in* e); + virtual void visit_comparison (comparison* e); + virtual void visit_concatenation (concatenation* e); + virtual void visit_ternary_expression (ternary_expression* e); + virtual void visit_assignment (assignment* e); + virtual void visit_symbol (symbol* e); + virtual void visit_target_symbol (target_symbol* e); + virtual void visit_arrayindex (arrayindex* e); + virtual void visit_functioncall (functioncall* e); + virtual void visit_print_format (print_format* e); + virtual void visit_stat_op (stat_op* e); + virtual void visit_hist_op (hist_op* e); +}; #endif // STAPTREE_H diff --git a/tapsets.cxx b/tapsets.cxx index 615ba07b..d479efda 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4205,17 +4205,17 @@ dwflpp::query_modules(dwarf_query *q) iterate_over_modules(&query_module, q); } -struct var_expanding_copy_visitor: public deep_copy_visitor +struct var_expanding_visitor: public update_visitor { static unsigned tick; stack<functioncall**> target_symbol_setter_functioncalls; - var_expanding_copy_visitor() {} + var_expanding_visitor() {} void visit_assignment (assignment* e); }; -struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct dwarf_var_expanding_visitor: public var_expanding_visitor { dwarf_query & q; Dwarf_Die *scope_die; @@ -4225,17 +4225,17 @@ struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor std::map<std::string, symbol *> return_ts_map; bool visited; - dwarf_var_expanding_copy_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): + dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {} void visit_target_symbol (target_symbol* e); }; -unsigned var_expanding_copy_visitor::tick = 0; +unsigned var_expanding_visitor::tick = 0; void -var_expanding_copy_visitor::visit_assignment (assignment* e) +var_expanding_visitor::visit_assignment (assignment* e) { // Our job would normally be to require() the left and right sides // into a new assignment. What we're doing is slightly trickier: @@ -4253,9 +4253,9 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) expression *new_left, *new_right; target_symbol_setter_functioncalls.push (&fcall); - require<expression*> (this, &new_left, e->left); + new_left = require (e->left); target_symbol_setter_functioncalls.pop (); - require<expression*> (this, &new_right, e->right); + new_right = require (e->right); if (fcall != NULL) { @@ -4263,7 +4263,7 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) // and it has been replaced with a set_target_foo() function // call; we are going to provide that function call -- with the // right child spliced in as sole argument -- in place of - // ourselves, in the deep copy we're in the middle of making. + // ourselves, in the var expansion we're in the middle of making. // FIXME: for the time being, we only support plan $foo = bar, // not += or any other op= variant. This is fixable, but a bit @@ -4274,22 +4274,19 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) assert (new_left == fcall); fcall->args.push_back (new_right); - provide <expression*> (this, fcall); + provide (fcall); } else { - assignment* n = new assignment; - n->op = e->op; - n->tok = e->tok; - n->left = new_left; - n->right = new_right; - provide <assignment*> (this, n); + e->left = new_left; + e->right = new_right; + provide (e); } } void -dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); visited = true; @@ -4318,7 +4315,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) map<string, symbol *>::iterator i = return_ts_map.find(ts_name); if (i != return_ts_map.end()) { - provide <symbol*> (this, i->second); + provide (i->second); return; } @@ -4576,7 +4573,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target // symbol. - provide <symbol*> (this, tmpsym); + provide (tmpsym); // (5) Remember this replacement since we might be able to reuse // it later if the same return probe references this target @@ -4622,7 +4619,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { @@ -4631,7 +4629,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += "return"; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } else @@ -4665,7 +4663,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (q.sess.verbose>2) @@ -4684,14 +4683,14 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += diename; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } while (dwarf_siblingof (&result, &result) == 0); } pf->components = print_format::string_to_components(pf->raw_components); - provide <print_format*> (this, pf); + provide (pf); return; } @@ -4735,7 +4734,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // target_symbol to the next pass. We hope that this value ends // up not being referenced after all, so it can be optimized out // quietly. - provide <target_symbol*> (this, e); + provide (e); semantic_error* saveme = new semantic_error (er); // copy it saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines // NB: we can have multiple errors, since a $target variable @@ -4783,7 +4782,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) *(target_symbol_setter_functioncalls.top()) = n; } - provide <functioncall*> (this, n); + provide (n); } @@ -4852,11 +4851,11 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, + lex_cast<string>(USHRT_MAX) + "]", q.base_loc->tok); - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); - require <statement*> (&v, &(this->body), this->body); + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); + this->body = v.require (this->body); this->access_vars = v.visited; // If during target-variable-expanding the probe, we added a new block @@ -6240,10 +6239,10 @@ public: }; -struct utrace_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct utrace_var_expanding_visitor: public var_expanding_visitor { - utrace_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - enum utrace_derived_probe_flags f): + utrace_var_expanding_visitor(systemtap_session& s, const string& pn, + enum utrace_derived_probe_flags f): sess (s), probe_name (pn), flags (f), target_symbol_seen (false) {} systemtap_session& sess; @@ -6266,9 +6265,9 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, has_path(hp), path(pn), pid(pd), flags(f), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - utrace_var_expanding_copy_visitor v (s, name, flags); - require <statement*> (&v, &(this->body), base->body); + // Expand local variables in the probe body + utrace_var_expanding_visitor v (s, name, flags); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; // Reset the sole element of the "locations" vector as a @@ -6330,7 +6329,7 @@ utrace_derived_probe::join_group (systemtap_session& s) void -utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = lex_cast<int>(argnum_s); @@ -6379,11 +6378,11 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) num->tok = e->tok; n->args.push_back(num); - provide <functioncall*> (this, n); + provide (n); } void -utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -6430,11 +6429,11 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -utrace_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -6994,11 +6993,11 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, this->tok = q.base_probe->tok; - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! - require <statement*> (&v, &(this->body), this->body); + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! + this->body = v.require (this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. @@ -7779,10 +7778,10 @@ public: }; -struct procfs_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct procfs_var_expanding_visitor: public var_expanding_visitor { - procfs_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - string path, bool write_probe): + procfs_var_expanding_visitor(systemtap_session& s, const string& pn, + string path, bool write_probe): sess (s), probe_name (pn), path (path), write_probe (write_probe), target_symbol_seen (false) {} @@ -7800,9 +7799,9 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, probe_point* l, string ps, bool w): derived_probe(p, l), path(ps), write(w), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - procfs_var_expanding_copy_visitor v (s, name, path, write); - require <statement*> (&v, &(this->body), base->body); + // Expand local variables in the probe body + procfs_var_expanding_visitor v (s, name, path, write); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; } @@ -8051,7 +8050,7 @@ procfs_derived_probe_group::emit_module_exit (systemtap_session& s) void -procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8136,7 +8135,7 @@ procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) *(target_symbol_setter_functioncalls.top()) = n; } - provide <functioncall*> (this, n); + provide (n); } @@ -8255,11 +8254,10 @@ public: }; -struct mark_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct mark_var_expanding_visitor: public var_expanding_visitor { - mark_var_expanding_copy_visitor(systemtap_session& s, - const string& pn, - vector <struct mark_arg *> &mark_args): + mark_var_expanding_visitor(systemtap_session& s, const string& pn, + vector <struct mark_arg *> &mark_args): sess (s), probe_name (pn), mark_args (mark_args), target_symbol_seen (false) {} systemtap_session& sess; @@ -8310,7 +8308,7 @@ hex_dump(unsigned char *data, size_t len) void -mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = atoi (argnum_s.c_str()); @@ -8371,12 +8369,12 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -8413,11 +8411,11 @@ mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -mark_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8450,9 +8448,9 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // expand the marker format parse_probe_format(); - // Now make a local-variable-expanded copy of the probe body - mark_var_expanding_copy_visitor v (sess, name, mark_args); - require <statement*> (&v, &(this->body), base->body); + // Now expand the local variables in the probe body + mark_var_expanding_visitor v (sess, name, mark_args); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) @@ -9220,18 +9218,18 @@ timer_builder::register_patterns(match_node *root) // -struct perfmon_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct perfmon_var_expanding_visitor: public var_expanding_visitor { systemtap_session & sess; unsigned counter_number; - perfmon_var_expanding_copy_visitor(systemtap_session & s, unsigned c): + perfmon_var_expanding_visitor(systemtap_session & s, unsigned c): sess(s), counter_number(c) {} void visit_target_symbol (target_symbol* e); }; void -perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -9285,7 +9283,7 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } @@ -9353,9 +9351,9 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, { ++probes_allocated; - // Now make a local-variable-expanded copy of the probe body - perfmon_var_expanding_copy_visitor v (sess, probes_allocated-1); - require <statement*> (&v, &(this->body), base->body); + // Now expand the local variables in the probe body + perfmon_var_expanding_visitor v (sess, probes_allocated-1); + this->body = v.require (this->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; |