diff options
author | dsmith <dsmith> | 2006-11-06 16:05:50 +0000 |
---|---|---|
committer | dsmith <dsmith> | 2006-11-06 16:05:50 +0000 |
commit | 27f21e8c049b0cd20fd2d4e2fd9b96cad6c910cc (patch) | |
tree | 78fad282ce4f36ad50a3b944d6c659941591d5f6 /translate.cxx | |
parent | a90b629e6fe7420caeb0f7494f712c9664afbdc8 (diff) | |
download | systemtap-steved-27f21e8c049b0cd20fd2d4e2fd9b96cad6c910cc.tar.gz systemtap-steved-27f21e8c049b0cd20fd2d4e2fd9b96cad6c910cc.tar.xz systemtap-steved-27f21e8c049b0cd20fd2d4e2fd9b96cad6c910cc.zip |
2006-11-06 David Smith <dsmith@redhat.com>
Added "limit EXP" support to foreach statements.
* translate.cxx (c_tmpcounter::visit_foreach_loop): Handles
"limit" member variable.
(c_unparser::visit_foreach_loop): Ditto.
* staptree.cxx (foreach_loop::print): Prints "limit EXP"
addition.
(traversing_visitor::visit_foreach_loop): Handles "limit" member
variable.
(deep_copy_visitor::visit_foreach_loop): Ditto.
* staptree.h (struct foreach_loop): Added "limit" member
variable.
* stap.1.in: Added documentation for the "limit EXP" addition to
foreach statement.
* parse.cxx (lexer::scan): Added "limit" keyword for foreach
statements.
(parser::parse_foreach_loop): Parses "limit" keyword for foreach
statements.
* elaborate.cxx (symresolution_info::visit_foreach_loop): Handles
"limit" member variable.
(typeresolution_info::visit_foreach_loop): Ditto.
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 107 |
1 files changed, 98 insertions, 9 deletions
diff --git a/translate.cxx b/translate.cxx index 1f2e47f0..14d58ef2 100644 --- a/translate.cxx +++ b/translate.cxx @@ -2196,6 +2196,19 @@ c_tmpcounter::visit_foreach_loop (foreach_loop *s) } } + // Create a temporary for the loop limit counter and the limit + // expression result. + if (s->limit) + { + tmpvar res_limit = parent->gensym (pe_long); + res_limit.declare(*parent); + + s->limit->visit (this); + + tmpvar limitv = parent->gensym (pe_long); + limitv.declare(*parent); + } + s->block->visit (this); } @@ -2223,6 +2236,14 @@ c_unparser::visit_foreach_loop (foreach_loop *s) // initialization + tmpvar *res_limit = NULL; + if (s->limit) + { + // Evaluate the limit expression once. + res_limit = new tmpvar(gensym(pe_long)); + c_assign (res_limit->qname(), s->limit, "foreach limit"); + } + // aggregate array if required if (mv.is_parallel()) { @@ -2231,20 +2252,43 @@ c_unparser::visit_foreach_loop (foreach_loop *s) o->indent(-1); // sort array if desired - if (s->sort_direction) { - o->newline() << "else"; // only sort if aggregation was ok - o->newline(1) << "_stp_map_sort (" << mv.fetch_existing_aggregate() << ", " - << s->sort_column << ", " << - s->sort_direction << ");"; - o->indent(-1); - } - } + if (s->sort_direction) + { + o->newline() << "else"; // only sort if aggregation was ok + if (s->limit) + { + o->newline(1) << "_stp_map_sortn (" + << mv.fetch_existing_aggregate() << ", " + << *res_limit << ", " << s->sort_column << ", " + << - s->sort_direction << ");"; + } + else + { + o->newline(1) << "_stp_map_sort (" + << mv.fetch_existing_aggregate() << ", " + << s->sort_column << ", " + << - s->sort_direction << ");"; + } + o->indent(-1); + } + } else { // sort array if desired if (s->sort_direction) { - o->newline() << "_stp_map_sort (" << mv.qname() << ", " - << s->sort_column << ", " << - s->sort_direction << ");"; + if (s->limit) + { + o->newline() << "_stp_map_sortn (" << mv.qname() << ", " + << *res_limit << ", " << s->sort_column << ", " + << - s->sort_direction << ");"; + } + else + { + o->newline() << "_stp_map_sort (" << mv.qname() << ", " + << s->sort_column << ", " + << - s->sort_direction << ");"; + } } } @@ -2254,6 +2298,14 @@ c_unparser::visit_foreach_loop (foreach_loop *s) aggregations_active.insert(mv.qname()); o->newline() << iv << " = " << iv.start (mv) << ";"; + tmpvar *limitv = NULL; + if (s->limit) + { + // Create the loop limit variable here and initialize it. + limitv = new tmpvar(gensym (pe_long)); + o->newline() << *limitv << " = 0LL;"; + } + // condition o->newline(-1) << toplabel << ":"; @@ -2270,6 +2322,18 @@ c_unparser::visit_foreach_loop (foreach_loop *s) loop_continue_labels.push_back (contlabel); o->newline() << "{"; o->indent (1); + + if (s->limit) + { + // If we've been through LIMIT loop iterations, quit. + o->newline() << "if (" << *limitv << "++ >= " << *res_limit + << ") goto " << breaklabel << ";"; + + // We're done with limitv and res_limit. + delete limitv; + delete res_limit; + } + for (unsigned i = 0; i < s->indexes.size(); ++i) { // copy the iter values into the specified locals @@ -2307,11 +2371,36 @@ c_unparser::visit_foreach_loop (foreach_loop *s) var v = getvar(sym->referent, sym->tok); v.assert_hist_compatible(*hist); + tmpvar *res_limit = NULL; + tmpvar *limitv = NULL; + if (s->limit) + { + // Evaluate the limit expression once. + res_limit = new tmpvar(gensym(pe_long)); + c_assign (res_limit->qname(), s->limit, "foreach limit"); + + // Create the loop limit variable here and initialize it. + limitv = new tmpvar(gensym (pe_long)); + o->newline() << *limitv << " = 0LL;"; + } + // XXX: break / continue don't work here yet o->newline() << "for (" << bucketvar << " = 0; " << bucketvar << " < " << v.buckets() << "; " << bucketvar << "++) { "; o->newline(1); + + if (s->limit) + { + // If we've been through LIMIT loop iterations, quit. + o->newline() << "if (" << *limitv << "++ >= " << *res_limit + << ") break;"; + + // We're done with limitv and res_limit. + delete limitv; + delete res_limit; + } + s->block->visit (this); o->newline(-1) << "}"; } |