From 6fda2dff51c667a8c73545dd397b844108715310 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 14:45:21 -0700 Subject: PR2049: support arbitrary $target-array indexing Rather than just numeric literals, we can now support arbitrary expressions for the index value. Note that loc2c won't allow this for noncontiguous arrays, as the access methods need to be statically computed, but for contiguous arrays and pointers-as-arrays it works just fine. * staptree.h (target_symbol::component): Add expression_array_index. * staptree.cxx (target_symbol::visit_components): New helper. (target_symbol::assert_no_components): Recognize new array type. (target_symbol::component::print): Print subexpressions. (traversing_visitor::visit_target_symbol, visit_cast_op): Visit the indexing components too. (varuse_collecting_visitor::visit_target_symbol): Ditto. (update_visitor::visit_target_symbol, visit_cast_op): Ditto. * elaborate.cxx (void_statement_reducer::visit_target_symbol): New. (void_statement_reducer::visit_cast_op): Save indexes too. * parse.cxx (parser::parse_target_symbol_components): Parse expressions. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Pass expression-indexes as parameters (indexN) to the dwarf function. (dwarf_cast_expanding_visitor::visit_cast_op): Ditto. (tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto. (sdt_var_expanding_visitor::visit_target_symbol): Visit the new @cast. * dwflpp.cxx (dwflpp::translate_components): Use THIS->indexN. * translate.cxx (c_unparser::visit_target_symbol): Correct error msg. * testsuite/systemtap.base/pointer_array.stp: Use a simple index. --- elaborate.cxx | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index fafc5e63..d1ebe326 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2534,6 +2534,7 @@ struct void_statement_reducer: public update_visitor void visit_concatenation (concatenation* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); + void visit_target_symbol (target_symbol* e); void visit_cast_op (cast_op* e); // these are a bit hairy to grok due to the intricacies of indexables and @@ -2802,17 +2803,74 @@ void_statement_reducer::visit_print_format (print_format* e) provide (e); } +void +void_statement_reducer::visit_target_symbol (target_symbol* e) +{ + // When target_symbol isn't needed, it's just as good to + // evaluate any array indexes directly + + block *b = new block; + b->tok = e->tok; + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + expr_statement *es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } + + if (b->statements.empty()) + { + delete b; + provide (e); + return; + } + + if (session.verbose>2) + clog << "Eliding unused target symbol " << *e->tok << endl; + + b->visit(this); + relaxed_p = false; + e = 0; + provide (e); +} + void void_statement_reducer::visit_cast_op (cast_op* e) { // When the result of a cast operation isn't needed, it's just as good to - // evaluate the operand directly + // evaluate the operand and any array indexes directly + + block *b = new block; + b->tok = e->tok; + + expr_statement *es = new expr_statement; + es->value = e->operand; + es->tok = es->value->tok; + b->statements.push_back(es); + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } if (session.verbose>2) clog << "Eliding unused typecast " << *e->tok << endl; + b->visit(this); relaxed_p = false; - e->operand->visit(this); + e = 0; + provide (e); } -- cgit From 8b095b454b34e88c04592be6c651153f802eced6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 15:49:40 -0700 Subject: Add update_visitor::replace I noticed that most uses of update_visitor::require() were simply writing the value back to the same place, i.e. foo = require(foo). The new replace() method just encapsulates that paradigm, so we don't have the duplication between the LHS and RHS. * staptree.h (update_visitor::replace): New. * elaborate.cxx, staptree.cxx, tapset-mark.cxx, tapset-perfmon.cxx, tapset-procfs.cxx, tapset-utrace.cxx, tapsets.cxx: Update all require calls that are simply updating the value in-place. --- elaborate.cxx | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index d1ebe326..9271e847 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1108,7 +1108,7 @@ semantic_pass_symbols (systemtap_session& s) try { for (unsigned j=0; jbody = s.code_filters[j]->require (fd->body); + s.code_filters[j]->replace (fd->body); sym.current_function = fd; sym.current_probe = 0; @@ -1143,7 +1143,7 @@ semantic_pass_symbols (systemtap_session& s) try { for (unsigned k=0; kbody = s.code_filters[k]->require (dp->body); + s.code_filters[k]->replace (dp->body); sym.current_function = 0; sym.current_probe = dp; @@ -2136,8 +2136,8 @@ struct dead_assignment_remover: public update_visitor void dead_assignment_remover::visit_assignment (assignment* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); symbol* left = get_symbol_within_expression (e->left); vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target @@ -2203,10 +2203,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; ibody = dar.require (s.probes[i]->body); + dar.replace (s.probes[i]->body); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body = dar.require (it->second->body); + dar.replace (it->second->body); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here @@ -2290,8 +2290,8 @@ dead_stmtexpr_remover::visit_block (block *s) void dead_stmtexpr_remover::visit_if_statement (if_statement *s) { - s->thenblock = require (s->thenblock, true); - s->elseblock = require (s->elseblock, true); + replace (s->thenblock, true); + replace (s->elseblock, true); if (s->thenblock == 0) { @@ -2343,7 +2343,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) void dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) { - s->block = require(s->block, true); + replace (s->block, true); if (s->block == 0) { @@ -2357,7 +2357,7 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) void dead_stmtexpr_remover::visit_for_loop (for_loop *s) { - s->block = require(s->block, true); + replace (s->block, true); if (s->block == 0) { @@ -2446,7 +2446,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (p->locals.begin(), p->locals.end()); - p->body = duv.require(p->body, true); + duv.replace (p->body, true); if (p->body == 0) { if (! s.suppress_warnings @@ -2472,7 +2472,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - fn->body = duv.require(fn->body, true); + duv.replace (fn->body, true); if (fn->body == 0) { if (! s.suppress_warnings) @@ -2556,7 +2556,7 @@ struct void_statement_reducer: public update_visitor void void_statement_reducer::visit_expr_statement (expr_statement* s) { - s->value = require (s->value, true); + replace (s->value, true); // if the expression provides 0, that's our signal that a new // statement has been provided, so we shouldn't provide this one. @@ -2568,8 +2568,8 @@ void void_statement_reducer::visit_if_statement (if_statement* s) { // s->condition is never void - s->thenblock = require (s->thenblock); - s->elseblock = require (s->elseblock); + replace (s->thenblock); + replace (s->elseblock); provide (s); } @@ -2577,7 +2577,7 @@ void void_statement_reducer::visit_for_loop (for_loop* s) { // s->init/cond/incr are never void - s->block = require (s->block); + replace (s->block); provide (s); } @@ -2585,7 +2585,7 @@ void void_statement_reducer::visit_foreach_loop (foreach_loop* s) { // s->indexes/base/limit are never void - s->block = require (s->block); + replace (s->block); provide (s); } @@ -2884,10 +2884,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; ibody = vuv.require (s.probes[i]->body); + vuv.replace (s.probes[i]->body); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body = vuv.require (it->second->body); + vuv.replace (it->second->body); } -- cgit