summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--elaborate.cxx23
-rw-r--r--staptree.cxx293
-rw-r--r--staptree.h43
-rwxr-xr-xtestsuite/semok/fifteen.stp12
5 files changed, 369 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 79df0253..1d3002a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
+}
diff --git a/staptree.h b/staptree.h
index 858c93a0..b2cfc1ac 100644
--- a/staptree.h
+++ b/staptree.h
@@ -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)
+}