--- systemtap-0.5.4/parse.h.const 2006-02-13 07:50:25.000000000 +0000 +++ systemtap-0.5.4/parse.h 2006-02-12 09:56:17.000000000 +0000 @@ -118,7 +118,8 @@ private: // nonterminals void parse_probe (std::vector&, std::vector&); - void parse_global (std::vector&); + void parse_global (std::vector&); + void parse_const (std::vector&); void parse_functiondecl (std::vector&); embeddedcode* parse_embeddedcode (); probe_point* parse_probe_point (); --- systemtap-0.5.4/staptree.cxx.const 2006-02-13 07:49:59.000000000 +0000 +++ systemtap-0.5.4/staptree.cxx 2006-02-13 10:59:49.000000000 +0000 @@ -89,6 +89,23 @@ { } + +bool +symboldecl::is_var (vardecl *& var_out) +{ + var_out = NULL; + return false; +} + + +bool +symboldecl::is_const (constdecl *& const_out) +{ + const_out = NULL; + return false; +} + + probe_point::probe_point (std::vector const & comps, const token * t): components(comps), tok(t) @@ -125,6 +142,14 @@ } +bool +vardecl::is_var(vardecl *& var_out) +{ + var_out = this; + return true; +} + + void vardecl::set_arity (int a) { @@ -152,6 +177,19 @@ } +constdecl::constdecl () +{ +} + + +bool +constdecl::is_const(constdecl *& const_out) +{ + const_out = this; + return true; +} + + functiondecl::functiondecl (): body (0) { @@ -299,6 +337,19 @@ } +void constdecl::print (ostream& o) const +{ + o << name << " = "; + value->print (o); +} + + +void constdecl::printsig (ostream& o) const +{ + o << name << ":" << type; +} + + void functiondecl::print (ostream& o) const { o << "function " << name << " ("; @@ -776,7 +827,11 @@ for (unsigned i=0; iis_const (c)) + o << "const "; + else + o << "global "; globals[i]->print (o); o << endl; } @@ -1075,11 +1130,11 @@ } void -indexable::print_indexable (std::ostream& o) const +indexable::print_indexable (std::ostream& o) { - const symbol *sym; - const hist_op *hist; - classify_const_indexable(this, sym, hist); + symbol *sym; + hist_op *hist; + classify_indexable(this, sym, hist); if (sym) sym->print (o); else @@ -1120,33 +1175,12 @@ } bool -indexable::is_const_symbol(const symbol *& sym_out) const -{ - sym_out = NULL; - return false; -} - -bool -indexable::is_const_hist_op(const hist_op *& hist_out) const -{ - hist_out = NULL; - return false; -} - -bool symbol::is_symbol(symbol *& sym_out) { sym_out = this; return true; } -bool -symbol::is_const_symbol(const symbol *& sym_out) const -{ - sym_out = this; - return true; -} - const token * symbol::get_tok() const { @@ -1160,13 +1194,6 @@ return true; } -bool -hist_op::is_const_hist_op(const hist_op *& hist_out) const -{ - hist_out = this; - return true; -} - const token * hist_op::get_tok() const { @@ -1186,17 +1213,6 @@ throw semantic_error("Failed to classify indexable", ix->get_tok()); } -void -classify_const_indexable(const indexable* ix, - const symbol *& array_out, - const hist_op *& hist_out) -{ - array_out = NULL; - hist_out = NULL; - if (!(ix->is_const_symbol(array_out) || ix->is_const_hist_op(hist_out))) - throw semantic_error("Expecting symbol or histogram operator", ix->get_tok()); -} - // ------------------------------------------------------------------------ bool --- systemtap-0.5.4/tapset/aux_syscalls.stp.const 2006-02-13 17:23:05.000000000 +0000 +++ systemtap-0.5.4/tapset/aux_syscalls.stp 2006-02-13 17:23:13.000000000 +0000 @@ -298,19 +298,31 @@ return substr(bs,0,strlen(bs)-1) } +const O_ASYNC = 8192 +const O_SYNC = 4096 +const O_NONBLOCK = 2048 +const O_APPEND = 1024 +const O_TRUNC = 512 +const O_NDCTTY = 256 +const O_EXCL = 128 +const O_CREAT = 64 +const O_RDWR = 2 +const O_WRONLY = 1 +const O_RDONLY = 0 + /* `man 2 open` for more information */ function _sys_open_flag_str(f) { - if(f & 8192) bs="O_ASYNC|".bs - if(f & 4096) bs="O_SYNC|".bs - if(f & 2048) bs="O_NONBLOCK|".bs - if(f & 1024) bs="O_APPEND|".bs - if(f & 512) bs="O_TRUNC|".bs - if(f & 256) bs="O_NDCTTY|".bs - if(f & 128) bs="O_EXCL|".bs - if(f & 64) bs="O_CREAT|".bs - if((f & 3) == 2) bs="O_RDWR|".bs - else if((f & 3) == 1) bs="O_WRONLY|".bs - else if((f & 3) == 0) bs="O_RDONLY|".bs + if(f & O_ASYNC) bs="O_ASYNC|".bs + if(f & O_SYNC) bs="O_SYNC|".bs + if(f & O_NONBLOCK) bs="O_NONBLOCK|".bs + if(f & O_APPEND) bs="O_APPEND|".bs + if(f & O_TRUNC) bs="O_TRUNC|".bs + if(f & O_NDCTTY) bs="O_NDCTTY|".bs + if(f & O_EXCL) bs="O_EXCL|".bs + if(f & O_CREAT) bs="O_CREAT|".bs + if((f & 3) == O_RDWR) bs="O_RDWR|".bs + else if((f & 3) == O_WRONLY) bs="O_WRONLY|".bs + else if((f & 3) == O_RDONLY) bs="O_RDONLY|".bs return substr(bs,0,strlen(bs)-1) } --- systemtap-0.5.4/translate.cxx.const 2006-02-13 07:49:44.000000000 +0000 +++ systemtap-0.5.4/translate.cxx 2006-02-13 17:22:44.000000000 +0000 @@ -56,6 +56,8 @@ } +struct sym; +struct constsym; struct var; struct tmpvar; struct aggvar; @@ -80,7 +82,8 @@ void emit_map_type_instantiations (); void emit_common_header (); - void emit_global (vardecl* v); + void emit_global_const (constdecl* c); + void emit_global_var (vardecl* v); void emit_functionsig (functiondecl* v); void emit_module_init (); void emit_module_exit (); @@ -123,6 +126,7 @@ tmpvar gensym(exp_type ty); aggvar gensym_aggregate(); + constsym getconst(constdecl* c); var getvar(vardecl* v, token const* tok = NULL); itervar getiter(symbol* s); mapvar getmap(vardecl* v, token const* tok = NULL); @@ -133,8 +137,10 @@ void load_aggregate (expression *e, aggvar & agg, bool pre_agg=false); string histogram_index_check(var & vase, tmpvar & idx) const; - void collect_map_index_types(vector const & vars, - set< pair, exp_type> > & types); + void collect_map_index_types_from_syms(vector const & syms, + set< pair, exp_type> > & types); + void collect_map_index_types_from_vars(vector const & vars, + set< pair, exp_type> > & types); void visit_statement (statement* s, unsigned actions); @@ -227,7 +233,7 @@ token const* tok); void c_assignop(tmpvar & res, - var const & lvar, + sym const & lvar, tmpvar const & tmp, token const* tok); @@ -253,7 +259,47 @@ }; -ostream & operator<<(ostream & o, var const & v); +class sym +{ +protected: + exp_type ty; + string name; + +public: + sym (exp_type type, const string & name) + : ty(type), name(name) + {} + virtual ~sym() {} + + exp_type type() const + { + return ty; + } + + virtual string qname() const = 0; +}; + +ostream & operator<<(ostream & o, sym const & s) +{ + return o << s.qname(); +} + + +class constsym : public sym +{ +protected: + literal *value; + +public: + constsym(exp_type type, string const & name, literal* value) + : sym (ty, name), value(value) + {} + + string qname() const + { + return "const_" + name; + } +}; /* @@ -288,25 +334,24 @@ the user wants to track. */ -class var +class var : public sym { protected: bool local; - exp_type ty; statistic_decl sd; - string name; public: var(bool local, exp_type ty, statistic_decl const & sd, string const & name) - : local(local), ty(ty), sd(sd), name(name) + : sym (ty, name), local(local), sd(sd) {} var(bool local, exp_type ty, string const & name) - : local(local), ty(ty), name(name) + : sym (ty, name), local(local) {} + virtual ~var() {} bool is_local() const @@ -342,11 +387,6 @@ } } - exp_type type() const - { - return ty; - } - string qname() const { if (local) @@ -412,11 +452,6 @@ } }; -ostream & operator<<(ostream & o, var const & v) -{ - return o << v.qname(); -} - struct stmt_expr { c_unparser & c; @@ -963,7 +998,15 @@ void -c_unparser::emit_global (vardecl *v) +c_unparser::emit_global_const (constdecl *c) +{ + o->newline() << "#define const_" << c_varname (c->name) << " "; + c->value->visit (this); +} + + +void +c_unparser::emit_global_var (vardecl *v) { if (v->arity == 0) o->newline() << "static " @@ -1056,7 +1099,9 @@ for (unsigned i=0; iglobals.size(); i++) { // XXX: handle failure! - vardecl* v = session->globals[i]; + vardecl* v; + if (!session->globals[i]->is_var (v)) + continue; if (v->index_types.size() > 0) o->newline() << getmap (v).init(); else @@ -1105,8 +1150,8 @@ // as this is our only chance. for (unsigned i=0; iglobals.size(); i++) { - vardecl* v = session->globals[i]; - if (v->index_types.size() > 0) + vardecl* v; + if (session->globals[i]->is_var (v) && v->index_types.size() > 0) o->newline() << getmap (v).fini(); } @@ -1159,8 +1204,8 @@ for (unsigned i=0; iglobals.size(); i++) { - vardecl* v = session->globals[i]; - if (v->index_types.size() > 0) + vardecl* v; + if (session->globals[i]->is_var (v) && v->index_types.size() > 0) o->newline() << getmap (v).fini(); } @@ -1296,7 +1341,9 @@ string last_locked_var; for (unsigned i = 0; i < session->globals.size(); i++) { - vardecl* v = session->globals[i]; + vardecl* v; + if (!session->globals[i]->is_var (v)) + continue; bool read_p = vut.read.find(v) != vut.read.end(); bool write_p = vut.written.find(v) != vut.written.end(); if (!read_p && !write_p) continue; @@ -1344,7 +1391,9 @@ for (int i = session->globals.size()-1; i>=0; i--) // in reverse order! { - vardecl* v = session->globals[i]; + vardecl* v; + if (!session->globals[i]->is_var (v)) + continue; bool read_p = vut.read.find(v) != vut.read.end(); bool write_p = vut.written.find(v) != vut.written.end(); if (!read_p && !write_p) continue; @@ -1394,8 +1443,22 @@ void -c_unparser::collect_map_index_types(vector const & vars, - set< pair, exp_type> > & types) +c_unparser::collect_map_index_types_from_syms(vector const & syms, + set< pair, exp_type> > & types) +{ + for (unsigned i = 0; i < syms.size(); ++i) + { + vardecl *v; + if (syms[i]->is_var (v) && v->arity > 0) + { + types.insert(make_pair(v->index_types, v->type)); + } + } +} + +void +c_unparser::collect_map_index_types_from_vars(vector const & vars, + set< pair, exp_type> > & types) { for (unsigned i = 0; i < vars.size(); ++i) { @@ -1467,13 +1530,13 @@ { set< pair, exp_type> > types; - collect_map_index_types(session->globals, types); + collect_map_index_types_from_syms(session->globals, types); for (unsigned i = 0; i < session->probes.size(); ++i) - collect_map_index_types(session->probes[i]->locals, types); + collect_map_index_types_from_vars(session->probes[i]->locals, types); for (unsigned i = 0; i < session->functions.size(); ++i) - collect_map_index_types(session->functions[i]->locals, types); + collect_map_index_types_from_vars(session->functions[i]->locals, types); if (!types.empty()) o->newline() << "#include \"alloc.c\""; @@ -1607,7 +1670,7 @@ void c_unparser_assignment::c_assignop(tmpvar & res, - var const & lval, + sym const & lval, tmpvar const & rval, token const * tok) { @@ -1817,6 +1880,13 @@ } +constsym +c_unparser::getconst(constdecl *c) +{ + return constsym (c->type, c->name, c->value); +} + + var c_unparser::getvar(vardecl *v, token const *tok) { @@ -2094,16 +2164,19 @@ agg.declare(*(this->parent)); symbol *sym = get_symbol_within_expression (hist->stat); - var v = parent->getvar(sym->referent, sym->tok); - if (sym->referent->arity != 0) + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); + var v = parent->getvar(rv, sym->tok); + if (rv->arity != 0) { arrayindex *arr = NULL; if (!expression_is_arrayindex (hist->stat, arr)) throw semantic_error("expected arrayindex expression in iterated hist_op", s->tok); - for (unsigned i=0; ireferent->index_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->gensym (sym->referent->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); } @@ -2123,8 +2196,12 @@ if (array) { visit_statement (s, 1); + + vardecl *rv; + array->referent->is_var (rv); + assert (rv); - mapvar mv = getmap (array->referent, s->tok); + mapvar mv = getmap (rv, s->tok); itervar iv = getiter (array); vector keys; @@ -2188,7 +2265,10 @@ for (unsigned i = 0; i < s->indexes.size(); ++i) { // copy the iter values into the specified locals - var v = getvar (s->indexes[i]->referent); + vardecl* rv; + s->indexes[i]->referent->is_var (rv); + assert (rv); + var v = getvar (rv); c_assign (v, iv.get_key (v.type(), i), s->tok); } s->block->visit (this); @@ -2214,13 +2294,20 @@ // Iterating over buckets in a histogram. assert(s->indexes.size() == 1); assert(s->indexes[0]->referent->type == pe_long); - var bucketvar = getvar (s->indexes[0]->referent); + + vardecl* ri; + s->indexes[0]->referent->is_var (ri); + assert (ri); + var bucketvar = getvar (ri); aggvar agg = gensym_aggregate (); load_aggregate(hist->stat, agg); symbol *sym = get_symbol_within_expression (hist->stat); - var v = getvar(sym->referent, sym->tok); + vardecl* rv; + sym->referent->is_var(rv); + assert(rv); + var v = getvar(rv, sym->tok); v.assert_hist_compatible(*hist); // XXX: break / continue don't work here yet @@ -2292,9 +2379,13 @@ void delete_statement_operand_visitor::visit_symbol (symbol* e) { - if (e->referent->arity > 0) + vardecl *rv; + e->referent->is_var (rv); + assert (rv); + + if (rv->arity > 0) { - mapvar mvar = parent->getmap(e->referent, e->tok); + mapvar mvar = parent->getmap(rv, e->tok); varlock_w guard (*parent, mvar); /* NB: such memory deallocation/allocation operations are not generally legal in all probe contexts. @@ -2308,7 +2399,7 @@ } else { - var v = parent->getvar(e->referent, e->tok); + var v = parent->getvar(rv, e->tok); varlock_w guard (*parent, v); switch (e->type) { @@ -2337,12 +2428,14 @@ if (array) { - vardecl* r = array->referent; + vardecl *rv; + array->referent->is_var (rv); + assert (rv); // One temporary per index dimension. - for (unsigned i=0; iindex_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->parent->gensym (r->index_types[i]); + tmpvar ix = parent->parent->gensym (rv->index_types[i]); ix.declare (*(parent->parent)); e->indexes[i]->visit(parent); } @@ -2366,7 +2459,11 @@ parent->load_map_indices (e, idx); { - mapvar mvar = parent->getmap (array->referent, e->tok); + vardecl *rv; + array->referent->is_var (rv); + assert (rv); + + mapvar mvar = parent->getmap (rv, e->tok); varlock_w guard (*parent, mvar); parent->o->newline() << mvar.del (idx) << ";"; } @@ -2564,12 +2661,14 @@ if (array) { - vardecl* r = array->referent; + vardecl *rv; + array->referent->is_var (rv); + assert (rv); // One temporary per index dimension. - for (unsigned i=0; iindex_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->gensym (r->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); e->operand->indexes[i]->visit(this); } @@ -2610,7 +2709,10 @@ tmpvar res = gensym (pe_long); { // block used to control varlock_r lifespan - mapvar mvar = getmap (array->referent, e->tok); + vardecl *rv; + array->referent->is_var (rv); + assert (rv); + mapvar mvar = getmap (rv, e->tok); varlock_r guard (*this, mvar); c_assign (res, mvar.exists(idx), e->tok); } @@ -2803,13 +2905,21 @@ void c_unparser::visit_symbol (symbol* e) { - vardecl* r = e->referent; + vardecl* rv; - if (r->index_types.size() != 0) - throw semantic_error ("invalid reference to array", e->tok); - - var v = getvar(r, e->tok); - o->line() << v; + if (e->referent->is_var (rv)) + { + if (rv->index_types.size() != 0) + throw semantic_error ("invalid reference to array", e->tok); + o->line() << getvar(rv, e->tok); + } + else + { + constdecl* rc; + e->referent->is_const (rc); + assert (rc); + o->line() << getconst(rc); + } } @@ -2873,9 +2983,11 @@ void c_unparser_assignment::visit_symbol (symbol *e) { + vardecl *rv; + stmt_expr block(*parent); - if (e->referent->index_types.size() != 0) + if (e->referent->is_var (rv) && rv->index_types.size() != 0) throw semantic_error ("unexpected reference to array", e->tok); parent->o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; @@ -2885,11 +2997,20 @@ prepare_rvalue (op, rval, e->tok); - { - var lvar = parent->getvar (e->referent, e->tok); - varlock_w guard (*parent, lvar); - c_assignop (res, lvar, rval, e->tok); - } + if (rv) + { + var lvar = parent->getvar (rv, e->tok); + varlock_w guard (*parent, lvar); + c_assignop (res, lvar, rval, e->tok); + } + else + { + constdecl *rc; + e->referent->is_const (rc); + assert (rc); + constsym lsym = parent->getconst (rc); + c_assignop (res, lsym, rval, e->tok); + } parent->o->newline() << res << ";"; } @@ -2914,18 +3035,20 @@ { idx.clear(); - vardecl* r = array->referent; + vardecl* rv; + array->referent->is_var (rv); + assert (rv); - if (r->index_types.size() == 0 || - r->index_types.size() != e->indexes.size()) + if (rv->index_types.size() == 0 || + rv->index_types.size() != e->indexes.size()) throw semantic_error ("invalid array reference", e->tok); - for (unsigned i=0; iindex_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - if (r->index_types[i] != e->indexes[i]->type) + if (rv->index_types[i] != e->indexes[i]->type) throw semantic_error ("array index type mismatch", e->indexes[i]->tok); - tmpvar ix = gensym (r->index_types[i]); + tmpvar ix = gensym (rv->index_types[i]); o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->indexes[i]->tok) << ";"; c_assign (ix.qname(), e->indexes[i], "array index copy"); @@ -2952,10 +3075,14 @@ if (sym->referent->type != pe_stats) throw semantic_error ("unexpected aggregate of non-statistic", sym->tok); + + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); - var v = getvar(sym->referent, e->tok); + var v = getvar(rv, e->tok); - if (sym->referent->arity == 0) + if (rv->arity == 0) { o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";"; o->newline() << agg << " = _stp_stat_get (" << v << ", 0);"; @@ -2968,7 +3095,7 @@ vector idx; load_map_indices (arr, idx); - mapvar mvar = getmap (sym->referent, sym->tok); + mapvar mvar = getmap (rv, sym->tok); o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";"; o->newline() << agg << " = " << mvar.get(idx, pre_agg) << ";"; } @@ -2992,12 +3119,14 @@ if (array) { - vardecl* r = array->referent; + vardecl* rv; + array->referent->is_var (rv); + assert (rv); // One temporary per index dimension. - for (unsigned i=0; iindex_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->gensym (r->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); e->indexes[i]->visit(this); } @@ -3054,16 +3183,19 @@ agg.declare(*(this->parent)); symbol *sym = get_symbol_within_expression (hist->stat); - var v = parent->getvar(sym->referent, sym->tok); - if (sym->referent->arity != 0) + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); + var v = parent->getvar(rv, sym->tok); + if (rv->arity != 0) { arrayindex *arr = NULL; if (!expression_is_arrayindex (hist->stat, arr)) throw semantic_error("expected arrayindex expression in indexed hist_op", e->tok); - for (unsigned i=0; ireferent->index_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->gensym (sym->referent->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); } @@ -3081,8 +3213,12 @@ if (array) { + vardecl *rv; + array->referent->is_var (rv); + assert (rv); + // Visiting an statistic-valued array in a non-lvalue context is prohibited. - if (array->referent->type == pe_stats) + if (rv->type == pe_stats) throw semantic_error ("statistic-valued array in rvalue context", e->tok); stmt_expr block(*this); @@ -3108,7 +3244,7 @@ // e.g. a[a[c]=5] could deadlock { // block used to control varlock_r lifespan - mapvar mvar = getmap (array->referent, e->tok); + mapvar mvar = getmap (rv, e->tok); o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; varlock_r guard (*this, mvar); c_assign (res, mvar.get(idx), e->tok); @@ -3138,12 +3274,15 @@ assert(idx[0].type() == pe_long); symbol *sym = get_symbol_within_expression (hist->stat); + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); var *v; - if (sym->referent->arity < 1) - v = new var(getvar(sym->referent, e->tok)); + if (rv->arity < 1) + v = new var(getvar(rv, e->tok)); else - v = new mapvar(getmap(sym->referent, e->tok)); + v = new mapvar(getmap(rv, e->tok)); v->assert_hist_compatible(*hist); @@ -3199,12 +3338,14 @@ if (array) { - vardecl* r = array->referent; + vardecl* rv; + array->referent->is_var (rv); + assert (rv); // One temporary per index dimension. - for (unsigned i=0; iindex_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { - tmpvar ix = parent->parent->gensym (r->index_types[i]); + tmpvar ix = parent->parent->gensym (rv->index_types[i]); ix.declare (*(parent->parent)); e->indexes[i]->visit(parent); } @@ -3243,7 +3384,11 @@ translator_output *o = parent->o; - if (array->referent->index_types.size() == 0) + vardecl *rv; + array->referent->is_var (rv); + assert (rv); + + if (rv->index_types.size() == 0) throw semantic_error ("unexpected reference to scalar", e->tok); // nb: Do not adjust the order of the next few lines; the tmpvar @@ -3293,7 +3438,7 @@ assert (e->type == pe_stats); assert (rvalue->type == pe_long); - mapvar mvar = parent->getmap (array->referent, e->tok); + mapvar mvar = parent->getmap (rv, e->tok); o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; // NB: *no need to* varlock_w guard (*parent, mvar); o->newline() << mvar.add (idx, rvar) << ";"; @@ -3304,7 +3449,7 @@ } else { // block used to control varlock_w lifespan - mapvar mvar = parent->getmap (array->referent, e->tok); + mapvar mvar = parent->getmap (rv, e->tok); o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; varlock_w guard (*parent, mvar); if (op != "=") // don't bother fetch slot if we will just overwrite it @@ -3419,21 +3564,24 @@ if (e->hist) { symbol *sym = get_symbol_within_expression (e->hist->stat); - var v = parent->getvar(sym->referent, sym->tok); + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); + var v = parent->getvar(rv, sym->tok); aggvar agg = parent->gensym_aggregate (); agg.declare(*(this->parent)); - if (sym->referent->arity != 0) + if (rv->arity != 0) { // One temporary per index dimension. - for (unsigned i=0; ireferent->index_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { arrayindex *arr = NULL; if (!expression_is_arrayindex (e->hist->stat, arr)) throw semantic_error("expected arrayindex expression in printed hist_op", e->tok); - tmpvar ix = parent->gensym (sym->referent->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); } @@ -3476,11 +3624,14 @@ symbol *sym = get_symbol_within_expression (e->hist->stat); aggvar agg = gensym_aggregate (); + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); var *v; - if (sym->referent->arity < 1) - v = new var(getvar(sym->referent, e->tok)); + if (rv->arity < 1) + v = new var(getvar(rv, e->tok)); else - v = new mapvar(getmap(sym->referent, e->tok)); + v = new mapvar(getmap(rv, e->tok)); v->assert_hist_compatible(*e->hist); @@ -3607,17 +3758,20 @@ c_tmpcounter::visit_stat_op (stat_op* e) { symbol *sym = get_symbol_within_expression (e->stat); - var v = parent->getvar(sym->referent, e->tok); + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); + var v = parent->getvar(rv, e->tok); aggvar agg = parent->gensym_aggregate (); tmpvar res = parent->gensym (pe_long); agg.declare(*(this->parent)); res.declare(*(this->parent)); - if (sym->referent->arity != 0) + if (rv->arity != 0) { // One temporary per index dimension. - for (unsigned i=0; ireferent->index_types.size(); i++) + for (unsigned i=0; iindex_types.size(); i++) { // Sorry about this, but with no dynamic_cast<> and no // constructor patterns, this is how things work. @@ -3625,7 +3779,7 @@ if (!expression_is_arrayindex (e->stat, arr)) throw semantic_error("expected arrayindex expression in stat_op of array", e->tok); - tmpvar ix = parent->gensym (sym->referent->index_types[i]); + tmpvar ix = parent->gensym (rv->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); } @@ -3654,7 +3808,10 @@ symbol *sym = get_symbol_within_expression (e->stat); aggvar agg = gensym_aggregate (); tmpvar res = gensym (pe_long); - var v = getvar(sym->referent, e->tok); + vardecl *rv; + sym->referent->is_var (rv); + assert (rv); + var v = getvar(rv, e->tok); { varlock_w *guard = NULL; if (aggregation_locks.count(v.qname())) @@ -3878,7 +4035,19 @@ for (unsigned i=0; inewline(); - s.up->emit_global (s.globals[i]); + + constdecl* c; + if (s.globals[i]->is_const (c)) + s.up->emit_global_const (c); + } + + for (unsigned i=0; inewline(); + + vardecl* v; + if (s.globals[i]->is_var (v)) + s.up->emit_global_var (v); } for (unsigned i=0; i probes; std::vector aliases; std::vector functions; - std::vector globals; + std::vector globals; std::vector embeds; bool privileged; stapfile (): privileged (false) {} @@ -688,8 +693,8 @@ // the elaboration-time optimizer pass. struct varuse_collecting_visitor: public functioncall_traversing_visitor { - std::set read; - std::set written; + std::set read; + std::set written; bool embedded_seen; expression* current_lvalue; expression* current_lrvalue; --- systemtap-0.5.4/session.h.const 2006-02-13 09:43:43.000000000 +0000 +++ systemtap-0.5.4/session.h 2006-02-13 10:26:20.000000000 +0000 @@ -19,7 +19,7 @@ // forward decls for all referenced systemtap types struct match_node; struct stapfile; -struct vardecl; +struct symboldecl; struct functiondecl; struct derived_probe; struct embeddedcode; @@ -90,7 +90,7 @@ // resolved globals/functions/probes for the run as a whole std::vector files; - std::vector globals; + std::vector globals; std::vector functions; std::vector probes; std::vector embeds; --- systemtap-0.5.4/parse.cxx.const 2006-02-13 07:49:33.000000000 +0000 +++ systemtap-0.5.4/parse.cxx 2006-02-13 07:53:05.000000000 +0000 @@ -697,6 +697,8 @@ parse_probe (f->probes, f->aliases); else if (t->type == tok_identifier && t->content == "global") parse_global (f->globals); + else if (t->type == tok_identifier && t->content == "const") + parse_const (f->globals); else if (t->type == tok_identifier && t->content == "function") parse_functiondecl (f->functions); else if (t->type == tok_embedded) @@ -910,7 +912,7 @@ void -parser::parse_global (vector & globals) +parser::parse_global (vector & globals) { const token* t0 = next (); if (! (t0->type == tok_identifier && t0->content == "global")) @@ -944,6 +946,35 @@ void +parser::parse_const (vector & globals) +{ + const token* t = next (); + if (! (t->type == tok_identifier && t->content == "const")) + throw parse_error ("expected 'const'"); + + t = next (); + if (! (t->type == tok_identifier)) + throw parse_error ("expected identifier"); + + for (unsigned i=0; iname == t->content) + throw parse_error ("duplicate global name"); + + constdecl* d = new constdecl; + d->name = t->content; + d->tok = t; + globals.push_back (d); + + t = next (); + if (!t || ! (t->type == tok_operator && t->content == "=")) + throw ("expected '='"); + + d->value = parse_literal (); + d->type = d->value->type; +} + + +void parser::parse_functiondecl (std::vector& functions) { const token* t = next (); --- systemtap-0.5.4/elaborate.h.const 2006-02-13 09:43:56.000000000 +0000 +++ systemtap-0.5.4/elaborate.h 2006-02-13 11:03:23.000000000 +0000 @@ -33,7 +33,7 @@ derived_probe* current_probe; symresolution_info (systemtap_session& s); - vardecl* find_var (const std::string& name, int arity); + symboldecl* find_symboldecl (const std::string& name, bool writable, int arity); functiondecl* find_function (const std::string& name, unsigned arity); void visit_block (block *s); --- systemtap-0.5.4/elaborate.cxx.const 2006-02-13 07:50:12.000000000 +0000 +++ systemtap-0.5.4/elaborate.cxx 2006-02-13 11:04:16.000000000 +0000 @@ -517,9 +517,14 @@ { if (e->type == pe_stats && e->op == "<<<") { - vardecl *vd = get_symbol_within_expression (e->left)->referent; - if (vd) - mutated_vars->insert (vd); + symboldecl *sd = get_symbol_within_expression (e->left)->referent; + if (sd) + { + vardecl *vd; + sd->is_var (vd); + assert (vd); + mutated_vars->insert (vd); + } } traversing_visitor::visit_assignment(e); } @@ -530,7 +535,12 @@ { symbol *sym; if (e->base->is_symbol (sym)) - mutated_vars->insert (sym->referent); + { + vardecl *vd; + sym->referent->is_var (vd); + assert (vd); + mutated_vars->insert (vd); + } else throw semantic_error("Assignment to read-only histogram bucket", e->tok); } @@ -556,9 +566,12 @@ { if (is_active_lvalue(e)) { - vardecl *vd = get_symbol_within_indexable (e->base)->referent; - if (vd) + symboldecl *sd = get_symbol_within_indexable (e->base)->referent; + if (sd) { + vardecl *vd; + sd->is_var (vd); + assert (vd); for (unsigned i = 0; i < vars_being_iterated.size(); ++i) { vardecl *v = vars_being_iterated[i]; @@ -598,14 +611,19 @@ void visit_foreach_loop(foreach_loop* s) { - vardecl *vd = get_symbol_within_indexable (s->base)->referent; + symboldecl *sd = get_symbol_within_indexable (s->base)->referent; - if (vd) - vars_being_iterated.push_back (vd); + if (sd) + { + vardecl *vd; + sd->is_var (vd); + assert (vd); + vars_being_iterated.push_back (vd); + } traversing_visitor::visit_foreach_loop (s); - if (vd) + if (sd) vars_being_iterated.pop_back(); } }; @@ -732,10 +750,9 @@ for (unsigned i = 0; i < sess.globals.size(); ++i) { - vardecl *v = sess.globals[i]; - if (v->type == pe_stats) + vardecl *v; + if (sess.globals[i]->is_var (v) && v->type == pe_stats) { - if (sess.stat_decls.find(v->name) == sess.stat_decls.end()) { semantic_error se("unable to infer statistic parameters for global '" + v->name + "'"); @@ -931,7 +948,7 @@ { if (!array->referent) { - vardecl* d = find_var (array->name, e->indexes.size ()); + symboldecl* d = find_symboldecl (array->name, true, e->indexes.size ()); if (d) array->referent = d; else @@ -972,7 +989,7 @@ if (e->referent) return; - vardecl* d = parent->find_var (e->name, -1); + symboldecl* d = parent->find_symboldecl (e->name, true, -1); if (d) e->referent = d; else @@ -994,7 +1011,7 @@ if (e->referent) return; - vardecl* d = find_var (e->name, 0); + symboldecl* d = find_symboldecl (e->name, is_active_lvalue (e), 0); if (d) e->referent = d; else @@ -1030,7 +1047,7 @@ if (array->referent) return; - vardecl* d = find_var (array->name, e->indexes.size ()); + symboldecl* d = find_symboldecl (array->name, true, e->indexes.size ()); if (d) array->referent = d; else @@ -1075,8 +1092,8 @@ } -vardecl* -symresolution_info::find_var (const string& name, int arity) +symboldecl* +symresolution_info::find_symboldecl (const string& name, bool writable, int arity) { // search locals @@ -1105,11 +1122,21 @@ // search processed globals for (unsigned i=0; iname == name - && session.globals[i]->compatible_arity(arity)) + if (session.globals[i]->name == name) { - session.globals[i]->set_arity (arity); - return session.globals[i]; + vardecl *v; + if (session.globals[i]->is_var (v)) + { + if (v->compatible_arity (arity)) + { + v->set_arity (arity); + return v; + } + } + else if (!writable) + { + return session.globals[i]; + } } // search library globals @@ -1118,17 +1145,31 @@ stapfile* f = session.library_files[i]; for (unsigned j=0; jglobals.size(); j++) { - vardecl* g = f->globals[j]; - if (g->name == name && g->compatible_arity (arity)) + if (f->globals[j]->name == name) { - g->set_arity (arity); + vardecl *g; + if (f->globals[j]->is_var (g)) + { + if (g->compatible_arity (arity)) + { + g->set_arity (arity); + } + else + { + continue; + } + } + else if (writable) + { + continue; + } // put library into the queue if not already there if (find (session.files.begin(), session.files.end(), f) == session.files.end()) session.files.push_back (f); - return g; + return f->globals[j]; } } } @@ -1260,12 +1301,12 @@ } for (unsigned i=0; i2) - clog << "Eliding unused global variable " + clog << "Eliding unused global symbol " << l->name << endl; s.globals.erase(s.globals.begin() + i); relaxed_p = false; @@ -1311,15 +1352,14 @@ void dead_assignment_remover::visit_assignment (assignment* e) { - symbol* left = get_symbol_within_expression (e->left); - vardecl* leftvar = left->referent; if (*current_expr == e) // we're not nested any deeper than expected { - // clog << "Checking assignment to " << leftvar->name << " at " << *e->tok << endl; - if (vut.read.find(leftvar) == vut.read.end()) // var never read? + symboldecl* leftsym = get_symbol_within_expression (e->left)->referent; + // clog << "Checking assignment to " << leftsym->name << " at " << *e->tok << endl; + if (vut.read.find(leftsym) == vut.read.end()) // var never read? { if (session.verbose>2) - clog << "Eliding assignment to " << leftvar->name + clog << "Eliding assignment to " << leftsym->name << " at " << *e->tok << endl; *current_expr = e->right; // goodbye assignment* relaxed_p = false; @@ -1515,7 +1555,7 @@ for (unsigned j=0; jtype == pe_unknown) ti.unresolved (gd->tok); } @@ -1909,18 +1949,22 @@ assert (array->referent != 0); resolve_2types (e, array->referent, this, t); + vardecl *arraydecl; + array->referent->is_var (arraydecl); + assert (arraydecl); + // now resolve the array indexes - // if (e->referent->index_types.size() == 0) + // if (arraydecl->index_types.size() == 0) // // redesignate referent as array - // e->referent->set_arity (e->indexes.size ()); + // arraydecl->set_arity (e->indexes.size ()); - if (e->indexes.size() != array->referent->index_types.size()) + if (e->indexes.size() != arraydecl->index_types.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; iindexes.size(); i++) { expression* ee = e->indexes[i]; - exp_type& ft = array->referent->index_types [i]; + exp_type& ft = arraydecl->index_types [i]; t = ft; ee->visit (this); exp_type at = ee->type; @@ -1929,7 +1973,7 @@ { // propagate to formal type ft = at; - resolved (array->referent->tok, ft); + resolved (arraydecl->tok, ft); // uses array decl as there is no token for "formal type" } if (at == pe_stats) @@ -2069,13 +2113,16 @@ } else { - assert (array); - if (e->indexes.size() != array->referent->index_types.size()) + vardecl *arraydecl; + assert (array); + array->referent->is_var (arraydecl); + assert (arraydecl); + if (e->indexes.size() != arraydecl->index_types.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; iindexes.size(); i++) { expression* ee = e->indexes[i]; - exp_type& ft = array->referent->index_types [i]; + exp_type& ft = arraydecl->index_types [i]; t = ft; ee->visit (this); exp_type at = ee->type; @@ -2084,7 +2131,7 @@ { // propagate to formal type ft = at; - resolved (array->referent->tok, ft); + resolved (arraydecl->tok, ft); // uses array decl as there is no token for "formal type" } if (at == pe_stats) --- systemtap-0.5.4/main.cxx.const 2006-02-13 07:49:21.000000000 +0000 +++ systemtap-0.5.4/main.cxx 2006-02-13 10:59:19.000000000 +0000 @@ -418,11 +418,34 @@ if (rc == 0 && s.last_pass == 2) { - if (s.globals.size() > 0) - cout << "# globals" << endl; + bool print_header; + + print_header = true; + for (unsigned i=0; iis_const (c)) + continue; + if (print_header) + { + cout << "# constants" << endl; + print_header = false; + } + c->printsig (cout); + cout << endl; + } + + print_header = true; for (unsigned i=0; iis_var (v)) + continue; + if (print_header) + { + cout << "# globals" << endl; + print_header = false; + } v->printsig (cout); cout << endl; } @@ -480,7 +503,7 @@ if (s.verbose) clog << "Pass 2: analyzed script: " << s.probes.size() << " probe(s), " << s.functions.size() << " function(s), " - << s.globals.size() << " global(s) in " + << s.globals.size() << " global symbol(s) in " << TIMESPRINT << endl;