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 :
|