This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]