This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Global constants
- From: Mark McLoughlin <markmc at redhat dot com>
- To: systemtap at sourceware dot org
- Date: Mon, 13 Feb 2006 17:38:51 +0000
- Subject: Global constants
Hi,
Trying out systemtap, I found myself doing the likes of:
---
global O_CREAT
probe begin {
O_CREAT = 64
}
probe kernel.function ("sys_open") {
if ($flags & O_CREAT) {
printf ("foo\n");
}
}
---
Then I thought it might be handy to have these kind of globals defined
in the system tapsets so I patched stap with:
---
o->newline() << "static rwlock_t "
<< "global_" << c_varname (v->name) << "_lock;";
+ o->newline() << "#define global_"
+ << c_varname(v->name) << "_DEFINED 1";
---
and put the likes of this in the system tapsets:
---
global O_CREAT
function init_sys_open_flags () %{
#ifdef global_O_CREAT_DEFINED
global_O_CREAT = 64;
#endif
%}
probe begin {
init_sys_open_flags ();
}
---
But then I thought that perhaps support for global constants like this
in the language wouldn't be such a bad idea, so you could just do:
---
const O_CREAT = 64
probe kernel.function ("sys_open") {
if ($flags & O_CREAT) {
printf ("foo\n");
}
}
---
Attached is a patch which implements this. The patch still needs closer
review, a bit of tidying up, perhaps some more optimisations for
constants, test cases for it in the test suite etc. but it does
basically seem to work. I thought I'd send it here for comments before
finishing it off.
So, thoughts?
Thanks,
Mark
--- 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<probe*>&, std::vector<probe_alias*>&);
- void parse_global (std::vector<vardecl*>&);
+ void parse_global (std::vector<symboldecl*>&);
+ void parse_const (std::vector<symboldecl*>&);
void parse_functiondecl (std::vector<functiondecl*>&);
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<component*> 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; i<globals.size(); i++)
{
- o << "global ";
+ constdecl *c;
+ if (globals[i]->is_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<vardecl* > const & vars,
- set< pair<vector<exp_type>, exp_type> > & types);
+ void collect_map_index_types_from_syms(vector<symboldecl* > const & syms,
+ set< pair<vector<exp_type>, exp_type> > & types);
+ void collect_map_index_types_from_vars(vector<vardecl* > const & vars,
+ set< pair<vector<exp_type>, 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; i<session->globals.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; i<session->globals.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; i<session->globals.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<vardecl *> const & vars,
- set< pair<vector<exp_type>, exp_type> > & types)
+c_unparser::collect_map_index_types_from_syms(vector<symboldecl *> const & syms,
+ set< pair<vector<exp_type>, 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<vardecl *> const & vars,
+ set< pair<vector<exp_type>, exp_type> > & types)
{
for (unsigned i = 0; i < vars.size(); ++i)
{
@@ -1467,13 +1530,13 @@
{
set< pair<vector<exp_type>, 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; i<sym->referent->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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<var> 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; i<r->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<r->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<r->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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<tmpvar> 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; i<r->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<sym->referent->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<r->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<sym->referent->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<sym->referent->index_types.size(); i++)
+ for (unsigned i=0; i<rv->index_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; i<s.globals.size(); i++)
{
s.op->newline();
- 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; i<s.globals.size(); i++)
+ {
+ s.op->newline();
+
+ vardecl* v;
+ if (s.globals[i]->is_var (v))
+ s.up->emit_global_var (v);
}
for (unsigned i=0; i<s.functions.size(); i++)
--- systemtap-0.5.4/translate.h.const 2006-02-13 09:44:11.000000000 +0000
+++ systemtap-0.5.4/translate.h 2006-02-13 16:02:24.000000000 +0000
@@ -66,7 +66,10 @@
// } locals [MAXNESTING];
// } context [MAXCONCURRENCY];
- virtual void emit_global (vardecl* v) = 0;
+ virtual void emit_global_const (constdecl* v) = 0;
+ // #define const_NAME VALUE;
+
+ virtual void emit_global_var (vardecl* v) = 0;
// static TYPE global_NAME;
// static rwlock_t global_NAME_lock;
--- systemtap-0.5.4/staptree.h.const 2006-02-13 07:50:36.000000000 +0000
+++ systemtap-0.5.4/staptree.h 2006-02-13 11:00:02.000000000 +0000
@@ -181,12 +181,10 @@
// This is a helper class which, type-wise, acts as a disjoint union
// of symbols and histograms. You can ask it whether it's a
// histogram or a symbol, and downcast accordingly.
- void print_indexable (std::ostream& o) const;
+ void print_indexable (std::ostream& o);
void visit_indexable (visitor* u);
virtual bool is_symbol(symbol *& sym_out);
virtual bool is_hist_op(hist_op *& hist_out);
- virtual bool is_const_symbol(const symbol *& sym_out) const;
- virtual bool is_const_hist_op(const hist_op *& hist_out) const;
virtual const token *get_tok() const = 0;
virtual ~indexable() {}
};
@@ -199,24 +197,18 @@
symbol *& array_out,
hist_op *& hist_out);
-void
-classify_const_indexable(const indexable* ix,
- symbol const *& array_out,
- hist_op const *& hist_out);
-
class vardecl;
struct symbol:
public expression,
public indexable
{
std::string name;
- vardecl *referent;
+ symboldecl *referent;
symbol ();
void print (std::ostream& o) const;
void visit (visitor* u);
// overrides of type 'indexable'
const token *get_tok() const;
- bool is_const_symbol(const symbol *& sym_out) const;
bool is_symbol(symbol *& sym_out);
};
@@ -358,13 +350,13 @@
void visit (visitor* u);
// overrides of type 'indexable'
const token *get_tok() const;
- bool is_const_hist_op(const hist_op *& hist_out) const;
bool is_hist_op(hist_op *& hist_out);
};
// ------------------------------------------------------------------------
+class constdecl;
struct symboldecl // unique object per (possibly implicit)
// symbol declaration
{
@@ -375,6 +367,8 @@
virtual ~symboldecl ();
virtual void print (std::ostream &o) const = 0;
virtual void printsig (std::ostream &o) const = 0;
+ virtual bool is_var(vardecl *& var_out);
+ virtual bool is_const(constdecl *& const_out);
};
@@ -385,6 +379,7 @@
{
void print (std::ostream& o) const;
void printsig (std::ostream& o) const;
+ bool is_var(vardecl *& var_out);
vardecl ();
void set_arity (int arity);
bool compatible_arity (int a);
@@ -398,6 +393,16 @@
};
+struct constdecl: public symboldecl
+{
+ void print (std::ostream& o) const;
+ void printsig (std::ostream& o) const;
+ bool is_const(constdecl *& const_out);
+ constdecl ();
+ literal* value;
+};
+
+
struct statement;
struct functiondecl: public symboldecl
{
@@ -536,7 +541,7 @@
std::vector<probe*> probes;
std::vector<probe_alias*> aliases;
std::vector<functiondecl*> functions;
- std::vector<vardecl*> globals;
+ std::vector<symboldecl*> globals;
std::vector<embeddedcode*> 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<vardecl*> read;
- std::set<vardecl*> written;
+ std::set<symboldecl*> read;
+ std::set<symboldecl*> 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<stapfile*> files;
- std::vector<vardecl*> globals;
+ std::vector<symboldecl*> globals;
std::vector<functiondecl*> functions;
std::vector<derived_probe*> probes;
std::vector<embeddedcode*> 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 <vardecl*>& globals)
+parser::parse_global (vector <symboldecl*>& globals)
{
const token* t0 = next ();
if (! (t0->type == tok_identifier && t0->content == "global"))
@@ -944,6 +946,35 @@
void
+parser::parse_const (vector <symboldecl*>& 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; i<globals.size(); i++)
+ if (globals[i]->name == 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<functiondecl*>& 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; i<session.globals.size(); i++)
- if (session.globals[i]->name == 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; j<f->globals.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; i<s.globals.size(); /* see below */)
{
- vardecl* l = s.globals[i];
+ symboldecl* l = s.globals[i];
if (vut.read.find (l) == vut.read.end() &&
vut.written.find (l) == vut.written.end())
{
if (s.verbose>2)
- 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; j<s.globals.size(); j++)
{
- vardecl* gd = s.globals[j];
+ symboldecl* gd = s.globals[j];
if (gd->type == 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; i<e->indexes.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; i<e->indexes.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; i<s.globals.size(); i++)
+ {
+ constdecl* c;
+ if (!s.globals[i]->is_const (c))
+ continue;
+ if (print_header)
+ {
+ cout << "# constants" << endl;
+ print_header = false;
+ }
+ c->printsig (cout);
+ cout << endl;
+ }
+
+ print_header = true;
for (unsigned i=0; i<s.globals.size(); i++)
{
- vardecl* v = s.globals[i];
+ vardecl* v;
+ if (!s.globals[i]->is_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;