summaryrefslogtreecommitdiffstats
path: root/staptree.cxx
diff options
context:
space:
mode:
authorfche <fche>2006-01-24 17:58:02 +0000
committerfche <fche>2006-01-24 17:58:02 +0000
commitcbfbbf6996cbe3b9fe57ac2014aa7262bb6890d6 (patch)
tree89b507411bd828b12142f0962be3eb4a33c3a45d /staptree.cxx
parent46746514a6943520ff73b6f77d35477e2abb30ba (diff)
downloadsystemtap-steved-cbfbbf6996cbe3b9fe57ac2014aa7262bb6890d6.tar.gz
systemtap-steved-cbfbbf6996cbe3b9fe57ac2014aa7262bb6890d6.tar.xz
systemtap-steved-cbfbbf6996cbe3b9fe57ac2014aa7262bb6890d6.zip
2006-01-24 Frank Ch. Eigler <fche@elastic.org>
PR 2060 etc. * tapsets.cxx (visit_target_symbol): Tolerate failed resolution by letting target_symbol instance pass through to optimizer and type checker. * elaborate.cxx (semantic_pass_optimize): New family of functions and associated visitor classes. (visit_for_loop): Tolerate absent init/incr clauses. (semantic_pass): Invoke unless unoptimized (-u) option given. * main.cxx, session.h: Add support for flag. * staptree.cxx (visit_for_loop): Tolerate absent init/incr clauses. (traversing_visitor::visit_arrayindex): Visit the index expressions. (functioncall_traversing_visitor): New class. (varuse_tracking_visitor): New class. * staptree.h: Corresponding changes. * parse.cxx (parse_for_loop): Represent absent init/incr expressions with null statement pointer instead of optimized-out dummy numbers. * stap.1.in: Document optimization. * testsuite/{semko,transko}/*.stp: Added "-u" or other code to many tests to check bad code without optimizer elision. * testsuite/semok/optimize.stp: New test. * elaborate.cxx (unresolved, invalid, mismatch): Standardize error message wording. * stapfuncs.5.in: Tweak print/printf docs. * tapset/logging.stp: Remove redundant "print" auxiliary function, since it's a translator built-in. * testsuite/transok/five.stp: Extend test. * translate.cxx (emit_symbol_data): Put symbol table into a separate temporary header file, to make "-p3" output easier on the eyes. * buildrun.cxx (compile_pass): Eliminate test-mode support throughout. * main.cxx, session.h, translate.cxx: Ditto. * main.cxx (main): For last-pass=2 runs, print post-optimization ASTs.
Diffstat (limited to 'staptree.cxx')
-rw-r--r--staptree.cxx149
1 files changed, 143 insertions, 6 deletions
diff --git a/staptree.cxx b/staptree.cxx
index 0eb898ac..97b4bcc1 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -691,11 +691,11 @@ void block::print (ostream& o) const
void for_loop::print (ostream& o) const
{
o << "for (";
- init->print (o);
+ if (init) init->print (o);
o << "; ";
cond->print (o);
o << "; ";
- incr->print (o);
+ if (incr) incr->print (o);
o << ") ";
block->print (o);
}
@@ -1262,9 +1262,9 @@ traversing_visitor::visit_if_statement (if_statement* s)
void
traversing_visitor::visit_for_loop (for_loop* s)
{
- s->init->visit (this);
+ if (s->init) s->init->visit (this);
s->cond->visit (this);
- s->incr->visit (this);
+ if (s->incr) s->incr->visit (this);
s->block->visit (this);
}
@@ -1409,6 +1409,9 @@ traversing_visitor::visit_target_symbol (target_symbol* e)
void
traversing_visitor::visit_arrayindex (arrayindex* e)
{
+ for (unsigned i=0; i<e->indexes.size(); i++)
+ e->indexes[i]->visit (this);
+
symbol *array = NULL;
hist_op *hist = NULL;
classify_indexable(e->base, array, hist);
@@ -1416,8 +1419,6 @@ traversing_visitor::visit_arrayindex (arrayindex* e)
return array->visit(this);
else
return hist->visit(this);
- for (unsigned i=0; i<e->indexes.size(); i++)
- e->indexes[i]->visit (this);
}
void
@@ -1449,6 +1450,142 @@ traversing_visitor::visit_hist_op (hist_op* e)
}
+void
+functioncall_traversing_visitor::visit_functioncall (functioncall* e)
+{
+ traversing_visitor::visit_functioncall (e);
+
+ // prevent infinite recursion
+ if (traversed.find (e->referent) == traversed.end ())
+ {
+ traversed.insert (e->referent);
+ // recurse
+ e->referent->body->visit (this);
+ }
+}
+
+
+void
+varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s)
+{
+ embedded_seen = true;
+}
+
+
+void
+varuse_collecting_visitor::visit_print_format (print_format* e)
+{
+ // NB: Instead of being top-level statements, "print" and "printf"
+ // are implemented as statement-expressions containing a
+ // print_format. They have side-effects, but not via the
+ // embedded-code detection method above.
+ embedded_seen = true;
+ functioncall_traversing_visitor::visit_print_format (e);
+}
+
+
+void
+varuse_collecting_visitor::visit_assignment (assignment *e)
+{
+ if (e->op == "=" || e->op == "<<<") // pure writes
+ {
+ expression* last_lvalue = current_lrvalue;
+ current_lvalue = e->left; // leave a mark for ::visit_symbol
+ functioncall_traversing_visitor::visit_assignment (e);
+ current_lvalue = last_lvalue;
+ }
+ else // read-modify-writes
+ {
+ expression* last_lrvalue = current_lrvalue;
+ current_lrvalue = e->left; // leave a mark for ::visit_symbol
+ functioncall_traversing_visitor::visit_assignment (e);
+ current_lrvalue = last_lrvalue;
+ }
+}
+
+void
+varuse_collecting_visitor::visit_symbol (symbol *e)
+{
+ if (e->referent == 0)
+ throw semantic_error ("symbol without referent", e->tok);
+
+ if (current_lvalue == e || current_lrvalue == e)
+ {
+ written.insert (e->referent);
+ // clog << "write ";
+ }
+ if (current_lvalue != e || current_lrvalue == e)
+ {
+ read.insert (e->referent);
+ // clog << "read ";
+ }
+ // clog << *e->tok << endl;
+}
+
+// NB: stat_op need not be overridden, since it will get to
+// visit_symbol and only as a possible rvalue.
+
+void
+varuse_collecting_visitor::visit_arrayindex (arrayindex *e)
+{
+ // Hooking this callback is necessary because of the hacky
+ // statistics representation. For the expression "i[4] = 5", the
+ // incoming lvalue will point to this arrayindex. However, the
+ // symbol corresponding to the "i[4]" is multiply inherited with
+ // arrayindex. If the symbol base part of this object is not at
+ // offset 0, then static_cast<symbol*>(e) may result in a different
+ // address, and not match lvalue by number when we recurse that way.
+ // So we explicitly override the incoming lvalue/lrvalue values to
+ // point at the embedded objects' actual base addresses.
+
+ expression* last_lrvalue = current_lrvalue;
+ expression* last_lvalue = current_lvalue;
+
+ symbol *array = NULL;
+ hist_op *hist = NULL;
+ classify_indexable(e->base, array, hist);
+
+ if (array)
+ {
+ if (current_lrvalue == e) current_lrvalue = array;
+ if (current_lvalue == e) current_lvalue = array;
+ functioncall_traversing_visitor::visit_arrayindex (e);
+ }
+ else // if (hist)
+ {
+ if (current_lrvalue == e) current_lrvalue = hist->stat;
+ if (current_lvalue == e) current_lvalue = hist->stat;
+ functioncall_traversing_visitor::visit_arrayindex (e);
+ }
+
+ current_lrvalue = last_lrvalue;
+ current_lvalue = last_lvalue;
+}
+
+
+void
+varuse_collecting_visitor::visit_pre_crement (pre_crement *e)
+{
+ expression* last_lrvalue = current_lrvalue;
+ current_lrvalue = e->operand; // leave a mark for ::visit_symbol
+ functioncall_traversing_visitor::visit_pre_crement (e);
+ current_lrvalue = last_lrvalue;
+}
+
+void
+varuse_collecting_visitor::visit_post_crement (post_crement *e)
+{
+ expression* last_lrvalue = current_lrvalue;
+ current_lrvalue = e->operand; // leave a mark for ::visit_symbol
+ functioncall_traversing_visitor::visit_post_crement (e);
+ current_lrvalue = last_lrvalue;
+}
+
+
+
+
+
+
// ------------------------------------------------------------------------