diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | elaborate.cxx | 23 | ||||
-rw-r--r-- | staptree.cxx | 293 | ||||
-rw-r--r-- | staptree.h | 43 | ||||
-rwxr-xr-x | testsuite/semok/fifteen.stp | 12 |
5 files changed, 369 insertions, 10 deletions
@@ -1,3 +1,11 @@ +2005-07-07 Graydon Hoare <graydon@redhat.com> + + * staptree.{h,cxx} (deep_copy_visitor): New visitor. + * elaborate.cxx + (derived_probe::derived_probe): + (alias_expansion_builder::build): Use it. + * testsuite/semok/fifteen.stp: New test which relies on deep copy. + 2005-07-07 Frank Ch. Eigler <fche@redhat.com> * Makefile.am (dist): Package up the source tree, including diff --git a/elaborate.cxx b/elaborate.cxx index 37d43ee1..e38cef51 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -37,8 +37,7 @@ derived_probe::derived_probe (probe *p): { this->locations = p->locations; this->tok = p->tok; - this->body = p->body; - this->locals = p->locals; + this->body = deep_copy_visitor::deep_copy(p->body); } @@ -47,8 +46,7 @@ derived_probe::derived_probe (probe *p, probe_point *l): { this->locations.push_back (l); this->tok = p->tok; - this->body = p->body; - this->locals = p->locals; + this->body = deep_copy_visitor::deep_copy(p->body); } // ------------------------------------------------------------------------ @@ -262,12 +260,17 @@ alias_expansion_builder // there's concatenated code here and we only want one vardecl per // resulting variable. - copy(alias->body->statements.begin(), - alias->body->statements.end(), - back_inserter(n->body->statements)); - copy(use->body->statements.begin(), - use->body->statements.end(), - back_inserter(n->body->statements)); + for (unsigned i = 0; i < alias->body->statements.size(); ++i) + { + statement *s = deep_copy_visitor::deep_copy(alias->body->statements[i]); + n->body->statements.push_back(s); + } + + for (unsigned i = 0; i < use->body->statements.size(); ++i) + { + statement *s = deep_copy_visitor::deep_copy(use->body->statements[i]); + n->body->statements.push_back(s); + } results_to_expand_further.push_back(n); } diff --git a/staptree.cxx b/staptree.cxx index e64c3710..94c04894 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -979,3 +979,296 @@ throwing_visitor::visit_functioncall (functioncall* e) { throwone (e->tok); } + + +// ------------------------------------------------------------------------ + +template <typename T> static void +require (deep_copy_visitor *v, T *dst, T src) +{ + *dst = NULL; + v->targets.push(static_cast<void *>(dst)); + src->visit(v); + v->targets.pop(); + assert(*dst); +} + +template <typename T> static void +provide (deep_copy_visitor *v, T src) +{ + assert(!v->targets.empty()); + *(static_cast<T*>(v->targets.top())) = src; +} + +void +deep_copy_visitor::visit_block (block *s) +{ + block *n = new block; + for (unsigned i = 0; i < s->statements.size(); ++i) + { + statement *ns; + require <statement*> (this, &ns, s->statements[i]); + n->statements.push_back(ns); + } + provide <block*> (this, n); +} + +void +deep_copy_visitor::visit_null_statement (null_statement *s) +{ + provide <null_statement*> (this, new null_statement); +} + +void +deep_copy_visitor::visit_expr_statement (expr_statement *s) +{ + expr_statement *n = new expr_statement; + require <expression*> (this, &(n->value), s->value); + provide <expr_statement*> (this, n); +} + +void +deep_copy_visitor::visit_if_statement (if_statement* s) +{ + if_statement *n = new if_statement; + 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); +} + +void +deep_copy_visitor::visit_for_loop (for_loop* s) +{ + for_loop *n = new for_loop; + 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); +} + +void +deep_copy_visitor::visit_foreach_loop (foreach_loop* s) +{ + foreach_loop *n = new foreach_loop; + for (unsigned i = 0; i < s->indexes.size(); ++i) + { + symbol *sym; + require <symbol*> (this, &sym, s->indexes[i]); + n->indexes.push_back(sym); + } + n->base = s->base; + n->base_referent = NULL; + require <statement*> (this, &(n->block), s->block); + provide <foreach_loop*> (this, n); +} + +void +deep_copy_visitor::visit_return_statement (return_statement* s) +{ + return_statement *n = new return_statement; + require <expression*> (this, &(n->value), s->value); + provide <return_statement*> (this, n); +} + +void +deep_copy_visitor::visit_delete_statement (delete_statement* s) +{ + delete_statement *n = new delete_statement; + require <expression*> (this, &(n->value), s->value); + provide <delete_statement*> (this, n); +} + +void +deep_copy_visitor::visit_next_statement (next_statement* s) +{ + provide <next_statement*> (this, new next_statement); +} + +void +deep_copy_visitor::visit_break_statement (break_statement* s) +{ + provide <break_statement*> (this, new break_statement); +} + +void +deep_copy_visitor::visit_continue_statement (continue_statement* s) +{ + provide <continue_statement*> (this, new continue_statement); +} + +void +deep_copy_visitor::visit_literal_string (literal_string* e) +{ + provide <literal_string*> (this, new literal_string(e->value)); +} + +void +deep_copy_visitor::visit_literal_number (literal_number* e) +{ + provide <literal_number*> (this, new literal_number(e->value)); +} + +void +deep_copy_visitor::visit_binary_expression (binary_expression* e) +{ + binary_expression *n = new binary_expression; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <binary_expression*> (this, n); +} + +void +deep_copy_visitor::visit_unary_expression (unary_expression* e) +{ + unary_expression *n = new unary_expression; + n->op = e->op; + require <expression*> (this, &(n->operand), e->operand); + provide <unary_expression*> (this, n); +} + +void +deep_copy_visitor::visit_pre_crement (pre_crement* e) +{ + pre_crement *n = new pre_crement; + n->op = e->op; + require <expression*> (this, &(n->operand), e->operand); + provide <pre_crement*> (this, n); +} + +void +deep_copy_visitor::visit_post_crement (post_crement* e) +{ + post_crement *n = new post_crement; + n->op = e->op; + require <expression*> (this, &(n->operand), e->operand); + provide <post_crement*> (this, n); +} + + +void +deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) +{ + logical_or_expr *n = new logical_or_expr; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <logical_or_expr*> (this, n); +} + +void +deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) +{ + logical_and_expr *n = new logical_and_expr; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <logical_and_expr*> (this, n); +} + +void +deep_copy_visitor::visit_array_in (array_in* e) +{ + array_in *n = new array_in; + require <arrayindex*> (this, &(n->operand), e->operand); + provide <array_in*> (this, n); +} + +void +deep_copy_visitor::visit_comparison (comparison* e) +{ + comparison *n = new comparison; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <comparison*> (this, n); +} + +void +deep_copy_visitor::visit_concatenation (concatenation* e) +{ + concatenation *n = new concatenation; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <concatenation*> (this, n); +} + +void +deep_copy_visitor::visit_ternary_expression (ternary_expression* e) +{ + ternary_expression *n = new ternary_expression; + 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); +} + +void +deep_copy_visitor::visit_assignment (assignment* e) +{ + assignment *n = new assignment; + n->op = e->op; + require <expression*> (this, &(n->left), e->left); + require <expression*> (this, &(n->right), e->right); + provide <assignment*> (this, n); +} + +void +deep_copy_visitor::visit_symbol (symbol* e) +{ + symbol *n = new symbol; + n->name = e->name; + n->referent = NULL; + provide <symbol*> (this, n); +} + +void +deep_copy_visitor::visit_arrayindex (arrayindex* e) +{ + arrayindex *n = new arrayindex; + n->base = e->base; + n->referent = NULL; + 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); +} + +void +deep_copy_visitor::visit_functioncall (functioncall* e) +{ + functioncall *n = new functioncall; + 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); +} + +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; +} @@ -9,6 +9,7 @@ #ifndef STAPTREE_H #define STAPTREE_H +#include <stack> #include <string> #include <vector> #include <iostream> @@ -515,6 +516,48 @@ struct throwing_visitor: public visitor void visit_functioncall (functioncall* 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). + +struct deep_copy_visitor: public visitor +{ + std::stack<void *> targets; + + static statement *deep_copy (statement *s); + static block *deep_copy (block *s); + + void visit_block (block *s); + void visit_null_statement (null_statement *s); + void visit_expr_statement (expr_statement *s); + void visit_if_statement (if_statement* s); + void visit_for_loop (for_loop* s); + void visit_foreach_loop (foreach_loop* s); + void visit_return_statement (return_statement* s); + void visit_delete_statement (delete_statement* s); + void visit_next_statement (next_statement* s); + void visit_break_statement (break_statement* s); + void visit_continue_statement (continue_statement* s); + void visit_literal_string (literal_string* e); + void visit_literal_number (literal_number* e); + void visit_binary_expression (binary_expression* e); + void visit_unary_expression (unary_expression* e); + void visit_pre_crement (pre_crement* e); + void visit_post_crement (post_crement* e); + void visit_logical_or_expr (logical_or_expr* e); + void visit_logical_and_expr (logical_and_expr* e); + void visit_array_in (array_in* e); + void visit_comparison (comparison* e); + void visit_concatenation (concatenation* e); + void visit_ternary_expression (ternary_expression* e); + void visit_assignment (assignment* e); + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); + void visit_functioncall (functioncall* e); +}; + #endif // STAPTREE_H diff --git a/testsuite/semok/fifteen.stp b/testsuite/semok/fifteen.stp new file mode 100755 index 00000000..c57d28eb --- /dev/null +++ b/testsuite/semok/fifteen.stp @@ -0,0 +1,12 @@ +#! stap -p2 + +function trace (n) { return 0 } + +# multiple independent derived probes using the "same" variable +# (this used to crash before we deep-copied the body) + +probe begin, begin, begin +{ + base_num = 10 + trace(base_num) +} |