LTP GCOV extension - code coverage report
Current view: directory - src - elaborate.cxx
Test: stap.info
Date: 2008-03-12 Instrumented lines: 1382
Code covered: 91.4 % Executed lines: 1263

       1                 : // elaboration functions
       2                 : // Copyright (C) 2005-2008 Red Hat Inc.
       3                 : //
       4                 : // This file is part of systemtap, and is free software.  You can
       5                 : // redistribute it and/or modify it under the terms of the GNU General
       6                 : // Public License (GPL); either version 2, or (at your option) any
       7                 : // later version.
       8                 : 
       9                 : #include "config.h"
      10                 : #include "elaborate.h"
      11                 : #include "parse.h"
      12                 : #include "tapsets.h"
      13                 : #include "session.h"
      14                 : #include "util.h"
      15                 : 
      16                 : extern "C" {
      17                 : #include <sys/utsname.h>
      18                 : #include <fnmatch.h>
      19                 : }
      20                 : 
      21                 : #include <algorithm>
      22                 : #include <fstream>
      23                 : #include <map>
      24                 : #include <cassert>
      25                 : #include <set>
      26                 : #include <vector>
      27                 : #include <algorithm>
      28                 : #include <iterator>
      29                 : 
      30                 : 
      31                 : using namespace std;
      32                 : 
      33                 : 
      34                 : // ------------------------------------------------------------------------
      35                 : 
      36                 : // Used in probe_point condition construction.  Either argument may be
      37                 : // NULL; if both, return NULL too.  Resulting expression is a deep
      38                 : // copy for symbol resolution purposes.
      39           55607 : expression* add_condition (expression* a, expression* b)
      40                 : {
      41           55607 :   if (!a && !b) return 0;
      42              10 :   if (! a) return deep_copy_visitor::deep_copy(b);
      43              10 :   if (! b) return deep_copy_visitor::deep_copy(a);
      44              10 :   logical_and_expr la;
      45              10 :   la.op = "&&";
      46              10 :   la.left = a;
      47              10 :   la.right = b;
      48              10 :   la.tok = a->tok; // or could be b->tok
      49              10 :   return deep_copy_visitor::deep_copy(& la);
      50                 : }
      51                 : 
      52                 : // ------------------------------------------------------------------------
      53                 : 
      54                 : 
      55                 : 
      56               0 : derived_probe::derived_probe (probe *p):
      57               0 :   base (p)
      58                 : {
      59               0 :   assert (p);
      60               0 :   this->locations = p->locations;
      61               0 :   this->tok = p->tok;
      62               0 :   this->privileged = p->privileged;
      63               0 :   this->body = deep_copy_visitor::deep_copy(p->body);
      64               0 : }
      65                 : 
      66                 : 
      67          529755 : derived_probe::derived_probe (probe *p, probe_point *l):
      68          529755 :   base (p)
      69                 : {
      70          529755 :   assert (p);
      71          529755 :   this->tok = p->tok;
      72          529755 :   this->privileged = p->privileged;
      73          529755 :   this->body = deep_copy_visitor::deep_copy(p->body);
      74                 : 
      75          529755 :   assert (l);
      76          529755 :   this->locations.push_back (l);
      77          529755 : }
      78                 : 
      79                 : 
      80                 : void
      81           50469 : derived_probe::printsig (ostream& o) const
      82                 : {
      83           50469 :   probe::printsig (o);
      84           50469 :   printsig_nested (o);
      85           50469 : }
      86                 : 
      87                 : void
      88          537633 : derived_probe::printsig_nested (ostream& o) const
      89                 : {
      90                 :   // We'd like to enclose the probe derivation chain in a /* */
      91                 :   // comment delimiter.  But just printing /* base->printsig() */ is
      92                 :   // not enough, since base might itself be a derived_probe.  So we,
      93                 :   // er, "cleverly" encode our nesting state as a formatting flag for
      94                 :   // the ostream.
      95          537633 :   ios::fmtflags f = o.flags (ios::internal);
      96          537633 :   if (f & ios::internal)
      97                 :     {
      98                 :       // already nested
      99           49107 :       o << " <- ";
     100           49107 :       base->printsig (o);
     101                 :     }
     102                 :   else
     103                 :     {
     104                 :       // outermost nesting
     105          488526 :       o << " /* <- ";
     106          488526 :       base->printsig (o);
     107          488526 :       o << " */";
     108                 :     }
     109                 :   // restore flags
     110          537633 :   (void) o.flags (f);
     111          537633 : }
     112                 : 
     113                 : 
     114                 : void
     115             653 : derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list)
     116                 : {
     117             653 :   probes_list.push_back(this);
     118             653 :   base->collect_derivation_chain(probes_list);
     119             653 : }
     120                 : 
     121                 : 
     122                 : probe_point*
     123         3791612 : derived_probe::sole_location () const
     124                 : {
     125         3791612 :   if (locations.size() == 0)
     126               0 :     throw semantic_error ("derived_probe with no locations", this->tok);
     127         3791612 :   else if (locations.size() > 1)
     128               0 :     throw semantic_error ("derived_probe with too many locations", this->tok);
     129                 :   else 
     130         3791612 :     return locations[0];
     131                 : }
     132                 : 
     133                 : 
     134                 : 
     135                 : // ------------------------------------------------------------------------
     136                 : // Members of derived_probe_builder
     137                 : 
     138                 : bool
     139                 : derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
     140                 :                                   const std::string& key,
     141          109798 :                                   std::string& value)
     142                 : {
     143          109798 :   map<string, literal *>::const_iterator i = params.find (key);
     144          109798 :   if (i == params.end())
     145           54600 :     return false;
     146           55198 :   literal_string * ls = dynamic_cast<literal_string *>(i->second);
     147           55198 :   if (!ls)
     148               9 :     return false;
     149           55189 :   value = ls->value;
     150           55189 :   return true;
     151                 : }
     152                 : 
     153                 : 
     154                 : bool
     155                 : derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
     156                 :                                   const std::string& key,
     157          165576 :                                   int64_t& value)
     158                 : {
     159          165576 :   map<string, literal *>::const_iterator i = params.find (key);
     160          165576 :   if (i == params.end())
     161          109564 :     return false;
     162           56012 :   if (i->second == NULL)
     163            1258 :     return false;
     164           54754 :   literal_number * ln = dynamic_cast<literal_number *>(i->second);
     165           54754 :   if (!ln)
     166           54594 :     return false;
     167             160 :   value = ln->value;
     168             160 :   return true;
     169                 : }
     170                 : 
     171                 : 
     172                 : bool
     173                 : derived_probe_builder::has_null_param (std::map<std::string, literal*> const & params,
     174          272995 :                                        const std::string& key)
     175                 : {
     176          272995 :   map<string, literal *>::const_iterator i = params.find(key);
     177          272995 :   return (i != params.end() && i->second == NULL);
     178                 : }
     179                 : 
     180                 : 
     181                 : 
     182                 : // ------------------------------------------------------------------------
     183                 : // Members of match_key.
     184                 : 
     185         1459940 : match_key::match_key(string const & n) 
     186                 :   : name(n), 
     187                 :     have_parameter(false), 
     188         1459940 :     parameter_type(pe_unknown)
     189                 : {
     190         1459940 : }
     191                 : 
     192          159230 : match_key::match_key(probe_point::component const & c)
     193                 :   : name(c.functor),
     194                 :     have_parameter(c.arg != NULL),
     195          159230 :     parameter_type(c.arg ? c.arg->type : pe_unknown)
     196                 : {
     197          159230 : }
     198                 : 
     199                 : match_key &
     200           21340 : match_key::with_number() 
     201                 : {
     202           21340 :   have_parameter = true;
     203           21340 :   parameter_type = pe_long;
     204           21340 :   return *this;
     205                 : }
     206                 : 
     207                 : match_key &
     208            5335 : match_key::with_string() 
     209                 : {
     210            5335 :   have_parameter = true;
     211            5335 :   parameter_type = pe_string;
     212            5335 :   return *this;
     213                 : }
     214                 : 
     215                 : string 
     216             553 : match_key::str() const
     217                 : {
     218             553 :   if (have_parameter)
     219              74 :     switch (parameter_type)
     220                 :       {
     221              24 :       case pe_string: return name + "(string)";
     222              50 :       case pe_long: return name + "(number)";
     223               0 :       default: return name + "(...)";
     224                 :       }
     225             479 :   return name;
     226                 : }
     227                 : 
     228                 : bool 
     229        11070226 : match_key::operator<(match_key const & other) const
     230                 : {
     231                 :   return ((name < other.name)
     232                 :           
     233                 :           || (name == other.name 
     234                 :               && have_parameter < other.have_parameter)
     235                 :           
     236                 :           || (name == other.name 
     237                 :               && have_parameter == other.have_parameter 
     238        11070226 :               && parameter_type < other.parameter_type));
     239                 : }
     240                 : 
     241                 : static bool
     242          159230 : isglob(string const & str)
     243                 : {
     244          159230 :   return(str.find('*') != str.npos);
     245                 : }
     246                 : 
     247                 : bool
     248           41431 : match_key::globmatch(match_key const & other) const
     249                 : {
     250           41431 :   const char *other_str = other.name.c_str();
     251           41431 :   const char *name_str = name.c_str();
     252                 : 
     253                 :   return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0)
     254                 :           && have_parameter == other.have_parameter 
     255           41431 :           && parameter_type == other.parameter_type);
     256                 : }
     257                 : 
     258                 : // ------------------------------------------------------------------------
     259                 : // Members of match_node
     260                 : // ------------------------------------------------------------------------
     261                 : 
     262          569578 : match_node::match_node()
     263          569578 :   : end(NULL)
     264          569578 : {}
     265                 : 
     266                 : match_node *
     267         1459940 : match_node::bind(match_key const & k) 
     268                 : {
     269         1459940 :   if (k.name == "*")
     270               1 :     throw semantic_error("invalid use of wildcard probe point component");
     271                 : 
     272         1459939 :   map<match_key, match_node *>::const_iterator i = sub.find(k);
     273         1459939 :   if (i != sub.end())
     274          891455 :     return i->second;
     275          568484 :   match_node * n = new match_node();
     276         1136968 :   sub.insert(make_pair(k, n));
     277          568484 :   return n;
     278                 : }
     279                 : 
     280                 : void 
     281          545192 : match_node::bind(derived_probe_builder * e)
     282                 : {
     283          545192 :   if (end)
     284               0 :     throw semantic_error("duplicate probe point pattern");
     285          545192 :   end = e;
     286          545192 : }
     287                 : 
     288                 : match_node * 
     289         1433265 : match_node::bind(string const & k)
     290                 : {
     291         1433265 :   return bind(match_key(k));
     292                 : }
     293                 : 
     294                 : match_node *
     295            5335 : match_node::bind_str(string const & k)
     296                 : {
     297            5335 :   return bind(match_key(k).with_string());
     298                 : }
     299                 : 
     300                 : match_node * 
     301           21340 : match_node::bind_num(string const & k)
     302                 : {
     303           21340 :   return bind(match_key(k).with_number());
     304                 : }
     305                 : 
     306                 : 
     307                 : void
     308                 : match_node::find_and_build (systemtap_session& s,
     309                 :                             probe* p, probe_point *loc, unsigned pos,
     310          256292 :                             vector<derived_probe *>& results)
     311                 : {
     312          256292 :   assert (pos <= loc->components.size());
     313          256292 :   if (pos == loc->components.size()) // matched all probe point components so far 
     314                 :     {
     315           97062 :       derived_probe_builder *b = end; // may be 0 if only nested names are bound
     316                 : 
     317           97062 :       if (! b)
     318                 :         {
     319              77 :           string alternatives;
     320             205 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
     321             128 :             alternatives += string(" ") + i->first.str();
     322                 : 
     323                 :           throw semantic_error (string("probe point truncated at position ") + 
     324                 :                                 lex_cast<string> (pos) +
     325              77 :                                 " (follow:" + alternatives + ")");
     326                 :         }
     327                 : 
     328           96985 :       map<string, literal *> param_map;
     329          336703 :       for (unsigned i=0; i<pos; i++)
     330          239718 :         param_map[loc->components[i]->functor] = loc->components[i]->arg;
     331                 :       // maybe 0
     332                 : 
     333           96985 :       b->build (s, p, loc, param_map, results);
     334                 :     }
     335          159230 :   else if (isglob(loc->components[pos]->functor)) // wildcard?
     336                 :     {
     337             465 :       match_key match (* loc->components[pos]);
     338                 : 
     339                 :       // Call find_and_build for each possible match.  Ignore errors -
     340                 :       // unless we don't find any match.
     341             465 :       unsigned int num_results = results.size();
     342           41896 :       for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
     343                 :         {
     344           41431 :           const match_key& subkey = i->first;
     345           41431 :           match_node* subnode = i->second;
     346                 : 
     347           41431 :           if (pending_interrupts) break;
     348                 : 
     349           41431 :           if (match.globmatch(subkey))
     350                 :             {
     351           40868 :               if (s.verbose > 2)
     352                 :                 clog << "wildcard '" << loc->components[pos]->functor
     353               0 :                      << "' matched '" << subkey.name << "'" << endl;
     354                 : 
     355                 :               // When we have a wildcard, we need to create a copy of
     356                 :               // the probe point.  Then we'll create a copy of the
     357                 :               // wildcard component, and substitute the non-wildcard
     358                 :               // functor.
     359           40868 :               probe_point *non_wildcard_pp = new probe_point(*loc);
     360                 :               probe_point::component *non_wildcard_component
     361           81736 :                 = new probe_point::component(*loc->components[pos]);
     362           40868 :               non_wildcard_component->functor = subkey.name;
     363           40868 :               non_wildcard_pp->components[pos] = non_wildcard_component;
     364                 : 
     365                 :               // NB: probe conditions are not attached at the wildcard
     366                 :               // (component/functor) level, but at the overall
     367                 :               // probe_point level.
     368                 : 
     369                 :               // recurse (with the non-wildcard probe point)
     370                 :               try
     371                 :                 {
     372                 :                   subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
     373           40868 :                                            results);
     374                 :                 }
     375             510 :               catch (const semantic_error& e)
     376                 :                 {
     377                 :                   // Ignore semantic_errors while expanding wildcards.
     378                 :                   // If we get done and nothing was expanded, the code
     379                 :                   // following the loop will complain.
     380                 : 
     381                 :                   // If this wildcard didn't match, cleanup.
     382             255 :                   delete non_wildcard_pp;
     383             255 :                   delete non_wildcard_component;
     384                 :                 }
     385                 :             }
     386                 :         }
     387             465 :       if (! loc->optional && num_results == results.size())
     388                 :         {
     389                 :           // We didn't find any wildcard matches (since the size of
     390                 :           // the result vector didn't change).  Throw an error.
     391              63 :           string alternatives;
     392              82 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
     393              19 :             alternatives += string(" ") + i->first.str();
     394                 :           
     395                 :           throw semantic_error(string("probe point mismatch at position ") +
     396                 :                                lex_cast<string> (pos) +
     397              63 :                                " (alternatives:" + alternatives + ")");
     398             402 :         }
     399                 :     }
     400                 :   else 
     401                 :     {
     402          158765 :       match_key match (* loc->components[pos]);
     403          158765 :       sub_map_iterator_t i = sub.find (match);
     404          158765 :       if (i == sub.end()) // no match
     405                 :         {
     406             139 :           string alternatives;
     407             545 :           for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
     408             406 :             alternatives += string(" ") + i->first.str();
     409                 :           
     410                 :           throw semantic_error (string("probe point mismatch at position ") + 
     411                 :                                 lex_cast<string> (pos) +
     412             139 :                                 " (alternatives:" + alternatives + ")");
     413                 :         }
     414                 : 
     415          158626 :       match_node* subnode = i->second;
     416                 :       // recurse
     417          158626 :       subnode->find_and_build (s, p, loc, pos+1, results);
     418                 :     }
     419          255961 : }
     420                 : 
     421                 : 
     422                 : void
     423          567796 : match_node::build_no_more (systemtap_session& s)
     424                 : {
     425         1135108 :   for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
     426          567312 :     i->second->build_no_more (s);
     427          567796 :   if (end) end->build_no_more (s);
     428          567796 : }
     429                 : 
     430                 : 
     431                 : // ------------------------------------------------------------------------
     432                 : // Alias probes
     433                 : // ------------------------------------------------------------------------
     434                 : 
     435                 : struct alias_derived_probe: public derived_probe
     436               0 : {
     437           40971 :   alias_derived_probe (probe* base, probe_point *l, const probe_alias *a):
     438           40971 :     derived_probe (base, l), alias(a) {}
     439                 : 
     440               0 :   void upchuck () { throw semantic_error ("inappropriate", this->tok); }
     441                 : 
     442                 :   // Alias probes are immediately expanded to other derived_probe
     443                 :   // types, and are not themselves emitted or listed in
     444                 :   // systemtap_session.probes
     445                 : 
     446               0 :   void join_group (systemtap_session&) { upchuck (); }
     447                 : 
     448             814 :   virtual const probe_alias *get_alias () const { return alias; }
     449                 : 
     450                 : private:
     451                 :   const probe_alias *alias; // Used to check for recursion
     452                 : };
     453                 : 
     454                 : 
     455                 : struct
     456                 : alias_expansion_builder 
     457                 :   : public derived_probe_builder
     458               0 : {
     459                 :   probe_alias * alias;
     460                 : 
     461          515607 :   alias_expansion_builder(probe_alias * a) 
     462          515607 :     : alias(a)
     463          515607 :   {}
     464                 : 
     465                 :   virtual void build(systemtap_session & sess,
     466                 :                      probe * use, 
     467                 :                      probe_point * location,
     468                 :                      std::map<std::string, literal *> const &,
     469           40973 :                      vector<derived_probe *> & finished_results)
     470                 :   {
     471                 :     // Don't build the alias expansion if infinite recursion is detected.
     472           40973 :     if (checkForRecursiveExpansion (use)) {
     473               2 :       stringstream msg;
     474               2 :       msg << "Recursive loop in alias expansion of " << *location  << " at " << location->tok->location;
     475                 :       // semantic_errors thrown here are ignored.
     476               2 :       sess.print_error (semantic_error (msg.str()));
     477               2 :       return;
     478                 :     }
     479                 : 
     480                 :     // We're going to build a new probe and wrap it up in an
     481                 :     // alias_expansion_probe so that the expansion loop recognizes it as
     482                 :     // such and re-expands its expansion.
     483                 :     
     484           40971 :     alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias);
     485           81942 :     n->body = new block();
     486                 : 
     487                 :     // The new probe gets the location list of the alias (with incoming condition joined)
     488           40971 :     n->locations = alias->locations;
     489           96578 :     for (unsigned i=0; i<n->locations.size(); i++)
     490                 :       n->locations[i]->condition = add_condition (n->locations[i]->condition,
     491           55607 :                                                   location->condition);
     492                 : 
     493                 :     // the token location of the alias,
     494           40971 :     n->tok = location->tok;
     495           40971 :     n->body->tok = location->tok;
     496                 : 
     497                 :     // and statements representing the concatenation of the alias'
     498                 :     // body with the use's. 
     499                 :     //
     500                 :     // NB: locals are *not* copied forward, from either alias or
     501                 :     // use. The expansion should have its locals re-inferred since
     502                 :     // there's concatenated code here and we only want one vardecl per
     503                 :     // resulting variable.
     504                 : 
     505           40971 :     if (alias->epilogue_style)
     506                 :       {
     507               0 :         for (unsigned i = 0; i < use->body->statements.size(); ++i)
     508                 :           n->body->statements.push_back
     509               0 :             (deep_copy_visitor::deep_copy(use->body->statements[i]));
     510                 : 
     511               0 :         for (unsigned i = 0; i < alias->body->statements.size(); ++i)
     512                 :           n->body->statements.push_back
     513               0 :             (deep_copy_visitor::deep_copy(alias->body->statements[i]));
     514                 :       }
     515                 :     else
     516                 :       {
     517          174334 :         for (unsigned i = 0; i < alias->body->statements.size(); ++i)
     518                 :           n->body->statements.push_back
     519          133363 :             (deep_copy_visitor::deep_copy(alias->body->statements[i]));
     520                 :         
     521           81796 :         for (unsigned i = 0; i < use->body->statements.size(); ++i)
     522                 :           n->body->statements.push_back
     523           40825 :             (deep_copy_visitor::deep_copy(use->body->statements[i]));
     524                 :       }
     525                 :     
     526           40971 :     derive_probes (sess, n, finished_results, location->optional);
     527                 :   }
     528                 : 
     529           40973 :   bool checkForRecursiveExpansion (probe *use)
     530                 :   {
     531                 :     // Collect the derivation chain of this probe.
     532           40973 :     vector<probe*>derivations;
     533           40973 :     use->collect_derivation_chain (derivations);
     534                 : 
     535                 :     // Check all probe points in the alias expansion against the currently-being-expanded probe point
     536                 :     // of each of the probes in the derivation chain, looking for a match. This
     537                 :     // indicates infinite recursion.
     538                 :     // The first element of the derivation chain will be the derived_probe representing 'use', so
     539                 :     // start the search with the second element.
     540           40973 :     assert (derivations.size() > 0);
     541           40973 :     assert (derivations[0] == use);
     542           41622 :     for (unsigned d = 1; d < derivations.size(); ++d) {
     543             651 :       if (use->get_alias() == derivations[d]->get_alias())
     544               2 :         return true; // recursion detected
     545                 :     }
     546           40971 :     return false;
     547                 :   }
     548                 : };
     549                 : 
     550                 : 
     551                 : // ------------------------------------------------------------------------
     552                 : // Pattern matching
     553                 : // ------------------------------------------------------------------------
     554                 : 
     555                 : 
     556                 : // Register all the aliases we've seen in library files, and the user
     557                 : // file, as patterns.
     558                 : 
     559                 : void
     560             485 : systemtap_session::register_library_aliases()
     561                 : {
     562             485 :   vector<stapfile*> files(library_files);
     563             485 :   files.push_back(user_file);
     564                 : 
     565           19406 :   for (unsigned f = 0; f < files.size(); ++f)
     566                 :     {
     567           18921 :       stapfile * file = files[f];
     568          534529 :       for (unsigned a = 0; a < file->aliases.size(); ++a)
     569                 :         {
     570          515608 :           probe_alias * alias = file->aliases[a];
     571                 :           try 
     572                 :             {
     573         1031215 :               for (unsigned n = 0; n < alias->alias_names.size(); ++n)
     574                 :                 {
     575          515608 :                   probe_point * name = alias->alias_names[n];
     576          515608 :                   match_node * n = pattern_root;
     577         1930442 :                   for (unsigned c = 0; c < name->components.size(); ++c)
     578                 :                     {
     579         1414835 :                       probe_point::component * comp = name->components[c];
     580                 :                       // XXX: alias parameters
     581         1414835 :                       if (comp->arg)
     582                 :                         throw semantic_error("alias component " 
     583                 :                                              + comp->functor 
     584               0 :                                              + " contains illegal parameter");
     585         1414835 :                       n = n->bind(comp->functor);
     586                 :                     }
     587          515607 :                   n->bind(new alias_expansion_builder(alias));
     588                 :                 }
     589                 :             }
     590               2 :           catch (const semantic_error& e)
     591                 :             {
     592               1 :               semantic_error* er = new semantic_error (e); // copy it
     593               1 :               stringstream msg;
     594               1 :               msg << e.msg2;
     595               1 :               msg << " while registering probe alias ";
     596               1 :               alias->printsig(msg);
     597               1 :               er->msg2 = msg.str();
     598               1 :               print_error (* er);
     599               1 :               delete er;
     600                 :             }
     601                 :         }
     602             485 :     }
     603             485 : }
     604                 : 
     605                 : 
     606                 : static unsigned max_recursion = 100;
     607                 : 
     608                 : struct 
     609                 : recursion_guard
     610                 : {
     611                 :   unsigned & i;
     612                 :   recursion_guard(unsigned & i) : i(i)
     613                 :     {
     614                 :       if (i > max_recursion)
     615                 :         throw semantic_error("recursion limit reached");
     616                 :       ++i;
     617                 :     }
     618                 :   ~recursion_guard() 
     619                 :     {
     620                 :       --i;
     621                 :     }
     622                 : };
     623                 : 
     624                 : // The match-and-expand loop.
     625                 : void
     626                 : derive_probes (systemtap_session& s,
     627                 :                probe *p, vector<derived_probe*>& dps,
     628           42099 :                bool optional)
     629                 : {
     630           98893 :   for (unsigned i = 0; i < p->locations.size(); ++i)
     631                 :     {
     632           56798 :       if (pending_interrupts) break;
     633                 : 
     634           56798 :       probe_point *loc = p->locations[i];
     635                 : 
     636                 :       try
     637                 :         {
     638           56798 :           unsigned num_atbegin = dps.size();
     639                 : 
     640                 :           // Pass down optional flag from e.g. alias reference to each
     641                 :           // probe_point instance.  We do this by temporarily overriding
     642                 :           // the probe_point optional flag.  We could instead deep-copy
     643                 :           // and set a flag on the copy permanently.
     644           56798 :           bool old_loc_opt = loc->optional;
     645           56798 :           loc->optional = loc->optional || optional;
     646           56798 :           s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
     647           56763 :           loc->optional = old_loc_opt;
     648           56763 :           unsigned num_atend = dps.size();
     649                 : 
     650           56763 :           if (! (loc->optional||optional) && // something required, but
     651                 :               num_atbegin == num_atend) // nothing new derived!
     652              20 :             throw semantic_error ("no match");
     653                 : 
     654           56743 :           if (loc->sufficient && (num_atend > num_atbegin))
     655                 :             {
     656               4 :               if (s.verbose > 1)
     657                 :                 {
     658               0 :                   clog << "Probe point ";
     659               0 :                   p->locations[i]->print(clog);
     660               0 :                   clog << " sufficient, skipped";
     661               0 :                   for (unsigned j = i+1; j < p->locations.size(); ++j)
     662                 :                     {
     663               0 :                       clog << " ";
     664               0 :                       p->locations[j]->print(clog);
     665                 :                     }
     666               0 :                   clog << endl;
     667                 :                 }
     668               4 :               break; // we need not try to derive for any other locations
     669                 :             }
     670                 :         }
     671             110 :       catch (const semantic_error& e)
     672                 :         {
     673                 :           // XXX: prefer not to print_error at every nest/unroll level
     674                 : 
     675              55 :           semantic_error* er = new semantic_error (e); // copy it
     676              55 :           stringstream msg;
     677              55 :           msg << e.msg2;
     678              55 :           msg << " while resolving probe point " << *loc;
     679              55 :           er->msg2 = msg.str();
     680              55 :           s.print_error (* er);
     681              55 :           delete er;
     682                 :         }
     683                 : 
     684                 :     }
     685           42099 : }
     686                 : 
     687                 : 
     688                 : 
     689                 : // ------------------------------------------------------------------------
     690                 : //
     691                 : // Indexable usage checks
     692                 : //
     693                 : 
     694                 : struct symbol_fetcher
     695                 :   : public throwing_visitor
     696          474942 : {
     697                 :   symbol *&sym;
     698                 : 
     699          474942 :   symbol_fetcher (symbol *&sym): sym(sym) 
     700          474942 :   {}
     701                 : 
     702          474940 :   void visit_symbol (symbol* e)
     703                 :   {
     704          474940 :     sym = e;
     705          474940 :   }
     706                 : 
     707               1 :   void visit_target_symbol (target_symbol* e)
     708                 :   {
     709               1 :     sym = e;
     710               1 :   }
     711                 : 
     712            5285 :   void visit_arrayindex (arrayindex* e)
     713                 :   {
     714            5285 :     e->base->visit_indexable (this);
     715            5285 :   }
     716                 : 
     717               1 :   void throwone (const token* t)
     718                 :   {
     719               1 :     throw semantic_error ("Expecting symbol or array index expression", t);
     720                 :   }
     721                 : };
     722                 : 
     723                 : symbol *
     724          474942 : get_symbol_within_expression (expression *e)
     725                 : {
     726          474942 :   symbol *sym = NULL;
     727          474942 :   symbol_fetcher fetcher(sym);
     728          474942 :   e->visit (&fetcher);
     729          474941 :   return sym; // NB: may be null!
     730                 : }
     731                 : 
     732                 : static symbol *
     733            3888 : get_symbol_within_indexable (indexable *ix)
     734                 : {
     735            3888 :   symbol *array = NULL;
     736            3888 :   hist_op *hist = NULL;
     737            3888 :   classify_indexable(ix, array, hist);
     738            3888 :   if (array)
     739            3882 :     return array;
     740                 :   else
     741               6 :     return get_symbol_within_expression (hist->stat);
     742                 : }
     743                 : 
     744                 : struct mutated_var_collector
     745                 :   : public traversing_visitor
     746            7654 : {
     747                 :   set<vardecl *> * mutated_vars;
     748                 : 
     749            7654 :   mutated_var_collector (set<vardecl *> * mm) 
     750            7654 :     : mutated_vars (mm)
     751            7654 :   {}
     752                 : 
     753            3130 :   void visit_assignment(assignment* e)
     754                 :   {
     755            3130 :     if (e->type == pe_stats && e->op == "<<<")
     756                 :       {
     757               0 :         vardecl *vd = get_symbol_within_expression (e->left)->referent;
     758               0 :         if (vd)
     759               0 :           mutated_vars->insert (vd);
     760                 :       }
     761            3130 :     traversing_visitor::visit_assignment(e);
     762            3130 :   }
     763                 : 
     764             120 :   void visit_arrayindex (arrayindex *e)
     765                 :   {
     766             120 :     if (is_active_lvalue (e))
     767                 :       {
     768                 :         symbol *sym;
     769              42 :         if (e->base->is_symbol (sym))
     770              42 :           mutated_vars->insert (sym->referent);
     771                 :         else
     772               0 :           throw semantic_error("Assignment to read-only histogram bucket", e->tok);
     773                 :       }
     774             120 :     traversing_visitor::visit_arrayindex (e);
     775             120 :   }
     776                 : };
     777                 : 
     778                 : 
     779                 : struct no_var_mutation_during_iteration_check
     780                 :   : public traversing_visitor
     781             402 : {
     782                 :   systemtap_session & session;
     783                 :   map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
     784                 :   vector<vardecl *> vars_being_iterated;
     785                 :   
     786                 :   no_var_mutation_during_iteration_check 
     787                 :   (systemtap_session & sess,
     788             402 :    map<functiondecl *,set<vardecl *> *> & fmv)
     789             402 :     : session(sess), function_mutates_vars (fmv)
     790             402 :   {}
     791                 : 
     792           48862 :   void visit_arrayindex (arrayindex *e)
     793                 :   {
     794           48862 :     if (is_active_lvalue(e))
     795                 :       {
     796            3771 :         vardecl *vd = get_symbol_within_indexable (e->base)->referent;
     797            3771 :         if (vd)
     798                 :           {
     799            3777 :             for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
     800                 :               {
     801               6 :                 vardecl *v = vars_being_iterated[i];
     802               6 :                 if (v == vd)
     803                 :                   {
     804                 :                     string err = ("variable '" + v->name +
     805               2 :                                   "' modified during 'foreach' iteration");
     806               4 :                     session.print_error (semantic_error (err, e->tok));
     807                 :                   }
     808                 :               }
     809                 :           }
     810                 :       }
     811           48862 :     traversing_visitor::visit_arrayindex (e);
     812           48862 :   }
     813                 : 
     814          227931 :   void visit_functioncall (functioncall* e)
     815                 :   {
     816                 :     map<functiondecl *,set<vardecl *> *>::const_iterator i 
     817          227931 :       = function_mutates_vars.find (e->referent);
     818                 : 
     819          227931 :     if (i != function_mutates_vars.end())
     820                 :       {
     821          227946 :         for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
     822                 :           {
     823              15 :             vardecl *m = vars_being_iterated[j];
     824              15 :             if (i->second->find (m) != i->second->end())
     825                 :               {
     826                 :                 string err = ("function call modifies var '" + m->name +
     827               2 :                               "' during 'foreach' iteration");
     828               4 :                 session.print_error (semantic_error (err, e->tok));
     829                 :               }
     830                 :           }
     831                 :       }
     832                 : 
     833          227931 :     traversing_visitor::visit_functioncall (e);
     834          227931 :   }
     835                 : 
     836             117 :   void visit_foreach_loop(foreach_loop* s)
     837                 :   {
     838             117 :     vardecl *vd = get_symbol_within_indexable (s->base)->referent;
     839                 : 
     840             117 :     if (vd)
     841             117 :       vars_being_iterated.push_back (vd);
     842                 :     
     843             117 :     traversing_visitor::visit_foreach_loop (s);
     844                 : 
     845             117 :     if (vd)
     846             117 :       vars_being_iterated.pop_back();
     847             117 :   }
     848                 : };
     849                 : 
     850                 : 
     851                 : // ------------------------------------------------------------------------
     852                 : 
     853                 : struct stat_decl_collector
     854                 :   : public traversing_visitor
     855             398 : {
     856                 :   systemtap_session & session;
     857                 :   
     858             398 :   stat_decl_collector(systemtap_session & sess)
     859             398 :     : session(sess)
     860             398 :   {}
     861                 : 
     862             245 :   void visit_stat_op (stat_op* e)
     863                 :   {
     864             245 :     symbol *sym = get_symbol_within_expression (e->stat);
     865             245 :     if (session.stat_decls.find(sym->name) == session.stat_decls.end())
     866               7 :       session.stat_decls[sym->name] = statistic_decl();
     867             245 :   }
     868                 : 
     869          132708 :   void visit_assignment (assignment* e)
     870                 :   {
     871          132708 :     if (e->op == "<<<")
     872                 :       {
     873            2374 :         symbol *sym = get_symbol_within_expression (e->left);
     874            2374 :         if (session.stat_decls.find(sym->name) == session.stat_decls.end())
     875              61 :           session.stat_decls[sym->name] = statistic_decl();
     876                 :       }
     877                 :     else
     878          130334 :       traversing_visitor::visit_assignment(e);
     879          132708 :   }
     880                 : 
     881             112 :   void visit_hist_op (hist_op* e)
     882                 :   {
     883             112 :     symbol *sym = get_symbol_within_expression (e->stat);
     884             112 :     statistic_decl new_stat;
     885                 : 
     886             112 :     if (e->htype == hist_linear)
     887                 :       {
     888              53 :         new_stat.type = statistic_decl::linear;
     889              53 :         assert (e->params.size() == 3);
     890              53 :         new_stat.linear_low = e->params[0];
     891              53 :         new_stat.linear_high = e->params[1];
     892              53 :         new_stat.linear_step = e->params[2];
     893                 :       }
     894                 :     else
     895                 :       {
     896              59 :         assert (e->htype == hist_log);
     897              59 :         new_stat.type = statistic_decl::logarithmic;
     898              59 :         assert (e->params.size() == 0);
     899                 :       }
     900                 : 
     901             112 :     map<string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
     902             112 :     if (i == session.stat_decls.end())
     903               0 :       session.stat_decls[sym->name] = new_stat;
     904                 :     else
     905                 :       {
     906             112 :         statistic_decl & old_stat = i->second;
     907             112 :         if (!(old_stat == new_stat))
     908                 :           {
     909              43 :             if (old_stat.type == statistic_decl::none)
     910              43 :               i->second = new_stat;
     911                 :             else
     912                 :               {
     913                 :                 // FIXME: Support multiple co-declared histogram types
     914                 :                 semantic_error se("multiple histogram types declared on '" + sym->name + "'", 
     915               0 :                                   e->tok);
     916               0 :                 session.print_error (se);
     917                 :               }
     918                 :           }
     919                 :       }    
     920             112 :   }
     921                 : 
     922                 : };
     923                 : 
     924                 : static int
     925             398 : semantic_pass_stats (systemtap_session & sess)
     926                 : {
     927             398 :   stat_decl_collector sdc(sess);
     928                 : 
     929            8046 :   for (unsigned i = 0; i < sess.functions.size(); ++i)    
     930            7648 :     sess.functions[i]->body->visit (&sdc);
     931                 : 
     932          488943 :   for (unsigned i = 0; i < sess.probes.size(); ++i)    
     933          488545 :     sess.probes[i]->body->visit (&sdc);
     934                 : 
     935            1076 :   for (unsigned i = 0; i < sess.globals.size(); ++i)
     936                 :     {
     937             678 :       vardecl *v = sess.globals[i];
     938             678 :       if (v->type == pe_stats)
     939                 :         {
     940                 :           
     941              66 :           if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
     942                 :             {
     943               0 :               semantic_error se("unable to infer statistic parameters for global '" + v->name + "'");
     944               0 :               sess.print_error (se);
     945                 :             }
     946                 :         }
     947                 :     }
     948                 :   
     949             398 :   return sess.num_errors();
     950                 : }
     951                 : 
     952                 : // ------------------------------------------------------------------------
     953                 : 
     954                 : // Enforce variable-related invariants: no modification of
     955                 : // a foreach()-iterated array.
     956                 : static int
     957             402 : semantic_pass_vars (systemtap_session & sess)
     958                 : {
     959                 :   
     960             402 :   map<functiondecl *, set<vardecl *> *> fmv;
     961             402 :   no_var_mutation_during_iteration_check chk(sess, fmv);
     962                 :   
     963            8056 :   for (unsigned i = 0; i < sess.functions.size(); ++i)
     964                 :     {
     965            7654 :       functiondecl * fn = sess.functions[i];
     966            7654 :       if (fn->body)
     967                 :         {
     968            7654 :           set<vardecl *> * m = new set<vardecl *>();
     969            7654 :           mutated_var_collector mc (m);
     970            7654 :           fn->body->visit (&mc);
     971            7654 :           fmv[fn] = m;
     972                 :         }
     973                 :     }
     974                 : 
     975            8056 :   for (unsigned i = 0; i < sess.functions.size(); ++i)
     976                 :     {
     977            7654 :       if (sess.functions[i]->body)
     978            7654 :         sess.functions[i]->body->visit (&chk);
     979                 :     }
     980                 : 
     981          488951 :   for (unsigned i = 0; i < sess.probes.size(); ++i)
     982                 :     {
     983          488549 :       if (sess.probes[i]->body)
     984          488549 :         sess.probes[i]->body->visit (&chk);
     985                 :     }  
     986                 : 
     987             402 :   return sess.num_errors();
     988                 : }
     989                 : 
     990                 : 
     991                 : // ------------------------------------------------------------------------
     992                 : 
     993                 : // Rewrite probe condition expressions into probe bodies.  Tricky and
     994                 : // exciting business, this.  This:
     995                 : //
     996                 : // probe foo if (g1 || g2) { ... }
     997                 : // probe bar { ... g1 ++ ... }
     998                 : //
     999                 : // becomes:
    1000                 : //
    1001                 : // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
    1002                 : // probe foo { if (! (g1 || g2)) next; ... }
    1003                 : // probe bar { ... g1 ++ ...; 
    1004                 : //             if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
    1005                 : //           }
    1006                 : //
    1007                 : // XXX: As a first cut, do only the "inline probe condition" part of the
    1008                 : // transform.
    1009                 : 
    1010                 : static int
    1011             434 : semantic_pass_conditions (systemtap_session & sess)
    1012                 : {
    1013          489089 :   for (unsigned i = 0; i < sess.probes.size(); ++i)
    1014                 :     {
    1015          488655 :       derived_probe* p = sess.probes[i];
    1016          488655 :       expression* e = p->sole_location()->condition;
    1017          488655 :       if (e)
    1018                 :         {
    1019              14 :           varuse_collecting_visitor vut;
    1020              14 :           e->visit (& vut);
    1021                 : 
    1022              14 :           if (! vut.written.empty())
    1023                 :             {
    1024               1 :               string err = ("probe condition must not modify any variables");
    1025               2 :               sess.print_error (semantic_error (err, e->tok));
    1026                 :             }
    1027              13 :           else if (vut.embedded_seen)
    1028                 :             {
    1029               0 :               sess.print_error (semantic_error ("probe condition must not include impure embedded-C", e->tok));
    1030                 :             }
    1031                 : 
    1032                 :           // Add the condition expression to the front of the
    1033                 :           // derived_probe body.
    1034              14 :           if_statement *ifs = new if_statement ();
    1035              14 :           ifs->tok = e->tok;
    1036              28 :           ifs->thenblock = new next_statement ();
    1037              14 :           ifs->thenblock->tok = e->tok;
    1038              14 :           ifs->elseblock = NULL;
    1039              28 :           unary_expression *notex = new unary_expression ();
    1040              14 :           notex->op = "!";
    1041              14 :           notex->tok = e->tok;
    1042              14 :           notex->operand = e;
    1043              14 :           ifs->condition = notex;
    1044              14 :           p->body->statements.insert (p->body->statements.begin(), ifs);
    1045                 :         }
    1046                 :     }  
    1047                 : 
    1048             434 :   return sess.num_errors();
    1049                 : }
    1050                 : 
    1051                 : 
    1052                 : // ------------------------------------------------------------------------
    1053                 : 
    1054                 : 
    1055                 : static int semantic_pass_symbols (systemtap_session&);
    1056                 : static int semantic_pass_optimize1 (systemtap_session&);
    1057                 : static int semantic_pass_optimize2 (systemtap_session&);
    1058                 : static int semantic_pass_types (systemtap_session&);
    1059                 : static int semantic_pass_vars (systemtap_session&);
    1060                 : static int semantic_pass_stats (systemtap_session&);
    1061                 : static int semantic_pass_conditions (systemtap_session&);
    1062                 : 
    1063                 : 
    1064                 : // Link up symbols to their declarations.  Set the session's
    1065                 : // files/probes/functions/globals vectors from the transitively
    1066                 : // reached set of stapfiles in s.library_files, starting from
    1067                 : // s.user_file.  Perform automatic tapset inclusion and probe
    1068                 : // alias expansion.
    1069                 : static int
    1070             485 : semantic_pass_symbols (systemtap_session& s)
    1071                 : {
    1072             485 :   symresolution_info sym (s);
    1073                 : 
    1074                 :   // NB: s.files can grow during this iteration, so size() can
    1075                 :   // return gradually increasing numbers.
    1076             485 :   s.files.push_back (s.user_file);
    1077            1825 :   for (unsigned i = 0; i < s.files.size(); i++)
    1078                 :     {
    1079            1341 :       if (pending_interrupts) break;
    1080            1341 :       stapfile* dome = s.files[i];
    1081                 : 
    1082                 :       // Pass 1: add globals and functions to systemtap-session master list,
    1083                 :       //         so the find_* functions find them
    1084                 : 
    1085            1976 :       for (unsigned i=0; i<dome->globals.size(); i++)
    1086             635 :         s.globals.push_back (dome->globals[i]);
    1087                 : 
    1088           13284 :       for (unsigned i=0; i<dome->functions.size(); i++)
    1089           11943 :         s.functions.push_back (dome->functions[i]);
    1090                 : 
    1091            2501 :       for (unsigned i=0; i<dome->embeds.size(); i++)
    1092            1160 :         s.embeds.push_back (dome->embeds[i]);
    1093                 : 
    1094                 :       // Pass 2: process functions
    1095                 : 
    1096           13284 :       for (unsigned i=0; i<dome->functions.size(); i++)
    1097                 :         {
    1098           11943 :           if (pending_interrupts) break;
    1099           11943 :           functiondecl* fd = dome->functions[i];
    1100                 : 
    1101                 :           try 
    1102                 :             {
    1103           11943 :               sym.current_function = fd;
    1104           11943 :               sym.current_probe = 0;
    1105           11943 :               fd->body->visit (& sym);
    1106                 :             }
    1107               0 :           catch (const semantic_error& e)
    1108                 :             {
    1109               0 :               s.print_error (e);
    1110                 :             }
    1111                 :         }
    1112                 : 
    1113                 :       // Pass 3: derive probes and resolve any further symbols in the
    1114                 :       // derived results. 
    1115                 : 
    1116            2468 :       for (unsigned i=0; i<dome->probes.size(); i++)
    1117                 :         {
    1118            1128 :           if (pending_interrupts) break;
    1119            1128 :           probe* p = dome->probes [i];
    1120            1128 :           vector<derived_probe*> dps;
    1121                 : 
    1122                 :           // much magic happens here: probe alias expansion, wildcard
    1123                 :           // matching, low-level derived_probe construction.
    1124            1128 :           derive_probes (s, p, dps);
    1125                 : 
    1126          489904 :           for (unsigned j=0; j<dps.size(); j++)
    1127                 :             {
    1128          488777 :               if (pending_interrupts) break;
    1129          488777 :               derived_probe* dp = dps[j];
    1130          488777 :               s.probes.push_back (dp);
    1131          488777 :               dp->join_group (s);
    1132                 : 
    1133                 :               try 
    1134                 :                 {
    1135          488776 :                   sym.current_function = 0;
    1136          488776 :                   sym.current_probe = dp;
    1137          488776 :                   dp->body->visit (& sym);
    1138                 : 
    1139                 :                   // Process the probe-point condition expression.
    1140          488776 :                   sym.current_function = 0;
    1141          488776 :                   sym.current_probe = 0;
    1142          488776 :                   if (dp->sole_location()->condition)
    1143              16 :                     dp->sole_location()->condition->visit (& sym);
    1144                 :                 }
    1145               4 :               catch (const semantic_error& e)
    1146                 :                 {
    1147               2 :                   s.print_error (e);
    1148                 :                 }
    1149                 :             }
    1150                 :         }
    1151                 :     }
    1152                 : 
    1153                 :   // Inform all derived_probe builders that we're done with
    1154                 :   // all resolution, so it's time to release caches.
    1155             484 :   s.pattern_root->build_no_more (s);
    1156                 :   
    1157             484 :   return s.num_errors(); // all those print_error calls
    1158                 : }
    1159                 : 
    1160                 : 
    1161                 : 
    1162                 : int
    1163             485 : semantic_pass (systemtap_session& s)
    1164                 : {
    1165             485 :   int rc = 0;
    1166                 : 
    1167                 :   try 
    1168                 :     {
    1169             485 :       s.register_library_aliases();
    1170             485 :       register_standard_tapsets(s);
    1171                 :       
    1172             485 :       if (rc == 0) rc = semantic_pass_symbols (s);
    1173             484 :       if (rc == 0) rc = semantic_pass_conditions (s);
    1174             484 :       if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize1 (s);
    1175             483 :       if (rc == 0) rc = semantic_pass_types (s);
    1176             483 :       if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize2 (s);
    1177             483 :       if (rc == 0) rc = semantic_pass_vars (s);
    1178             483 :       if (rc == 0) rc = semantic_pass_stats (s);
    1179                 :     }
    1180               4 :   catch (const semantic_error& e)
    1181                 :     {
    1182               2 :       s.print_error (e);
    1183               2 :       rc ++;
    1184                 :     }
    1185                 :   
    1186             485 :   return rc;
    1187                 : }
    1188                 : 
    1189                 : 
    1190                 : // ------------------------------------------------------------------------
    1191                 : 
    1192                 : 
    1193            1094 : systemtap_session::systemtap_session ():
    1194                 :   // NB: pointer members must be manually initialized!
    1195                 :   pattern_root(new match_node),
    1196                 :   user_file (0),
    1197                 :   be_derived_probes(0), 
    1198                 :   dwarf_derived_probes(0), 
    1199                 :   uprobe_derived_probes(0), 
    1200                 :   timer_derived_probes(0), 
    1201                 :   profile_derived_probes(0), 
    1202                 :   mark_derived_probes(0), 
    1203                 :   hrtimer_derived_probes(0), 
    1204                 :   perfmon_derived_probes(0), 
    1205                 :   procfs_derived_probes(0), 
    1206            1094 :   op (0), up (0)
    1207                 : {
    1208            1094 : }
    1209                 : 
    1210                 : 
    1211                 : void
    1212             163 : systemtap_session::print_error (const semantic_error& e)
    1213                 : {
    1214             163 :   string message_str;
    1215             163 :   stringstream message;
    1216                 : 
    1217             163 :   message << "semantic error: " << e.what ();
    1218             163 :   if (e.tok1 || e.tok2)
    1219             114 :     message << ": ";
    1220             163 :   if (e.tok1) message << *e.tok1;
    1221             163 :   message << e.msg2;
    1222             163 :   if (e.tok2) message << *e.tok2;
    1223             163 :   message << endl;
    1224             163 :   message_str = message.str();
    1225                 : 
    1226                 :   // Duplicate elimination
    1227             163 :   if (seen_errors.find (message_str) == seen_errors.end())
    1228                 :     {
    1229             126 :       seen_errors.insert (message_str);
    1230             126 :       cerr << message_str;
    1231                 :     }
    1232                 : 
    1233             163 :   if (e.chain)
    1234               0 :     print_error (* e.chain);
    1235             163 : }
    1236                 : 
    1237                 : 
    1238                 : // ------------------------------------------------------------------------
    1239                 : // semantic processing: symbol resolution
    1240                 : 
    1241                 : 
    1242             485 : symresolution_info::symresolution_info (systemtap_session& s):
    1243             485 :   session (s), current_function (0), current_probe (0)
    1244                 : {
    1245             485 : }
    1246                 : 
    1247                 : 
    1248                 : void
    1249          536919 : symresolution_info::visit_block (block* e)
    1250                 : {
    1251          946283 :   for (unsigned i=0; i<e->statements.size(); i++)
    1252                 :     {
    1253                 :       try 
    1254                 :         {
    1255          409364 :           e->statements[i]->visit (this);
    1256                 :         }
    1257               0 :       catch (const semantic_error& e)
    1258                 :         {
    1259               0 :           session.print_error (e);
    1260                 :         }
    1261                 :     }
    1262          536919 : }
    1263                 : 
    1264                 : 
    1265                 : void
    1266             123 : symresolution_info::visit_foreach_loop (foreach_loop* e)
    1267                 : {
    1268             268 :   for (unsigned i=0; i<e->indexes.size(); i++)
    1269             145 :     e->indexes[i]->visit (this);
    1270                 : 
    1271             123 :   symbol *array = NULL;  
    1272             123 :   hist_op *hist = NULL;
    1273             123 :   classify_indexable (e->base, array, hist);
    1274                 : 
    1275             123 :   if (array)
    1276                 :     {
    1277             117 :       if (!array->referent)
    1278                 :         {         
    1279             117 :           vardecl* d = find_var (array->name, e->indexes.size ());
    1280             117 :           if (d)
    1281             117 :             array->referent = d;
    1282                 :           else
    1283                 :             {
    1284               0 :               stringstream msg;
    1285                 :               msg << "unresolved arity-" << e->indexes.size()
    1286               0 :                   << " global array " << array->name;
    1287               0 :               throw semantic_error (msg.str(), e->tok);
    1288                 :             }
    1289                 :         }
    1290                 :     }
    1291                 :   else 
    1292                 :     {
    1293               6 :       assert (hist);
    1294               6 :       hist->visit (this);
    1295                 :     }
    1296                 : 
    1297             123 :   if (e->limit)
    1298              20 :     e->limit->visit (this);
    1299                 : 
    1300             123 :   e->block->visit (this);
    1301             123 : }
    1302                 : 
    1303                 : 
    1304                 : struct 
    1305                 : delete_statement_symresolution_info:
    1306                 :   public traversing_visitor
    1307             574 : {
    1308                 :   symresolution_info *parent;
    1309                 : 
    1310             574 :   delete_statement_symresolution_info (symresolution_info *p):
    1311             574 :     parent(p)
    1312             574 :   {}
    1313                 : 
    1314             496 :   void visit_arrayindex (arrayindex* e)
    1315                 :   {
    1316             496 :     parent->visit_arrayindex (e);
    1317             496 :   }
    1318               0 :   void visit_functioncall (functioncall* e)
    1319                 :   {
    1320               0 :     parent->visit_functioncall (e);
    1321               0 :   }
    1322                 : 
    1323              78 :   void visit_symbol (symbol* e)
    1324                 :   {
    1325              78 :     if (e->referent)
    1326               0 :       return;
    1327                 :     
    1328              78 :     vardecl* d = parent->find_var (e->name, -1);
    1329              78 :     if (d)
    1330              78 :       e->referent = d;
    1331                 :     else
    1332               0 :       throw semantic_error ("unresolved array in delete statement", e->tok);
    1333                 :   }
    1334                 : };
    1335                 : 
    1336                 : void 
    1337             574 : symresolution_info::visit_delete_statement (delete_statement* s)
    1338                 : {
    1339             574 :   delete_statement_symresolution_info di (this);
    1340             574 :   s->value->visit (&di);
    1341             574 : }
    1342                 : 
    1343                 : 
    1344                 : void
    1345          519153 : symresolution_info::visit_symbol (symbol* e)
    1346                 : {
    1347          519153 :   if (e->referent)
    1348             424 :     return;
    1349                 : 
    1350          518729 :   vardecl* d = find_var (e->name, 0);
    1351          518729 :   if (d)
    1352          357558 :     e->referent = d;
    1353                 :   else
    1354                 :     {
    1355                 :       // new local
    1356          161171 :       vardecl* v = new vardecl;
    1357          161171 :       v->name = e->name;
    1358          161171 :       v->tok = e->tok;
    1359          161171 :       if (current_function)
    1360             921 :         current_function->locals.push_back (v);
    1361          160250 :       else if (current_probe)
    1362          160249 :         current_probe->locals.push_back (v);
    1363                 :       else
    1364                 :         // must be probe-condition expression
    1365               1 :         throw semantic_error ("probe condition must not reference undeclared global", e->tok);
    1366          161170 :       e->referent = v;
    1367                 :     }
    1368                 : }
    1369                 : 
    1370                 : 
    1371                 : void
    1372           49289 : symresolution_info::visit_arrayindex (arrayindex* e)
    1373                 : {
    1374           99251 :   for (unsigned i=0; i<e->indexes.size(); i++)
    1375           49962 :     e->indexes[i]->visit (this);
    1376                 : 
    1377           49289 :   symbol *array = NULL;  
    1378           49289 :   hist_op *hist = NULL;
    1379           49289 :   classify_indexable(e->base, array, hist);
    1380                 : 
    1381           49289 :   if (array)
    1382                 :     {
    1383           49270 :       if (array->referent)
    1384             264 :         return;
    1385                 : 
    1386           49006 :       vardecl* d = find_var (array->name, e->indexes.size ());
    1387           49006 :       if (d)
    1388           49004 :         array->referent = d;
    1389                 :       else
    1390                 :         {
    1391                 :           // new local
    1392               2 :           vardecl* v = new vardecl;
    1393               2 :           v->set_arity(e->indexes.size());
    1394               2 :           v->name = array->name;
    1395               2 :           v->tok = array->tok;
    1396               2 :           if (current_function)
    1397               0 :             current_function->locals.push_back (v);
    1398               2 :           else if (current_probe)
    1399               2 :             current_probe->locals.push_back (v);
    1400                 :           else
    1401                 :             // must not happen
    1402               0 :             throw semantic_error ("no current probe/function", e->tok);
    1403               2 :           array->referent = v;
    1404                 :         }      
    1405                 :     }
    1406                 :   else
    1407                 :     {
    1408              19 :       assert (hist);
    1409              19 :       hist->visit (this);
    1410                 :     }
    1411                 : }
    1412                 : 
    1413                 : 
    1414                 : void
    1415          291449 : symresolution_info::visit_functioncall (functioncall* e)
    1416                 : {
    1417                 :   // XXX: we could relax this, if we're going to examine the
    1418                 :   // vartracking data recursively.  See testsuite/semko/fortytwo.stp.
    1419          291449 :   if (! (current_function || current_probe))
    1420                 :     {
    1421                 :       // must be probe-condition expression
    1422               1 :       throw semantic_error ("probe condition must not reference function", e->tok);
    1423                 :     }
    1424                 : 
    1425          350697 :   for (unsigned i=0; i<e->args.size(); i++)
    1426           59249 :     e->args[i]->visit (this);
    1427                 : 
    1428          291448 :   if (e->referent)
    1429               0 :     return;
    1430                 : 
    1431          291448 :   functiondecl* d = find_function (e->function, e->args.size ());
    1432          291448 :   if (d)
    1433          291448 :     e->referent = d;
    1434                 :   else
    1435                 :     {
    1436               0 :       stringstream msg;
    1437                 :       msg << "unresolved arity-" << e->args.size()
    1438               0 :           << " function";
    1439               0 :       throw semantic_error (msg.str(), e->tok);
    1440                 :     }
    1441                 : }
    1442                 : 
    1443                 : 
    1444                 : vardecl* 
    1445          567930 : symresolution_info::find_var (const string& name, int arity)
    1446                 : {
    1447          567930 :   if (current_function || current_probe)
    1448                 :     {
    1449                 :       // search locals
    1450                 :       vector<vardecl*>& locals = (current_function ? 
    1451                 :                                   current_function->locals :
    1452          567909 :                                   current_probe->locals);
    1453                 :       
    1454                 :       
    1455         1783221 :       for (unsigned i=0; i<locals.size(); i++)
    1456         1333623 :         if (locals[i]->name == name 
    1457                 :             && locals[i]->compatible_arity(arity))
    1458                 :           {
    1459          118311 :             locals[i]->set_arity (arity);
    1460          118311 :             return locals[i];
    1461                 :           }
    1462                 :     }
    1463                 : 
    1464                 :   // search function formal parameters (for scalars)
    1465          449619 :   if (arity == 0 && current_function)
    1466           38398 :     for (unsigned i=0; i<current_function->formal_args.size(); i++)
    1467           37434 :       if (current_function->formal_args[i]->name == name)
    1468                 :         {
    1469                 :           // NB: no need to check arity here: formal args always scalar
    1470           36430 :           current_function->formal_args[i]->set_arity (0);
    1471           36430 :           return current_function->formal_args[i];
    1472                 :         }
    1473                 : 
    1474                 :   // search processed globals
    1475         1152080 :   for (unsigned i=0; i<session.globals.size(); i++)
    1476          990587 :     if (session.globals[i]->name == name
    1477                 :         && session.globals[i]->compatible_arity(arity))  
    1478                 :       {
    1479          251696 :         session.globals[i]->set_arity (arity);
    1480          251696 :         return session.globals[i];
    1481                 :       }
    1482                 :   
    1483                 :   // search library globals
    1484         6295680 :   for (unsigned i=0; i<session.library_files.size(); i++)
    1485                 :     {
    1486         6134507 :       stapfile* f = session.library_files[i];
    1487        10493226 :       for (unsigned j=0; j<f->globals.size(); j++)
    1488                 :         {
    1489         4359039 :           vardecl* g = f->globals[j];
    1490         4359039 :           if (g->name == name && g->compatible_arity (arity))
    1491                 :             {
    1492             320 :               g->set_arity (arity);
    1493                 :               
    1494                 :               // put library into the queue if not already there            
    1495             320 :               if (find (session.files.begin(), session.files.end(), f) 
    1496                 :                   == session.files.end())
    1497              68 :                 session.files.push_back (f);
    1498                 :               
    1499             320 :               return g;
    1500                 :             }
    1501                 :         }
    1502                 :     }
    1503                 : 
    1504          161173 :   return 0;
    1505                 : }
    1506                 : 
    1507                 : 
    1508                 : functiondecl* 
    1509          291448 : symresolution_info::find_function (const string& name, unsigned arity)
    1510                 : {
    1511       393847520 :   for (unsigned j = 0; j < session.functions.size(); j++)
    1512                 :     {
    1513       393674650 :       functiondecl* fd = session.functions[j];
    1514       393674650 :       if (fd->name == name &&
    1515                 :           fd->formal_args.size() == arity)
    1516          118578 :         return fd;
    1517                 :     }
    1518                 : 
    1519                 :   // search library globals
    1520          738562 :   for (unsigned i=0; i<session.library_files.size(); i++)
    1521                 :     {
    1522          738562 :       stapfile* f = session.library_files[i];
    1523        16064963 :       for (unsigned j=0; j<f->functions.size(); j++)
    1524        15499271 :         if (f->functions[j]->name == name &&
    1525                 :             f->functions[j]->formal_args.size() == arity)
    1526                 :           {
    1527                 :             // put library into the queue if not already there
    1528                 :             if (0) // session.verbose_resolution
    1529                 :               cerr << "      function " << name << " "
    1530                 :                    << "is defined from " << f->name << endl;
    1531                 : 
    1532          172870 :             if (find (session.files.begin(), session.files.end(), f) 
    1533                 :                 == session.files.end())
    1534             760 :               session.files.push_back (f);
    1535                 :             // else .. print different message?
    1536                 : 
    1537          172870 :             return f->functions[j];
    1538                 :           }
    1539                 :     }
    1540                 : 
    1541               0 :   return 0;
    1542                 : }
    1543                 : 
    1544                 : 
    1545                 : 
    1546                 : // ------------------------------------------------------------------------
    1547                 : // optimization
    1548                 : 
    1549                 : 
    1550                 : // Do away with functiondecls that are never (transitively) called
    1551                 : // from probes.
    1552             874 : void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
    1553                 : {
    1554             874 :   functioncall_traversing_visitor ftv;
    1555          590621 :   for (unsigned i=0; i<s.probes.size(); i++)
    1556                 :     {
    1557          589747 :       s.probes[i]->body->visit (& ftv);
    1558          589747 :       if (s.probes[i]->sole_location()->condition)
    1559              26 :         s.probes[i]->sole_location()->condition->visit (& ftv);
    1560                 :     }
    1561          316609 :   for (unsigned i=0; i<s.functions.size(); /* see below */)
    1562                 :     {
    1563          314861 :       if (ftv.traversed.find(s.functions[i]) == ftv.traversed.end())
    1564                 :         {
    1565           59677 :           if (s.functions[i]->tok->location.file == s.user_file->name && // !tapset
    1566                 :               ! s.suppress_warnings)
    1567              31 :             clog << "WARNING: eliding unused function " << *s.functions[i]->tok << endl;
    1568           59646 :           else if (s.verbose>2)
    1569                 :             clog << "Eliding unused function " << s.functions[i]->name
    1570               0 :                  << endl;
    1571           59677 :           if (s.tapset_compile_coverage) {
    1572               0 :             s.unused_functions.push_back (s.functions[i]);
    1573                 :           }
    1574           59677 :           s.functions.erase (s.functions.begin() + i);
    1575           59677 :           relaxed_p = false;
    1576                 :           // NB: don't increment i
    1577                 :         }
    1578                 :       else
    1579          255184 :         i++;
    1580             874 :     }
    1581             874 : }
    1582                 : 
    1583                 : 
    1584                 : // ------------------------------------------------------------------------
    1585                 : 
    1586                 : // Do away with local & global variables that are never
    1587                 : // written nor read.
    1588             874 : void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p)
    1589                 : {
    1590             874 :   varuse_collecting_visitor vut;
    1591                 :   
    1592          590621 :   for (unsigned i=0; i<s.probes.size(); i++)
    1593                 :     {
    1594          589747 :       s.probes[i]->body->visit (& vut);
    1595                 : 
    1596          589747 :       if (s.probes[i]->sole_location()->condition)
    1597              26 :         s.probes[i]->sole_location()->condition->visit (& vut);
    1598                 :     }
    1599                 : 
    1600                 :   // NB: Since varuse_collecting_visitor also traverses down
    1601                 :   // actually called functions, we don't need to explicitly
    1602                 :   // iterate over them.  Uncalled ones should have been pruned
    1603                 :   // in _opt1 above.
    1604                 :   //
    1605                 :   // for (unsigned i=0; i<s.functions.size(); i++)
    1606                 :   //   s.functions[i]->body->visit (& vut);
    1607                 :   
    1608                 :   // Now in vut.read/written, we have a mixture of all locals, globals
    1609                 :   
    1610          590621 :   for (unsigned i=0; i<s.probes.size(); i++)
    1611         1579324 :     for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
    1612                 :       {
    1613          399830 :         vardecl* l = s.probes[i]->locals[j];
    1614                 : 
    1615          399830 :         if (vut.read.find (l) == vut.read.end() &&
    1616                 :             vut.written.find (l) == vut.written.end())
    1617                 :           {
    1618           77955 :             if (l->tok->location.file == s.user_file->name && // !tapset
    1619                 :                 ! s.suppress_warnings)
    1620              64 :               clog << "WARNING: eliding unused variable " << *l->tok << endl;
    1621           77891 :             else if (s.verbose>2)
    1622                 :               clog << "Eliding unused local variable "
    1623               0 :                    << l->name << " in " << s.probes[i]->name << endl;
    1624           77955 :             if (s.tapset_compile_coverage) {
    1625                 :               s.probes[i]->unused_locals.push_back
    1626               0 :                       (s.probes[i]->locals[j]);
    1627                 :             }
    1628           77955 :             s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
    1629           77955 :             relaxed_p = false;
    1630                 :             // don't increment j
    1631                 :           }
    1632                 :         else
    1633          321875 :           j++;
    1634                 :       }
    1635          256058 :   for (unsigned i=0; i<s.functions.size(); i++)
    1636          512339 :     for (unsigned j=0; j<s.functions[i]->locals.size(); /* see below */)
    1637                 :       {
    1638            1971 :         vardecl* l = s.functions[i]->locals[j];
    1639            1971 :         if (vut.read.find (l) == vut.read.end() &&
    1640                 :             vut.written.find (l) == vut.written.end())
    1641                 :           {
    1642               3 :             if (l->tok->location.file == s.user_file->name && // !tapset
    1643                 :                 ! s.suppress_warnings)
    1644               3 :               clog << "WARNING: eliding unused variable " << *l->tok << endl;
    1645               0 :             else if (s.verbose>2)
    1646                 :               clog << "Eliding unused local variable "
    1647                 :                    << l->name << " in function " << s.functions[i]->name
    1648               0 :                    << endl;
    1649               3 :             if (s.tapset_compile_coverage) {
    1650                 :               s.functions[i]->unused_locals.push_back
    1651               0 :                     (s.functions[i]->locals[j]);
    1652                 :             }
    1653               3 :             s.functions[i]->locals.erase(s.functions[i]->locals.begin() + j);
    1654               3 :             relaxed_p = false;
    1655                 :             // don't increment j
    1656                 :           }
    1657                 :         else
    1658            1968 :           j++;
    1659                 :       }
    1660            3700 :   for (unsigned i=0; i<s.globals.size(); /* see below */)
    1661                 :     {
    1662            1952 :       vardecl* l = s.globals[i];
    1663            1952 :       if (vut.read.find (l) == vut.read.end() &&
    1664                 :           vut.written.find (l) == vut.written.end())
    1665                 :         {
    1666              54 :           if (l->tok->location.file == s.user_file->name && // !tapset
    1667                 :               ! s.suppress_warnings)
    1668              24 :             clog << "WARNING: eliding unused variable " << *l->tok << endl;
    1669              30 :           else if (s.verbose>2)
    1670                 :             clog << "Eliding unused global variable "
    1671               0 :                  << l->name << endl;
    1672              54 :           if (s.tapset_compile_coverage) {
    1673               0 :             s.unused_globals.push_back(s.globals[i]);
    1674                 :           }
    1675              54 :           s.globals.erase(s.globals.begin() + i);
    1676              54 :           relaxed_p = false;
    1677                 :           // don't increment i
    1678                 :         }
    1679                 :       else
    1680            1898 :         i++;
    1681             874 :     }
    1682             874 : }
    1683                 : 
    1684                 : 
    1685                 : // ------------------------------------------------------------------------
    1686                 : 
    1687                 : struct dead_assignment_remover: public traversing_visitor
    1688             874 : {
    1689                 :   systemtap_session& session;
    1690                 :   bool& relaxed_p;
    1691                 :   const varuse_collecting_visitor& vut;
    1692                 :   expression** current_expr;
    1693                 : 
    1694                 :   dead_assignment_remover(systemtap_session& s, bool& r,
    1695             874 :                           const varuse_collecting_visitor& v): 
    1696             874 :     session(s), relaxed_p(r), vut(v), current_expr(0) {}
    1697                 : 
    1698                 :   void visit_expr_statement (expr_statement* s);
    1699                 :   // XXX: other places where an assignment may be nested should be
    1700                 :   // handled too (e.g., loop/if conditionals, array indexes, function
    1701                 :   // parameters).  Until then, they result in visit_assignment() being
    1702                 :   // called with null current_expr.
    1703                 : 
    1704                 :   void visit_assignment (assignment* e);
    1705                 : };
    1706                 : 
    1707                 : 
    1708                 : void
    1709          892169 : dead_assignment_remover::visit_expr_statement (expr_statement* s)
    1710                 : {
    1711          892169 :   expression** last_expr = current_expr;
    1712          892169 :   current_expr = & s->value;
    1713          892169 :   s->value->visit (this);
    1714          892168 :   s->tok = s->value->tok; // in case it was replaced
    1715          892168 :   current_expr = last_expr;
    1716          892168 : }
    1717                 : 
    1718                 : 
    1719                 : void
    1720          471256 : dead_assignment_remover::visit_assignment (assignment* e)
    1721                 : {
    1722          471256 :   symbol* left = get_symbol_within_expression (e->left);
    1723          471255 :   vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
    1724          471255 :   if (current_expr && // see XXX above: this case represents a missed
    1725                 :                       // optimization opportunity
    1726                 :       *current_expr == e && // we're not nested any deeper than expected 
    1727                 :       leftvar) // not unresolved $target; intended sideeffect cannot be elided
    1728                 :     {
    1729          471234 :       if (vut.read.find(leftvar) == vut.read.end()) // var never read?
    1730                 :         {
    1731                 :           // NB: Not so fast!  The left side could be an array whose
    1732                 :           // index expressions may have side-effects.  This would be
    1733                 :           // OK if we could replace the array assignment with a 
    1734                 :           // statement-expression containing all the index expressions
    1735                 :           // and the rvalue... but we can't.
    1736                 : 
    1737           78285 :           varuse_collecting_visitor vut;
    1738           78285 :           e->left->visit (& vut);
    1739           78285 :           if (vut.side_effect_free ()) // XXX: use _wrt() once we track focal_vars
    1740                 :             {
    1741                 :               /* PR 1119: NB: This is not necessary here.  A write-only
    1742                 :                  variable will also be elided soon at the next _opt2 iteration.
    1743                 :               if (e->left->tok->location.file == session.user_file->name && // !tapset
    1744                 :                   ! session.suppress_warnings)
    1745                 :                 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
    1746                 :               else
    1747                 :               */
    1748           78266 :               if (session.verbose>2)
    1749                 :                 clog << "Eliding assignment to " << leftvar->name 
    1750               0 :                      << " at " << *e->tok << endl;
    1751                 :               
    1752           78266 :               *current_expr = e->right; // goodbye assignment*
    1753           78266 :               relaxed_p = false;
    1754           78285 :             }
    1755                 :         }
    1756                 :     }
    1757          471255 : }
    1758                 : 
    1759                 : 
    1760                 : // Let's remove assignments to variables that are never read.  We
    1761                 : // rewrite "(foo = expr)" as "(expr)".  This makes foo a candidate to
    1762                 : // be optimized away as an unused variable, and expr a candidate to be
    1763                 : // removed as a side-effect-free statement expression.  Wahoo!
    1764             874 : void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
    1765                 : {
    1766                 :   // Recompute the varuse data, which will probably match the opt2
    1767                 :   // copy of the computation, except for those totally unused
    1768                 :   // variables that opt2 removed.
    1769             874 :   varuse_collecting_visitor vut;
    1770          590621 :   for (unsigned i=0; i<s.probes.size(); i++)
    1771          589747 :     s.probes[i]->body->visit (& vut); // includes reachable functions too
    1772                 : 
    1773             874 :   dead_assignment_remover dar (s, relaxed_p, vut);
    1774                 :   // This instance may be reused for multiple probe/function body trims.
    1775                 : 
    1776          590620 :   for (unsigned i=0; i<s.probes.size(); i++)
    1777          589747 :     s.probes[i]->body->visit (& dar);
    1778          256057 :   for (unsigned i=0; i<s.functions.size(); i++)
    1779          256058 :     s.functions[i]->body->visit (& dar);
    1780                 :   // The rewrite operation is performed within the visitor.
    1781             873 : }
    1782                 : 
    1783                 : 
    1784                 : // ------------------------------------------------------------------------
    1785                 : 
    1786                 : struct dead_stmtexpr_remover: public traversing_visitor
    1787             873 : {
    1788                 :   systemtap_session& session;
    1789                 :   bool& relaxed_p;
    1790                 :   statement** current_stmt; // pointer to current stmt* being iterated
    1791                 :   set<vardecl*> focal_vars; // vars considered subject to side-effects
    1792                 : 
    1793             873 :   dead_stmtexpr_remover(systemtap_session& s, bool& r): 
    1794             873 :     session(s), relaxed_p(r), current_stmt(0) {}
    1795                 : 
    1796                 :   void visit_block (block *s);
    1797                 :   void visit_if_statement (if_statement* s);
    1798                 :   void visit_foreach_loop (foreach_loop *s);
    1799                 :   void visit_for_loop (for_loop *s);
    1800                 :   // XXX: and other places where stmt_expr's might be nested
    1801                 : 
    1802                 :   void visit_expr_statement (expr_statement *s);
    1803                 : };
    1804                 : 
    1805                 : 
    1806                 : void
    1807          730854 : dead_stmtexpr_remover::visit_block (block *s)
    1808                 : {
    1809         1918719 :   for (unsigned i=0; i<s->statements.size(); i++)
    1810                 :     {
    1811         1187865 :       statement** last_stmt = current_stmt;
    1812         1187865 :       current_stmt = & s->statements[i];
    1813         1187865 :       s->statements[i]->visit (this);
    1814         1187865 :       current_stmt = last_stmt;
    1815                 :     }
    1816          730854 : }
    1817                 : 
    1818                 : void
    1819          411677 : dead_stmtexpr_remover::visit_if_statement (if_statement *s)
    1820                 : {
    1821          411677 :   statement** last_stmt = current_stmt;
    1822          411677 :   current_stmt = & s->thenblock;
    1823          411677 :   s->thenblock->visit (this);
    1824          411677 :   if (s->elseblock)
    1825                 :     {
    1826           74166 :       current_stmt = & s->elseblock;
    1827           74166 :       s->elseblock->visit (this);
    1828                 :     }
    1829          411677 :   current_stmt = last_stmt;
    1830          411677 : }
    1831                 : 
    1832                 : void
    1833             277 : dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
    1834                 : {
    1835             277 :   statement** last_stmt = current_stmt;
    1836             277 :   current_stmt = & s->block;
    1837             277 :   s->block->visit (this);
    1838             277 :   current_stmt = last_stmt;
    1839             277 : }
    1840                 : 
    1841                 : void
    1842             400 : dead_stmtexpr_remover::visit_for_loop (for_loop *s)
    1843                 : {
    1844             400 :   statement** last_stmt = current_stmt;
    1845             400 :   current_stmt = & s->block;
    1846             400 :   s->block->visit (this);
    1847             400 :   current_stmt = last_stmt;
    1848             400 : }
    1849                 : 
    1850                 : 
    1851                 : 
    1852                 : void
    1853          891457 : dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
    1854                 : {
    1855                 :   // Run a varuse query against the operand expression.  If it has no
    1856                 :   // side-effects, replace the entire statement expression by a null
    1857                 :   // statement.  This replacement is done by overwriting the
    1858                 :   // current_stmt pointer.
    1859                 :   //
    1860                 :   // Unlike many other visitors, we do *not* traverse this outermost
    1861                 :   // one into the expression subtrees.  There is no need - no
    1862                 :   // expr_statement nodes will be found there.  (Function bodies
    1863                 :   // need to be visited explicitly by our caller.)
    1864                 :   //
    1865                 :   // NB.  While we don't share nodes in the parse tree, let's not
    1866                 :   // deallocate *s anyway, just in case...
    1867                 : 
    1868          891457 :   varuse_collecting_visitor vut;
    1869          891457 :   s->value->visit (& vut);
    1870          891457 :   if (vut.side_effect_free_wrt (focal_vars) &&
    1871                 :       *current_stmt == s) // we're not nested any deeper than expected 
    1872                 :     {
    1873                 :       /* PR 1119: NB: this message is not a good idea here.  It can
    1874                 :          name some arbitrary RHS expression of an assignment.
    1875                 :       if (s->value->tok->location.file == session.user_file->name && // not tapset
    1876                 :           ! session.suppress_warnings)
    1877                 :         clog << "WARNING: eliding read-only " << *s->value->tok << endl;
    1878                 :       else 
    1879                 :       */
    1880           78403 :       if (session.verbose>2)
    1881                 :         clog << "Eliding side-effect-free expression "
    1882               0 :              << *s->tok << endl;
    1883                 : 
    1884           78403 :       null_statement* ns = new null_statement;
    1885           78403 :       ns->tok = s->tok;
    1886           78403 :       * current_stmt = ns;
    1887                 :       // XXX: A null_statement carries more weight in the translator's
    1888                 :       // output than a nonexistent statement.  It might be nice to
    1889                 :       // work a little harder and completely eliminate all traces of
    1890                 :       // an elided statement.
    1891                 :       
    1892           78403 :       relaxed_p = false;
    1893          891457 :     }
    1894          891457 : }
    1895                 : 
    1896                 : 
    1897             873 : void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
    1898                 : {
    1899                 :   // Finally, let's remove some statement-expressions that have no
    1900                 :   // side-effect.  These should be exactly those whose private varuse
    1901                 :   // visitors come back with an empty "written" and "embedded" lists.
    1902                 :   
    1903             873 :   dead_stmtexpr_remover duv (s, relaxed_p);
    1904                 :   // This instance may be reused for multiple probe/function body trims.
    1905                 : 
    1906          590619 :   for (unsigned i=0; i<s.probes.size(); i++)
    1907                 :     {
    1908          589746 :       duv.focal_vars.clear ();
    1909                 :       duv.focal_vars.insert (s.globals.begin(),
    1910          589746 :                              s.globals.end());
    1911                 :       duv.focal_vars.insert (s.probes[i]->locals.begin(),
    1912          589746 :                              s.probes[i]->locals.end());
    1913          589746 :       s.probes[i]->body->visit (& duv);
    1914                 :     }
    1915          256057 :   for (unsigned i=0; i<s.functions.size(); i++)
    1916                 :     {
    1917          255184 :       duv.focal_vars.clear ();
    1918                 :       duv.focal_vars.insert (s.functions[i]->locals.begin(),
    1919          255184 :                              s.functions[i]->locals.end());
    1920                 :       duv.focal_vars.insert (s.functions[i]->formal_args.begin(),
    1921          255184 :                              s.functions[i]->formal_args.end());
    1922                 :       duv.focal_vars.insert (s.globals.begin(),
    1923          255184 :                              s.globals.end());
    1924          255184 :       s.functions[i]->body->visit (& duv);
    1925             873 :     }
    1926             873 : }
    1927                 : 
    1928                 : struct duplicate_function_remover: public functioncall_traversing_visitor
    1929              89 : {
    1930                 :   systemtap_session& s;
    1931                 :   map<functiondecl*, functiondecl*>& duplicate_function_map;
    1932                 : 
    1933                 :   duplicate_function_remover(systemtap_session& sess,
    1934              89 :                              map<functiondecl*, functiondecl*>&dfm):
    1935              89 :     s(sess), duplicate_function_map(dfm) {};
    1936                 : 
    1937                 :   void visit_functioncall (functioncall* e);
    1938                 : };
    1939                 : 
    1940                 : void
    1941          217843 : duplicate_function_remover::visit_functioncall (functioncall *e)
    1942                 : {
    1943          217843 :   functioncall_traversing_visitor::visit_functioncall (e);
    1944                 : 
    1945                 :   // If the current function call reference points to a function that
    1946                 :   // is a duplicate, replace it.
    1947          217843 :   if (duplicate_function_map.count(e->referent) != 0)
    1948                 :     {
    1949           59261 :       if (s.verbose>2)
    1950                 :           clog << "Changing " << e->referent->name
    1951                 :                << " reference to "
    1952                 :                << duplicate_function_map[e->referent]->name
    1953               0 :                << " reference\n";
    1954           59261 :       e->tok = duplicate_function_map[e->referent]->tok;
    1955           59261 :       e->function = duplicate_function_map[e->referent]->name;
    1956           59261 :       e->referent = duplicate_function_map[e->referent];
    1957                 :     }
    1958          217843 : }
    1959                 : 
    1960                 : static string
    1961           73858 : get_functionsig (functiondecl* f)
    1962                 : {
    1963           73858 :   ostringstream s;
    1964                 : 
    1965                 :   // Get the "name:args body" of the function in s.  We have to
    1966                 :   // include the args since the function 'x1(a, b)' is different than
    1967                 :   // the function 'x2(b, a)' even if the bodies of the two functions
    1968                 :   // are exactly the same.
    1969           73858 :   f->printsig(s);
    1970           73858 :   f->body->print(s);
    1971                 : 
    1972                 :   // printsig puts f->name + ':' on the front.  Remove this
    1973                 :   // (otherwise, functions would never compare equal).
    1974           73858 :   string str = s.str().erase(0, f->name.size() + 1);
    1975                 : 
    1976                 :   // Return the function signature.
    1977           73858 :   return str;
    1978                 : }
    1979                 : 
    1980             473 : void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
    1981                 : {
    1982                 :   // Walk through all the functions, looking for duplicates.
    1983             473 :   map<string, functiondecl*> functionsig_map;
    1984             473 :   map<functiondecl*, functiondecl*> duplicate_function_map;
    1985           74331 :   for (unsigned i=0; i < s.functions.size(); /* see below */)
    1986                 :     {
    1987           73858 :       string functionsig = get_functionsig(s.functions[i]);
    1988                 : 
    1989           73858 :       if (functionsig_map.count(functionsig) == 0)
    1990                 :         {
    1991                 :           // This function is unique.  Remember it.
    1992           14597 :           functionsig_map[functionsig] = s.functions[i];
    1993           14597 :           i++;
    1994                 :         }
    1995                 :       else
    1996                 :         {
    1997                 :           // This function is a duplicate.
    1998                 :           duplicate_function_map[s.functions[i]]
    1999           59261 :             = functionsig_map[functionsig];
    2000                 : 
    2001                 :           // Remove the duplicate function (since we don't need it
    2002                 :           // anymore).
    2003           59261 :           s.functions.erase (s.functions.begin() + i);
    2004                 : 
    2005           59261 :           relaxed_p = false;
    2006                 :           // NB: don't increment i
    2007                 :         }
    2008                 :     }
    2009                 : 
    2010                 :   // If we have duplicate functions, traverse down the tree, replacing
    2011                 :   // the appropriate function calls.
    2012                 :   // duplicate_function_remover::visit_functioncall() handles the
    2013                 :   // details of replacing the function calls.
    2014             473 :   if (duplicate_function_map.size() != 0)
    2015                 :     {
    2016              89 :       duplicate_function_remover dfr (s, duplicate_function_map);
    2017                 : 
    2018           47598 :       for (unsigned i=0; i < s.probes.size(); i++)
    2019           47598 :         s.probes[i]->body->visit(&dfr);
    2020             473 :     }
    2021             473 : }
    2022                 : 
    2023                 : 
    2024                 : static int
    2025             400 : semantic_pass_optimize1 (systemtap_session& s)
    2026                 : {
    2027                 :   // In this pass, we attempt to rewrite probe/function bodies to
    2028                 :   // eliminate some blatantly unnecessary code.  This is run before
    2029                 :   // type inference, but after symbol resolution and derived_probe
    2030                 :   // creation.  We run an outer "relaxation" loop that repeats the
    2031                 :   // optimizations until none of them find anything to remove.
    2032                 : 
    2033             400 :   int rc = 0;
    2034                 : 
    2035             400 :   bool relaxed_p = false;
    2036            1673 :   while (! relaxed_p)
    2037                 :     {
    2038             874 :       if (pending_interrupts) break;
    2039                 : 
    2040             874 :       relaxed_p = true; // until proven otherwise
    2041                 : 
    2042             874 :       semantic_pass_opt1 (s, relaxed_p);
    2043             874 :       semantic_pass_opt2 (s, relaxed_p);
    2044             874 :       semantic_pass_opt3 (s, relaxed_p);
    2045             873 :       semantic_pass_opt4 (s, relaxed_p);
    2046                 :     }
    2047                 : 
    2048             399 :   if (s.probes.size() == 0)
    2049               0 :     throw semantic_error ("no probes found");
    2050                 : 
    2051             399 :   return rc;
    2052                 : }
    2053                 : 
    2054                 : 
    2055                 : static int
    2056             384 : semantic_pass_optimize2 (systemtap_session& s)
    2057                 : {
    2058                 :   // This is run after type inference.  We run an outer "relaxation"
    2059                 :   // loop that repeats the optimizations until none of them find
    2060                 :   // anything to remove.
    2061                 : 
    2062             384 :   int rc = 0;
    2063                 : 
    2064             384 :   bool relaxed_p = false;
    2065            1241 :   while (! relaxed_p)
    2066                 :     {
    2067             473 :       if (pending_interrupts) break;
    2068             473 :       relaxed_p = true; // until proven otherwise
    2069                 : 
    2070             473 :       semantic_pass_opt5 (s, relaxed_p);
    2071                 :     }
    2072                 : 
    2073             384 :   if (s.probes.size() == 0)
    2074               0 :     throw semantic_error ("no probes found");
    2075                 : 
    2076             384 :   return rc;
    2077                 : }
    2078                 : 
    2079                 : 
    2080                 : 
    2081                 : // ------------------------------------------------------------------------
    2082                 : // type resolution
    2083                 : 
    2084                 : 
    2085                 : static int
    2086             432 : semantic_pass_types (systemtap_session& s)
    2087                 : {
    2088             432 :   int rc = 0;
    2089                 : 
    2090                 :   // next pass: type inference
    2091             432 :   unsigned iterations = 0;
    2092             432 :   typeresolution_info ti (s);
    2093                 :   
    2094             432 :   ti.assert_resolvability = false;
    2095                 :   // XXX: maybe convert to exception-based error signalling
    2096             772 :   while (1)
    2097                 :     {
    2098            1204 :       if (pending_interrupts) break;
    2099                 : 
    2100            1204 :       iterations ++;
    2101            1204 :       ti.num_newly_resolved = 0;
    2102            1204 :       ti.num_still_unresolved = 0;
    2103                 : 
    2104          268877 :       for (unsigned j=0; j<s.functions.size(); j++)
    2105                 :         {
    2106          267673 :           if (pending_interrupts) break;
    2107                 : 
    2108          267673 :           functiondecl* fn = s.functions[j];
    2109          267673 :           ti.current_probe = 0;
    2110          267673 :           ti.current_function = fn;
    2111          267673 :           ti.t = pe_unknown;
    2112          267673 :           fn->body->visit (& ti);
    2113                 :           // NB: we don't have to assert a known type for
    2114                 :           // functions here, to permit a "void" function.
    2115                 :           // The translator phase will omit the "retvalue".
    2116                 :           //
    2117                 :           // if (fn->type == pe_unknown)
    2118                 :           //   ti.unresolved (fn->tok);
    2119                 :         }          
    2120                 : 
    2121          643840 :       for (unsigned j=0; j<s.probes.size(); j++)
    2122                 :         {
    2123          642636 :           if (pending_interrupts) break;
    2124                 : 
    2125          642636 :           derived_probe* pn = s.probes[j];
    2126          642636 :           ti.current_function = 0;
    2127          642636 :           ti.current_probe = pn;
    2128          642636 :           ti.t = pe_unknown;
    2129          642636 :           pn->body->visit (& ti);
    2130                 : 
    2131          642636 :           probe_point* pp = pn->sole_location();
    2132          642636 :           if (pp->condition)
    2133                 :             {
    2134              30 :               ti.current_function = 0;
    2135              30 :               ti.current_probe = 0;
    2136              30 :               ti.t = pe_long; // NB: expected type
    2137              30 :               pp->condition->visit (& ti);
    2138                 :             }
    2139                 :         }
    2140                 : 
    2141            3968 :       for (unsigned j=0; j<s.globals.size(); j++)
    2142                 :         {
    2143            2764 :           vardecl* gd = s.globals[j];
    2144            2764 :           if (gd->type == pe_unknown)
    2145             646 :             ti.unresolved (gd->tok);
    2146                 :         }
    2147                 :       
    2148            1204 :       if (ti.num_newly_resolved == 0) // converged
    2149                 :         {
    2150             448 :           if (ti.num_still_unresolved == 0)
    2151             416 :             break; // successfully
    2152              32 :           else if (! ti.assert_resolvability)
    2153              16 :             ti.assert_resolvability = true; // last pass, with error msgs
    2154                 :           else
    2155                 :             { // unsuccessful conclusion
    2156              16 :               rc ++;
    2157              16 :               break;
    2158                 :             }
    2159                 :         }
    2160                 :     }
    2161                 :   
    2162             432 :   return rc + s.num_errors();
    2163                 : }
    2164                 : 
    2165                 : 
    2166                 : 
    2167             432 : typeresolution_info::typeresolution_info (systemtap_session& s):
    2168             432 :   session(s), current_function(0), current_probe(0)
    2169                 : {
    2170             432 : }
    2171                 : 
    2172                 : 
    2173                 : void
    2174          389705 : typeresolution_info::visit_literal_number (literal_number* e)
    2175                 : {
    2176          389705 :   assert (e->type == pe_long);
    2177          389705 :   if ((t == e->type) || (t == pe_unknown))
    2178          389701 :     return;
    2179                 : 
    2180               4 :   mismatch (e->tok, e->type, t);
    2181                 : }
    2182                 : 
    2183                 : 
    2184                 : void
    2185          204762 : typeresolution_info::visit_literal_string (literal_string* e)
    2186                 : {
    2187          204762 :   assert (e->type == pe_string);
    2188          204762 :   if ((t == e->type) || (t == pe_unknown))
    2189          204754 :     return;
    2190                 : 
    2191               8 :   mismatch (e->tok, e->type, t);
    2192                 : }
    2193                 : 
    2194                 : 
    2195                 : void
    2196             247 : typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
    2197                 : {
    2198             247 :   visit_binary_expression (e);
    2199             247 : }
    2200                 : 
    2201                 : 
    2202                 : void
    2203             425 : typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
    2204                 : {
    2205             425 :   visit_binary_expression (e);
    2206             425 : }
    2207                 : 
    2208                 : 
    2209                 : void
    2210          271621 : typeresolution_info::visit_comparison (comparison *e)
    2211                 : {
    2212                 :   // NB: result of any comparison is an integer!
    2213          271621 :   if (t == pe_stats || t == pe_string)
    2214               0 :     invalid (e->tok, t);
    2215                 : 
    2216          271621 :   t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
    2217          271621 :   e->left->visit (this);
    2218          271619 :   t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
    2219          271619 :   e->right->visit (this);
    2220                 :   
    2221          271619 :   if (e->left->type != pe_unknown &&
    2222                 :       e->right->type != pe_unknown &&
    2223                 :       e->left->type != e->right->type)
    2224               0 :     mismatch (e->tok, e->left->type, e->right->type);
    2225                 :   
    2226          271619 :   if (e->type == pe_unknown)
    2227                 :     {
    2228           68103 :       e->type = pe_long;
    2229           68103 :       resolved (e->tok, e->type);
    2230                 :     }
    2231          271619 : }
    2232                 : 
    2233                 : 
    2234                 : void
    2235           12625 : typeresolution_info::visit_concatenation (concatenation *e)
    2236                 : {
    2237           12625 :   if (t != pe_unknown && t != pe_string)
    2238               0 :     invalid (e->tok, t);
    2239                 : 
    2240           12625 :   t = pe_string;
    2241           12625 :   e->left->visit (this);
    2242           12625 :   t = pe_string;
    2243           12625 :   e->right->visit (this);
    2244                 : 
    2245           12625 :   if (e->type == pe_unknown)
    2246                 :     {
    2247            3181 :       e->type = pe_string;
    2248            3181 :       resolved (e->tok, e->type);
    2249                 :     }
    2250           12625 : }
    2251                 : 
    2252                 : 
    2253                 : void
    2254          529676 : typeresolution_info::visit_assignment (assignment *e)
    2255                 : {
    2256          529676 :   if (t == pe_stats)
    2257               0 :     invalid (e->tok, t);
    2258                 : 
    2259          529676 :   if (e->op == "<<<") // stats aggregation
    2260                 :     {
    2261            7483 :       if (t == pe_string)
    2262               0 :         invalid (e->tok, t);
    2263                 : 
    2264            7483 :       t = pe_stats;
    2265            7483 :       e->left->visit (this);
    2266            7483 :       t = pe_long;
    2267            7483 :       e->right->visit (this);
    2268            7483 :       if (e->type == pe_unknown ||
    2269                 :           e->type == pe_stats)
    2270                 :         {
    2271            2382 :           e->type = pe_long;
    2272            2382 :           resolved (e->tok, e->type);
    2273                 :         }
    2274                 :     }
    2275                 : 
    2276          522193 :   else if (e->left->type == pe_stats)
    2277               0 :     invalid (e->left->tok, e->left->type);
    2278                 : 
    2279          522193 :   else if (e->right->type == pe_stats)
    2280               0 :     invalid (e->right->tok, e->right->type);
    2281                 : 
    2282          522193 :   else if (e->op == "+=" || // numeric only
    2283                 :            e->op == "-=" ||
    2284                 :            e->op == "*=" ||
    2285                 :            e->op == "/=" ||
    2286                 :            e->op == "%=" ||
    2287                 :            e->op == "&=" ||
    2288                 :            e->op == "^=" ||
    2289                 :            e->op == "|=" ||
    2290                 :            e->op == "<<=" ||
    2291                 :            e->op == ">>=" ||
    2292                 :            false)
    2293                 :     {
    2294             196 :       visit_binary_expression (e);
    2295                 :     }
    2296          521997 :   else if (e->op == ".=" || // string only
    2297                 :            false)
    2298                 :     {
    2299              50 :       if (t == pe_long || t == pe_stats)
    2300               0 :         invalid (e->tok, t);
    2301                 : 
    2302              50 :       t = pe_string;
    2303              50 :       e->left->visit (this);
    2304              50 :       t = pe_string;
    2305              50 :       e->right->visit (this);
    2306              50 :       if (e->type == pe_unknown)
    2307                 :         {
    2308              16 :           e->type = pe_string;
    2309              16 :           resolved (e->tok, e->type);
    2310                 :         }
    2311                 :     }
    2312          521947 :   else if (e->op == "=") // overloaded = for string & numeric operands
    2313                 :     {
    2314                 :       // logic similar to ternary_expression
    2315          521947 :       exp_type sub_type = t;
    2316                 : 
    2317                 :       // Infer types across the l/r values
    2318          521947 :       if (sub_type == pe_unknown && e->type != pe_unknown)
    2319          331647 :         sub_type = e->type;
    2320                 : 
    2321                 :       t = (sub_type != pe_unknown) ? sub_type :
    2322                 :         (e->right->type != pe_unknown) ? e->right->type :
    2323          521947 :         pe_unknown;
    2324          521947 :       e->left->visit (this);
    2325                 :       t = (sub_type != pe_unknown) ? sub_type :
    2326                 :         (e->left->type != pe_unknown) ? e->left->type :
    2327          521947 :         pe_unknown;
    2328          521947 :       e->right->visit (this);
    2329                 :       
    2330          521907 :       if ((sub_type != pe_unknown) && (e->type == pe_unknown))
    2331                 :         {
    2332               3 :           e->type = sub_type;
    2333               3 :           resolved (e->tok, e->type);
    2334                 :         }
    2335          521907 :       if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
    2336                 :         {
    2337          130409 :           e->type = e->left->type;
    2338          130409 :           resolved (e->tok, e->type);
    2339                 :         }
    2340                 : 
    2341          521907 :       if (e->left->type != pe_unknown &&
    2342                 :           e->right->type != pe_unknown &&
    2343                 :           e->left->type != e->right->type)
    2344               0 :         mismatch (e->tok, e->left->type, e->right->type);
    2345                 : 
    2346                 :     }
    2347                 :   else
    2348               0 :     throw semantic_error ("unsupported assignment operator " + e->op);
    2349          529636 : }
    2350                 : 
    2351                 : 
    2352                 : void
    2353           20516 : typeresolution_info::visit_binary_expression (binary_expression* e)
    2354                 : {
    2355           20516 :   if (t == pe_stats || t == pe_string)
    2356               0 :     invalid (e->tok, t);
    2357                 : 
    2358           20516 :   t = pe_long;
    2359           20516 :   e->left->visit (this);
    2360           20516 :   t = pe_long;
    2361           20516 :   e->right->visit (this);
    2362                 : 
    2363           20516 :   if (e->left->type != pe_unknown &&
    2364                 :       e->right->type != pe_unknown &&
    2365                 :       e->left->type != e->right->type)
    2366               0 :     mismatch (e->tok, e->left->type, e->right->type);
    2367                 :   
    2368           20516 :   if (e->type == pe_unknown)
    2369                 :     {
    2370            5210 :       e->type = pe_long;
    2371            5210 :       resolved (e->tok, e->type);
    2372                 :     }
    2373           20516 : }
    2374                 : 
    2375                 : 
    2376                 : void
    2377            2330 : typeresolution_info::visit_pre_crement (pre_crement *e)
    2378                 : {
    2379            2330 :   visit_unary_expression (e);
    2380            2330 : }
    2381                 : 
    2382                 : 
    2383                 : void
    2384          183387 : typeresolution_info::visit_post_crement (post_crement *e)
    2385                 : {
    2386          183387 :   visit_unary_expression (e);
    2387          183387 : }
    2388                 : 
    2389                 : 
    2390                 : void
    2391          189601 : typeresolution_info::visit_unary_expression (unary_expression* e)
    2392                 : {
    2393          189601 :   if (t == pe_stats || t == pe_string)
    2394               0 :     invalid (e->tok, t);
    2395                 : 
    2396          189601 :   t = pe_long;
    2397          189601 :   e->operand->visit (this);
    2398                 : 
    2399          189601 :   if (e->type == pe_unknown)
    2400                 :     {
    2401           47816 :       e->type = pe_long;
    2402           47816 :       resolved (e->tok, e->type);
    2403                 :     }
    2404          189601 : }
    2405                 : 
    2406                 : 
    2407                 : void
    2408             141 : typeresolution_info::visit_ternary_expression (ternary_expression* e)
    2409                 : {
    2410             141 :   exp_type sub_type = t;
    2411                 : 
    2412             141 :   t = pe_long;
    2413             141 :   e->cond->visit (this);
    2414                 : 
    2415                 :   // Infer types across the true/false arms of the ternary expression.
    2416                 : 
    2417             141 :   if (sub_type == pe_unknown && e->type != pe_unknown)
    2418               0 :     sub_type = e->type;
    2419             141 :   t = sub_type;
    2420             141 :   e->truevalue->visit (this);
    2421             141 :   t = sub_type;
    2422             141 :   e->falsevalue->visit (this);
    2423                 : 
    2424             141 :   if ((sub_type == pe_unknown) && (e->type != pe_unknown))
    2425                 :     ; // already resolved
    2426             166 :   else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
    2427                 :     {
    2428              25 :       e->type = sub_type;
    2429              25 :       resolved (e->tok, e->type);
    2430                 :     }
    2431             126 :   else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
    2432                 :     {
    2433              10 :       e->type = e->truevalue->type;
    2434              10 :       resolved (e->tok, e->type);
    2435                 :     }
    2436             106 :   else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
    2437                 :     {
    2438               0 :       e->type = e->falsevalue->type;
    2439               0 :       resolved (e->tok, e->type);
    2440                 :     }
    2441             106 :   else if (e->type != sub_type)
    2442               0 :     mismatch (e->tok, sub_type, e->type);
    2443             141 : }
    2444                 : 
    2445                 : 
    2446                 : template <class Referrer, class Referent>
    2447                 : void resolve_2types (Referrer* referrer, Referent* referent,
    2448         2790010 :                     typeresolution_info* r, exp_type t, bool accept_unknown = false)
    2449                 : {
    2450         2790010 :   exp_type& re_type = referrer->type;
    2451         2790010 :   const token* re_tok = referrer->tok;
    2452         2790010 :   exp_type& te_type = referent->type;
    2453         2790010 :   const token* te_tok = referent->tok;
    2454                 : 
    2455         2790010 :   if (t != pe_unknown && re_type == t && re_type == te_type)
    2456                 :     ; // do nothing: all three e->types in agreement
    2457          859606 :   else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
    2458                 :     ; // do nothing: two known e->types in agreement
    2459          854241 :   else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
    2460              47 :     r->mismatch (re_tok, re_type, te_type);
    2461          854147 :   else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
    2462               0 :     r->mismatch (re_tok, re_type, t);
    2463          854157 :   else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
    2464              10 :     r->mismatch (te_tok, te_type, t);
    2465         1465745 :   else if (re_type == pe_unknown && t != pe_unknown)
    2466                 :     {
    2467                 :       // propagate from upstream
    2468          611608 :       re_type = t;
    2469          611608 :       r->resolved (re_tok, re_type);
    2470                 :       // catch re_type/te_type mismatch later
    2471                 :     }
    2472          327443 :   else if (re_type == pe_unknown && te_type != pe_unknown)
    2473                 :     {
    2474                 :       // propagate from referent
    2475           84914 :       re_type = te_type;
    2476           84914 :       r->resolved (re_tok, re_type);
    2477                 :       // catch re_type/t mismatch later
    2478                 :     }
    2479          240733 :   else if (re_type != pe_unknown && te_type == pe_unknown)
    2480                 :     {
    2481                 :       // propagate to referent
    2482           83118 :       te_type = re_type;
    2483           83118 :       r->resolved (te_tok, te_type);
    2484                 :       // catch re_type/t mismatch later
    2485                 :     }
    2486           74497 :   else if (! accept_unknown)
    2487           65385 :     r->unresolved (re_tok);
    2488                 : }
    2489                 : 
    2490                 : 
    2491                 : void
    2492         1689145 : typeresolution_info::visit_symbol (symbol* e)
    2493                 : {
    2494         1689145 :   assert (e->referent != 0);
    2495         1689145 :   resolve_2types (e, e->referent, this, t);
    2496         1689145 : }
    2497                 : 
    2498                 : 
    2499                 : void
    2500              55 : typeresolution_info::visit_target_symbol (target_symbol* e)
    2501                 : {
    2502                 :   // This occurs only if a target symbol was not resolved over in
    2503                 :   // tapset.cxx land, that error was properly suppressed, and the
    2504                 :   // later unused-expression-elimination pass didn't get rid of it
    2505                 :   // either.  So we have a target symbol that is believed to be of
    2506                 :   // genuine use, yet unresolved by the provider.
    2507              55 :   if (e->saved_conversion_error)
    2508              54 :     throw (* (e->saved_conversion_error));
    2509                 :   else
    2510               1 :     throw semantic_error("unresolved target-symbol expression", e->tok);
    2511                 : }
    2512                 : 
    2513                 : 
    2514                 : void
    2515          195025 : typeresolution_info::visit_arrayindex (arrayindex* e)
    2516                 : {
    2517                 : 
    2518          195025 :   symbol *array = NULL;
    2519          195025 :   hist_op *hist = NULL;
    2520          195025 :   classify_indexable(e->base, array, hist);
    2521                 :   
    2522                 :   // Every hist_op has type [int]:int, that is to say, every hist_op
    2523                 :   // is a pseudo-one-dimensional integer array type indexed by
    2524                 :   // integers (bucket numbers).
    2525                 : 
    2526          195025 :   if (hist)
    2527                 :     {
    2528              59 :       if (e->indexes.size() != 1)
    2529               0 :         unresolved (e->tok);
    2530              59 :       t = pe_long;
    2531              59 :       e->indexes[0]->visit (this);
    2532              59 :       if (e->indexes[0]->type != pe_long)
    2533               0 :         unresolved (e->tok);
    2534              59 :       hist->visit (this);
    2535              59 :       if (e->type != pe_long)
    2536                 :         {
    2537              19 :           e->type = pe_long;
    2538              19 :           resolved (e->tok, pe_long);
    2539                 :         }
    2540              59 :       return;
    2541                 :     }
    2542                 : 
    2543                 :   // Now we are left with "normal" map inference and index checking.
    2544                 : 
    2545          194966 :   assert (array);
    2546          194966 :   assert (array->referent != 0);
    2547          194966 :   resolve_2types (e, array->referent, this, t);
    2548                 : 
    2549                 :   // now resolve the array indexes
    2550                 : 
    2551                 :   // if (e->referent->index_types.size() == 0)
    2552                 :   //   // redesignate referent as array
    2553                 :   //   e->referent->set_arity (e->indexes.size ());
    2554                 : 
    2555          194966 :   if (e->indexes.size() != array->referent->index_types.size())
    2556               0 :     unresolved (e->tok); // symbol resolution should prevent this
    2557          392927 :   else for (unsigned i=0; i<e->indexes.size(); i++)
    2558                 :     {
    2559          197961 :       expression* ee = e->indexes[i];
    2560          197961 :       exp_type& ft = array->referent->index_types [i];
    2561          197961 :       t = ft;
    2562          197961 :       ee->visit (this);
    2563          197961 :       exp_type at = ee->type;
    2564                 : 
    2565          197961 :       if ((at == pe_string || at == pe_long) && ft == pe_unknown)
    2566                 :         {
    2567                 :           // propagate to formal type
    2568             472 :           ft = at;
    2569             472 :           resolved (array->referent->tok, ft);
    2570                 :           // uses array decl as there is no token for "formal type"
    2571                 :         }
    2572          197961 :       if (at == pe_stats)
    2573               0 :         invalid (ee->tok, at);
    2574          197961 :       if (ft == pe_stats)
    2575               0 :         invalid (ee->tok, ft);
    2576          197961 :       if (at != pe_unknown && ft != pe_unknown && ft != at)
    2577               0 :         mismatch (e->tok, at, ft);
    2578          197961 :       if (at == pe_unknown)
    2579            1586 :           unresolved (ee->tok);
    2580                 :     }
    2581                 : }
    2582                 : 
    2583                 : 
    2584                 : void
    2585          905656 : typeresolution_info::visit_functioncall (functioncall* e)
    2586                 : {
    2587          905656 :   assert (e->referent != 0);
    2588                 : 
    2589          905656 :   resolve_2types (e, e->referent, this, t, true); // accept unknown type 
    2590                 : 
    2591          905656 :   if (e->type == pe_stats)
    2592               0 :     invalid (e->tok, e->type);
    2593                 : 
    2594                 :   // now resolve the function parameters
    2595          905656 :   if (e->args.size() != e->referent->formal_args.size())
    2596               0 :     unresolved (e->tok); // symbol resolution should prevent this
    2597         1096139 :   else for (unsigned i=0; i<e->args.size(); i++)
    2598                 :     {
    2599          190484 :       expression* ee = e->args[i];
    2600          190484 :       exp_type& ft = e->referent->formal_args[i]->type;
    2601          190484 :       const token* fe_tok = e->referent->formal_args[i]->tok;
    2602          190484 :       t = ft;
    2603          190484 :       ee->visit (this);
    2604          190483 :       exp_type at = ee->type;
    2605                 :       
    2606          190483 :       if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
    2607                 :         {
    2608                 :           // propagate to formal arg
    2609            1730 :           ft = at;
    2610            1730 :           resolved (e->referent->formal_args[i]->tok, ft);
    2611                 :         }
    2612          190483 :       if (at == pe_stats)
    2613               0 :         invalid (e->tok, at);
    2614          190483 :       if (ft == pe_stats)
    2615               3 :         invalid (fe_tok, ft);
    2616          190483 :       if (at != pe_unknown && ft != pe_unknown && ft != at)
    2617               0 :         mismatch (e->tok, at, ft);
    2618          190483 :       if (at == pe_unknown)
    2619             561 :         unresolved (e->tok);
    2620                 :     }
    2621          905655 : }
    2622                 : 
    2623                 : 
    2624                 : void
    2625          830802 : typeresolution_info::visit_block (block* e)
    2626                 : {
    2627         2402254 :   for (unsigned i=0; i<e->statements.size(); i++)
    2628                 :     {
    2629                 :       try 
    2630                 :         {
    2631         1571452 :           t = pe_unknown;
    2632         1571452 :           e->statements[i]->visit (this);
    2633                 :         }
    2634             110 :       catch (const semantic_error& e)
    2635                 :         {
    2636              55 :           session.print_error (e);
    2637                 :         }
    2638                 :     }
    2639          830802 : }
    2640                 : 
    2641                 : 
    2642                 : void
    2643          259433 : typeresolution_info::visit_embeddedcode (embeddedcode*)
    2644                 : {
    2645          259433 : }
    2646                 : 
    2647                 : 
    2648                 : void
    2649          549695 : typeresolution_info::visit_if_statement (if_statement* e)
    2650                 : {
    2651          549695 :   t = pe_long;
    2652          549695 :   e->condition->visit (this);
    2653                 : 
    2654          549693 :   t = pe_unknown;
    2655          549693 :   e->thenblock->visit (this);
    2656                 : 
    2657          549693 :   if (e->elseblock)
    2658                 :     {
    2659           98836 :       t = pe_unknown;
    2660           98836 :       e->elseblock->visit (this);
    2661                 :     }
    2662          549693 : }
    2663                 : 
    2664                 : 
    2665                 : void
    2666             683 : typeresolution_info::visit_for_loop (for_loop* e)
    2667                 : {
    2668             683 :   t = pe_unknown;
    2669             683 :   if (e->init) e->init->visit (this);
    2670             683 :   t = pe_long;
    2671             683 :   e->cond->visit (this);
    2672             683 :   t = pe_unknown;
    2673             683 :   if (e->incr) e->incr->visit (this);  
    2674             683 :   t = pe_unknown;
    2675             683 :   e->block->visit (this);  
    2676             683 : }
    2677                 : 
    2678                 : 
    2679                 : void
    2680             411 : typeresolution_info::visit_foreach_loop (foreach_loop* e)
    2681                 : {
    2682                 :   // See also visit_arrayindex.
    2683                 :   // This is different in that, being a statement, we can't assign
    2684                 :   // a type to the outer array, only propagate to/from the indexes
    2685                 : 
    2686                 :   // if (e->referent->index_types.size() == 0)
    2687                 :   //   // redesignate referent as array
    2688                 :   //   e->referent->set_arity (e->indexes.size ());
    2689                 : 
    2690             411 :   symbol *array = NULL;
    2691             411 :   hist_op *hist = NULL;
    2692             411 :   classify_indexable(e->base, array, hist);
    2693                 : 
    2694             411 :   if (hist)
    2695                 :     {      
    2696              18 :       if (e->indexes.size() != 1)
    2697               0 :         unresolved (e->tok);
    2698              18 :       t = pe_long;
    2699              18 :       e->indexes[0]->visit (this);
    2700              18 :       if (e->indexes[0]->type != pe_long)
    2701               0 :         unresolved (e->tok);
    2702              18 :       hist->visit (this);
    2703                 :     }
    2704                 :   else
    2705                 :     {
    2706             393 :       assert (array);  
    2707             393 :       if (e->indexes.size() != array->referent->index_types.size())
    2708               0 :         unresolved (e->tok); // symbol resolution should prevent this
    2709             871 :       else for (unsigned i=0; i<e->indexes.size(); i++)
    2710                 :         {
    2711             478 :           expression* ee = e->indexes[i];
    2712             478 :           exp_type& ft = array->referent->index_types [i];
    2713             478 :           t = ft;
    2714             478 :           ee->visit (this);
    2715             478 :           exp_type at = ee->type;
    2716                 :           
    2717             478 :           if ((at == pe_string || at == pe_long) && ft == pe_unknown)
    2718                 :             {
    2719                 :               // propagate to formal type
    2720               0 :               ft = at;
    2721               0 :               resolved (array->referent->tok, ft);
    2722                 :               // uses array decl as there is no token for "formal type"
    2723                 :             }
    2724             478 :           if (at == pe_stats)
    2725               0 :             invalid (ee->tok, at);
    2726             478 :           if (ft == pe_stats)
    2727               0 :             invalid (ee->tok, ft);
    2728             478 :           if (at != pe_unknown && ft != pe_unknown && ft != at)
    2729               0 :             mismatch (e->tok, at, ft);
    2730             478 :           if (at == pe_unknown)
    2731              64 :             unresolved (ee->tok);
    2732                 :         }
    2733                 :     }
    2734                 : 
    2735             411 :   if (e->limit)
    2736                 :     {
    2737              65 :       t = pe_long;
    2738              65 :       e->limit->visit (this);
    2739                 :     }
    2740                 : 
    2741             411 :   t = pe_unknown;
    2742             411 :   e->block->visit (this);  
    2743             411 : }
    2744                 : 
    2745                 : 
    2746                 : void
    2747          310264 : typeresolution_info::visit_null_statement (null_statement*)
    2748                 : {
    2749          310264 : }
    2750                 : 
    2751                 : 
    2752                 : void
    2753         1091337 : typeresolution_info::visit_expr_statement (expr_statement* e)
    2754                 : {
    2755         1091337 :   t = pe_unknown;
    2756         1091337 :   e->value->visit (this);
    2757         1091284 : }
    2758                 : 
    2759                 : 
    2760                 : struct delete_statement_typeresolution_info: 
    2761                 :   public throwing_visitor
    2762            2340 : {
    2763                 :   typeresolution_info *parent;
    2764            2340 :   delete_statement_typeresolution_info (typeresolution_info *p):
    2765                 :     throwing_visitor ("invalid operand of delete expression"),
    2766            2340 :     parent (p)
    2767            2340 :   {}
    2768                 : 
    2769            2097 :   void visit_arrayindex (arrayindex* e)
    2770                 :   {
    2771            2097 :     parent->visit_arrayindex (e);
    2772            2097 :   }
    2773                 :   
    2774             243 :   void visit_symbol (symbol* e)
    2775                 :   {
    2776             243 :     exp_type ignored = pe_unknown;
    2777             243 :     assert (e->referent != 0);    
    2778             243 :     resolve_2types (e, e->referent, parent, ignored);
    2779             243 :   }
    2780                 : };
    2781                 : 
    2782                 : 
    2783                 : void
    2784            2340 : typeresolution_info::visit_delete_statement (delete_statement* e)
    2785                 : {
    2786            2340 :   delete_statement_typeresolution_info di (this);
    2787            2340 :   t = pe_unknown;
    2788            2340 :   e->value->visit (&di);
    2789            2340 : }
    2790                 : 
    2791                 : 
    2792                 : void
    2793            2675 : typeresolution_info::visit_next_statement (next_statement*)
    2794                 : {
    2795            2675 : }
    2796                 : 
    2797                 : 
    2798                 : void
    2799              20 : typeresolution_info::visit_break_statement (break_statement*)
    2800                 : {
    2801              20 : }
    2802                 : 
    2803                 : 
    2804                 : void
    2805              19 : typeresolution_info::visit_continue_statement (continue_statement*)
    2806                 : {
    2807              19 : }
    2808                 : 
    2809                 : 
    2810                 : void
    2811             244 : typeresolution_info::visit_array_in (array_in* e)
    2812                 : {
    2813                 :   // all unary operators only work on numerics
    2814             244 :   exp_type t1 = t;
    2815             244 :   t = pe_unknown; // array value can be anything
    2816             244 :   e->operand->visit (this);
    2817                 : 
    2818             244 :   if (t1 == pe_unknown && e->type != pe_unknown)
    2819                 :     ; // already resolved
    2820             244 :   else if (t1 == pe_string || t1 == pe_stats)
    2821               0 :     mismatch (e->tok, t1, pe_long);
    2822             244 :   else if (e->type == pe_unknown)
    2823                 :     {
    2824              57 :       e->type = pe_long;
    2825              57 :       resolved (e->tok, e->type);
    2826                 :     }
    2827             244 : }
    2828                 : 
    2829                 : 
    2830                 : void
    2831           84975 : typeresolution_info::visit_return_statement (return_statement* e)
    2832                 : {
    2833                 :   // This is like symbol, where the referent is
    2834                 :   // the return value of the function.
    2835                 : 
    2836                 :   // translation pass will print error 
    2837           84975 :   if (current_function == 0)
    2838               0 :     return;
    2839                 : 
    2840           84975 :   exp_type& e_type = current_function->type;
    2841           84975 :   t = current_function->type;
    2842           84975 :   e->value->visit (this);
    2843                 : 
    2844           84975 :   if (e_type != pe_unknown && e->value->type != pe_unknown
    2845                 :       && e_type != e->value->type)
    2846               0 :     mismatch (current_function->tok, e_type, e->value->type);
    2847           84975 :   if (e_type == pe_unknown && 
    2848                 :       (e->value->type == pe_long || e->value->type == pe_string))
    2849                 :     {
    2850                 :       // propagate non-statistics from value
    2851            1921 :       e_type = e->value->type;
    2852            1921 :       resolved (current_function->tok, e->value->type);
    2853                 :     }
    2854           84975 :   if (e->value->type == pe_stats)
    2855               0 :     invalid (e->value->tok, e->value->type);
    2856                 : }
    2857                 : 
    2858                 : void 
    2859          460710 : typeresolution_info::visit_print_format (print_format* e)
    2860                 : {
    2861          460710 :   size_t unresolved_args = 0;
    2862                 : 
    2863          460710 :   if (e->hist)
    2864                 :     {
    2865             266 :       e->hist->visit(this);
    2866                 :     }
    2867                 : 
    2868          460444 :   else if (e->print_with_format)
    2869                 :     {
    2870                 :       // If there's a format string, we can do both inference *and*
    2871                 :       // checking.
    2872                 : 
    2873                 :       // First we extract the subsequence of formatting components
    2874                 :       // which are conversions (not just literal string components)
    2875                 : 
    2876          452478 :       unsigned expected_num_args = 0;
    2877          452478 :       std::vector<print_format::format_component> components;
    2878         2055500 :       for (size_t i = 0; i < e->components.size(); ++i)
    2879                 :         {
    2880         1603022 :           if (e->components[i].type == print_format::conv_unspecified)
    2881                 :             throw semantic_error ("Unspecified conversion in print operator format string",
    2882               0 :                                   e->tok);
    2883         1603022 :           else if (e->components[i].type == print_format::conv_literal 
    2884                 :                    || e->components[i].type == print_format::conv_size)
    2885          719162 :             continue;
    2886          883860 :           components.push_back(e->components[i]);
    2887          883860 :           ++expected_num_args;
    2888          883860 :           if (e->components[i].widthtype == print_format::width_dynamic)
    2889              84 :             ++expected_num_args;
    2890          883860 :           if (e->components[i].prectype == print_format::prec_dynamic)
    2891              96 :             ++expected_num_args;
    2892                 :         }
    2893                 : 
    2894                 :       // Then we check that the number of conversions and the number
    2895                 :       // of args agree.
    2896                 : 
    2897          452478 :       if (expected_num_args != e->args.size())
    2898                 :         throw semantic_error ("Wrong number of args to formatted print operator",
    2899               0 :                               e->tok);
    2900                 : 
    2901                 :       // Then we check that the types of the conversions match the types
    2902                 :       // of the args.
    2903          452478 :       unsigned argno = 0;
    2904         1336335 :       for (size_t i = 0; i < components.size(); ++i)
    2905                 :         {
    2906                 :           // Check the dynamic width, if specified
    2907          883859 :           if (components[i].widthtype == print_format::width_dynamic)
    2908                 :             {
    2909              84 :               check_arg_type (pe_long, e->args[argno]);
    2910              84 :               ++argno;
    2911                 :             }
    2912                 : 
    2913                 :           // Check the dynamic precision, if specified
    2914          883859 :           if (components[i].prectype == print_format::prec_dynamic)
    2915                 :             {
    2916              96 :               check_arg_type (pe_long, e->args[argno]);
    2917              96 :               ++argno;
    2918                 :             }
    2919                 : 
    2920          883859 :           exp_type wanted = pe_unknown;
    2921                 : 
    2922          883859 :           switch (components[i].type)
    2923                 :             {
    2924                 :             case print_format::conv_unspecified:
    2925                 :             case print_format::conv_literal:
    2926                 :             case print_format::conv_size:
    2927               0 :               assert (false);
    2928                 :               break;
    2929                 : 
    2930                 :             case print_format::conv_signed_decimal:
    2931                 :             case print_format::conv_unsigned_decimal:
    2932                 :             case print_format::conv_unsigned_octal:
    2933                 :             case print_format::conv_unsigned_ptr:
    2934                 :             case print_format::conv_unsigned_uppercase_hex:
    2935                 :             case print_format::conv_unsigned_lowercase_hex:
    2936                 :             case print_format::conv_binary:
    2937                 :             case print_format::conv_memory:
    2938          181901 :               wanted = pe_long;
    2939          181901 :               break;
    2940                 : 
    2941                 :             case print_format::conv_string:
    2942          701958 :               wanted = pe_string;
    2943                 :               break;
    2944                 :             }
    2945                 : 
    2946          883859 :           assert (wanted != pe_unknown);
    2947          883859 :           check_arg_type (wanted, e->args[argno]);
    2948          883857 :           ++argno;
    2949          452476 :         }
    2950                 :     }
    2951                 :   else
    2952                 :     {
    2953                 :       // Without a format string, the best we can do is require that
    2954                 :       // each argument resolve to a concrete type.
    2955           16230 :       for (size_t i = 0; i < e->args.size(); ++i)
    2956                 :         {
    2957            8272 :           t = pe_unknown;
    2958            8272 :           e->args[i]->visit (this);
    2959            8264 :           if (e->args[i]->type == pe_unknown)
    2960                 :             {
    2961            1053 :               unresolved (e->args[i]->tok);
    2962            1053 :               ++unresolved_args;
    2963                 :             }
    2964                 :         }
    2965                 :     }
    2966                 :   
    2967          460700 :   if (unresolved_args == 0)
    2968                 :     {
    2969          459671 :       if (e->type == pe_unknown)
    2970                 :         {
    2971          115634 :           if (e->print_to_stream)
    2972           92798 :             e->type = pe_long;
    2973                 :           else
    2974           22836 :             e->type = pe_string;      
    2975          115634 :           resolved (e->tok, e->type);
    2976                 :         }
    2977                 :     }
    2978                 :   else
    2979                 :     {
    2980            1029 :       e->type = pe_unknown;
    2981            1029 :       unresolved (e->tok);
    2982                 :     }
    2983          460700 : }
    2984                 : 
    2985                 : 
    2986                 : void 
    2987             772 : typeresolution_info::visit_stat_op (stat_op* e)
    2988                 : {
    2989             772 :   t = pe_stats;
    2990             772 :   e->stat->visit (this);
    2991             772 :   if (e->type == pe_unknown)
    2992                 :     {
    2993             245 :       e->type = pe_long;
    2994             245 :       resolved (e->tok, e->type);
    2995                 :     }
    2996             527 :   else if (e->type != pe_long)
    2997               0 :     mismatch (e->tok, e->type, pe_long);
    2998             772 : }
    2999                 : 
    3000                 : void 
    3001             343 : typeresolution_info::visit_hist_op (hist_op* e)
    3002                 : {
    3003             343 :   t = pe_stats;
    3004             343 :   e->stat->visit (this);
    3005             343 : }
    3006                 : 
    3007                 : 
    3008                 : void
    3009          884039 : typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
    3010                 : {
    3011          884039 :   t = wanted;
    3012          884039 :   arg->visit (this);
    3013                 : 
    3014          884037 :   if (arg->type == pe_unknown)
    3015                 :     {
    3016               1 :       arg->type = wanted;
    3017               1 :       resolved (arg->tok, wanted);
    3018                 :     }
    3019          884036 :   else if (arg->type != wanted)
    3020                 :     {
    3021               0 :       mismatch (arg->tok, arg->type, wanted);
    3022                 :     }
    3023          884037 : }
    3024                 : 
    3025                 : 
    3026                 : void
    3027           70324 : typeresolution_info::unresolved (const token* tok)
    3028                 : {
    3029           70324 :   num_still_unresolved ++;
    3030                 : 
    3031           70324 :   if (assert_resolvability)
    3032                 :     {
    3033              12 :       stringstream msg;
    3034                 :       string nm = (current_function ? current_function->name :
    3035                 :                    current_probe ? current_probe->name :
    3036              12 :                    "probe condition");
    3037              12 :       msg << nm + " with unresolved type";
    3038              12 :       session.print_error (semantic_error (msg.str(), tok));
    3039                 :     }
    3040           70324 : }
    3041                 : 
    3042                 : 
    3043                 : void
    3044               3 : typeresolution_info::invalid (const token* tok, exp_type pe)
    3045                 : {
    3046               3 :   num_still_unresolved ++;
    3047                 : 
    3048               3 :   if (assert_resolvability)
    3049                 :     {
    3050               1 :       stringstream msg;
    3051                 :       string nm = (current_function ? current_function->name :
    3052                 :                    current_probe ? current_probe->name :
    3053               1 :                    "probe condition");
    3054               1 :       if (tok && tok->type == tok_operator)
    3055               0 :         msg << nm + " uses invalid operator";
    3056                 :       else
    3057               1 :         msg << nm + " with invalid type " << pe;
    3058               1 :       session.print_error (semantic_error (msg.str(), tok));
    3059                 :     }
    3060               3 : }
    3061                 : 
    3062                 : 
    3063                 : void
    3064              69 : typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
    3065                 : {
    3066              69 :   num_still_unresolved ++;
    3067                 : 
    3068              69 :   if (assert_resolvability)
    3069                 :     {
    3070              20 :       stringstream msg;
    3071                 :       string nm = (current_function ? current_function->name :
    3072                 :                    current_probe ? current_probe->name :
    3073              20 :                    "probe condition");
    3074              20 :       msg << nm + " with type mismatch (" << t1 << " vs. " << t2 << ")";
    3075              20 :       session.print_error (semantic_error (msg.str(), tok));
    3076                 :     }
    3077              69 : }
    3078                 : 
    3079                 : 
    3080                 : void
    3081         1156874 : typeresolution_info::resolved (const token*, exp_type)
    3082                 : {
    3083         1156874 :   num_newly_resolved ++;
    3084         1159062 : }
    3085            1094 : 

Generated by: LTP GCOV extension version 1.5