From 73267b89ea6ede28b1a0a10667774bca6eb2b37e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 28 Jan 2009 17:01:20 -0800 Subject: Add Vim modelines for GNU style in stap --- elaborate.cxx | 1 + 1 file changed, 1 insertion(+) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index db1a4d78..3b4c944c 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -4105,3 +4105,4 @@ typeresolution_info::resolved (const token*, exp_type) num_newly_resolved ++; } +/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ -- cgit From a8cf6a4550d0e9197e668177ae09643c81b31791 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 3 Feb 2009 17:16:27 +0100 Subject: match_node::find_and_build disambiguate error messages. --- elaborate.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 3b4c944c..5678e8a7 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -395,7 +395,8 @@ match_node::find_and_build (systemtap_session& s, throw semantic_error(string("probe point mismatch at position ") + lex_cast (pos) + - " (alternatives:" + alternatives + ")", + " (alternatives:" + alternatives + ")" + + " didn't find any wildcard matches", loc->tok); } } -- cgit From 8bda649876b523f7733aa547ff86924a90f0e57b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 15:31:50 -0800 Subject: Simplify dead_assignment_remover By converting to an update_visitor, we now get full statement coverage in this optimizer for free. * elaborate.cxx (dead_assignment_remover): Convert into an update_visitor and remove its now-redundant traversal methods. --- elaborate.cxx | 124 ++++++++-------------------------------------------------- 1 file changed, 16 insertions(+), 108 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 5678e8a7..d4b07e8d 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2091,59 +2091,30 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati // ------------------------------------------------------------------------ -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 @@ -2163,9 +2134,9 @@ dead_assignment_remover::visit_assignment (assignment* e) 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. @@ -2178,77 +2149,13 @@ dead_assignment_remover::visit_assignment (assignment* e) 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; iargs.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 @@ -2268,9 +2175,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->visit (& dar); - for (map::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::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 -- cgit From 1cd151d5b9e1fd46590d5e4c3473a86ea9bbe043 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 18:29:55 -0800 Subject: Simplify dead_stmtexpr_remover * staptree.h (update_visitor::require): Add a clearok parameter for optimizing traversers to signal that they're ready for NULL back. * elaborate.cxx (dead_stmtexpr_remover): Convert to an update_visitor. --- elaborate.cxx | 91 ++++++++++++++++++++++++----------------------------------- 1 file changed, 37 insertions(+), 54 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index d4b07e8d..bc9c4e7d 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2187,15 +2187,14 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // ------------------------------------------------------------------------ -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 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); @@ -2214,7 +2213,8 @@ dead_stmtexpr_remover::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); } @@ -2224,13 +2224,11 @@ dead_stmtexpr_remover::visit_block (block *s) vector new_stmts; for (unsigned i=0; istatements.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(*current_stmt); + block *b = dynamic_cast(new_stmt); if (b) { if (session.verbose>2) @@ -2240,42 +2238,32 @@ dead_stmtexpr_remover::visit_block (block *s) 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) { @@ -2290,7 +2278,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) if (session.verbose>2) clog << "Eliding side-effect-free if statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby + s = 0; // yeah, baby } else { @@ -2301,7 +2289,8 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) expr_statement *es = new expr_statement; es->value = s->condition; es->tok = es->value->tok; - *current_stmt = es; + provide (es); + return; } } else @@ -2320,31 +2309,27 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) 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) { @@ -2358,14 +2343,16 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s) { 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); } @@ -2375,8 +2362,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *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 @@ -2389,8 +2375,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) 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. @@ -2405,10 +2390,10 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) // 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); } @@ -2433,8 +2418,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) 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) @@ -2459,8 +2443,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) 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) -- cgit From 9f9873dfc0978ef3ce7b7b5aa7ae1e2b5b4909b9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 19:51:12 -0800 Subject: Simplify void_statement_reducer * elaborate.cxx (void_statement_reducer): Convert to an update_visitor. --- elaborate.cxx | 161 ++++++++++++++++++++++++---------------------------------- 1 file changed, 67 insertions(+), 94 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index bc9c4e7d..ba50defb 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2468,21 +2468,27 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) // 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 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); @@ -2502,72 +2508,54 @@ struct void_statement_reducer: public traversing_visitor // 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; istatements.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 @@ -2576,8 +2564,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) // 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; @@ -2585,8 +2571,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) 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; @@ -2601,6 +2585,8 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2609,8 +2595,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) // 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; @@ -2619,8 +2603,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) 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; @@ -2629,6 +2611,8 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2637,8 +2621,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) // 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; @@ -2646,8 +2628,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) 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; @@ -2661,6 +2641,8 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2669,15 +2651,11 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) // 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; @@ -2691,6 +2669,8 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2699,16 +2679,11 @@ void_statement_reducer::visit_unary_expression (unary_expression* e) // 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 @@ -2730,24 +2705,26 @@ void_statement_reducer::visit_functioncall (functioncall* e) // 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; iargs.size(); i++ ) { @@ -2759,6 +2736,8 @@ void_statement_reducer::visit_functioncall (functioncall* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2768,17 +2747,16 @@ void_statement_reducer::visit_print_format (print_format* e) // 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; iargs.size(); i++ ) { @@ -2790,6 +2768,8 @@ void_statement_reducer::visit_print_format (print_format* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } @@ -2803,17 +2783,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; - p->body->visit (& vuv); - } - for (map::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::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + it->second->body = vuv.require (it->second->body); } -- cgit From 9b5af2958a35174a67076c0f27cff0ed5950736d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Feb 2009 14:34:32 -0800 Subject: Add high-level support for @cast()ing This handles all of the parsing, traversal, and optimization. It doesn't actually resolve the cast yet though. * staptree.h (struct cast_op, visitor::visit_cast_op): New. * staptree.cxx (cast_op::print/visit, various visitor::visit_cast_op's): Incorporate cast_op into the basic tree operations. * parse.cxx (parser::parse_symbol): Parse @cast operator with an expression operand, type string, and optional module string. * translate.cxx (c_unparser::visit_cast_op): Error out if a @cast survives to translation. * elaborate.cxx (typeresolution_info::visit_cast_op): Error out if a @cast survives to type resolution. (symbol_fetcher::visit_cast_op): treat @casts as a symbol target (void_statement_reducer::visit_cast_op): unused @casts can be discarded, but the operand should still be evaluated. --- elaborate.cxx | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index ba50defb..981fc7c7 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -701,6 +701,11 @@ struct symbol_fetcher e->base->visit_indexable (this); } + void visit_cast_op (cast_op* e) + { + sym = e; + } + void throwone (const token* t) { throw semantic_error ("Expecting symbol or array index expression", t); @@ -2505,6 +2510,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_cast_op (cast_op* e); // these are a bit hairy to grok due to the intricacies of indexables and // stats, so I'm chickening out and skipping them... @@ -2772,6 +2778,19 @@ void_statement_reducer::visit_print_format (print_format* e) 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 + + if (session.verbose>2) + clog << "Eliding unused typecast " << *e->tok << endl; + + relaxed_p = false; + e->operand->visit(this); +} + void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) { @@ -3398,6 +3417,18 @@ typeresolution_info::visit_target_symbol (target_symbol* e) } +void +typeresolution_info::visit_cast_op (cast_op* e) +{ + // Like target_symbol, a cast_op shouldn't survive this far + // unless it was not resolved and its value is really needed. + if (e->saved_conversion_error) + throw (* (e->saved_conversion_error)); + else + throw semantic_error("unresolved cast expression", e->tok); +} + + void typeresolution_info::visit_arrayindex (arrayindex* e) { -- cgit From f80d90043cf900dc6027329a61489444d7ab4ee3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Feb 2009 15:28:41 -0800 Subject: Enable session-wide code filtering This will be used to hook to dwarf_builder to all functions and probes so it can attempt @cast expansion. * session.h (systemtap_session): Add a vector of update_visitors that will act as filters for all probes and functions. * elaborate.cxx (semantic_pass_symbols): Run probes and functions through each registered code filter. --- elaborate.cxx | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 981fc7c7..9f8aa450 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1092,6 +1092,9 @@ semantic_pass_symbols (systemtap_session& s) try { + for (unsigned j=0; jbody = s.code_filters[j]->require (fd->body); + sym.current_function = fd; sym.current_probe = 0; fd->body->visit (& sym); @@ -1124,6 +1127,9 @@ semantic_pass_symbols (systemtap_session& s) try { + for (unsigned k=0; kbody = s.code_filters[k]->require (dp->body); + sym.current_function = 0; sym.current_probe = dp; dp->body->visit (& sym); -- cgit From 482fe2af17347b472232c5d7c4b26e53606e395e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 17 Feb 2009 19:19:48 -0800 Subject: Bump copyright years to 2009 --- elaborate.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 9f8aa450..02229fbe 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1,5 +1,5 @@ // elaboration functions -// Copyright (C) 2005-2008 Red Hat Inc. +// Copyright (C) 2005-2009 Red Hat Inc. // Copyright (C) 2008 Intel Corporation // // This file is part of systemtap, and is free software. You can -- cgit From d5f0c423890f54b7f12da85fbcfc61879efc368e Mon Sep 17 00:00:00 2001 From: Rajan Arora Date: Wed, 18 Feb 2009 20:16:03 -0500 Subject: BZ 9719: Improve type mismatch messages --- elaborate.cxx | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 6 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 02229fbe..25c52c33 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -3987,23 +3987,70 @@ typeresolution_info::invalid (const token* tok, exp_type pe) void typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2) { + bool tok_resolved; + size_t i; + semantic_error* err1 = 0; num_still_unresolved ++; + //BZ 9719: for improving type mismatch messages, a semantic error is + //generated with the token where type was first resolved. All such + //resolved tokens, stored in a vector, are matched against their + //content. If an error for the matching token hasn't been printed out + //already, it is and the token pushed in another printed_toks vector + if (assert_resolvability) { stringstream msg; - string nm = (current_function ? current_function->name : - current_probe ? current_probe->name : - "probe condition"); - msg << nm + " with type mismatch (" << t1 << " vs. " << t2 << ")"; - session.print_error (semantic_error (msg.str(), tok)); + for (i=0; icontent == tok->content) + { + tok_resolved = true; + break; + } + } + if (!tok_resolved) + { + string nm = (current_function ? current_function->name : + current_probe ? current_probe->name : + "probe condition"); + msg << nm + " with type mismatch (" << t1 << " vs. " << t2 << ")"; + } + else + { + bool tok_printed; + for (size_t j=0; jname : + current_probe ? current_probe->name : + "probe condition"); + msg << nm + " with type mismatch (" << t1 << " vs. " << t2 << ")"; + if (!tok_printed) + { + //error for possible mismatch in the earlier resolved token + printed_toks.push_back (resolved_toks[i]); + stringstream type_msg; + type_msg << nm + " type first inferred here (" << t2 << ")"; + err1 = new semantic_error (type_msg.str(), resolved_toks[i]); + } + } + semantic_error err (msg.str(), tok); + err.chain = err1; + session.print_error (err); } } void -typeresolution_info::resolved (const token*, exp_type) +typeresolution_info::resolved (const token* tok, exp_type) { + resolved_toks.push_back (tok); num_newly_resolved ++; } -- cgit From d784c94d2b2d4664dad6a1f881c85169ab457288 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 18 Feb 2009 23:08:52 -0500 Subject: PR9719: uninitialized variable fix --- elaborate.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'elaborate.cxx') diff --git a/elaborate.cxx b/elaborate.cxx index 25c52c33..0a00ebf2 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -3987,7 +3987,7 @@ typeresolution_info::invalid (const token* tok, exp_type pe) void typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2) { - bool tok_resolved; + bool tok_resolved = false; size_t i; semantic_error* err1 = 0; num_still_unresolved ++; @@ -4018,7 +4018,7 @@ typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2) } else { - bool tok_printed; + bool tok_printed = false; for (size_t j=0; j