diff options
author | fche <fche> | 2005-06-03 21:01:35 +0000 |
---|---|---|
committer | fche <fche> | 2005-06-03 21:01:35 +0000 |
commit | 553d27a587615e4b242a89bf1a7af93b71f050f0 (patch) | |
tree | 1ca4e5d35908208e5d533bb32e22b6aa567221b8 | |
parent | 63a7c90e365874972925e886ed50941f5620bdfe (diff) | |
download | systemtap-steved-553d27a587615e4b242a89bf1a7af93b71f050f0.tar.gz systemtap-steved-553d27a587615e4b242a89bf1a7af93b71f050f0.tar.xz systemtap-steved-553d27a587615e4b242a89bf1a7af93b71f050f0.zip |
2005-06-03 Frank Ch. Eigler <fche@redhat.com>
* TODO: Removed entries already represented in bugzilla.
* elaborate.cxx: Rewrite type inference for several operators.
* main.cxx (main): For -p2 runs, print types of function/probe locals.
* parse.cxx (scan): Identify more two-character operators.
(parse_comparison): Support the whole suite.
* translate.cxx (visit_unary_expression, logical_or_expr,
logical_and_expr, comparison,ternary_expression): New support.
* testsuite/parseok/semok.stp: Clever new test.
* testsuite/transok/four.stp: New test.
* testsuite/*: Some tweaked tests for syntax changes.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | TODO | 16 | ||||
-rw-r--r-- | elaborate.cxx | 157 | ||||
-rw-r--r-- | main.cxx | 29 | ||||
-rw-r--r-- | parse.cxx | 25 | ||||
-rw-r--r-- | staptree.cxx | 1 | ||||
-rwxr-xr-x | testsuite/parseok/semko.stp | 6 | ||||
-rwxr-xr-x | testsuite/semko/eight.stp | 2 | ||||
-rwxr-xr-x | testsuite/semko/four.stp | 2 | ||||
-rwxr-xr-x | testsuite/semko/three.stp | 3 | ||||
-rwxr-xr-x | testsuite/semko/two.stp | 2 | ||||
-rwxr-xr-x | testsuite/transok/four.stp | 13 | ||||
-rw-r--r-- | translate.cxx | 86 |
13 files changed, 252 insertions, 103 deletions
@@ -1,5 +1,18 @@ 2005-06-03 Frank Ch. Eigler <fche@redhat.com> + * TODO: Removed entries already represented in bugzilla. + * elaborate.cxx: Rewrite type inference for several operators. + * main.cxx (main): For -p2 runs, print types of function/probe locals. + * parse.cxx (scan): Identify more two-character operators. + (parse_comparison): Support the whole suite. + * translate.cxx (visit_unary_expression, logical_or_expr, + logical_and_expr, comparison,ternary_expression): New support. + * testsuite/parseok/semok.stp: Clever new test. + * testsuite/transok/four.stp: New test. + * testsuite/*: Some tweaked tests for syntax changes. + +2005-06-03 Frank Ch. Eigler <fche@redhat.com> + * parse.cxx (scan): Support C and C++ comment styles. * testsuite/parseok/four.stp: Test them some ... * testsuite/parseko/nine.stp: ... and some more. @@ -1,8 +1,6 @@ LANGUAGE for/while/break/continue statements lock (var) { block } (http://tinyurl.com/5rpzg) - "in" predicate / looping construct - /* */ and // comments builtin functions varargs/overloaded functions (?) syntax for dereferencing C structures (http://tinyurl.com/4tpgh); @@ -13,7 +11,6 @@ LANGUAGE TRANSLATOR lots of "XXX" markers - use "restrict" pointers for context* deal with (warn/elide?) local variables only written or read RUNTIME @@ -29,15 +26,8 @@ OPROFILE/timers PROVIDERS lkst("process_contextswitch") - syscall("name").return - syscall("*") - kernel.function("wait_for_godot") kernel.function("wait_for_godot").callees kernel.function("batman").calledfrom("commissioner") - kernel.function("name").line(10) - kernel.source("mempool.c").line(5004) - kernel.address(0xdeadbeef) - kernel.module("driver.ko").function("name").return kernel.module("cpqarray.ko").jumptable("ida_fops") kernel.watch("datasymbol").write user("fche").inode("/bin/vi").function("refresh") @@ -45,15 +35,9 @@ PROVIDERS time.real.hz(500) time.virtual.jiffies(100) perfcounter("tlbmiss").count(4000) - resource.freemembelow(50) # pages? - begin - end KPROBES - smp friendliness: no kprobes-wide lock held during probe execution - multiple probes at same address user-level probe points (via ptrace mechanism?) - separate stack treatment of nested probe hits (prefer no permanent disablement; require flagging of occurrence) self-monitoring of performance overhead diff --git a/elaborate.cxx b/elaborate.cxx index 7a6c2359..e733132f 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -546,14 +546,43 @@ typeresolution_info::visit_logical_and_expr (logical_and_expr *e) void typeresolution_info::visit_comparison (comparison *e) { - visit_binary_expression (e); + if (t == pe_stats || t == pe_string) + invalid (e->tok, t); + + t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown; + e->left->visit (this); + t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown; + e->right->visit (this); + + if (e->left->type != pe_unknown && + e->right->type != pe_unknown && + e->left->type != e->right->type) + mismatch (e->tok, e->left->type, e->right->type); + + if (e->type == pe_unknown) + { + e->type = pe_long; + resolved (e->tok, e->type); + } } void typeresolution_info::visit_concatenation (concatenation *e) { - visit_binary_expression (e); + if (t != pe_unknown && t != pe_string) + invalid (e->tok, t); + + t = pe_string; + e->left->visit (this); + t = pe_string; + e->right->visit (this); + + if (e->type == pe_unknown) + { + e->type = pe_string; + resolved (e->tok, e->type); + } } @@ -567,89 +596,86 @@ typeresolution_info::visit_exponentiation (exponentiation *e) void typeresolution_info::visit_assignment (assignment *e) { - visit_binary_expression (e); -} - + if (t == pe_stats) + invalid (e->tok, t); -void -typeresolution_info::visit_binary_expression (binary_expression* e) -{ if (e->op == "<<<") // stats aggregation { - exp_type t1 = t; + if (t == pe_string) + invalid (e->tok, t); + t = pe_stats; e->left->visit (this); t = pe_long; e->right->visit (this); - if (t1 == pe_stats || t1 == pe_string) - invalid (e->tok, t1); - else if (e->type == pe_unknown) + if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); } } - else if (e->op == ".") // string concatenation + else if (e->op == "+=" || // numeric only + false) { - exp_type t1 = t; - t = pe_string; - e->left->visit (this); - t = pe_string; - e->right->visit (this); - if (t1 == pe_long || t1 == pe_stats) - mismatch (e->tok, t1, pe_string); - else if (e->type == pe_unknown) - { - e->type = pe_string; - resolved (e->tok, e->type); - } - } - else if (e->op == "==" - || false) // XXX: other comparison operators - { - exp_type t1 = t; - t = pe_unknown; - e->left->visit (this); - t = pe_unknown; - e->right->visit (this); - if (t1 == pe_string || t1 == pe_stats) - mismatch (e->tok, t1, pe_long); - else if (e->type == pe_unknown) - { - e->type = pe_long; - resolved (e->tok, e->type); - } + visit_binary_expression (e); } - else // general arithmetic operators? + else // overloaded for string & numeric operands { - // propagate e->type downward + // logic similar to ternary_expression exp_type sub_type = t; - if ((sub_type == pe_unknown) && (e->type != pe_unknown)) + + // Infer types across the l/r values + if (sub_type == pe_unknown && e->type != pe_unknown) sub_type = e->type; - t = sub_type; + + t = (sub_type != pe_unknown) ? sub_type : + (e->right->type != pe_unknown) ? e->right->type : + pe_unknown; e->left->visit (this); - t = sub_type; + t = (sub_type != pe_unknown) ? sub_type : + (e->left->type != pe_unknown) ? e->left->type : + pe_unknown; e->right->visit (this); - - if ((sub_type == pe_unknown) && (e->type != pe_unknown)) - ; // already resolved - else if ((sub_type != pe_unknown) && (e->type == pe_unknown)) + + if ((sub_type != pe_unknown) && (e->type == pe_unknown)) { e->type = sub_type; resolved (e->tok, e->type); } - else if ((sub_type == pe_unknown) && (e->left->type != pe_unknown)) + if ((sub_type == pe_unknown) && (e->left->type != pe_unknown)) { e->type = e->left->type; resolved (e->tok, e->type); } - else if ((sub_type == pe_unknown) && (e->right->type != pe_unknown)) - { - e->type = e->right->type; - resolved (e->tok, e->type); - } - else if (e->type != sub_type) - mismatch (e->tok, sub_type, e->type); + + if (e->left->type != pe_unknown && + e->right->type != pe_unknown && + e->left->type != e->right->type) + mismatch (e->tok, e->left->type, e->right->type); + } +} + + +void +typeresolution_info::visit_binary_expression (binary_expression* e) +{ + if (t == pe_stats || t == pe_string) + invalid (e->tok, t); + + t = pe_long; + e->left->visit (this); + t = pe_long; + e->right->visit (this); + + if (e->left->type != pe_unknown && + e->right->type != pe_unknown && + e->left->type != e->right->type) + mismatch (e->tok, e->left->type, e->right->type); + + if (e->type == pe_unknown) + { + e->type = pe_long; + resolved (e->tok, e->type); } } @@ -671,16 +697,13 @@ typeresolution_info::visit_post_crement (post_crement *e) void typeresolution_info::visit_unary_expression (unary_expression* e) { - // all unary operators only work on numerics - exp_type t1 = t; + if (t == pe_stats || t == pe_string) + invalid (e->tok, t); + t = pe_long; e->operand->visit (this); - if (t1 == pe_unknown && e->type != pe_unknown) - ; // already resolved - else if (t1 == pe_string || t1 == pe_stats) - mismatch (e->tok, t1, pe_long); - else if (e->type == pe_unknown) + if (e->type == pe_unknown) { e->type = pe_long; resolved (e->tok, e->type); @@ -688,7 +711,6 @@ typeresolution_info::visit_unary_expression (unary_expression* e) } - void typeresolution_info::visit_ternary_expression (ternary_expression* e) { @@ -697,8 +719,7 @@ typeresolution_info::visit_ternary_expression (ternary_expression* e) t = pe_long; e->cond->visit (this); - // Match ordinary binary_expression type inference for the true/false - // arms of the ternary expression. + // Infer types across the true/false arms of the ternary expression. if (sub_type == pe_unknown && e->type != pe_unknown) sub_type = e->type; @@ -175,26 +175,49 @@ main (int argc, char * const argv []) rc = semantic_pass (s); if (last_pass == 2 && rc == 0) { - s.op->line() << "# globals"; + if (s.globals.size() > 0) + s.op->line() << "# globals"; for (unsigned i=0; i<s.globals.size(); i++) { vardecl* v = s.globals[i]; v->printsig (s.op->newline()); } - s.op->newline() << "# functions"; + if (s.functions.size() > 0) + s.op->newline() << "# functions"; for (unsigned i=0; i<s.functions.size(); i++) { functiondecl* f = s.functions[i]; f->printsig (s.op->newline()); + s.op->indent(1); + if (f->locals.size() > 0) + s.op->newline(1) << "# locals"; + for (unsigned j=0; j<f->locals.size(); j++) + { + vardecl* v = f->locals[j]; + v->printsig (s.op->newline()); + } + s.op->indent(-1); } - s.op->newline() << "# probes"; + if (s.probes.size() > 0) + s.op->newline() << "# probes"; for (unsigned i=0; i<s.probes.size(); i++) { derived_probe* p = s.probes[i]; p->printsig (s.op->newline()); + s.op->indent(1); + if (p->locals.size() > 0) + s.op->newline() << "# locals"; + for (unsigned j=0; j<p->locals.size(); j++) + { + vardecl* v = p->locals[j]; + v->printsig (s.op->newline()); + } + s.op->indent(-1); } + + s.op->newline(); } // PASS 3: TRANSLATION @@ -286,14 +286,17 @@ lexer::scan () // handle two-character operators if ((c == '=' && c2 == '=') || + (c == '!' && c2 == '=') || + (c == '<' && c2 == '=') || + (c == '>' && c2 == '=') || (c == '+' && c2 == '+') || (c == '-' && c2 == '-') || (c == '|' && c2 == '|') || (c == '&' && c2 == '&') || - (c == '<' && c2 == '<') || + // (c == '<' && c2 == '<') || + // (c == '>' && c2 == '>') || (c == '+' && c2 == '=') || (c == '-' && c2 == '=') || - (c == ':' && c2 == ':') || (c == '-' && c2 == '>') || false) // XXX: etc. n->content.push_back ((char) input_get ()); @@ -301,9 +304,15 @@ lexer::scan () // handle three-character operator if (c == '<' && c2 == '<') { + input_get (); // swallow c2 int c3 = input.peek (); if (c3 == '<') - n->content.push_back ((char) input_get ()); + { + input_get (); // swallow c3 + n->content = "<<<"; + } + else + n->content = "<<"; } return n; @@ -843,7 +852,7 @@ parser::parse_assignment () next (); e->right = parse_expression (); op1 = e; - // XXX: map assign/accumlate operators like +=, /= + // XXX: map assign/accumulate operators like +=, /= // to ordinary assignment + nested binary_expression } @@ -994,7 +1003,13 @@ parser::parse_comparison () const token* t = peek (); while (t && t->type == tok_operator - && (t->content == ">" || t->content == "==")) // xxx: more + && (t->content == ">" || + t->content == "<" || + t->content == "==" || + t->content == "!=" || + t->content == "<=" || + t->content == ">=" || + false )) // xxx: more { comparison* e = new comparison; e->left = op1; diff --git a/staptree.cxx b/staptree.cxx index d0fd79be..a8651d1d 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -373,7 +373,6 @@ void probe::printsig (ostream& o) o << (i>0 ? ", " : ""); locations[i]->print (o); } - o << endl; } diff --git a/testsuite/parseok/semko.stp b/testsuite/parseok/semko.stp new file mode 100755 index 00000000..11f2a2da --- /dev/null +++ b/testsuite/parseok/semko.stp @@ -0,0 +1,6 @@ +#! /bin/sh + +# make sure that we can *parse* all semko test files, to ensure +# that it is semantic (elaboration) checks that fail, not parse errors + +./stap -p1 -I${SRCDIR}/testsuite/semko -e 'global nothing' diff --git a/testsuite/semko/eight.stp b/testsuite/semko/eight.stp index 7d297295..d95e225f 100755 --- a/testsuite/semko/eight.stp +++ b/testsuite/semko/eight.stp @@ -1,5 +1,5 @@ #! stap -p2 probe foo { - stats << "string" # stats only collect numbers + stats <<< "string" # stats only collect numbers } diff --git a/testsuite/semko/four.stp b/testsuite/semko/four.stp index fd2b3928..21e2be20 100755 --- a/testsuite/semko/four.stp +++ b/testsuite/semko/four.stp @@ -1,6 +1,6 @@ #! stap -p2 -global a, b; # types unknown +global a, b # types unknown function bar () { diff --git a/testsuite/semko/three.stp b/testsuite/semko/three.stp index 423dbcdf..7a64a93c 100755 --- a/testsuite/semko/three.stp +++ b/testsuite/semko/three.stp @@ -1,6 +1,7 @@ #! stap -p2 +global b probe foo { - a << 2; + a <<< 2; b[a] = 4; # must not index with stats variable } diff --git a/testsuite/semko/two.stp b/testsuite/semko/two.stp index acf0a973..5906687c 100755 --- a/testsuite/semko/two.stp +++ b/testsuite/semko/two.stp @@ -1,6 +1,6 @@ #! stap -p2 -function zoo (p) { p << 5; return 0 } # passing stats as function arg +function zoo (p) { p <<< 5; return 0 } # passing stats as function arg probe foo { bar = 2 + "string"; # mixing integer+string arithmetic diff --git a/testsuite/transok/four.stp b/testsuite/transok/four.stp new file mode 100755 index 00000000..daad4f5d --- /dev/null +++ b/testsuite/transok/four.stp @@ -0,0 +1,13 @@ +#! stap + +function f () { + return 0 +} + +probe end { + a = 0 as = "" + b = a * (b + c) - d bs = as . "bs" . as + c = (a > b) ? (a == b) : (a != b) cs = (as > bs) ? (as == bs) : (as != bs) + d = (a > b) + (a >= b) + (a < b) + (a <= b) + if (a) b else c if (cs) 0 else 1 +} diff --git a/translate.cxx b/translate.cxx index f53e2952..972e188c 100644 --- a/translate.cxx +++ b/translate.cxx @@ -709,7 +709,7 @@ c_unparser::visit_binary_expression (binary_expression* e) if (e->type != pe_long || e->left->type != pe_long || e->right->type != pe_long) - throw semantic_error ("expected string types", e->tok); + throw semantic_error ("expected numeric types", e->tok); o->line() << "("; e->left->visit (this); @@ -722,36 +722,66 @@ c_unparser::visit_binary_expression (binary_expression* e) throw semantic_error ("not yet implemented", e->tok); } + void c_unparser::visit_unary_expression (unary_expression* e) { - throw semantic_error ("not yet implemented", e->tok); + if (e->type != pe_long || + e->operand->type != pe_long) + throw semantic_error ("expected numeric types", e->tok); + + o->line() << e->op << " ("; + e->operand->visit (this); + o->line() << ")"; } + void c_unparser::visit_pre_crement (pre_crement* e) { throw semantic_error ("not yet implemented", e->tok); } + void c_unparser::visit_post_crement (post_crement* e) { throw semantic_error ("not yet implemented", e->tok); } + void c_unparser::visit_logical_or_expr (logical_or_expr* e) { - throw semantic_error ("not yet implemented", e->tok); + if (e->type != pe_long || + e->left->type != pe_long || + e->right->type != pe_long) + throw semantic_error ("expected numeric types", e->tok); + + o->line() << "("; + e->left->visit (this); + o->line() << ") " << e->op << " ("; + e->right->visit (this); + o->line() << ")"; } + void c_unparser::visit_logical_and_expr (logical_and_expr* e) { - throw semantic_error ("not yet implemented", e->tok); + if (e->type != pe_long || + e->left->type != pe_long || + e->right->type != pe_long) + throw semantic_error ("expected numeric types", e->tok); + + o->line() << "("; + e->left->visit (this); + o->line() << ") " << e->op << " ("; + e->right->visit (this); + o->line() << ")"; } + void c_unparser::visit_array_in (array_in* e) { @@ -762,7 +792,37 @@ c_unparser::visit_array_in (array_in* e) void c_unparser::visit_comparison (comparison* e) { - throw semantic_error ("not yet implemented", e->tok); + o->line() << "("; + + if (e->left->type == pe_string) + { + if (e->left->type != pe_string || + e->right->type != pe_string) + throw semantic_error ("expected string types", e->tok); + + o->line() << "strncmp ("; + e->left->visit (this); + o->line() << ", "; + e->right->visit (this); + o->line() << ", MAXSTRINGLEN"; + o->line() << ") " << e->op << " 0"; + } + else if (e->left->type == pe_long) + { + if (e->left->type != pe_long || + e->right->type != pe_long) + throw semantic_error ("expected numeric types", e->tok); + + o->line() << "("; + e->left->visit (this); + o->line() << ") " << e->op << " ("; + e->right->visit (this); + o->line() << ")"; + } + else + throw semantic_error ("unexpected type", e->left->tok); + + o->line() << ")"; } @@ -811,7 +871,21 @@ c_unparser::visit_exponentiation (exponentiation* e) void c_unparser::visit_ternary_expression (ternary_expression* e) { - throw semantic_error ("not yet implemented", e->tok); + if (e->cond->type != pe_long) + throw semantic_error ("expected numeric condition", e->cond->tok); + + if (e->truevalue->type != e->falsevalue->type || + e->type != e->truevalue->type || + (e->truevalue->type != pe_long && e->truevalue->type != pe_string)) + throw semantic_error ("expected matching types", e->tok); + + o->line() << "(("; + e->cond->visit (this); + o->line() << ") ? ("; + e->truevalue->visit (this); + o->line() << ") : ("; + e->falsevalue->visit (this); + o->line() << "))"; } |