diff options
author | Stan Cox <scox@redhat.com> | 2008-08-27 17:56:28 -0400 |
---|---|---|
committer | Stan Cox <scox@redhat.com> | 2008-08-27 17:56:28 -0400 |
commit | 0a102c820c4ee8da300b4a834ef0f15fa13016d3 (patch) | |
tree | 02d0b0a216d46ad37f712d063d05f47402283183 | |
parent | 695ae5272479f77d261eea37a9ee4bef55c4ab12 (diff) | |
download | systemtap-steved-0a102c820c4ee8da300b4a834ef0f15fa13016d3.tar.gz systemtap-steved-0a102c820c4ee8da300b4a834ef0f15fa13016d3.tar.xz systemtap-steved-0a102c820c4ee8da300b4a834ef0f15fa13016d3.zip |
Automatically print written but unread globals
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | elaborate.cxx | 202 | ||||
-rw-r--r-- | testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | testsuite/systemtap.base/bench.exp | 2 | ||||
-rw-r--r-- | testsuite/systemtap.base/global_end.exp | 23 | ||||
-rw-r--r-- | testsuite/systemtap.base/global_end.stp | 30 | ||||
-rw-r--r-- | testsuite/systemtap.base/optim_arridx.exp | 40 | ||||
-rw-r--r-- | testsuite/systemtap.base/optim_arridx.stp | 6 |
8 files changed, 298 insertions, 20 deletions
@@ -1,3 +1,10 @@ +2008-08-27 Stan Cox <scox@redhat.com> + + * elaborate.cxx (add_global_var_display): New. + (semantic_pass): Call it. + (dead_assignment_remover::visit_assignment): Don't remove written + but unread global variables. + 2008-08-26 David Smith <dsmith@redhat.com> * buildrun.cxx (compile_pass): Added autoconf-dpath-path.c. diff --git a/elaborate.cxx b/elaborate.cxx index 0950b086..4fe228ab 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1144,6 +1144,180 @@ semantic_pass_symbols (systemtap_session& s) } +// Keep unread global variables for probe end value display. +void add_global_var_display (systemtap_session& s) +{ + varuse_collecting_visitor vut; + for (unsigned i=0; i<s.probes.size(); i++) + { + s.probes[i]->body->visit (& vut); + + if (s.probes[i]->sole_location()->condition) + s.probes[i]->sole_location()->condition->visit (& vut); + } + + for (unsigned g=0; g < s.globals.size(); g++) + { + vardecl* l = s.globals[g]; + if (vut.read.find (l) != vut.read.end() + || vut.written.find (l) == vut.written.end() + || l->type == pe_stats) + continue; + + print_format* pf = new print_format; + probe* p = new probe; + probe_point* pl = new probe_point; + probe_point::component* c = new probe_point::component("end"); + token* print_tok = new token; + vector<derived_probe*> dps; + + pl->components.push_back (c); + token* p_tok = new token; + p_tok->type = tok_identifier; + p_tok->content = "probe"; + p->tok = p_tok; + p->locations.push_back (pl); + print_tok->type = tok_identifier; + print_tok->content = "printf"; + + // Create a symbol + symbol* g_sym = new symbol; + g_sym->name = l->name; + g_sym->tok = l->tok; + g_sym->type = l->type; + g_sym->referent = l; + + pf->print_to_stream = true; + pf->print_with_format = true; + pf->print_with_delim = false; + pf->print_with_newline = false; + pf->print_char = false; + pf->raw_components += l->name; + pf->tok = print_tok; + + if (l->index_types.size() == 0) // Scalar + { + if (l->type == pe_string) + pf->raw_components += "=\"%#s\"\\n"; + else + pf->raw_components += "=%#x\\n"; + pf->args.push_back(g_sym); + pf->components = print_format::string_to_components(pf->raw_components); + expr_statement* feb = new expr_statement; + feb->value = pf; + feb->tok = print_tok; + block *b = new block; + b->statements.push_back(feb); + p->body = b; + + derive_probes (s, p, dps); + + // Repopulate the type info. Should semantic_pass_types do this? + ((class symbol*) + ((class print_format*) + ((class expr_statement*) + ((class block*)dps[0]->body)->statements[0])->value)->args[0])->type = g_sym->type; + } + else // Array + { + int idx_count = l->index_types.size(); + token* idx_tok[idx_count]; + symbol* idx_sym[idx_count]; + vardecl* idx_v[idx_count]; + // Create a foreach loop + token* fe_tok = new token; + fe_tok->type = tok_identifier; + fe_tok->content = "foreach"; + foreach_loop* fe = new foreach_loop; + fe->sort_direction = 0; + fe->limit = NULL; + + // Create indices for the foreach loop + for (int i=0; i < idx_count; i++) + { + idx_tok[i] = new token; + idx_tok[i]->type = tok_identifier; + char *idx_name; + if (asprintf (&idx_name, "idx%d", i) < 0) + return; + idx_tok[i]->content = idx_name; + idx_sym[i] = new symbol; + idx_sym[i]->tok = idx_tok[i]; + idx_sym[i]->name = idx_name; + idx_v[i] = new vardecl; + idx_v[i]->name = idx_name; + idx_v[i]->tok = idx_tok[i]; + idx_v[i]->type = l->index_types[i]; + idx_sym[i]->referent = idx_v[i]; + fe->indexes.push_back (idx_sym[i]); + } + + // Create a printf for the foreach loop + for (int i=0; i < idx_count; i++) + if (l->index_types[i] == pe_string) + pf->raw_components += "[\"%#s\"]"; + else + pf->raw_components += "[%#d]"; + if (l->type == pe_string) + pf->raw_components += "=\"%#s\"\\n"; + else + pf->raw_components += "=%#x\\n"; + + // Create an index for the array + struct arrayindex* ai = new arrayindex; + ai->tok = l->tok; + ai->base = g_sym; + for (int i=0; i < idx_count; i++) + { + ai->indexes.push_back (idx_sym[i]); + pf->args.push_back(idx_sym[i]); + } + pf->args.push_back(ai); + + pf->components = print_format::string_to_components(pf->raw_components); + expr_statement* feb = new expr_statement; + feb->value = pf; + block *b = new block; + fe->base = g_sym; + fe->block = (statement*)feb; + b->statements.push_back(fe); + p->body = b; + + derive_probes (s, p, dps); + + // Repopulate the type info. Should semantic_pass_types do this? + print_format* dpf = ((print_format*) + ((expr_statement*) + ((foreach_loop*) + ((block*)dps[0]->body)->statements[0])->block)->value); + for (int i=0; i < idx_count; i++) + { + // printf argument types + dpf->args[i]->type = l->index_types[i]; + // arrayindex indices types + ((struct arrayindex*)dpf->args[idx_count])->indexes[i]->type = l->index_types[i]; + dps[0]->locals.push_back(idx_v[i]); + } + // arrayindex type + dpf->args[idx_count]->type = l->type; + } + + symresolution_info sym (s); + sym.current_function = 0; + sym.current_probe = dps[0]; + dps[0]->body->visit (& sym); + + // Add created probe + for (unsigned i = 0; i < dps.size(); i++) + { + derived_probe* dp = dps[i]; + s.probes.push_back (dp); + dp->join_group (s); + } + + vut.read.insert (l); + } +} int semantic_pass (systemtap_session& s) @@ -1159,6 +1333,7 @@ semantic_pass (systemtap_session& s) if (rc == 0) rc = semantic_pass_conditions (s); if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize1 (s); if (rc == 0) rc = semantic_pass_types (s); + if (rc == 0) add_global_var_display (s); if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize2 (s); if (rc == 0) rc = semantic_pass_vars (s); if (rc == 0) rc = semantic_pass_stats (s); @@ -1745,16 +1920,16 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati { if (l->tok->location.file == s.user_file->name && // !tapset ! s.suppress_warnings) - s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); + s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); else if (s.verbose>2) clog << "Eliding unused global variable " << l->name << endl; if (s.tapset_compile_coverage) { - s.unused_globals.push_back(s.globals[i]); + s.unused_globals.push_back(s.globals[i]); } - s.globals.erase(s.globals.begin() + i); - relaxed_p = false; - // don't increment i + s.globals.erase(s.globals.begin() + i); + relaxed_p = false; + // don't increment i } else { @@ -1831,6 +2006,7 @@ dead_assignment_remover::visit_assignment (assignment* e) 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 @@ -1838,10 +2014,21 @@ dead_assignment_remover::visit_assignment (assignment* e) // OK if we could replace the array assignment with a // statement-expression containing all the index expressions // and the rvalue... but we can't. + // Another possibility is that we have an unread global variable + // which are kept for probe end value display. + + bool is_global = false; + vector<vardecl*>::iterator it; + for (it = session.globals.begin(); it != session.globals.end(); it++) + if (leftvar->name == (*it)->name) + { + is_global = true; + break; + } varuse_collecting_visitor vut; e->left->visit (& vut); - if (vut.side_effect_free ()) // XXX: use _wrt() once we track focal_vars + if (vut.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. @@ -2156,7 +2343,8 @@ 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) && + + if (vut.side_effect_free_wrt (focal_vars) && *current_stmt == s) // we're not nested any deeper than expected { /* PR 1119: NB: this message is not a good idea here. It can diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index 597c2665..e6649a36 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2008-08-27 Stan Cox <scox@redhat.com> + + * systemtap.base/global_end.exp: New. + * systemtap.base/global_end.stp: New. + * systemtap.base/bench.exp: Bump up ok. + * systemtap.base/optim_arridx.exp: Consider unread globals. + * systemtap.base/optim_arridx.stp: Fix typos. + 2008-08-27 Wenji Huang <wenji.huang@oracle.com> * semok/nodwf02.stp: Make syscall.q* optional. diff --git a/testsuite/systemtap.base/bench.exp b/testsuite/systemtap.base/bench.exp index 4863a00c..72864292 100644 --- a/testsuite/systemtap.base/bench.exp +++ b/testsuite/systemtap.base/bench.exp @@ -11,4 +11,4 @@ expect { eof { } } wait -if {$ok == 15} { pass "$test ($ok)" } { fail "$test ($ok)" } +if {$ok == 18} { pass "$test ($ok)" } { fail "$test ($ok)" } diff --git a/testsuite/systemtap.base/global_end.exp b/testsuite/systemtap.base/global_end.exp new file mode 100644 index 00000000..b1931a90 --- /dev/null +++ b/testsuite/systemtap.base/global_end.exp @@ -0,0 +1,23 @@ +# test end probe creation and display of written and unread global variables + +set test "global_end" + +if {![installtest_p]} {untested $test; return} + +spawn stap $srcdir/$subdir/global_end.stp +set ok 0 +expect { + -timeout 180 + -re {one,0x1.*one,0x2.*two,0x1.*two,0x2} { incr ok; exp_continue } + -re {alpha."one"..1.=0x1} { incr ok; exp_continue } + -re {alpha."one"..2.=0x2} { incr ok; exp_continue } + -re {alpha."two"..1.=0x3} { incr ok; exp_continue } + -re {alpha."two"..2.=0x4} { incr ok; exp_continue } + -re {gamma="abcdefghijklmnopqrstuvwxyz"} { incr ok; exp_continue } + -re {iota."one".="eleven"} { incr ok; exp_continue } + -re {iota."two".="twelve"} { incr ok; exp_continue } + timeout { fail "$test (timeout)" } + eof { } +} +wait +if {$ok == 8} { pass "$test ($ok)" } { fail "$test ($ok)" } diff --git a/testsuite/systemtap.base/global_end.stp b/testsuite/systemtap.base/global_end.stp new file mode 100644 index 00000000..e9a1eb8f --- /dev/null +++ b/testsuite/systemtap.base/global_end.stp @@ -0,0 +1,30 @@ +global alpha, beta, gamma, iota + +probe begin { + gamma = "abcdefghijklmnopqrstuvwxyz" + + iota["one"] = "eleven" + iota["two"] = "twelve" + + alpha["one",1] = 1 + alpha["one",2] = 2 + alpha["two",1] = 3 + alpha["two",2] = 4 + + beta["one",1] = 1 + beta["one",2] = 2 + beta["two",1] = 3 + beta["two",2] = 4 +} + +probe timer.ms(2000) { + exit () +} + +probe end { +foreach ([i,j] in beta) + printf("[%#s,%#x]=%#x ", i, j, beta[i,j]) +print("\n") +exit() +} + diff --git a/testsuite/systemtap.base/optim_arridx.exp b/testsuite/systemtap.base/optim_arridx.exp index f4308db5..89282d1b 100644 --- a/testsuite/systemtap.base/optim_arridx.exp +++ b/testsuite/systemtap.base/optim_arridx.exp @@ -5,11 +5,14 @@ set ::result_string {# globals arr1:long [long, long] arr2:long [long] arr3:long [long] +elide_idx1:long +elide_global_a:long +elide_global_b:long # functions fna:long (a:long) return a fnb:long (a:long, b:long) -return ((a) + (b)) + (printf("")) +return (a) + (b) exit:unknown () %{ atomic_set (&session_state, STAP_SESSION_STOPPING); @@ -23,33 +26,52 @@ begin /* <- begin */ k:long b:long m:long - arr1:long [long] - arr2:long [long, long] aa:long bb:long cc:long dd:long ee:long { +(arr2[(elide_idx1) = (1)]) = (10) (arr2[(idx2) = (2)]) = (20) +(arr2[3]) = (30) (arr2[(j) = (4)]) = (40) (arr1[fna((k) = (0)), k]) = (1) (arr1[(b) = (1), b]) = (2) -fnb((arr3[0]) = (4), arr3[0]) +(arr1[2, 2]) = (3) +(arr3[0]) = (4) (m) = (1) -for (2; (m) <= (10); (m)++) ; -printf("%d %d %d %d\\n", arr1[0], arr2[0, 0], idx2, j) +for (2; (m) <= (10); (m)++) (arr2[m]) = ((m) * (10)) +printf("%d %d %d %d\\n", arr1[0, 0], arr2[0], idx2, j) (aa) = (fna(1)) -(bb) = (fnb((cc) = (1), 2)) +(bb) = (fnb((cc) = (1), (elide_global_a) = (2))) for (1; (bb) < (10); (bb)++) (cc) += (bb) for ((dd) = (1); (dd) < (10); 1) (dd) += (1) -if (1) (ee) = (1) +if ((elide_global_b) = (1)) (ee) = (1) (cc) = ((dd) = (5)) (cc) = ((4) + ((cc) = (1))) -printf("%d %d %d %d %d", aa, bb, cc, dd, ee) +printf("%d %d %d %d %d\\n", aa, bb, cc, dd, ee) exit() } +end /* <- end */ + # locals + idx0:long +{ +foreach ([idx0] in arr3) printf("arr3[%#d]=%#x\\n", idx0, arr3[idx0]) +} +end /* <- end */ +{ +printf("elide_idx1=%#x\\n", elide_idx1) +} +end /* <- end */ +{ +printf("elide_global_a=%#x\\n", elide_global_a) +} +end /* <- end */ +{ +printf("elide_global_b=%#x\\n", elide_global_b) +} } proc optim_arridx_run { TEST_NAME args } { diff --git a/testsuite/systemtap.base/optim_arridx.stp b/testsuite/systemtap.base/optim_arridx.stp index 3e4f8fd2..5c9c1051 100644 --- a/testsuite/systemtap.base/optim_arridx.stp +++ b/testsuite/systemtap.base/optim_arridx.stp @@ -1,7 +1,7 @@ global arr1, arr2, arr3, elide_idx1, elide_global_a, elide_global_b function fna(a:long) {return a} -function fnb(a:long, b:long) {return a+b+printf("")} +function fnb(a:long, b:long) {return a+b} probe begin { // array indices @@ -16,7 +16,7 @@ probe begin { m = 1 for (elide_n=2; m <= 10; m++) arr2[m] = m * 10 - printf ("%d %d %d %d\n", arr1[0], arr2[0,0], idx2, j) + printf ("%d %d %d %d\n", arr1[0,0], arr2[0], idx2, j) // function args aa = fna(elide_aa = 1) @@ -40,6 +40,6 @@ probe begin { // binary expression cc = ((elide_hh = 4) + (cc = 1)) - printf("%d %d %d %d %d", aa, bb, cc, dd, ee) + printf("%d %d %d %d %d\n", aa, bb, cc, dd, ee) exit () } |