+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
// ------------------------------------------------------------------------
-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
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.
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
// 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
// ------------------------------------------------------------------------
-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);
// easy!
if (session.verbose>2)
clog << "Eliding side-effect-free null statement " << *s->tok << endl;
- *current_stmt = 0;
+ s = 0;
+ provide (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)
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)
{
if (session.verbose>2)
clog << "Eliding side-effect-free if statement "
<< *s->tok << endl;
- *current_stmt = 0; // yeah, baby
+ s = 0; // yeah, baby
}
else
{
expr_statement *es = new expr_statement;
es->value = s->condition;
es->tok = es->value->tok;
- *current_stmt = es;
+ provide (es);
+ return;
}
}
else
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)
{
{
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);
}
{
// 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
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.
// 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);
}
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)
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)
// 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);
// 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
// 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;
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;
is->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
void
// 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;
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;
is->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
void
// 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;
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;
is->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
void
// 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;
b->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
void
// 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
// 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++ )
{
b->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
void
// 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++ )
{
b->visit(this);
relaxed_p = false;
+ e = 0;
+ provide (e);
}
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);
}
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 : */
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);
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
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;
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:
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)
{
// 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
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;
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;
}
// (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
// 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.
{
{
pf->raw_components += "return";
pf->raw_components += "=%#x ";
- pf->args.push_back(*(expression**)this->targets.top());
+ pf->args.push_back(texp);
}
}
else
// 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)
{
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;
}
// 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
*(target_symbol_setter_functioncalls.top()) = n;
}
- provide <functioncall*> (this, n);
+ provide (n);
}
+ 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
};
-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;
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
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);
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;
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] == '$');
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.
};
-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) {}
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;
}
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] == '$');
*(target_symbol_setter_functioncalls.top()) = n;
}
- provide <functioncall*> (this, n);
+ provide (n);
}
};
-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;
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());
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;
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] == '$');
// 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)
//
-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] == '$');
n->function = fname;
n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
- provide <functioncall*> (this, n);
+ provide (n);
}
{
++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;