]> sourceware.org Git - systemtap.git/blob - elaborate.cxx
Correct systemtap.spec to match support currently available on aarch64
[systemtap.git] / elaborate.cxx
1 // elaboration functions
2 // Copyright (C) 2005-2013 Red Hat Inc.
3 // Copyright (C) 2008 Intel Corporation
4 //
5 // This file is part of systemtap, and is free software. You can
6 // redistribute it and/or modify it under the terms of the GNU General
7 // Public License (GPL); either version 2, or (at your option) any
8 // later version.
9
10 #include "config.h"
11 #include "elaborate.h"
12 #include "translate.h"
13 #include "parse.h"
14 #include "tapsets.h"
15 #include "session.h"
16 #include "util.h"
17 #include "task_finder.h"
18 #include "stapregex.h"
19
20 extern "C" {
21 #include <sys/utsname.h>
22 #include <fnmatch.h>
23 #define __STDC_FORMAT_MACROS
24 #include <inttypes.h>
25 }
26
27 #include <algorithm>
28 #include <fstream>
29 #include <map>
30 #include <cassert>
31 #include <set>
32 #include <vector>
33 #include <algorithm>
34 #include <iterator>
35 #include <climits>
36
37
38 using namespace std;
39
40
41 // ------------------------------------------------------------------------
42
43 // Used in probe_point condition construction. Either argument may be
44 // NULL; if both, return NULL too. Resulting expression is a deep
45 // copy for symbol resolution purposes.
46 expression* add_condition (expression* a, expression* b)
47 {
48 if (!a && !b) return 0;
49 if (! a) return deep_copy_visitor::deep_copy(b);
50 if (! b) return deep_copy_visitor::deep_copy(a);
51 logical_and_expr la;
52 la.op = "&&";
53 la.left = a;
54 la.right = b;
55 la.tok = a->tok; // or could be b->tok
56 return deep_copy_visitor::deep_copy(& la);
57 }
58
59 // ------------------------------------------------------------------------
60
61
62
63 derived_probe::derived_probe (probe *p, probe_point *l, bool rewrite_loc):
64 base (p), base_pp(l), sdt_semaphore_addr(0), session_index((unsigned)-1)
65 {
66 assert (p);
67 this->tok = p->tok;
68 this->privileged = p->privileged;
69 this->body = deep_copy_visitor::deep_copy(p->body);
70
71 assert (l);
72 // make a copy for subclasses which want to rewrite the location
73 if (rewrite_loc)
74 l = new probe_point(*l);
75 this->locations.push_back (l);
76 }
77
78
79 void
80 derived_probe::printsig (ostream& o) const
81 {
82 probe::printsig (o);
83 printsig_nested (o);
84 }
85
86 void
87 derived_probe::printsig_nested (ostream& o) const
88 {
89 // We'd like to enclose the probe derivation chain in a /* */
90 // comment delimiter. But just printing /* base->printsig() */ is
91 // not enough, since base might itself be a derived_probe. So we,
92 // er, "cleverly" encode our nesting state as a formatting flag for
93 // the ostream.
94 ios::fmtflags f = o.flags (ios::internal);
95 if (f & ios::internal)
96 {
97 // already nested
98 o << " <- ";
99 base->printsig (o);
100 }
101 else
102 {
103 // outermost nesting
104 o << " /* <- ";
105 base->printsig (o);
106 o << " */";
107 }
108 // restore flags
109 (void) o.flags (f);
110 }
111
112
113 void
114 derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list) const
115 {
116 probes_list.push_back(const_cast<derived_probe*>(this));
117 base->collect_derivation_chain(probes_list);
118 }
119
120
121 void
122 derived_probe::collect_derivation_pp_chain (std::vector<probe_point*> &pp_list) const
123 {
124 pp_list.push_back(const_cast<probe_point*>(this->sole_location()));
125 base->collect_derivation_pp_chain(pp_list);
126 }
127
128
129 string
130 derived_probe::derived_locations ()
131 {
132 ostringstream o;
133 vector<probe_point*> reference_point;
134 collect_derivation_pp_chain(reference_point);
135 if (reference_point.size() > 0)
136 for(unsigned i=1; i<reference_point.size(); ++i)
137 o << " from: " << reference_point[i]->str(false); // no ?,!,etc
138 return o.str();
139 }
140
141
142 probe_point*
143 derived_probe::sole_location () const
144 {
145 if (locations.size() == 0 || locations.size() > 1)
146 throw semantic_error (_N("derived_probe with no locations",
147 "derived_probe with too many locations",
148 locations.size()), this->tok);
149 else
150 return locations[0];
151 }
152
153
154 probe_point*
155 derived_probe::script_location () const
156 {
157 // This feeds function::pn() in the tapset, which is documented as the
158 // script-level probe point expression, *after wildcard expansion*. If
159 // it were not for wildcard stuff, we'd just return the last item in the
160 // derivation chain. But alas ... we need to search for the last one
161 // that doesn't have a * in the textual representation. Heuristics, eww.
162 vector<probe_point*> chain;
163 collect_derivation_pp_chain (chain);
164
165 // NB: we actually start looking from the second-to-last item, so the user's
166 // direct input is not considered. Input like 'kernel.function("init_once")'
167 // will thus be listed with the resolved @file:line too, disambiguating the
168 // distinct functions by this name, and matching our historical behavior.
169 for (int i=chain.size()-2; i>=0; i--)
170 {
171 probe_point pp_copy (* chain [i]);
172 // drop any ?/! denotations that would confuse a glob-char search
173 pp_copy.optional = false;
174 pp_copy.sufficient = false;
175 string pp_printed = lex_cast(pp_copy);
176 if (! contains_glob_chars(pp_printed))
177 return chain[i];
178 }
179
180 // If that didn't work, just fallback to -something-.
181 return sole_location();
182 }
183
184
185 void
186 derived_probe::emit_privilege_assertion (translator_output* o)
187 {
188 // Emit code which will cause compilation to fail if it is compiled in
189 // unprivileged mode.
190 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
191 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
192 o->newline() << "#error Internal Error: Probe ";
193 probe::printsig (o->line());
194 o->line() << " generated in --unprivileged mode";
195 o->newline() << "#endif";
196 }
197
198
199 void
200 derived_probe::emit_process_owner_assertion (translator_output* o)
201 {
202 // Emit code which will abort should the current target not belong to the
203 // user in unprivileged mode.
204 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
205 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
206 o->newline(1) << "if (! is_myproc ()) {";
207 o->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
208 o->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
209 o->newline() << " current->tgid, _stp_uid, c->probe_point);";
210 o->newline() << "c->last_error = c->error_buffer;";
211 // NB: since this check occurs before probe locking, its exit should
212 // not be a "goto out", which would attempt unlocking.
213 o->newline() << "return;";
214 o->newline(-1) << "}";
215 o->newline(-1) << "#endif";
216 }
217
218 void
219 derived_probe::print_dupe_stamp_unprivileged(ostream& o)
220 {
221 o << _("unprivileged users: authorized") << endl;
222 }
223
224 void
225 derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream& o)
226 {
227 o << _("unprivileged users: authorized for process owner") << endl;
228 }
229
230 // ------------------------------------------------------------------------
231 // Members of derived_probe_builder
232
233 void
234 derived_probe_builder::build_with_suffix(systemtap_session & sess,
235 probe * use,
236 probe_point * location,
237 std::map<std::string, literal *>
238 const & parameters,
239 std::vector<derived_probe *>
240 & finished_results,
241 std::vector<probe_point::component *>
242 const & suffix) {
243 // XXX perhaps build the probe if suffix is empty?
244 // if (suffix.empty()) {
245 // build (sess, use, location, parameters, finished_results);
246 // return;
247 // }
248 throw semantic_error (_("invalid suffix for probe"));
249 }
250
251 bool
252 derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
253 const std::string& key,
254 std::string& value)
255 {
256 map<string, literal *>::const_iterator i = params.find (key);
257 if (i == params.end())
258 return false;
259 literal_string * ls = dynamic_cast<literal_string *>(i->second);
260 if (!ls)
261 return false;
262 value = ls->value;
263 return true;
264 }
265
266
267 bool
268 derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
269 const std::string& key,
270 int64_t& value)
271 {
272 map<string, literal *>::const_iterator i = params.find (key);
273 if (i == params.end())
274 return false;
275 if (i->second == NULL)
276 return false;
277 literal_number * ln = dynamic_cast<literal_number *>(i->second);
278 if (!ln)
279 return false;
280 value = ln->value;
281 return true;
282 }
283
284
285 bool
286 derived_probe_builder::has_null_param (std::map<std::string, literal*> const & params,
287 const std::string& key)
288 {
289 map<string, literal *>::const_iterator i = params.find(key);
290 return (i != params.end() && i->second == NULL);
291 }
292
293
294
295 // ------------------------------------------------------------------------
296 // Members of match_key.
297
298 match_key::match_key(string const & n)
299 : name(n),
300 have_parameter(false),
301 parameter_type(pe_unknown)
302 {
303 }
304
305 match_key::match_key(probe_point::component const & c)
306 : name(c.functor),
307 have_parameter(c.arg != NULL),
308 parameter_type(c.arg ? c.arg->type : pe_unknown)
309 {
310 }
311
312 match_key &
313 match_key::with_number()
314 {
315 have_parameter = true;
316 parameter_type = pe_long;
317 return *this;
318 }
319
320 match_key &
321 match_key::with_string()
322 {
323 have_parameter = true;
324 parameter_type = pe_string;
325 return *this;
326 }
327
328 string
329 match_key::str() const
330 {
331 if (have_parameter)
332 switch (parameter_type)
333 {
334 case pe_string: return name + "(string)";
335 case pe_long: return name + "(number)";
336 default: return name + "(...)";
337 }
338 return name;
339 }
340
341 bool
342 match_key::operator<(match_key const & other) const
343 {
344 return ((name < other.name)
345
346 || (name == other.name
347 && have_parameter < other.have_parameter)
348
349 || (name == other.name
350 && have_parameter == other.have_parameter
351 && parameter_type < other.parameter_type));
352 }
353
354
355 // NB: these are only used in the probe point name components, where
356 // only "*" is permitted.
357 //
358 // Within module("bar"), function("foo"), process("baz") strings, real
359 // wildcards are permitted too. See also util.h:contains_glob_chars
360
361 static bool
362 isglob(string const & str)
363 {
364 return(str.find('*') != str.npos);
365 }
366
367 static bool
368 isdoubleglob(string const & str)
369 {
370 return(str.find("**") != str.npos);
371 }
372
373 bool
374 match_key::globmatch(match_key const & other) const
375 {
376 const char *other_str = other.name.c_str();
377 const char *name_str = name.c_str();
378
379 return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0)
380 && have_parameter == other.have_parameter
381 && parameter_type == other.parameter_type);
382 }
383
384 // ------------------------------------------------------------------------
385 // Members of match_node
386 // ------------------------------------------------------------------------
387
388 match_node::match_node() :
389 privilege(privilege_t (pr_stapdev | pr_stapsys))
390 {
391 }
392
393 match_node *
394 match_node::bind(match_key const & k)
395 {
396 if (k.name == "*")
397 throw semantic_error(_("invalid use of wildcard probe point component"));
398
399 map<match_key, match_node *>::const_iterator i = sub.find(k);
400 if (i != sub.end())
401 return i->second;
402 match_node * n = new match_node();
403 sub.insert(make_pair(k, n));
404 return n;
405 }
406
407 void
408 match_node::bind(derived_probe_builder * e)
409 {
410 ends.push_back (e);
411 }
412
413 match_node *
414 match_node::bind(string const & k)
415 {
416 return bind(match_key(k));
417 }
418
419 match_node *
420 match_node::bind_str(string const & k)
421 {
422 return bind(match_key(k).with_string());
423 }
424
425 match_node *
426 match_node::bind_num(string const & k)
427 {
428 return bind(match_key(k).with_number());
429 }
430
431 match_node *
432 match_node::bind_privilege(privilege_t p)
433 {
434 privilege = p;
435 return this;
436 }
437
438 void
439 match_node::find_and_build (systemtap_session& s,
440 probe* p, probe_point *loc, unsigned pos,
441 vector<derived_probe *>& results)
442 {
443 assert (pos <= loc->components.size());
444 if (pos == loc->components.size()) // matched all probe point components so far
445 {
446 if (ends.empty())
447 {
448 string alternatives;
449 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
450 alternatives += string(" ") + i->first.str();
451
452 throw semantic_error (_F("probe point truncated (follow: %s)",
453 alternatives.c_str()),
454 loc->components.back()->tok);
455 }
456
457 if (! pr_contains (privilege, s.privilege))
458 {
459 throw semantic_error (_F("probe point is not allowed for --privilege=%s",
460 pr_name (s.privilege)),
461 loc->components.back()->tok);
462 }
463
464 map<string, literal *> param_map;
465 for (unsigned i=0; i<pos; i++)
466 param_map[loc->components[i]->functor] = loc->components[i]->arg;
467 // maybe 0
468
469 // Iterate over all bound builders
470 for (unsigned k=0; k<ends.size(); k++)
471 {
472 derived_probe_builder *b = ends[k];
473 b->build (s, p, loc, param_map, results);
474 }
475 }
476 else if (isdoubleglob(loc->components[pos]->functor)) // ** wildcard?
477 {
478 unsigned int num_results = results.size();
479
480 // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
481
482 const probe_point::component *comp = loc->components[pos];
483 const string &functor = comp->functor;
484 size_t glob_start = functor.find("**");
485 size_t glob_end = functor.find_first_not_of('*', glob_start);
486 const string prefix = functor.substr(0, glob_start);
487 const string suffix = ((glob_end != string::npos) ?
488 functor.substr(glob_end) : "");
489
490 // Synthesize "foo*bar"
491 probe_point *simple_pp = new probe_point(*loc);
492 probe_point::component *simple_comp = new probe_point::component(*comp);
493 simple_comp->functor = prefix + "*" + suffix;
494 simple_pp->components[pos] = simple_comp;
495 try
496 {
497 find_and_build (s, p, simple_pp, pos, results);
498 }
499 catch (const semantic_error& e)
500 {
501 // Ignore semantic_errors, but cleanup
502 delete simple_pp;
503 delete simple_comp;
504 }
505
506 // Synthesize "foo*.**bar"
507 // NB: any component arg should attach to the latter part only
508 probe_point *expanded_pp = new probe_point(*loc);
509 probe_point::component *expanded_comp_pre = new probe_point::component(*comp);
510 expanded_comp_pre->functor = prefix + "*";
511 expanded_comp_pre->arg = NULL;
512 probe_point::component *expanded_comp_post = new probe_point::component(*comp);
513 expanded_comp_post->functor = "**" + suffix;
514 expanded_pp->components[pos] = expanded_comp_pre;
515 expanded_pp->components.insert(expanded_pp->components.begin() + pos + 1,
516 expanded_comp_post);
517 try
518 {
519 find_and_build (s, p, expanded_pp, pos, results);
520 }
521 catch (const semantic_error& e)
522 {
523 // Ignore semantic_errors, but cleanup
524 delete expanded_pp;
525 delete expanded_comp_pre;
526 delete expanded_comp_post;
527 }
528
529 // Try suffix expansion only if no matches found:
530 if (num_results == results.size())
531 try
532 {
533 this->try_suffix_expansion (s, p, loc, pos, results);
534 }
535 catch (const recursive_expansion_error &e)
536 {
537 s.print_error(e); return; // Suppress probe mismatch msg.
538 }
539
540 if (! loc->optional && num_results == results.size())
541 {
542 // We didn't find any wildcard matches (since the size of
543 // the result vector didn't change). Throw an error.
544 string alternatives;
545 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
546 alternatives += string(" ") + i->first.str();
547
548 throw semantic_error(_F("probe point mismatch (alternatives: %s)",
549 alternatives.c_str()), comp->tok);
550 }
551 }
552 else if (isglob(loc->components[pos]->functor)) // wildcard?
553 {
554 match_key match (* loc->components[pos]);
555
556 // Call find_and_build for each possible match. Ignore errors -
557 // unless we don't find any match.
558 unsigned int num_results = results.size();
559 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
560 {
561 const match_key& subkey = i->first;
562 match_node* subnode = i->second;
563
564 assert_no_interrupts();
565
566 if (match.globmatch(subkey))
567 {
568 if (s.verbose > 2)
569 clog << _F("wildcard '%s' matched '%s'",
570 loc->components[pos]->functor.c_str(),
571 subkey.name.c_str()) << endl;
572
573 // When we have a wildcard, we need to create a copy of
574 // the probe point. Then we'll create a copy of the
575 // wildcard component, and substitute the non-wildcard
576 // functor.
577 probe_point *non_wildcard_pp = new probe_point(*loc);
578 probe_point::component *non_wildcard_component
579 = new probe_point::component(*loc->components[pos]);
580 non_wildcard_component->functor = subkey.name;
581 non_wildcard_pp->components[pos] = non_wildcard_component;
582
583 // NB: probe conditions are not attached at the wildcard
584 // (component/functor) level, but at the overall
585 // probe_point level.
586
587 // recurse (with the non-wildcard probe point)
588 try
589 {
590 subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
591 results);
592 }
593 catch (const semantic_error& e)
594 {
595 // Ignore semantic_errors while expanding wildcards.
596 // If we get done and nothing was expanded, the code
597 // following the loop will complain.
598
599 // If this wildcard didn't match, cleanup.
600 delete non_wildcard_pp;
601 delete non_wildcard_component;
602 }
603 }
604 }
605
606 // Try suffix expansion only if no matches found:
607 if (num_results == results.size())
608 try
609 {
610 this->try_suffix_expansion (s, p, loc, pos, results);
611 }
612 catch (const recursive_expansion_error &e)
613 {
614 s.print_error(e); return; // Suppress probe mismatch msg.
615 }
616
617 if (! loc->optional && num_results == results.size())
618 {
619 // We didn't find any wildcard matches (since the size of
620 // the result vector didn't change). Throw an error.
621 string alternatives;
622 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
623 alternatives += string(" ") + i->first.str();
624
625 throw semantic_error(_F("probe point mismatch %s didn't find any wildcard matches",
626 (alternatives == "" ? "" : _(" (alternatives: ") +
627 alternatives + ")").c_str()), loc->components[pos]->tok);
628 }
629 }
630 else
631 {
632 match_key match (* loc->components[pos]);
633 sub_map_iterator_t i = sub.find (match);
634
635 if (i != sub.end()) // match found
636 {
637 match_node* subnode = i->second;
638 // recurse
639 subnode->find_and_build (s, p, loc, pos+1, results);
640 return;
641 }
642
643 unsigned int num_results = results.size();
644
645 try
646 {
647 this->try_suffix_expansion (s, p, loc, pos, results);
648 }
649 catch (const recursive_expansion_error &e)
650 {
651 s.print_error(e); return; // Suppress probe mismatch msg.
652 }
653
654 // XXX: how to correctly report alternatives + position numbers
655 // for alias suffixes? file a separate PR to address the issue
656 if (! loc->optional && num_results == results.size())
657 {
658 // We didn't find any alias suffixes (since the size of the
659 // result vector didn't change). Throw an error.
660 string alternatives;
661 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
662 alternatives += string(" ") + i->first.str();
663
664 throw semantic_error(_F("probe point mismatch %s",
665 (alternatives == "" ? "" : (_(" (alternatives:") + alternatives +
666 ")").c_str())),
667 loc->components[pos]->tok);
668 }
669 }
670 }
671
672
673 void
674 match_node::try_suffix_expansion (systemtap_session& s,
675 probe *p, probe_point *loc, unsigned pos,
676 vector<derived_probe *>& results)
677 {
678 // PR12210: match alias suffixes. If the components thus far
679 // have been matched, but there is an additional unknown
680 // suffix, we have a potential alias suffix on our hands. We
681 // need to expand the preceding components as probe aliases,
682 // reattach the suffix, and re-run derive_probes() on the
683 // resulting expansion. This is done by the routine
684 // build_with_suffix().
685
686 if (strverscmp(s.compatible.c_str(), "2.0") >= 0)
687 {
688 // XXX: technically, param_map isn't used here. So don't
689 // bother actually assembling it unless some
690 // derived_probe_builder appears that actually takes
691 // suffixes *and* consults parameters (currently no such
692 // builders exist).
693 map<string, literal *> param_map;
694 // for (unsigned i=0; i<pos; i++)
695 // param_map[loc->components[i]->functor] = loc->components[i]->arg;
696 // maybe 0
697
698 vector<probe_point::component *> suffix (loc->components.begin()+pos,
699 loc->components.end());
700
701 // Multiple derived_probe_builders may be bound at a
702 // match_node due to the possibility of multiply defined
703 // aliases.
704 for (unsigned k=0; k < ends.size(); k++)
705 {
706 derived_probe_builder *b = ends[k];
707 try
708 {
709 b->build_with_suffix (s, p, loc, param_map, results, suffix);
710 }
711 catch (const recursive_expansion_error &e)
712 {
713 // Re-throw:
714 throw semantic_error(e);
715 }
716 catch (const semantic_error &e)
717 {
718 // Adjust source coordinate and re-throw:
719 if (! loc->optional)
720 throw semantic_error(e.what(), loc->components[pos]->tok);
721 }
722 }
723 }
724 }
725
726
727 void
728 match_node::build_no_more (systemtap_session& s)
729 {
730 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
731 i->second->build_no_more (s);
732 for (unsigned k=0; k<ends.size(); k++)
733 {
734 derived_probe_builder *b = ends[k];
735 b->build_no_more (s);
736 }
737 }
738
739 void
740 match_node::dump (systemtap_session &s, const string &name)
741 {
742 // Dump this node, if it is complete.
743 for (unsigned k=0; k<ends.size(); k++)
744 {
745 // Don't print aliases at all (for now) until we can figure out how to determine whether
746 // the probes they resolve to are ok in unprivileged mode.
747 if (ends[k]->is_alias ())
748 continue;
749
750 // In unprivileged mode, don't show the probes which are not allowed for unprivileged
751 // users.
752 if (pr_contains (privilege, s.privilege))
753 {
754 cout << name << endl;
755 break; // we need only print one instance.
756 }
757 }
758
759 // Recursively dump the children of this node
760 string dot;
761 if (! name.empty ())
762 dot = ".";
763 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
764 {
765 i->second->dump (s, name + dot + i->first.str());
766 }
767 }
768
769
770 // ------------------------------------------------------------------------
771 // Alias probes
772 // ------------------------------------------------------------------------
773
774 struct alias_derived_probe: public derived_probe
775 {
776 alias_derived_probe (probe* base, probe_point *l, const probe_alias *a,
777 const vector<probe_point::component *> *suffix = 0);
778 ~alias_derived_probe();
779
780 void upchuck () { throw semantic_error (_("inappropriate"), this->tok); }
781
782 // Alias probes are immediately expanded to other derived_probe
783 // types, and are not themselves emitted or listed in
784 // systemtap_session.probes
785
786 void join_group (systemtap_session&) { upchuck (); }
787
788 virtual const probe_alias *get_alias () const { return alias; }
789 virtual probe_point *get_alias_loc () const { return alias_loc; }
790 virtual probe_point *sole_location () const;
791
792 private:
793 const probe_alias *alias; // Used to check for recursion
794 probe_point *alias_loc; // Hack to recover full probe name
795 };
796
797
798 alias_derived_probe::alias_derived_probe(probe *base, probe_point *l,
799 const probe_alias *a,
800 const vector<probe_point::component *>
801 *suffix):
802 derived_probe (base, l), alias(a)
803 {
804 // XXX pretty nasty -- this was cribbed from printscript() in main.cxx
805 assert (alias->alias_names.size() >= 1);
806 alias_loc = new probe_point(*alias->alias_names[0]); // XXX: [0] is arbitrary; it would make just as much sense to collect all of the names
807 if (suffix) {
808 alias_loc->components.insert(alias_loc->components.end(),
809 suffix->begin(), suffix->end());
810 }
811 }
812
813 alias_derived_probe::~alias_derived_probe ()
814 {
815 delete alias_loc;
816 }
817
818
819 probe_point*
820 alias_derived_probe::sole_location () const
821 {
822 return const_cast<probe_point*>(alias_loc);
823 }
824
825
826 probe*
827 probe::create_alias(probe_point* l, probe_point* a)
828 {
829 vector<probe_point*> aliases(1, a);
830 probe_alias* p = new probe_alias(aliases);
831 p->tok = tok;
832 p->locations.push_back(l);
833 p->body = body;
834 p->base = this;
835 p->privileged = privileged;
836 p->epilogue_style = false;
837 return new alias_derived_probe(this, l, p);
838 }
839
840
841 void
842 alias_expansion_builder::build(systemtap_session & sess,
843 probe * use,
844 probe_point * location,
845 std::map<std::string, literal *>
846 const & parameters,
847 vector<derived_probe *> & finished_results)
848 {
849 vector<probe_point::component *> empty_suffix;
850 build_with_suffix (sess, use, location, parameters,
851 finished_results, empty_suffix);
852 }
853
854 void
855 alias_expansion_builder::build_with_suffix(systemtap_session & sess,
856 probe * use,
857 probe_point * location,
858 std::map<std::string, literal *>
859 const &,
860 vector<derived_probe *>
861 & finished_results,
862 vector<probe_point::component *>
863 const & suffix)
864 {
865 // Don't build the alias expansion if infinite recursion is detected.
866 if (checkForRecursiveExpansion (use)) {
867 stringstream msg;
868 msg << _F("Recursive loop in alias expansion of %s at %s",
869 lex_cast(*location).c_str(), lex_cast(location->components.front()->tok->location).c_str());
870 // semantic_errors thrown here might be ignored, so we need a special class:
871 throw recursive_expansion_error (msg.str());
872 // XXX The point of throwing this custom error is to suppress a
873 // cascade of "probe mismatch" messages that appear in addition to
874 // the error. The current approach suppresses most of the error
875 // cascade, but leaves one spurious error; in any case, the way
876 // this particular error is reported could be improved.
877 }
878
879 // We're going to build a new probe and wrap it up in an
880 // alias_expansion_probe so that the expansion loop recognizes it as
881 // such and re-expands its expansion.
882
883 alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias, &suffix);
884 n->body = new block();
885
886 // The new probe gets a deep copy of the location list of the alias
887 // (with incoming condition joined) plus the suffix (if any),
888 n->locations.clear();
889 for (unsigned i=0; i<alias->locations.size(); i++)
890 {
891 probe_point *pp = new probe_point(*alias->locations[i]);
892 pp->components.insert(pp->components.end(), suffix.begin(), suffix.end());
893 pp->condition = add_condition (pp->condition, location->condition);
894 n->locations.push_back(pp);
895 }
896
897 // the token location of the alias,
898 n->tok = location->components.front()->tok;
899
900 // and statements representing the concatenation of the alias'
901 // body with the use's.
902 //
903 // NB: locals are *not* copied forward, from either alias or
904 // use. The expansion should have its locals re-inferred since
905 // there's concatenated code here and we only want one vardecl per
906 // resulting variable.
907
908 if (alias->epilogue_style)
909 n->body = new block (use->body, alias->body);
910 else
911 n->body = new block (alias->body, use->body);
912
913 unsigned old_num_results = finished_results.size();
914 // If expanding for an alias suffix, be sure to pass on any errors
915 // to the caller instead of printing them in derive_probes():
916 derive_probes (sess, n, finished_results, location->optional, !suffix.empty());
917
918 // Check whether we resolved something. If so, put the
919 // whole library into the queue if not already there.
920 if (finished_results.size() > old_num_results)
921 {
922 stapfile *f = alias->tok->location.file;
923 if (find (sess.files.begin(), sess.files.end(), f)
924 == sess.files.end())
925 sess.files.push_back (f);
926 }
927 }
928
929 bool
930 alias_expansion_builder::checkForRecursiveExpansion (probe *use)
931 {
932 // Collect the derivation chain of this probe.
933 vector<probe*>derivations;
934 use->collect_derivation_chain (derivations);
935
936 // Check all probe points in the alias expansion against the currently-being-expanded probe point
937 // of each of the probes in the derivation chain, looking for a match. This
938 // indicates infinite recursion.
939 // The first element of the derivation chain will be the derived_probe representing 'use', so
940 // start the search with the second element.
941 assert (derivations.size() > 0);
942 assert (derivations[0] == use);
943 for (unsigned d = 1; d < derivations.size(); ++d) {
944 if (use->get_alias() == derivations[d]->get_alias())
945 return true; // recursion detected
946 }
947 return false;
948 }
949
950
951 // ------------------------------------------------------------------------
952 // Pattern matching
953 // ------------------------------------------------------------------------
954
955 static unsigned max_recursion = 100;
956
957 struct
958 recursion_guard
959 {
960 unsigned & i;
961 recursion_guard(unsigned & i) : i(i)
962 {
963 if (i > max_recursion)
964 throw semantic_error(_("recursion limit reached"));
965 ++i;
966 }
967 ~recursion_guard()
968 {
969 --i;
970 }
971 };
972
973 // The match-and-expand loop.
974 void
975 derive_probes (systemtap_session& s,
976 probe *p, vector<derived_probe*>& dps,
977 bool optional,
978 bool rethrow_errors)
979 {
980 for (unsigned i = 0; i < p->locations.size(); ++i)
981 {
982 assert_no_interrupts();
983
984 probe_point *loc = p->locations[i];
985
986 if (s.verbose > 4)
987 clog << "derive-probes " << *loc << endl;
988
989 try
990 {
991 unsigned num_atbegin = dps.size();
992
993 // Pass down optional flag from e.g. alias reference to each
994 // probe_point instance. We do this by temporarily overriding
995 // the probe_point optional flag. We could instead deep-copy
996 // and set a flag on the copy permanently.
997 bool old_loc_opt = loc->optional;
998 loc->optional = loc->optional || optional;
999 try
1000 {
1001 s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
1002 }
1003 catch (const semantic_error& e)
1004 {
1005 if (!loc->optional)
1006 throw semantic_error(e);
1007 else /* tolerate failure for optional probe */
1008 continue;
1009 }
1010
1011 loc->optional = old_loc_opt;
1012 unsigned num_atend = dps.size();
1013
1014 if (! (loc->optional||optional) && // something required, but
1015 num_atbegin == num_atend) // nothing new derived!
1016 throw semantic_error (_("no match"));
1017
1018 if (loc->sufficient && (num_atend > num_atbegin))
1019 {
1020 if (s.verbose > 1)
1021 {
1022 clog << "Probe point ";
1023 p->locations[i]->print(clog);
1024 clog << " sufficient, skipped";
1025 for (unsigned j = i+1; j < p->locations.size(); ++j)
1026 {
1027 clog << " ";
1028 p->locations[j]->print(clog);
1029 }
1030 clog << endl;
1031 }
1032 break; // we need not try to derive for any other locations
1033 }
1034 }
1035 catch (const semantic_error& e)
1036 {
1037 // The rethrow_errors parameter lets the caller decide an
1038 // alternative to printing the error. This is necessary when
1039 // calling derive_probes() recursively during expansion of
1040 // an alias with suffix -- any message printed here would
1041 // point to the alias declaration and not the invalid suffix
1042 // usage, so the caller needs to catch the error themselves
1043 // and print a more appropriate message.
1044 if (rethrow_errors)
1045 {
1046 throw semantic_error(e);
1047 }
1048 // Only output in listing if -vv is supplied:
1049 else if (!s.listing_mode || (s.listing_mode && s.verbose > 1))
1050 {
1051 // XXX: prefer not to print_error at every nest/unroll level
1052 semantic_error* er = new semantic_error (_("while resolving probe point"),
1053 loc->components[0]->tok);
1054 er->chain = & e;
1055 s.print_error (* er);
1056 delete er;
1057 }
1058 }
1059
1060 }
1061 }
1062
1063
1064
1065 // ------------------------------------------------------------------------
1066 //
1067 // Indexable usage checks
1068 //
1069
1070 struct symbol_fetcher
1071 : public throwing_visitor
1072 {
1073 symbol *&sym;
1074
1075 symbol_fetcher (symbol *&sym): sym(sym)
1076 {}
1077
1078 void visit_symbol (symbol* e)
1079 {
1080 sym = e;
1081 }
1082
1083 void visit_target_symbol (target_symbol* e)
1084 {
1085 sym = e;
1086 }
1087
1088 void visit_arrayindex (arrayindex* e)
1089 {
1090 e->base->visit (this);
1091 }
1092
1093 void visit_atvar_op (atvar_op *e)
1094 {
1095 sym = e;
1096 }
1097
1098 void visit_cast_op (cast_op* e)
1099 {
1100 sym = e;
1101 }
1102
1103 void throwone (const token* t)
1104 {
1105 if (t->type == tok_operator && t->content == ".") // guess someone misused . in $foo->bar.baz expression
1106 throw semantic_error (_("Expecting symbol or array index expression, try -> instead"), t);
1107 else
1108 throw semantic_error (_("Expecting symbol or array index expression"), t);
1109 }
1110 };
1111
1112 symbol *
1113 get_symbol_within_expression (expression *e)
1114 {
1115 symbol *sym = NULL;
1116 symbol_fetcher fetcher(sym);
1117 e->visit (&fetcher);
1118 return sym; // NB: may be null!
1119 }
1120
1121 static symbol *
1122 get_symbol_within_indexable (indexable *ix)
1123 {
1124 symbol *array = NULL;
1125 hist_op *hist = NULL;
1126 classify_indexable(ix, array, hist);
1127 if (array)
1128 return array;
1129 else
1130 return get_symbol_within_expression (hist->stat);
1131 }
1132
1133 struct mutated_var_collector
1134 : public traversing_visitor
1135 {
1136 set<vardecl *> * mutated_vars;
1137
1138 mutated_var_collector (set<vardecl *> * mm)
1139 : mutated_vars (mm)
1140 {}
1141
1142 void visit_assignment(assignment* e)
1143 {
1144 if (e->type == pe_stats && e->op == "<<<")
1145 {
1146 vardecl *vd = get_symbol_within_expression (e->left)->referent;
1147 if (vd)
1148 mutated_vars->insert (vd);
1149 }
1150 traversing_visitor::visit_assignment(e);
1151 }
1152
1153 void visit_arrayindex (arrayindex *e)
1154 {
1155 if (is_active_lvalue (e))
1156 {
1157 symbol *sym;
1158 if (e->base->is_symbol (sym))
1159 mutated_vars->insert (sym->referent);
1160 else
1161 throw semantic_error(_("Assignment to read-only histogram bucket"), e->tok);
1162 }
1163 traversing_visitor::visit_arrayindex (e);
1164 }
1165 };
1166
1167
1168 struct no_var_mutation_during_iteration_check
1169 : public traversing_visitor
1170 {
1171 systemtap_session & session;
1172 map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
1173 vector<vardecl *> vars_being_iterated;
1174
1175 no_var_mutation_during_iteration_check
1176 (systemtap_session & sess,
1177 map<functiondecl *,set<vardecl *> *> & fmv)
1178 : session(sess), function_mutates_vars (fmv)
1179 {}
1180
1181 void visit_arrayindex (arrayindex *e)
1182 {
1183 if (is_active_lvalue(e))
1184 {
1185 vardecl *vd = get_symbol_within_indexable (e->base)->referent;
1186 if (vd)
1187 {
1188 for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
1189 {
1190 vardecl *v = vars_being_iterated[i];
1191 if (v == vd)
1192 {
1193 string err = _F("variable '%s' modified during 'foreach' iteration",
1194 v->name.c_str());
1195 session.print_error (semantic_error (err, e->tok));
1196 }
1197 }
1198 }
1199 }
1200 traversing_visitor::visit_arrayindex (e);
1201 }
1202
1203 void visit_functioncall (functioncall* e)
1204 {
1205 map<functiondecl *,set<vardecl *> *>::const_iterator i
1206 = function_mutates_vars.find (e->referent);
1207
1208 if (i != function_mutates_vars.end())
1209 {
1210 for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
1211 {
1212 vardecl *m = vars_being_iterated[j];
1213 if (i->second->find (m) != i->second->end())
1214 {
1215 string err = _F("function call modifies var '%s' during 'foreach' iteration",
1216 m->name.c_str());
1217 session.print_error (semantic_error (err, e->tok));
1218 }
1219 }
1220 }
1221
1222 traversing_visitor::visit_functioncall (e);
1223 }
1224
1225 void visit_foreach_loop(foreach_loop* s)
1226 {
1227 vardecl *vd = get_symbol_within_indexable (s->base)->referent;
1228
1229 if (vd)
1230 vars_being_iterated.push_back (vd);
1231
1232 traversing_visitor::visit_foreach_loop (s);
1233
1234 if (vd)
1235 vars_being_iterated.pop_back();
1236 }
1237 };
1238
1239
1240 // ------------------------------------------------------------------------
1241
1242 struct stat_decl_collector
1243 : public traversing_visitor
1244 {
1245 systemtap_session & session;
1246
1247 stat_decl_collector(systemtap_session & sess)
1248 : session(sess)
1249 {}
1250
1251 void visit_stat_op (stat_op* e)
1252 {
1253 symbol *sym = get_symbol_within_expression (e->stat);
1254 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1255 session.stat_decls[sym->name] = statistic_decl();
1256 }
1257
1258 void visit_assignment (assignment* e)
1259 {
1260 if (e->op == "<<<")
1261 {
1262 symbol *sym = get_symbol_within_expression (e->left);
1263 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1264 session.stat_decls[sym->name] = statistic_decl();
1265 }
1266 else
1267 traversing_visitor::visit_assignment(e);
1268 }
1269
1270 void visit_hist_op (hist_op* e)
1271 {
1272 symbol *sym = get_symbol_within_expression (e->stat);
1273 statistic_decl new_stat;
1274
1275 if (e->htype == hist_linear)
1276 {
1277 new_stat.type = statistic_decl::linear;
1278 assert (e->params.size() == 3);
1279 new_stat.linear_low = e->params[0];
1280 new_stat.linear_high = e->params[1];
1281 new_stat.linear_step = e->params[2];
1282 }
1283 else
1284 {
1285 assert (e->htype == hist_log);
1286 new_stat.type = statistic_decl::logarithmic;
1287 assert (e->params.size() == 0);
1288 }
1289
1290 map<string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
1291 if (i == session.stat_decls.end())
1292 session.stat_decls[sym->name] = new_stat;
1293 else
1294 {
1295 statistic_decl & old_stat = i->second;
1296 if (!(old_stat == new_stat))
1297 {
1298 if (old_stat.type == statistic_decl::none)
1299 i->second = new_stat;
1300 else
1301 {
1302 // FIXME: Support multiple co-declared histogram types
1303 semantic_error se(_F("multiple histogram types declared on '%s'", sym->name.c_str()), e->tok);
1304 session.print_error (se);
1305 }
1306 }
1307 }
1308 }
1309
1310 };
1311
1312 static int
1313 semantic_pass_stats (systemtap_session & sess)
1314 {
1315 stat_decl_collector sdc(sess);
1316
1317 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
1318 it->second->body->visit (&sdc);
1319
1320 for (unsigned i = 0; i < sess.probes.size(); ++i)
1321 sess.probes[i]->body->visit (&sdc);
1322
1323 for (unsigned i = 0; i < sess.globals.size(); ++i)
1324 {
1325 vardecl *v = sess.globals[i];
1326 if (v->type == pe_stats)
1327 {
1328
1329 if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
1330 {
1331 semantic_error se(_F("unable to infer statistic parameters for global '%s'", v->name.c_str()));
1332 sess.print_error (se);
1333 }
1334 }
1335 }
1336
1337 return sess.num_errors();
1338 }
1339
1340 // ------------------------------------------------------------------------
1341
1342 // Enforce variable-related invariants: no modification of
1343 // a foreach()-iterated array.
1344 static int
1345 semantic_pass_vars (systemtap_session & sess)
1346 {
1347
1348 map<functiondecl *, set<vardecl *> *> fmv;
1349 no_var_mutation_during_iteration_check chk(sess, fmv);
1350
1351 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
1352 {
1353 functiondecl * fn = it->second;
1354 if (fn->body)
1355 {
1356 set<vardecl *> * m = new set<vardecl *>();
1357 mutated_var_collector mc (m);
1358 fn->body->visit (&mc);
1359 fmv[fn] = m;
1360 }
1361 }
1362
1363 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
1364 {
1365 functiondecl * fn = it->second;
1366 if (fn->body) fn->body->visit (&chk);
1367 }
1368
1369 for (unsigned i = 0; i < sess.probes.size(); ++i)
1370 {
1371 if (sess.probes[i]->body)
1372 sess.probes[i]->body->visit (&chk);
1373 }
1374
1375 return sess.num_errors();
1376 }
1377
1378
1379 // ------------------------------------------------------------------------
1380
1381 // Rewrite probe condition expressions into probe bodies. Tricky and
1382 // exciting business, this. This:
1383 //
1384 // probe foo if (g1 || g2) { ... }
1385 // probe bar { ... g1 ++ ... }
1386 //
1387 // becomes:
1388 //
1389 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1390 // probe foo { if (! (g1 || g2)) next; ... }
1391 // probe bar { ... g1 ++ ...;
1392 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1393 // }
1394 //
1395 // XXX: As a first cut, do only the "inline probe condition" part of the
1396 // transform.
1397
1398 static int
1399 semantic_pass_conditions (systemtap_session & sess)
1400 {
1401 for (unsigned i = 0; i < sess.probes.size(); ++i)
1402 {
1403 derived_probe* p = sess.probes[i];
1404 expression* e = p->sole_location()->condition;
1405 if (e)
1406 {
1407 varuse_collecting_visitor vut(sess);
1408 e->visit (& vut);
1409
1410 if (! vut.written.empty())
1411 {
1412 string err = (_("probe condition must not modify any variables"));
1413 sess.print_error (semantic_error (err, e->tok));
1414 }
1415 else if (vut.embedded_seen)
1416 {
1417 sess.print_error (semantic_error (_("probe condition must not include impure embedded-C"), e->tok));
1418 }
1419
1420 // Add the condition expression to the front of the
1421 // derived_probe body.
1422 if_statement *ifs = new if_statement ();
1423 ifs->tok = e->tok;
1424 ifs->thenblock = new next_statement ();
1425 ifs->thenblock->tok = e->tok;
1426 ifs->elseblock = NULL;
1427 unary_expression *notex = new unary_expression ();
1428 notex->op = "!";
1429 notex->tok = e->tok;
1430 notex->operand = e;
1431 ifs->condition = notex;
1432 p->body = new block (ifs, p->body);
1433 }
1434 }
1435
1436 return sess.num_errors();
1437 }
1438
1439 // ------------------------------------------------------------------------
1440
1441
1442 // Simple visitor that just goes through all embedded code blocks that
1443 // are available at the end all the optimizations to register any
1444 // relevant pragmas or other indicators found, so that session flags can
1445 // be set that can be inspected at translation time to trigger any
1446 // necessary initialization of code needed by the embedded code functions.
1447
1448 // This is only for pragmas that don't have any other side-effect than
1449 // needing some initialization at module init time. Currently handles
1450 // /* pragma:vma */ /* pragma:unwind */ /* pragma:symbol */
1451
1452 // /* pragma:uprobes */ is handled during the typeresolution_info pass.
1453 // /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */
1454 // are handled by the varuse_collecting_visitor.
1455
1456 struct embeddedcode_info: public functioncall_traversing_visitor
1457 {
1458 protected:
1459 systemtap_session& session;
1460
1461 public:
1462 embeddedcode_info (systemtap_session& s): session(s) { }
1463
1464 void visit_embeddedcode (embeddedcode* c)
1465 {
1466 if (! vma_tracker_enabled(session)
1467 && c->code.find("/* pragma:vma */") != string::npos)
1468 {
1469 if (session.verbose > 2)
1470 clog << _F("Turning on task_finder vma_tracker, pragma:vma found in %s",
1471 current_function->name.c_str()) << endl;
1472
1473 // PR15052: stapdyn doesn't have VMA-tracking yet.
1474 if (session.runtime_usermode_p())
1475 throw semantic_error(_("VMA-tracking is only supported by the kernel runtime (PR15052)"), c->tok);
1476
1477 enable_vma_tracker(session);
1478 }
1479
1480 if (! session.need_unwind
1481 && c->code.find("/* pragma:unwind */") != string::npos)
1482 {
1483 if (session.verbose > 2)
1484 clog << _F("Turning on unwind support, pragma:unwind found in %s",
1485 current_function->name.c_str()) << endl;
1486 session.need_unwind = true;
1487 }
1488
1489 if (! session.need_symbols
1490 && c->code.find("/* pragma:symbols */") != string::npos)
1491 {
1492 if (session.verbose > 2)
1493 clog << _F("Turning on symbol data collecting, pragma:symbols found in %s",
1494 current_function->name.c_str()) << endl;
1495 session.need_symbols = true;
1496 }
1497 }
1498 };
1499
1500 void embeddedcode_info_pass (systemtap_session& s)
1501 {
1502 embeddedcode_info eci (s);
1503 for (unsigned i=0; i<s.probes.size(); i++)
1504 s.probes[i]->body->visit (& eci);
1505 }
1506
1507 // ------------------------------------------------------------------------
1508
1509
1510 // Simple visitor that collects all the regular expressions in the
1511 // file and adds them to the session DFA table.
1512
1513 struct regex_collecting_visitor: public functioncall_traversing_visitor
1514 {
1515 protected:
1516 systemtap_session& session;
1517
1518 public:
1519 regex_collecting_visitor (systemtap_session& s): session(s) { }
1520
1521 void visit_regex_query (regex_query *q) {
1522 functioncall_traversing_visitor::visit_regex_query (q);
1523
1524 string re = q->right->value;
1525 regex_to_stapdfa (&session, re, q->right->tok);
1526 }
1527 };
1528
1529 // Go through the regex match invocations and generate corresponding DFAs.
1530 int gen_dfa_table (systemtap_session& s)
1531 {
1532 regex_collecting_visitor rcv(s);
1533
1534 for (unsigned i=0; i<s.probes.size(); i++)
1535 {
1536 try
1537 {
1538 s.probes[i]->body->visit (& rcv);
1539
1540 if (s.probes[i]->sole_location()->condition)
1541 s.probes[i]->sole_location()->condition->visit (& rcv);
1542 }
1543 catch (const semantic_error& e)
1544 {
1545 s.print_error (e);
1546 }
1547 }
1548
1549 return s.num_errors();
1550 }
1551
1552 // ------------------------------------------------------------------------
1553
1554
1555 static int semantic_pass_symbols (systemtap_session&);
1556 static int semantic_pass_optimize1 (systemtap_session&);
1557 static int semantic_pass_optimize2 (systemtap_session&);
1558 static int semantic_pass_types (systemtap_session&);
1559 static int semantic_pass_vars (systemtap_session&);
1560 static int semantic_pass_stats (systemtap_session&);
1561 static int semantic_pass_conditions (systemtap_session&);
1562
1563
1564 // Link up symbols to their declarations. Set the session's
1565 // files/probes/functions/globals vectors from the transitively
1566 // reached set of stapfiles in s.library_files, starting from
1567 // s.user_file. Perform automatic tapset inclusion and probe
1568 // alias expansion.
1569 static int
1570 semantic_pass_symbols (systemtap_session& s)
1571 {
1572 symresolution_info sym (s);
1573
1574 // NB: s.files can grow during this iteration, so size() can
1575 // return gradually increasing numbers.
1576 s.files.push_back (s.user_file);
1577 for (unsigned i = 0; i < s.files.size(); i++)
1578 {
1579 assert_no_interrupts();
1580 stapfile* dome = s.files[i];
1581
1582 // Pass 1: add globals and functions to systemtap-session master list,
1583 // so the find_* functions find them
1584 //
1585 // NB: tapset global/function definitions may duplicate or conflict
1586 // with those already in s.globals/functions. We need to deconflict
1587 // here.
1588
1589 for (unsigned i=0; i<dome->globals.size(); i++)
1590 {
1591 vardecl* g = dome->globals[i];
1592 for (unsigned j=0; j<s.globals.size(); j++)
1593 {
1594 vardecl* g2 = s.globals[j];
1595 if (g->name == g2->name)
1596 {
1597 s.print_error (semantic_error (_("conflicting global variables"),
1598 g->tok, g2->tok));
1599 }
1600 }
1601 s.globals.push_back (g);
1602 }
1603
1604 for (unsigned i=0; i<dome->functions.size(); i++)
1605 {
1606 functiondecl* f = dome->functions[i];
1607 functiondecl* f2 = s.functions[f->name];
1608 if (f2 && f != f2)
1609 {
1610 s.print_error (semantic_error (_("conflicting functions"),
1611 f->tok, f2->tok));
1612 }
1613 s.functions[f->name] = f;
1614 }
1615
1616 // NB: embeds don't conflict with each other
1617 for (unsigned i=0; i<dome->embeds.size(); i++)
1618 s.embeds.push_back (dome->embeds[i]);
1619
1620 // Pass 2: derive probes and resolve any further symbols in the
1621 // derived results.
1622
1623 for (unsigned i=0; i<dome->probes.size(); i++)
1624 {
1625 assert_no_interrupts();
1626 probe* p = dome->probes [i];
1627 vector<derived_probe*> dps;
1628
1629 // much magic happens here: probe alias expansion, wildcard
1630 // matching, low-level derived_probe construction.
1631 derive_probes (s, p, dps);
1632
1633 for (unsigned j=0; j<dps.size(); j++)
1634 {
1635 assert_no_interrupts();
1636 derived_probe* dp = dps[j];
1637 s.probes.push_back (dp);
1638 dp->join_group (s);
1639
1640 try
1641 {
1642 for (unsigned k=0; k<s.code_filters.size(); k++)
1643 s.code_filters[k]->replace (dp->body);
1644
1645 sym.current_function = 0;
1646 sym.current_probe = dp;
1647 dp->body->visit (& sym);
1648
1649 // Process the probe-point condition expression.
1650 sym.current_function = 0;
1651 sym.current_probe = 0;
1652 if (dp->sole_location()->condition)
1653 dp->sole_location()->condition->visit (& sym);
1654 }
1655 catch (const semantic_error& e)
1656 {
1657 s.print_error (e);
1658 }
1659 }
1660 }
1661
1662 // Pass 3: process functions
1663
1664 for (unsigned i=0; i<dome->functions.size(); i++)
1665 {
1666 assert_no_interrupts();
1667 functiondecl* fd = dome->functions[i];
1668
1669 try
1670 {
1671 for (unsigned j=0; j<s.code_filters.size(); j++)
1672 s.code_filters[j]->replace (fd->body);
1673
1674 sym.current_function = fd;
1675 sym.current_probe = 0;
1676 fd->body->visit (& sym);
1677 }
1678 catch (const semantic_error& e)
1679 {
1680 s.print_error (e);
1681 }
1682 }
1683 }
1684
1685 // Inform all derived_probe builders that we're done with
1686 // all resolution, so it's time to release caches.
1687 s.pattern_root->build_no_more (s);
1688
1689 if(s.systemtap_v_check){
1690 for(unsigned i=0;i<s.globals.size();i++){
1691 if(s.globals[i]->systemtap_v_conditional)
1692 s.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s.globals[i]->tok);
1693 }
1694
1695 for(map<string, functiondecl*>::const_iterator i=s.functions.begin();i != s.functions.end();++i){
1696 if(i->second->systemtap_v_conditional)
1697 s.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i->second->tok);
1698 }
1699
1700 for(unsigned i=0;i<s.probes.size();i++){
1701 vector<probe*> sysvc;
1702 s.probes[i]->collect_derivation_chain(sysvc);
1703 for(unsigned j=0;j<sysvc.size();j++){
1704 if(sysvc[j]->systemtap_v_conditional)
1705 s.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc[j]->tok);
1706 if(sysvc[j]->get_alias() && sysvc[j]->get_alias()->systemtap_v_conditional)
1707 s.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc[j]->get_alias()->tok);
1708 }
1709 }
1710 }
1711
1712 return s.num_errors(); // all those print_error calls
1713 }
1714
1715
1716 // Keep unread global variables for probe end value display.
1717 void add_global_var_display (systemtap_session& s)
1718 {
1719 // Don't generate synthetic end probes when in listings mode;
1720 // it would clutter up the list of probe points with "end ...".
1721 if (s.listing_mode) return;
1722
1723 varuse_collecting_visitor vut(s);
1724
1725 for (unsigned i=0; i<s.probes.size(); i++)
1726 {
1727 s.probes[i]->body->visit (& vut);
1728
1729 if (s.probes[i]->sole_location()->condition)
1730 s.probes[i]->sole_location()->condition->visit (& vut);
1731 }
1732
1733 for (unsigned g=0; g < s.globals.size(); g++)
1734 {
1735 vardecl* l = s.globals[g];
1736 if ((vut.read.find (l) != vut.read.end()
1737 && vut.used.find (l) != vut.used.end())
1738 || vut.written.find (l) == vut.written.end())
1739 continue;
1740
1741 // Don't generate synthetic end probes for unread globals
1742 // declared only within tapsets. (RHBZ 468139), but rather
1743 // only within the end-user script.
1744
1745 bool tapset_global = false;
1746 for (size_t m=0; m < s.library_files.size(); m++)
1747 {
1748 for (size_t n=0; n < s.library_files[m]->globals.size(); n++)
1749 {
1750 if (l->name == s.library_files[m]->globals[n]->name)
1751 {tapset_global = true; break;}
1752 }
1753 }
1754 if (tapset_global)
1755 continue;
1756
1757 probe_point::component* c = new probe_point::component("end");
1758 probe_point* pl = new probe_point;
1759 pl->components.push_back (c);
1760
1761 vector<derived_probe*> dps;
1762 block *b = new block;
1763 b->tok = l->tok;
1764
1765 probe* p = new probe;
1766 p->tok = l->tok;
1767 p->locations.push_back (pl);
1768
1769 // Create a symbol
1770 symbol* g_sym = new symbol;
1771 g_sym->name = l->name;
1772 g_sym->tok = l->tok;
1773 g_sym->type = l->type;
1774 g_sym->referent = l;
1775
1776 token* print_tok = new token(*l->tok);
1777 print_tok->type = tok_identifier;
1778 print_tok->content = "printf";
1779
1780 print_format* pf = print_format::create(print_tok);
1781 pf->raw_components += l->name;
1782
1783 if (l->index_types.size() == 0) // Scalar
1784 {
1785 if (l->type == pe_stats)
1786 if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
1787 pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1788 else
1789 pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1790 else if (l->type == pe_string)
1791 pf->raw_components += "=\"%#s\"\\n";
1792 else
1793 pf->raw_components += "=%#x\\n";
1794 pf->components = print_format::string_to_components(pf->raw_components);
1795 expr_statement* feb = new expr_statement;
1796 feb->value = pf;
1797 feb->tok = print_tok;
1798 if (l->type == pe_stats)
1799 {
1800 struct stat_op* so [5];
1801 const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
1802
1803 for (unsigned si = 0;
1804 si < (sizeof(so)/sizeof(struct stat_op*));
1805 si++)
1806 {
1807 so[si]= new stat_op;
1808 so[si]->ctype = stypes[si];
1809 so[si]->type = pe_long;
1810 so[si]->stat = g_sym;
1811 so[si]->tok = l->tok;
1812 pf->args.push_back(so[si]);
1813 }
1814 }
1815 else
1816 pf->args.push_back(g_sym);
1817
1818 /* PR7053: Checking empty aggregate for global variable */
1819 if (l->type == pe_stats) {
1820 stat_op *so= new stat_op;
1821 so->ctype = sc_count;
1822 so->type = pe_long;
1823 so->stat = g_sym;
1824 so->tok = l->tok;
1825 comparison *be = new comparison;
1826 be->op = ">";
1827 be->tok = l->tok;
1828 be->left = so;
1829 be->right = new literal_number(0);
1830
1831 /* Create printf @count=0x0 in else block */
1832 print_format* pf_0 = print_format::create(print_tok);
1833 pf_0->raw_components += l->name;
1834 pf_0->raw_components += " @count=0x0\\n";
1835 pf_0->components = print_format::string_to_components(pf_0->raw_components);
1836 expr_statement* feb_else = new expr_statement;
1837 feb_else->value = pf_0;
1838 feb_else->tok = print_tok;
1839 if_statement *ifs = new if_statement;
1840 ifs->tok = l->tok;
1841 ifs->condition = be;
1842 ifs->thenblock = feb ;
1843 ifs->elseblock = feb_else;
1844 b->statements.push_back(ifs);
1845 }
1846 else /* other non-stat cases */
1847 b->statements.push_back(feb);
1848 }
1849 else // Array
1850 {
1851 int idx_count = l->index_types.size();
1852 symbol* idx_sym[idx_count];
1853 vardecl* idx_v[idx_count];
1854 // Create a foreach loop
1855 foreach_loop* fe = new foreach_loop;
1856 fe->sort_direction = -1; // imply decreasing sort on value
1857 fe->sort_column = 0; // as in foreach ([a,b,c] in array-) { }
1858 fe->sort_aggr = sc_none; // as in default @count
1859 fe->value = NULL;
1860 fe->limit = NULL;
1861 fe->tok = l->tok;
1862
1863 // Create indices for the foreach loop
1864 for (int i=0; i < idx_count; i++)
1865 {
1866 char *idx_name;
1867 if (asprintf (&idx_name, "idx%d", i) < 0) {
1868 delete pf;
1869 delete b;
1870 delete p;
1871 delete g_sym;
1872 delete fe;
1873 return;
1874 }
1875 idx_sym[i] = new symbol;
1876 idx_sym[i]->name = idx_name;
1877 idx_sym[i]->tok = l->tok;
1878 idx_v[i] = new vardecl;
1879 idx_v[i]->name = idx_name;
1880 idx_v[i]->type = l->index_types[i];
1881 idx_v[i]->tok = l->tok;
1882 idx_sym[i]->referent = idx_v[i];
1883 fe->indexes.push_back (idx_sym[i]);
1884 }
1885
1886 // Create a printf for the foreach loop
1887 pf->raw_components += "[";
1888 for (int i=0; i < idx_count; i++)
1889 {
1890 if (i > 0)
1891 pf->raw_components += ",";
1892 if (l->index_types[i] == pe_string)
1893 pf->raw_components += "\"%#s\"";
1894 else
1895 pf->raw_components += "%#d";
1896 }
1897 pf->raw_components += "]";
1898 if (l->type == pe_stats)
1899 if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
1900 pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1901 else
1902 pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1903 else if (l->type == pe_string)
1904 pf->raw_components += "=\"%#s\"\\n";
1905 else
1906 pf->raw_components += "=%#x\\n";
1907
1908 // Create an index for the array
1909 struct arrayindex* ai = new arrayindex;
1910 ai->tok = l->tok;
1911 ai->base = g_sym;
1912
1913 for (int i=0; i < idx_count; i++)
1914 {
1915 ai->indexes.push_back (idx_sym[i]);
1916 pf->args.push_back(idx_sym[i]);
1917 }
1918 if (l->type == pe_stats)
1919 {
1920 struct stat_op* so [5];
1921 const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
1922
1923 ai->type = pe_stats;
1924 for (unsigned si = 0;
1925 si < (sizeof(so)/sizeof(struct stat_op*));
1926 si++)
1927 {
1928 so[si]= new stat_op;
1929 so[si]->ctype = stypes[si];
1930 so[si]->type = pe_long;
1931 so[si]->stat = ai;
1932 so[si]->tok = l->tok;
1933 pf->args.push_back(so[si]);
1934 }
1935 }
1936 else
1937 {
1938 // Create value for the foreach loop
1939 fe->value = new symbol;
1940 fe->value->name = "val";
1941 fe->value->tok = l->tok;
1942 pf->args.push_back(fe->value);
1943 }
1944
1945 pf->components = print_format::string_to_components(pf->raw_components);
1946 expr_statement* feb = new expr_statement;
1947 feb->value = pf;
1948 feb->tok = l->tok;
1949 fe->base = g_sym;
1950 fe->block = (statement*)feb;
1951 b->statements.push_back(fe);
1952 }
1953
1954 // Add created probe
1955 p->body = b;
1956 derive_probes (s, p, dps);
1957 for (unsigned i = 0; i < dps.size(); i++)
1958 {
1959 derived_probe* dp = dps[i];
1960 s.probes.push_back (dp);
1961 dp->join_group (s);
1962 }
1963 // Repopulate symbol and type info
1964 symresolution_info sym (s);
1965 sym.current_function = 0;
1966 sym.current_probe = dps[0];
1967 dps[0]->body->visit (& sym);
1968
1969 semantic_pass_types(s);
1970 // Mark that variable is read
1971 vut.read.insert (l);
1972 }
1973 }
1974
1975 int
1976 semantic_pass (systemtap_session& s)
1977 {
1978 int rc = 0;
1979
1980 try
1981 {
1982 s.register_library_aliases();
1983 register_standard_tapsets(s);
1984
1985 if (rc == 0) rc = semantic_pass_symbols (s);
1986 if (rc == 0) rc = semantic_pass_conditions (s);
1987 if (rc == 0) rc = semantic_pass_optimize1 (s);
1988 if (rc == 0) rc = semantic_pass_types (s);
1989 if (rc == 0) rc = gen_dfa_table(s);
1990 if (rc == 0) add_global_var_display (s);
1991 if (rc == 0) rc = semantic_pass_optimize2 (s);
1992 if (rc == 0) rc = semantic_pass_vars (s);
1993 if (rc == 0) rc = semantic_pass_stats (s);
1994 if (rc == 0) embeddedcode_info_pass (s);
1995
1996 if (s.num_errors() == 0 && s.probes.size() == 0 && !s.listing_mode)
1997 throw semantic_error (_("no probes found"));
1998 }
1999 catch (const semantic_error& e)
2000 {
2001 s.print_error (e);
2002 rc ++;
2003 }
2004
2005 // PR11443
2006 // NB: listing mode only cares whether we have any probes,
2007 // so all previous error conditions are disregarded.
2008 if (s.listing_mode)
2009 rc = s.probes.empty();
2010
2011 return rc;
2012 }
2013
2014
2015 // ------------------------------------------------------------------------
2016 // semantic processing: symbol resolution
2017
2018
2019 symresolution_info::symresolution_info (systemtap_session& s):
2020 session (s), current_function (0), current_probe (0)
2021 {
2022 }
2023
2024
2025 void
2026 symresolution_info::visit_block (block* e)
2027 {
2028 for (unsigned i=0; i<e->statements.size(); i++)
2029 {
2030 try
2031 {
2032 e->statements[i]->visit (this);
2033 }
2034 catch (const semantic_error& e)
2035 {
2036 session.print_error (e);
2037 }
2038 }
2039 }
2040
2041
2042 void
2043 symresolution_info::visit_foreach_loop (foreach_loop* e)
2044 {
2045 for (unsigned i=0; i<e->indexes.size(); i++)
2046 e->indexes[i]->visit (this);
2047
2048 symbol *array = NULL;
2049 hist_op *hist = NULL;
2050 classify_indexable (e->base, array, hist);
2051
2052 if (array)
2053 {
2054 if (!array->referent)
2055 {
2056 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
2057 if (d)
2058 array->referent = d;
2059 else
2060 {
2061 stringstream msg;
2062 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
2063 e->indexes.size(), array->name.c_str());
2064 throw semantic_error (msg.str(), e->tok);
2065 }
2066 }
2067 }
2068 else
2069 {
2070 assert (hist);
2071 hist->visit (this);
2072 }
2073
2074 if (e->value)
2075 e->value->visit (this);
2076
2077 if (e->limit)
2078 e->limit->visit (this);
2079
2080 e->block->visit (this);
2081 }
2082
2083
2084 struct
2085 delete_statement_symresolution_info:
2086 public traversing_visitor
2087 {
2088 symresolution_info *parent;
2089
2090 delete_statement_symresolution_info (symresolution_info *p):
2091 parent(p)
2092 {}
2093
2094 void visit_arrayindex (arrayindex* e)
2095 {
2096 parent->visit_arrayindex (e);
2097 }
2098 void visit_functioncall (functioncall* e)
2099 {
2100 parent->visit_functioncall (e);
2101 }
2102
2103 void visit_symbol (symbol* e)
2104 {
2105 if (e->referent)
2106 return;
2107
2108 vardecl* d = parent->find_var (e->name, -1, e->tok);
2109 if (d)
2110 e->referent = d;
2111 else
2112 throw semantic_error (_("unresolved array in delete statement"), e->tok);
2113 }
2114 };
2115
2116 void
2117 symresolution_info::visit_delete_statement (delete_statement* s)
2118 {
2119 delete_statement_symresolution_info di (this);
2120 s->value->visit (&di);
2121 }
2122
2123
2124 void
2125 symresolution_info::visit_symbol (symbol* e)
2126 {
2127 if (e->referent)
2128 return;
2129
2130 vardecl* d = find_var (e->name, 0, e->tok);
2131 if (d)
2132 e->referent = d;
2133 else
2134 {
2135 // new local
2136 vardecl* v = new vardecl;
2137 v->name = e->name;
2138 v->tok = e->tok;
2139 v->set_arity(0, e->tok);
2140 if (current_function)
2141 current_function->locals.push_back (v);
2142 else if (current_probe)
2143 current_probe->locals.push_back (v);
2144 else
2145 // must be probe-condition expression
2146 throw semantic_error (_("probe condition must not reference undeclared global"), e->tok);
2147 e->referent = v;
2148 }
2149 }
2150
2151
2152 void
2153 symresolution_info::visit_arrayindex (arrayindex* e)
2154 {
2155 for (unsigned i=0; i<e->indexes.size(); i++)
2156 e->indexes[i]->visit (this);
2157
2158 symbol *array = NULL;
2159 hist_op *hist = NULL;
2160 classify_indexable(e->base, array, hist);
2161
2162 if (array)
2163 {
2164 if (array->referent)
2165 return;
2166
2167 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
2168 if (d)
2169 array->referent = d;
2170 else
2171 {
2172 stringstream msg;
2173 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
2174 e->indexes.size(), array->name.c_str());
2175 throw semantic_error (msg.str(), e->tok);
2176 }
2177 }
2178 else
2179 {
2180 assert (hist);
2181 hist->visit (this);
2182 }
2183 }
2184
2185
2186 void
2187 symresolution_info::visit_functioncall (functioncall* e)
2188 {
2189 // XXX: we could relax this, if we're going to examine the
2190 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
2191 if (! (current_function || current_probe))
2192 {
2193 // must be probe-condition expression
2194 throw semantic_error (_("probe condition must not reference function"), e->tok);
2195 }
2196
2197 for (unsigned i=0; i<e->args.size(); i++)
2198 e->args[i]->visit (this);
2199
2200 if (e->referent)
2201 return;
2202
2203 functiondecl* d = find_function (e->function, e->args.size ());
2204 if (d)
2205 e->referent = d;
2206 else
2207 {
2208 stringstream msg;
2209 msg << _F("unresolved arity-%zu function", e->args.size());
2210 throw semantic_error (msg.str(), e->tok);
2211 }
2212 }
2213
2214 /*find_var will return an argument other than zero if the name matches the var
2215 * name ie, if the current local name matches the name passed to find_var*/
2216 vardecl*
2217 symresolution_info::find_var (const string& name, int arity, const token* tok)
2218 {
2219 if (current_function || current_probe)
2220 {
2221 // search locals
2222 vector<vardecl*>& locals = (current_function ?
2223 current_function->locals :
2224 current_probe->locals);
2225
2226
2227 for (unsigned i=0; i<locals.size(); i++)
2228 if (locals[i]->name == name)
2229 {
2230 locals[i]->set_arity (arity, tok);
2231 return locals[i];
2232 }
2233 }
2234
2235 // search function formal parameters (for scalars)
2236 if (arity == 0 && current_function)
2237 for (unsigned i=0; i<current_function->formal_args.size(); i++)
2238 if (current_function->formal_args[i]->name == name)
2239 {
2240 // NB: no need to check arity here: formal args always scalar
2241 current_function->formal_args[i]->set_arity (0, tok);
2242 return current_function->formal_args[i];
2243 }
2244
2245 // search processed globals
2246 for (unsigned i=0; i<session.globals.size(); i++)
2247 if (session.globals[i]->name == name)
2248 {
2249 if (! session.suppress_warnings)
2250 {
2251 vardecl* v = session.globals[i];
2252 // clog << "resolved " << *tok << " to global " << *v->tok << endl;
2253 if (v->tok->location.file != tok->location.file)
2254 {
2255 session.print_warning (_F("cross-file global variable reference to %s from",
2256 lex_cast(*v->tok).c_str()), tok);
2257 }
2258 }
2259 session.globals[i]->set_arity (arity, tok);
2260 return session.globals[i];
2261 }
2262
2263 // search library globals
2264 for (unsigned i=0; i<session.library_files.size(); i++)
2265 {
2266 stapfile* f = session.library_files[i];
2267 for (unsigned j=0; j<f->globals.size(); j++)
2268 {
2269 vardecl* g = f->globals[j];
2270 if (g->name == name)
2271 {
2272 g->set_arity (arity, tok);
2273
2274 // put library into the queue if not already there
2275 if (find (session.files.begin(), session.files.end(), f)
2276 == session.files.end())
2277 session.files.push_back (f);
2278
2279 return g;
2280 }
2281 }
2282 }
2283
2284 return 0;
2285 }
2286
2287
2288 functiondecl*
2289 symresolution_info::find_function (const string& name, unsigned arity)
2290 {
2291 // the common path
2292 if (session.functions.find(name) != session.functions.end())
2293 {
2294 functiondecl* fd = session.functions[name];
2295 assert (fd->name == name);
2296 if (fd->formal_args.size() == arity)
2297 return fd;
2298
2299 session.print_warning (_F("mismatched arity-%zu function found", fd->formal_args.size()),
2300 fd->tok);
2301 // and some semantic_error will shortly follow
2302 }
2303
2304 // search library functions
2305 for (unsigned i=0; i<session.library_files.size(); i++)
2306 {
2307 stapfile* f = session.library_files[i];
2308 for (unsigned j=0; j<f->functions.size(); j++)
2309 if (f->functions[j]->name == name &&
2310 f->functions[j]->formal_args.size() == arity)
2311 {
2312 // put library into the queue if not already there
2313 if (0) // session.verbose_resolution
2314 cerr << _F(" function %s is defined from %s",
2315 name.c_str(), f->name.c_str()) << endl;
2316
2317 if (find (session.files.begin(), session.files.end(), f)
2318 == session.files.end())
2319 session.files.push_back (f);
2320 // else .. print different message?
2321
2322 return f->functions[j];
2323 }
2324 }
2325
2326 return 0;
2327 }
2328
2329
2330
2331 // ------------------------------------------------------------------------
2332 // optimization
2333
2334
2335 // Do away with functiondecls that are never (transitively) called
2336 // from probes.
2337 void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
2338 {
2339 functioncall_traversing_visitor ftv;
2340 for (unsigned i=0; i<s.probes.size(); i++)
2341 {
2342 s.probes[i]->body->visit (& ftv);
2343 if (s.probes[i]->sole_location()->condition)
2344 s.probes[i]->sole_location()->condition->visit (& ftv);
2345 }
2346 vector<functiondecl*> new_unused_functions;
2347 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2348 {
2349 functiondecl* fd = it->second;
2350 if (ftv.traversed.find(fd) == ftv.traversed.end())
2351 {
2352 if (fd->tok->location.file->name == s.user_file->name && ! fd->synthetic)// !tapset
2353 s.print_warning (_F("Eliding unused function '%s'", fd->name.c_str()), fd->tok);
2354 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
2355 new_unused_functions.push_back (fd);
2356 relaxed_p = false;
2357 }
2358 }
2359 for (unsigned i=0; i<new_unused_functions.size(); i++)
2360 {
2361 map<string,functiondecl*>::iterator where = s.functions.find (new_unused_functions[i]->name);
2362 assert (where != s.functions.end());
2363 s.functions.erase (where);
2364 if (s.tapset_compile_coverage)
2365 s.unused_functions.push_back (new_unused_functions[i]);
2366 }
2367 }
2368
2369
2370 // ------------------------------------------------------------------------
2371
2372 // Do away with local & global variables that are never
2373 // written nor read.
2374 void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations)
2375 {
2376 varuse_collecting_visitor vut(s);
2377
2378 for (unsigned i=0; i<s.probes.size(); i++)
2379 {
2380 s.probes[i]->body->visit (& vut);
2381
2382 if (s.probes[i]->sole_location()->condition)
2383 s.probes[i]->sole_location()->condition->visit (& vut);
2384 }
2385
2386 // NB: Since varuse_collecting_visitor also traverses down
2387 // actually called functions, we don't need to explicitly
2388 // iterate over them. Uncalled ones should have been pruned
2389 // in _opt1 above.
2390 //
2391 // for (unsigned i=0; i<s.functions.size(); i++)
2392 // s.functions[i]->body->visit (& vut);
2393
2394 // Now in vut.read/written, we have a mixture of all locals, globals
2395
2396 for (unsigned i=0; i<s.probes.size(); i++)
2397 for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
2398 {
2399 vardecl* l = s.probes[i]->locals[j];
2400
2401 // skip over "special" locals
2402 if (l->synthetic) { j++; continue; }
2403
2404 if (vut.read.find (l) == vut.read.end() &&
2405 vut.written.find (l) == vut.written.end())
2406 {
2407 if (l->tok->location.file->name == s.user_file->name) // !tapset
2408 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
2409 if (s.tapset_compile_coverage) {
2410 s.probes[i]->unused_locals.push_back
2411 (s.probes[i]->locals[j]);
2412 }
2413 s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
2414 relaxed_p = false;
2415 // don't increment j
2416 }
2417 else
2418 {
2419 if (vut.written.find (l) == vut.written.end())
2420 if (iterations == 0 && ! s.suppress_warnings)
2421 {
2422 stringstream o;
2423 vector<vardecl*>::iterator it;
2424 for (it = s.probes[i]->locals.begin(); it != s.probes[i]->locals.end(); it++)
2425 if (l->name != (*it)->name)
2426 o << " " << (*it)->name;
2427 for (it = s.globals.begin(); it != s.globals.end(); it++)
2428 if (l->name != (*it)->name)
2429 o << " " << (*it)->name;
2430
2431 s.print_warning (_F("never-assigned local variable '%s' %s",
2432 l->name.c_str(), (o.str() == "" ? "" :
2433 (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
2434 }
2435 j++;
2436 }
2437 }
2438
2439 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2440 {
2441 functiondecl *fd = it->second;
2442 for (unsigned j=0; j<fd->locals.size(); /* see below */)
2443 {
2444 vardecl* l = fd->locals[j];
2445 if (vut.read.find (l) == vut.read.end() &&
2446 vut.written.find (l) == vut.written.end())
2447 {
2448 if (l->tok->location.file->name == s.user_file->name) // !tapset
2449 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
2450 if (s.tapset_compile_coverage) {
2451 fd->unused_locals.push_back (fd->locals[j]);
2452 }
2453 fd->locals.erase(fd->locals.begin() + j);
2454 relaxed_p = false;
2455 // don't increment j
2456 }
2457 else
2458 {
2459 if (vut.written.find (l) == vut.written.end())
2460 if (iterations == 0 && ! s.suppress_warnings)
2461 {
2462 stringstream o;
2463 vector<vardecl*>::iterator it;
2464 for (it = fd->formal_args.begin() ;
2465 it != fd->formal_args.end(); it++)
2466 if (l->name != (*it)->name)
2467 o << " " << (*it)->name;
2468 for (it = fd->locals.begin(); it != fd->locals.end(); it++)
2469 if (l->name != (*it)->name)
2470 o << " " << (*it)->name;
2471 for (it = s.globals.begin(); it != s.globals.end(); it++)
2472 if (l->name != (*it)->name)
2473 o << " " << (*it)->name;
2474
2475 s.print_warning (_F("never-assigned local variable '%s' %s",
2476 l->name.c_str(), (o.str() == "" ? "" :
2477 (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
2478 }
2479
2480 j++;
2481 }
2482 }
2483 }
2484 for (unsigned i=0; i<s.globals.size(); /* see below */)
2485 {
2486 vardecl* l = s.globals[i];
2487 if (vut.read.find (l) == vut.read.end() &&
2488 vut.written.find (l) == vut.written.end())
2489 {
2490 if (l->tok->location.file->name == s.user_file->name) // !tapset
2491 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
2492 if (s.tapset_compile_coverage) {
2493 s.unused_globals.push_back(s.globals[i]);
2494 }
2495 s.globals.erase(s.globals.begin() + i);
2496 relaxed_p = false;
2497 // don't increment i
2498 }
2499 else
2500 {
2501 if (vut.written.find (l) == vut.written.end() && ! l->init) // no initializer
2502 if (iterations == 0 && ! s.suppress_warnings)
2503 {
2504 stringstream o;
2505 vector<vardecl*>::iterator it;
2506 for (it = s.globals.begin(); it != s.globals.end(); it++)
2507 if (l->name != (*it)->name)
2508 o << " " << (*it)->name;
2509
2510 s.print_warning (_F("never assigned global variable '%s' %s", l->name.c_str(),
2511 (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
2512 }
2513
2514 i++;
2515 }
2516 }
2517 }
2518
2519
2520 // ------------------------------------------------------------------------
2521
2522 struct dead_assignment_remover: public update_visitor
2523 {
2524 systemtap_session& session;
2525 bool& relaxed_p;
2526 const varuse_collecting_visitor& vut;
2527
2528 dead_assignment_remover(systemtap_session& s, bool& r,
2529 const varuse_collecting_visitor& v):
2530 session(s), relaxed_p(r), vut(v) {}
2531
2532 void visit_assignment (assignment* e);
2533 void visit_try_block (try_block *s);
2534 };
2535
2536
2537 void
2538 dead_assignment_remover::visit_assignment (assignment* e)
2539 {
2540 replace (e->left);
2541 replace (e->right);
2542
2543 symbol* left = get_symbol_within_expression (e->left);
2544 vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
2545 if (leftvar) // not unresolved $target, so intended sideeffect may be elided
2546 {
2547 if (vut.read.find(leftvar) == vut.read.end()) // var never read?
2548 {
2549 // NB: Not so fast! The left side could be an array whose
2550 // index expressions may have side-effects. This would be
2551 // OK if we could replace the array assignment with a
2552 // statement-expression containing all the index expressions
2553 // and the rvalue... but we can't.
2554 // Another possibility is that we have an unread global variable
2555 // which are kept for probe end value display.
2556
2557 bool is_global = false;
2558 vector<vardecl*>::iterator it;
2559 for (it = session.globals.begin(); it != session.globals.end(); it++)
2560 if (leftvar->name == (*it)->name)
2561 {
2562 is_global = true;
2563 break;
2564 }
2565
2566 varuse_collecting_visitor lvut(session);
2567 e->left->visit (& lvut);
2568 if (lvut.side_effect_free () && !is_global // XXX: use _wrt() once we track focal_vars
2569 && !leftvar->synthetic) // don't elide assignment to synthetic $context variables
2570 {
2571 /* PR 1119: NB: This is not necessary here. A write-only
2572 variable will also be elided soon at the next _opt2 iteration.
2573 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
2574 session.print_warning("eliding write-only ", *e->left->tok);
2575 else
2576 */
2577 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
2578 session.print_warning(_F("Eliding assignment to '%s'", leftvar->name.c_str()), e->tok);
2579 provide (e->right); // goodbye assignment*
2580 relaxed_p = false;
2581 return;
2582 }
2583 }
2584 }
2585 provide (e);
2586 }
2587
2588
2589 void
2590 dead_assignment_remover::visit_try_block (try_block *s)
2591 {
2592 replace (s->try_block);
2593 if (s->catch_error_var)
2594 {
2595 vardecl* errvar = s->catch_error_var->referent;
2596 if (vut.read.find(errvar) == vut.read.end()) // never read?
2597 {
2598 if (session.verbose>2)
2599 clog << _F("Eliding unused error string catcher %s at %s",
2600 errvar->name.c_str(), lex_cast(*s->tok).c_str()) << endl;
2601 s->catch_error_var = 0;
2602 }
2603 }
2604 replace (s->catch_block);
2605 provide (s);
2606 }
2607
2608
2609 // Let's remove assignments to variables that are never read. We
2610 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2611 // be optimized away as an unused variable, and expr a candidate to be
2612 // removed as a side-effect-free statement expression. Wahoo!
2613 void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
2614 {
2615 // Recompute the varuse data, which will probably match the opt2
2616 // copy of the computation, except for those totally unused
2617 // variables that opt2 removed.
2618 varuse_collecting_visitor vut(s);
2619 for (unsigned i=0; i<s.probes.size(); i++)
2620 s.probes[i]->body->visit (& vut); // includes reachable functions too
2621
2622 dead_assignment_remover dar (s, relaxed_p, vut);
2623 // This instance may be reused for multiple probe/function body trims.
2624
2625 for (unsigned i=0; i<s.probes.size(); i++)
2626 dar.replace (s.probes[i]->body);
2627 for (map<string,functiondecl*>::iterator it = s.functions.begin();
2628 it != s.functions.end(); it++)
2629 dar.replace (it->second->body);
2630 // The rewrite operation is performed within the visitor.
2631
2632 // XXX: we could also zap write-only globals here
2633 }
2634
2635
2636 // ------------------------------------------------------------------------
2637
2638 struct dead_stmtexpr_remover: public update_visitor
2639 {
2640 systemtap_session& session;
2641 bool& relaxed_p;
2642 set<vardecl*> focal_vars; // vars considered subject to side-effects
2643
2644 dead_stmtexpr_remover(systemtap_session& s, bool& r):
2645 session(s), relaxed_p(r) {}
2646
2647 void visit_block (block *s);
2648 void visit_try_block (try_block *s);
2649 void visit_null_statement (null_statement *s);
2650 void visit_if_statement (if_statement* s);
2651 void visit_foreach_loop (foreach_loop *s);
2652 void visit_for_loop (for_loop *s);
2653 // XXX: and other places where stmt_expr's might be nested
2654
2655 void visit_expr_statement (expr_statement *s);
2656 };
2657
2658
2659 void
2660 dead_stmtexpr_remover::visit_null_statement (null_statement *s)
2661 {
2662 // easy!
2663 if (session.verbose>2)
2664 clog << _("Eliding side-effect-free null statement ") << *s->tok << endl;
2665 s = 0;
2666 provide (s);
2667 }
2668
2669
2670 void
2671 dead_stmtexpr_remover::visit_block (block *s)
2672 {
2673 vector<statement*> new_stmts;
2674 for (unsigned i=0; i<s->statements.size(); i++ )
2675 {
2676 statement* new_stmt = require (s->statements[i], true);
2677 if (new_stmt != 0)
2678 {
2679 // flatten nested blocks into this one
2680 block *b = dynamic_cast<block *>(new_stmt);
2681 if (b)
2682 {
2683 if (session.verbose>2)
2684 clog << _("Flattening nested block ") << *b->tok << endl;
2685 new_stmts.insert(new_stmts.end(),
2686 b->statements.begin(), b->statements.end());
2687 relaxed_p = false;
2688 }
2689 else
2690 new_stmts.push_back (new_stmt);
2691 }
2692 }
2693 if (new_stmts.size() == 0)
2694 {
2695 if (session.verbose>2)
2696 clog << _("Eliding side-effect-free empty block ") << *s->tok << endl;
2697 s = 0;
2698 }
2699 else if (new_stmts.size() == 1)
2700 {
2701 if (session.verbose>2)
2702 clog << _("Eliding side-effect-free singleton block ") << *s->tok << endl;
2703 provide (new_stmts[0]);
2704 return;
2705 }
2706 else
2707 s->statements = new_stmts;
2708 provide (s);
2709 }
2710
2711
2712 void
2713 dead_stmtexpr_remover::visit_try_block (try_block *s)
2714 {
2715 replace (s->try_block, true);
2716 replace (s->catch_block, true); // null catch{} is ok and useful
2717 if (s->try_block == 0)
2718 {
2719 if (session.verbose>2)
2720 clog << _("Eliding empty try {} block ") << *s->tok << endl;
2721 s = 0;
2722 }
2723 provide (s);
2724 }
2725
2726
2727 void
2728 dead_stmtexpr_remover::visit_if_statement (if_statement *s)
2729 {
2730 replace (s->thenblock, true);
2731 replace (s->elseblock, true);
2732
2733 if (s->thenblock == 0)
2734 {
2735 if (s->elseblock == 0)
2736 {
2737 // We may be able to elide this statement, if the condition
2738 // expression is side-effect-free.
2739 varuse_collecting_visitor vct(session);
2740 s->condition->visit(& vct);
2741 if (vct.side_effect_free ())
2742 {
2743 if (session.verbose>2)
2744 clog << _("Eliding side-effect-free if statement ")
2745 << *s->tok << endl;
2746 s = 0; // yeah, baby
2747 }
2748 else
2749 {
2750 // We can still turn it into a simple expr_statement though...
2751 if (session.verbose>2)
2752 clog << _("Creating simple evaluation from if statement ")
2753 << *s->tok << endl;
2754 expr_statement *es = new expr_statement;
2755 es->value = s->condition;
2756 es->tok = es->value->tok;
2757 provide (es);
2758 return;
2759 }
2760 }
2761 else
2762 {
2763 // For an else without a then, we can invert the condition logic to
2764 // avoid having a null statement in the thenblock
2765 if (session.verbose>2)
2766 clog << _("Inverting the condition of if statement ")
2767 << *s->tok << endl;
2768 unary_expression *ue = new unary_expression;
2769 ue->operand = s->condition;
2770 ue->tok = ue->operand->tok;
2771 ue->op = "!";
2772 s->condition = ue;
2773 s->thenblock = s->elseblock;
2774 s->elseblock = 0;
2775 }
2776 }
2777 provide (s);
2778 }
2779
2780 void
2781 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
2782 {
2783 replace (s->block, true);
2784
2785 if (s->block == 0)
2786 {
2787 // XXX what if s->limit has side effects?
2788 // XXX what about s->indexes or s->value used outside the loop?
2789 if(session.verbose > 2)
2790 clog << _("Eliding side-effect-free foreach statement ") << *s->tok << endl;
2791 s = 0; // yeah, baby
2792 }
2793 provide (s);
2794 }
2795
2796 void
2797 dead_stmtexpr_remover::visit_for_loop (for_loop *s)
2798 {
2799 replace (s->block, true);
2800
2801 if (s->block == 0)
2802 {
2803 // We may be able to elide this statement, if the condition
2804 // expression is side-effect-free.
2805 varuse_collecting_visitor vct(session);
2806 if (s->init) s->init->visit(& vct);
2807 s->cond->visit(& vct);
2808 if (s->incr) s->incr->visit(& vct);
2809 if (vct.side_effect_free ())
2810 {
2811 if (session.verbose>2)
2812 clog << _("Eliding side-effect-free for statement ") << *s->tok << endl;
2813 s = 0; // yeah, baby
2814 }
2815 else
2816 {
2817 // Can't elide this whole statement; put a null in there.
2818 s->block = new null_statement(s->tok);
2819 }
2820 }
2821 provide (s);
2822 }
2823
2824
2825
2826 void
2827 dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
2828 {
2829 // Run a varuse query against the operand expression. If it has no
2830 // side-effects, replace the entire statement expression by a null
2831 // statement with the provide() call.
2832 //
2833 // Unlike many other visitors, we do *not* traverse this outermost
2834 // one into the expression subtrees. There is no need - no
2835 // expr_statement nodes will be found there. (Function bodies
2836 // need to be visited explicitly by our caller.)
2837 //
2838 // NB. While we don't share nodes in the parse tree, let's not
2839 // deallocate *s anyway, just in case...
2840
2841 varuse_collecting_visitor vut(session);
2842 s->value->visit (& vut);
2843
2844 if (vut.side_effect_free_wrt (focal_vars))
2845 {
2846 /* PR 1119: NB: this message is not a good idea here. It can
2847 name some arbitrary RHS expression of an assignment.
2848 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
2849 session.print_warning("eliding never-assigned ", *s->value->tok);
2850 else
2851 */
2852 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
2853 session.print_warning("Eliding side-effect-free expression ", s->tok);
2854
2855 // NB: this 0 pointer is invalid to leave around for any length of
2856 // time, but the parent parse tree objects above handle it.
2857 s = 0;
2858 relaxed_p = false;
2859 }
2860 provide (s);
2861 }
2862
2863
2864 void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
2865 {
2866 // Finally, let's remove some statement-expressions that have no
2867 // side-effect. These should be exactly those whose private varuse
2868 // visitors come back with an empty "written" and "embedded" lists.
2869
2870 dead_stmtexpr_remover duv (s, relaxed_p);
2871 // This instance may be reused for multiple probe/function body trims.
2872
2873 for (unsigned i=0; i<s.probes.size(); i++)
2874 {
2875 assert_no_interrupts();
2876
2877 derived_probe* p = s.probes[i];
2878
2879 duv.focal_vars.clear ();
2880 duv.focal_vars.insert (s.globals.begin(),
2881 s.globals.end());
2882 duv.focal_vars.insert (p->locals.begin(),
2883 p->locals.end());
2884
2885 duv.replace (p->body, true);
2886 if (p->body == 0)
2887 {
2888 if (! s.timing) // PR10070
2889 s.print_warning (_F("side-effect-free probe '%s'", p->name.c_str()), p->tok);
2890
2891 p->body = new null_statement(p->tok);
2892
2893 // XXX: possible duplicate warnings; see below
2894 }
2895 }
2896 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2897 {
2898 assert_no_interrupts();
2899
2900 functiondecl* fn = it->second;
2901 duv.focal_vars.clear ();
2902 duv.focal_vars.insert (fn->locals.begin(),
2903 fn->locals.end());
2904 duv.focal_vars.insert (fn->formal_args.begin(),
2905 fn->formal_args.end());
2906 duv.focal_vars.insert (s.globals.begin(),
2907 s.globals.end());
2908
2909 duv.replace (fn->body, true);
2910 if (fn->body == 0)
2911 {
2912 s.print_warning (_F("side-effect-free function '%s'", fn->name.c_str()), fn->tok);
2913
2914 fn->body = new null_statement(fn->tok);
2915
2916 // XXX: the next iteration of the outer optimization loop may
2917 // take this new null_statement away again, and thus give us a
2918 // fresh warning. It would be better if this fixup was performed
2919 // only after the relaxation iterations.
2920 // XXX: or else see bug #6469.
2921 }
2922 }
2923 }
2924
2925
2926 // ------------------------------------------------------------------------
2927
2928 // The goal of this visitor is to reduce top-level expressions in void context
2929 // into separate statements that evaluate each subcomponent of the expression.
2930 // The dead-statement-remover can later remove some parts if they have no side
2931 // effects.
2932 //
2933 // All expressions must be overridden here so we never visit their subexpressions
2934 // accidentally. Thus, the only visited expressions should be value of an
2935 // expr_statement.
2936 //
2937 // For an expression to replace its expr_statement with something else, it will
2938 // let the new statement provide(), and then provide(0) for itself. The
2939 // expr_statement will take this as a sign that it's been replaced.
2940 struct void_statement_reducer: public update_visitor
2941 {
2942 systemtap_session& session;
2943 bool& relaxed_p;
2944 set<vardecl*> focal_vars; // vars considered subject to side-effects
2945
2946 void_statement_reducer(systemtap_session& s, bool& r):
2947 session(s), relaxed_p(r) {}
2948
2949 void visit_expr_statement (expr_statement* s);
2950
2951 // expressions in conditional / loop controls are definitely a side effect,
2952 // but still recurse into the child statements
2953 void visit_if_statement (if_statement* s);
2954 void visit_for_loop (for_loop* s);
2955 void visit_foreach_loop (foreach_loop* s);
2956
2957 // these expressions get rewritten into their statement equivalents
2958 void visit_logical_or_expr (logical_or_expr* e);
2959 void visit_logical_and_expr (logical_and_expr* e);
2960 void visit_ternary_expression (ternary_expression* e);
2961
2962 // all of these can (usually) be reduced into simpler statements
2963 void visit_binary_expression (binary_expression* e);
2964 void visit_unary_expression (unary_expression* e);
2965 void visit_regex_query (regex_query* e); // XXX depends on subexpr extraction
2966 void visit_comparison (comparison* e);
2967 void visit_concatenation (concatenation* e);
2968 void visit_functioncall (functioncall* e);
2969 void visit_print_format (print_format* e);
2970 void visit_target_symbol (target_symbol* e);
2971 void visit_atvar_op (atvar_op* e);
2972 void visit_cast_op (cast_op* e);
2973 void visit_defined_op (defined_op* e);
2974
2975 // these are a bit hairy to grok due to the intricacies of indexables and
2976 // stats, so I'm chickening out and skipping them...
2977 void visit_array_in (array_in* e) { provide (e); }
2978 void visit_arrayindex (arrayindex* e) { provide (e); }
2979 void visit_stat_op (stat_op* e) { provide (e); }
2980 void visit_hist_op (hist_op* e) { provide (e); }
2981
2982 // these can't be reduced because they always have an effect
2983 void visit_return_statement (return_statement* s) { provide (s); }
2984 void visit_delete_statement (delete_statement* s) { provide (s); }
2985 void visit_pre_crement (pre_crement* e) { provide (e); }
2986 void visit_post_crement (post_crement* e) { provide (e); }
2987 void visit_assignment (assignment* e) { provide (e); }
2988 };
2989
2990
2991 void
2992 void_statement_reducer::visit_expr_statement (expr_statement* s)
2993 {
2994 replace (s->value, true);
2995
2996 // if the expression provides 0, that's our signal that a new
2997 // statement has been provided, so we shouldn't provide this one.
2998 if (s->value != 0)
2999 provide(s);
3000 }
3001
3002 void
3003 void_statement_reducer::visit_if_statement (if_statement* s)
3004 {
3005 // s->condition is never void
3006 replace (s->thenblock);
3007 replace (s->elseblock);
3008 provide (s);
3009 }
3010
3011 void
3012 void_statement_reducer::visit_for_loop (for_loop* s)
3013 {
3014 // s->init/cond/incr are never void
3015 replace (s->block);
3016 provide (s);
3017 }
3018
3019 void
3020 void_statement_reducer::visit_foreach_loop (foreach_loop* s)
3021 {
3022 // s->indexes/base/value/limit are never void
3023 replace (s->block);
3024 provide (s);
3025 }
3026
3027 void
3028 void_statement_reducer::visit_logical_or_expr (logical_or_expr* e)
3029 {
3030 // In void context, the evaluation of "a || b" is exactly like
3031 // "if (!a) b", so let's do that instead.
3032
3033 if (session.verbose>2)
3034 clog << _("Creating if statement from unused logical-or ")
3035 << *e->tok << endl;
3036
3037 if_statement *is = new if_statement;
3038 is->tok = e->tok;
3039 is->elseblock = 0;
3040
3041 unary_expression *ue = new unary_expression;
3042 ue->operand = e->left;
3043 ue->tok = e->tok;
3044 ue->op = "!";
3045 is->condition = ue;
3046
3047 expr_statement *es = new expr_statement;
3048 es->value = e->right;
3049 es->tok = es->value->tok;
3050 is->thenblock = es;
3051
3052 is->visit(this);
3053 relaxed_p = false;
3054 e = 0;
3055 provide (e);
3056 }
3057
3058 void
3059 void_statement_reducer::visit_logical_and_expr (logical_and_expr* e)
3060 {
3061 // In void context, the evaluation of "a && b" is exactly like
3062 // "if (a) b", so let's do that instead.
3063
3064 if (session.verbose>2)
3065 clog << _("Creating if statement from unused logical-and ")
3066 << *e->tok << endl;
3067
3068 if_statement *is = new if_statement;
3069 is->tok = e->tok;
3070 is->elseblock = 0;
3071 is->condition = e->left;
3072
3073 expr_statement *es = new expr_statement;
3074 es->value = e->right;
3075 es->tok = es->value->tok;
3076 is->thenblock = es;
3077
3078 is->visit(this);
3079 relaxed_p = false;
3080 e = 0;
3081 provide (e);
3082 }
3083
3084 void
3085 void_statement_reducer::visit_ternary_expression (ternary_expression* e)
3086 {
3087 // In void context, the evaluation of "a ? b : c" is exactly like
3088 // "if (a) b else c", so let's do that instead.
3089
3090 if (session.verbose>2)
3091 clog << _("Creating if statement from unused ternary expression ")
3092 << *e->tok << endl;
3093
3094 if_statement *is = new if_statement;
3095 is->tok = e->tok;
3096 is->condition = e->cond;
3097
3098 expr_statement *es = new expr_statement;
3099 es->value = e->truevalue;
3100 es->tok = es->value->tok;
3101 is->thenblock = es;
3102
3103 es = new expr_statement;
3104 es->value = e->falsevalue;
3105 es->tok = es->value->tok;
3106 is->elseblock = es;
3107
3108 is->visit(this);
3109 relaxed_p = false;
3110 e = 0;
3111 provide (e);
3112 }
3113
3114 void
3115 void_statement_reducer::visit_binary_expression (binary_expression* e)
3116 {
3117 // When the result of a binary operation isn't needed, it's just as good to
3118 // evaluate the operands as sequential statements in a block.
3119
3120 if (session.verbose>2)
3121 clog << _("Eliding unused binary ") << *e->tok << endl;
3122
3123 block *b = new block;
3124 b->tok = e->tok;
3125
3126 expr_statement *es = new expr_statement;
3127 es->value = e->left;
3128 es->tok = es->value->tok;
3129 b->statements.push_back(es);
3130
3131 es = new expr_statement;
3132 es->value = e->right;
3133 es->tok = es->value->tok;
3134 b->statements.push_back(es);
3135
3136 b->visit(this);
3137 relaxed_p = false;
3138 e = 0;
3139 provide (e);
3140 }
3141
3142 void
3143 void_statement_reducer::visit_unary_expression (unary_expression* e)
3144 {
3145 // When the result of a unary operation isn't needed, it's just as good to
3146 // evaluate the operand directly
3147
3148 if (session.verbose>2)
3149 clog << _("Eliding unused unary ") << *e->tok << endl;
3150
3151 relaxed_p = false;
3152 e->operand->visit(this);
3153 }
3154
3155 void
3156 void_statement_reducer::visit_regex_query (regex_query* e)
3157 {
3158 // TODOXXX After subexpression extraction is implemented,
3159 // regular expression matches *may* have side-effects in
3160 // terms of producing matched subexpressions, e.g.:
3161 //
3162 // str =~ "pat"; println(matched(0));
3163 //
3164 // It's debatable if we want to actually allow this, though.
3165
3166 // Treat e as a unary expression on the left operand -- since the
3167 // right hand side must be a literal (as verified by the parser),
3168 // evaluating it never has side effects.
3169
3170 if (session.verbose>2)
3171 clog << _("Eliding regex query ") << *e->tok << endl;
3172
3173 relaxed_p = false;
3174 e->left->visit(this);
3175 }
3176
3177 void
3178 void_statement_reducer::visit_comparison (comparison* e)
3179 {
3180 visit_binary_expression(e);
3181 }
3182
3183 void
3184 void_statement_reducer::visit_concatenation (concatenation* e)
3185 {
3186 visit_binary_expression(e);
3187 }
3188
3189 void
3190 void_statement_reducer::visit_functioncall (functioncall* e)
3191 {
3192 // If a function call is pure and its result ignored, we can elide the call
3193 // and just evaluate the arguments in sequence
3194
3195 if (!e->args.size())
3196 {
3197 provide (e);
3198 return;
3199 }
3200
3201 varuse_collecting_visitor vut(session);
3202 vut.traversed.insert (e->referent);
3203 vut.current_function = e->referent;
3204 e->referent->body->visit (& vut);
3205 if (!vut.side_effect_free_wrt (focal_vars))
3206 {
3207 provide (e);
3208 return;
3209 }
3210
3211 if (session.verbose>2)
3212 clog << _("Eliding side-effect-free function call ") << *e->tok << endl;
3213
3214 block *b = new block;
3215 b->tok = e->tok;
3216
3217 for (unsigned i=0; i<e->args.size(); i++ )
3218 {
3219 expr_statement *es = new expr_statement;
3220 es->value = e->args[i];
3221 es->tok = es->value->tok;
3222 b->statements.push_back(es);
3223 }
3224
3225 b->visit(this);
3226 relaxed_p = false;
3227 e = 0;
3228 provide (e);
3229 }
3230
3231 void
3232 void_statement_reducer::visit_print_format (print_format* e)
3233 {
3234 // When an sprint's return value is ignored, we can simply evaluate the
3235 // arguments in sequence
3236
3237 if (e->print_to_stream || !e->args.size())
3238 {
3239 provide (e);
3240 return;
3241 }
3242
3243 if (session.verbose>2)
3244 clog << _("Eliding unused print ") << *e->tok << endl;
3245
3246 block *b = new block;
3247 b->tok = e->tok;
3248
3249 for (unsigned i=0; i<e->args.size(); i++ )
3250 {
3251 expr_statement *es = new expr_statement;
3252 es->value = e->args[i];
3253 es->tok = es->value->tok;
3254 b->statements.push_back(es);
3255 }
3256
3257 b->visit(this);
3258 relaxed_p = false;
3259 e = 0;
3260 provide (e);
3261 }
3262
3263 void
3264 void_statement_reducer::visit_atvar_op (atvar_op* e)
3265 {
3266 visit_target_symbol (e);
3267 }
3268
3269 void
3270 void_statement_reducer::visit_target_symbol (target_symbol* e)
3271 {
3272 // When target_symbol isn't needed, it's just as good to
3273 // evaluate any array indexes directly
3274
3275 block *b = new block;
3276 b->tok = e->tok;
3277
3278 for (unsigned i=0; i<e->components.size(); i++ )
3279 {
3280 if (e->components[i].type != target_symbol::comp_expression_array_index)
3281 continue;
3282
3283 expr_statement *es = new expr_statement;
3284 es->value = e->components[i].expr_index;
3285 es->tok = es->value->tok;
3286 b->statements.push_back(es);
3287 }
3288
3289 if (b->statements.empty())
3290 {
3291 delete b;
3292 provide (e);
3293 return;
3294 }
3295
3296 if (session.verbose>2)
3297 clog << _("Eliding unused target symbol ") << *e->tok << endl;
3298
3299 b->visit(this);
3300 relaxed_p = false;
3301 e = 0;
3302 provide (e);
3303 }
3304
3305 void
3306 void_statement_reducer::visit_cast_op (cast_op* e)
3307 {
3308 // When the result of a cast operation isn't needed, it's just as good to
3309 // evaluate the operand and any array indexes directly
3310
3311 block *b = new block;
3312 b->tok = e->tok;
3313
3314 expr_statement *es = new expr_statement;
3315 es->value = e->operand;
3316 es->tok = es->value->tok;
3317 b->statements.push_back(es);
3318
3319 for (unsigned i=0; i<e->components.size(); i++ )
3320 {
3321 if (e->components[i].type != target_symbol::comp_expression_array_index)
3322 continue;
3323
3324 es = new expr_statement;
3325 es->value = e->components[i].expr_index;
3326 es->tok = es->value->tok;
3327 b->statements.push_back(es);
3328 }
3329
3330 if (session.verbose>2)
3331 clog << _("Eliding unused typecast ") << *e->tok << endl;
3332
3333 b->visit(this);
3334 relaxed_p = false;
3335 e = 0;
3336 provide (e);
3337 }
3338
3339
3340 void
3341 void_statement_reducer::visit_defined_op (defined_op* e)
3342 {
3343 // When the result of a @defined operation isn't needed, just elide
3344 // it entirely. Its operand $expression must already be
3345 // side-effect-free.
3346
3347 if (session.verbose>2)
3348 clog << _("Eliding unused check ") << *e->tok << endl;
3349
3350 relaxed_p = false;
3351 e = 0;
3352 provide (e);
3353 }
3354
3355
3356
3357 void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
3358 {
3359 // Let's simplify statements with unused computed values.
3360
3361 void_statement_reducer vuv (s, relaxed_p);
3362 // This instance may be reused for multiple probe/function body trims.
3363
3364 vuv.focal_vars.insert (s.globals.begin(), s.globals.end());
3365
3366 for (unsigned i=0; i<s.probes.size(); i++)
3367 vuv.replace (s.probes[i]->body);
3368 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3369 it != s.functions.end(); it++)
3370 vuv.replace (it->second->body);
3371 }
3372
3373
3374 struct const_folder: public update_visitor
3375 {
3376 systemtap_session& session;
3377 bool& relaxed_p;
3378
3379 const_folder(systemtap_session& s, bool& r):
3380 session(s), relaxed_p(r), last_number(0), last_string(0) {}
3381
3382 literal_number* last_number;
3383 literal_number* get_number(expression*& e);
3384 void visit_literal_number (literal_number* e);
3385
3386 literal_string* last_string;
3387 literal_string* get_string(expression*& e);
3388 void visit_literal_string (literal_string* e);
3389
3390 void get_literal(expression*& e, literal_number*& n, literal_string*& s);
3391
3392 void visit_if_statement (if_statement* s);
3393 void visit_for_loop (for_loop* s);
3394 void visit_foreach_loop (foreach_loop* s);
3395 void visit_binary_expression (binary_expression* e);
3396 void visit_unary_expression (unary_expression* e);
3397 void visit_logical_or_expr (logical_or_expr* e);
3398 void visit_logical_and_expr (logical_and_expr* e);
3399 // void visit_regex_query (regex_query* e); // XXX: would require executing dfa at compile-time
3400 void visit_comparison (comparison* e);
3401 void visit_concatenation (concatenation* e);
3402 void visit_ternary_expression (ternary_expression* e);
3403 void visit_defined_op (defined_op* e);
3404 void visit_target_symbol (target_symbol* e);
3405 };
3406
3407 void
3408 const_folder::get_literal(expression*& e,
3409 literal_number*& n,
3410 literal_string*& s)
3411 {
3412 replace (e);
3413 n = (e == last_number) ? last_number : NULL;
3414 s = (e == last_string) ? last_string : NULL;
3415 }
3416
3417 literal_number*
3418 const_folder::get_number(expression*& e)
3419 {
3420 replace (e);
3421 return (e == last_number) ? last_number : NULL;
3422 }
3423
3424 void
3425 const_folder::visit_literal_number (literal_number* e)
3426 {
3427 last_number = e;
3428 provide (e);
3429 }
3430
3431 literal_string*
3432 const_folder::get_string(expression*& e)
3433 {
3434 replace (e);
3435 return (e == last_string) ? last_string : NULL;
3436 }
3437
3438 void
3439 const_folder::visit_literal_string (literal_string* e)
3440 {
3441 last_string = e;
3442 provide (e);
3443 }
3444
3445 void
3446 const_folder::visit_if_statement (if_statement* s)
3447 {
3448 literal_number* cond = get_number (s->condition);
3449 if (!cond)
3450 {
3451 replace (s->thenblock);
3452 replace (s->elseblock);
3453 provide (s);
3454 }
3455 else
3456 {
3457 if (session.verbose>2)
3458 clog << _F("Collapsing constant-%" PRIi64 " if-statement %s",
3459 cond->value, lex_cast(*s->tok).c_str()) << endl;
3460 relaxed_p = false;
3461
3462 statement* n = cond->value ? s->thenblock : s->elseblock;
3463 if (n)
3464 n->visit (this);
3465 else
3466 provide (new null_statement (s->tok));
3467 }
3468 }
3469
3470 void
3471 const_folder::visit_for_loop (for_loop* s)
3472 {
3473 literal_number* cond = get_number (s->cond);
3474 if (!cond || cond->value)
3475 {
3476 replace (s->init);
3477 replace (s->incr);
3478 replace (s->block);
3479 provide (s);
3480 }
3481 else
3482 {
3483 if (session.verbose>2)
3484 clog << _("Collapsing constantly-false for-loop ") << *s->tok << endl;
3485 relaxed_p = false;
3486
3487 if (s->init)
3488 s->init->visit (this);
3489 else
3490 provide (new null_statement (s->tok));
3491 }
3492 }
3493
3494 void
3495 const_folder::visit_foreach_loop (foreach_loop* s)
3496 {
3497 literal_number* limit = get_number (s->limit);
3498 if (!limit || limit->value > 0)
3499 {
3500 for (unsigned i = 0; i < s->indexes.size(); ++i)
3501 replace (s->indexes[i]);
3502 replace (s->base);
3503 replace (s->value);
3504 replace (s->block);
3505 provide (s);
3506 }
3507 else
3508 {
3509 if (session.verbose>2)
3510 clog << _("Collapsing constantly-limited foreach-loop ") << *s->tok << endl;
3511 relaxed_p = false;
3512
3513 provide (new null_statement (s->tok));
3514 }
3515 }
3516
3517 void
3518 const_folder::visit_binary_expression (binary_expression* e)
3519 {
3520 int64_t value;
3521 literal_number* left = get_number (e->left);
3522 literal_number* right = get_number (e->right);
3523
3524 if (right && !right->value && (e->op == "/" || e->op == "%"))
3525 {
3526 // Give divide-by-zero a chance to be optimized out elsewhere,
3527 // and if not it will be a runtime error anyway...
3528 provide (e);
3529 return;
3530 }
3531
3532 if (left && right)
3533 {
3534 if (e->op == "+")
3535 value = left->value + right->value;
3536 else if (e->op == "-")
3537 value = left->value - right->value;
3538 else if (e->op == "*")
3539 value = left->value * right->value;
3540 else if (e->op == "&")
3541 value = left->value & right->value;
3542 else if (e->op == "|")
3543 value = left->value | right->value;
3544 else if (e->op == "^")
3545 value = left->value ^ right->value;
3546 else if (e->op == ">>")
3547 value = left->value >> max(min(right->value, (int64_t)64), (int64_t)0);
3548 else if (e->op == "<<")
3549 value = left->value << max(min(right->value, (int64_t)64), (int64_t)0);
3550 else if (e->op == "/")
3551 value = (left->value == LLONG_MIN && right->value == -1) ? LLONG_MIN :
3552 left->value / right->value;
3553 else if (e->op == "%")
3554 value = (left->value == LLONG_MIN && right->value == -1) ? 0 :
3555 left->value % right->value;
3556 else
3557 throw semantic_error (_("unsupported binary operator ") + e->op);
3558 }
3559
3560 else if ((left && ((left->value == 0 && (e->op == "*" || e->op == "&" ||
3561 e->op == ">>" || e->op == "<<" )) ||
3562 (left->value ==-1 && (e->op == "|" || e->op == ">>"))))
3563 ||
3564 (right && ((right->value == 0 && (e->op == "*" || e->op == "&")) ||
3565 (right->value == 1 && (e->op == "%")) ||
3566 (right->value ==-1 && (e->op == "%" || e->op == "|")))))
3567 {
3568 expression* other = left ? e->right : e->left;
3569 varuse_collecting_visitor vu(session);
3570 other->visit(&vu);
3571 if (!vu.side_effect_free())
3572 {
3573 provide (e);
3574 return;
3575 }
3576
3577 if (left)
3578 value = left->value;
3579 else if (e->op == "%")
3580 value = 0;
3581 else
3582 value = right->value;
3583 }
3584
3585 else if ((left && ((left->value == 0 && (e->op == "+" || e->op == "|" ||
3586 e->op == "^")) ||
3587 (left->value == 1 && (e->op == "*")) ||
3588 (left->value ==-1 && (e->op == "&"))))
3589 ||
3590 (right && ((right->value == 0 && (e->op == "+" || e->op == "-" ||
3591 e->op == "|" || e->op == "^")) ||
3592 (right->value == 1 && (e->op == "*" || e->op == "/")) ||
3593 (right->value ==-1 && (e->op == "&")) ||
3594 (right->value <= 0 && (e->op == ">>" || e->op == "<<")))))
3595 {
3596 if (session.verbose>2)
3597 clog << _("Collapsing constant-identity binary operator ") << *e->tok << endl;
3598 relaxed_p = false;
3599
3600 provide (left ? e->right : e->left);
3601 return;
3602 }
3603
3604 else
3605 {
3606 provide (e);
3607 return;
3608 }
3609
3610 if (session.verbose>2)
3611 clog << _F("Collapsing constant-%" PRIi64 " binary operator %s",
3612 value, lex_cast(*e->tok).c_str()) << endl;
3613 relaxed_p = false;
3614
3615 literal_number* n = new literal_number(value);
3616 n->tok = e->tok;
3617 n->visit (this);
3618 }
3619
3620 void
3621 const_folder::visit_unary_expression (unary_expression* e)
3622 {
3623 literal_number* operand = get_number (e->operand);
3624 if (!operand)
3625 provide (e);
3626 else
3627 {
3628 if (session.verbose>2)
3629 clog << _("Collapsing constant unary ") << *e->tok << endl;
3630 relaxed_p = false;
3631
3632 literal_number* n = new literal_number (*operand);
3633 n->tok = e->tok;
3634 if (e->op == "+")
3635 ; // nothing to do
3636 else if (e->op == "-")
3637 n->value = -n->value;
3638 else if (e->op == "!")
3639 n->value = !n->value;
3640 else if (e->op == "~")
3641 n->value = ~n->value;
3642 else
3643 throw semantic_error (_("unsupported unary operator ") + e->op);
3644 n->visit (this);
3645 }
3646 }
3647
3648 void
3649 const_folder::visit_logical_or_expr (logical_or_expr* e)
3650 {
3651 int64_t value;
3652 literal_number* left = get_number (e->left);
3653 literal_number* right = get_number (e->right);
3654
3655 if (left && right)
3656 value = left->value || right->value;
3657
3658 else if ((left && left->value) || (right && right->value))
3659 {
3660 // If the const is on the left, we get to short-circuit the right
3661 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3662 if (right)
3663 {
3664 varuse_collecting_visitor vu(session);
3665 e->left->visit(&vu);
3666 if (!vu.side_effect_free())
3667 {
3668 provide (e);
3669 return;
3670 }
3671 }
3672
3673 value = 1;
3674 }
3675
3676 // We might also get rid of useless "0||x" and "x||0", except it does
3677 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3678 // that this would gain us much.
3679
3680 else
3681 {
3682 provide (e);
3683 return;
3684 }
3685
3686 if (session.verbose>2)
3687 clog << _("Collapsing constant logical-OR ") << *e->tok << endl;
3688 relaxed_p = false;
3689
3690 literal_number* n = new literal_number(value);
3691 n->tok = e->tok;
3692 n->visit (this);
3693 }
3694
3695 void
3696 const_folder::visit_logical_and_expr (logical_and_expr* e)
3697 {
3698 int64_t value;
3699 literal_number* left = get_number (e->left);
3700 literal_number* right = get_number (e->right);
3701
3702 if (left && right)
3703 value = left->value && right->value;
3704
3705 else if ((left && !left->value) || (right && !right->value))
3706 {
3707 // If the const is on the left, we get to short-circuit the right
3708 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3709 if (right)
3710 {
3711 varuse_collecting_visitor vu(session);
3712 e->left->visit(&vu);
3713 if (!vu.side_effect_free())
3714 {
3715 provide (e);
3716 return;
3717 }
3718 }
3719
3720 value = 0;
3721 }
3722
3723 // We might also get rid of useless "1&&x" and "x&&1", except it does
3724 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3725 // that this would gain us much.
3726
3727 else
3728 {
3729 provide (e);
3730 return;
3731 }
3732
3733 if (session.verbose>2)
3734 clog << _("Collapsing constant logical-AND ") << *e->tok << endl;
3735 relaxed_p = false;
3736
3737 literal_number* n = new literal_number(value);
3738 n->tok = e->tok;
3739 n->visit (this);
3740 }
3741
3742 void
3743 const_folder::visit_comparison (comparison* e)
3744 {
3745 int comp;
3746
3747 literal_number *left_num, *right_num;
3748 literal_string *left_str, *right_str;
3749 get_literal(e->left, left_num, left_str);
3750 get_literal(e->right, right_num, right_str);
3751
3752 if (left_str && right_str)
3753 comp = left_str->value.compare(right_str->value);
3754
3755 else if (left_num && right_num)
3756 comp = left_num->value < right_num->value ? -1 :
3757 left_num->value > right_num->value ? 1 : 0;
3758
3759 else if ((left_num && ((left_num->value == LLONG_MIN &&
3760 (e->op == "<=" || e->op == ">")) ||
3761 (left_num->value == LLONG_MAX &&
3762 (e->op == ">=" || e->op == "<"))))
3763 ||
3764 (right_num && ((right_num->value == LLONG_MIN &&
3765 (e->op == ">=" || e->op == "<")) ||
3766 (right_num->value == LLONG_MAX &&
3767 (e->op == "<=" || e->op == ">")))))
3768 {
3769 expression* other = left_num ? e->right : e->left;
3770 varuse_collecting_visitor vu(session);
3771 other->visit(&vu);
3772 if (!vu.side_effect_free())
3773 provide (e);
3774 else
3775 {
3776 if (session.verbose>2)
3777 clog << _("Collapsing constant-boundary comparison ") << *e->tok << endl;
3778 relaxed_p = false;
3779
3780 // ops <= and >= are true, < and > are false
3781 literal_number* n = new literal_number( e->op.length() == 2 );
3782 n->tok = e->tok;
3783 n->visit (this);
3784 }
3785 return;
3786 }
3787
3788 else
3789 {
3790 provide (e);
3791 return;
3792 }
3793
3794 if (session.verbose>2)
3795 clog << _("Collapsing constant comparison ") << *e->tok << endl;
3796 relaxed_p = false;
3797
3798 int64_t value;
3799 if (e->op == "==")
3800 value = comp == 0;
3801 else if (e->op == "!=")
3802 value = comp != 0;
3803 else if (e->op == "<")
3804 value = comp < 0;
3805 else if (e->op == ">")
3806 value = comp > 0;
3807 else if (e->op == "<=")
3808 value = comp <= 0;
3809 else if (e->op == ">=")
3810 value = comp >= 0;
3811 else
3812 throw semantic_error (_("unsupported comparison operator ") + e->op);
3813
3814 literal_number* n = new literal_number(value);
3815 n->tok = e->tok;
3816 n->visit (this);
3817 }
3818
3819 void
3820 const_folder::visit_concatenation (concatenation* e)
3821 {
3822 literal_string* left = get_string (e->left);
3823 literal_string* right = get_string (e->right);
3824
3825 if (left && right)
3826 {
3827 if (session.verbose>2)
3828 clog << _("Collapsing constant concatenation ") << *e->tok << endl;
3829 relaxed_p = false;
3830
3831 literal_string* n = new literal_string (*left);
3832 n->tok = e->tok;
3833 n->value.append(right->value);
3834 n->visit (this);
3835 }
3836 else if ((left && left->value.empty()) ||
3837 (right && right->value.empty()))
3838 {
3839 if (session.verbose>2)
3840 clog << _("Collapsing identity concatenation ") << *e->tok << endl;
3841 relaxed_p = false;
3842 provide(left ? e->right : e->left);
3843 }
3844 else
3845 provide (e);
3846 }
3847
3848 void
3849 const_folder::visit_ternary_expression (ternary_expression* e)
3850 {
3851 literal_number* cond = get_number (e->cond);
3852 if (!cond)
3853 {
3854 replace (e->truevalue);
3855 replace (e->falsevalue);
3856 provide (e);
3857 }
3858 else
3859 {
3860 if (session.verbose>2)
3861 clog << _F("Collapsing constant-%" PRIi64 " ternary %s",
3862 cond->value, lex_cast(*e->tok).c_str()) << endl;
3863 relaxed_p = false;
3864
3865 expression* n = cond->value ? e->truevalue : e->falsevalue;
3866 n->visit (this);
3867 }
3868 }
3869
3870 void
3871 const_folder::visit_defined_op (defined_op* e)
3872 {
3873 // If a @defined makes it this far, then it is, de facto, undefined.
3874
3875 if (session.verbose>2)
3876 clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
3877 relaxed_p = false;
3878
3879 literal_number* n = new literal_number (0);
3880 n->tok = e->tok;
3881 n->visit (this);
3882 }
3883
3884 void
3885 const_folder::visit_target_symbol (target_symbol* e)
3886 {
3887 if (session.skip_badvars)
3888 {
3889 // Upon user request for ignoring context, the symbol is replaced
3890 // with a literal 0 and a warning message displayed
3891 // XXX this ignores possible side-effects, e.g. in array indexes
3892 literal_number* ln_zero = new literal_number (0);
3893 ln_zero->tok = e->tok;
3894 provide (ln_zero);
3895 session.print_warning (_("Bad $context variable being substituted with literal 0"),
3896 e->tok);
3897 relaxed_p = false;
3898 }
3899 else
3900 update_visitor::visit_target_symbol (e);
3901 }
3902
3903 static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p)
3904 {
3905 // Let's simplify statements with constant values.
3906
3907 const_folder cf (s, relaxed_p);
3908 // This instance may be reused for multiple probe/function body trims.
3909
3910 for (unsigned i=0; i<s.probes.size(); i++)
3911 cf.replace (s.probes[i]->body);
3912 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3913 it != s.functions.end(); it++)
3914 cf.replace (it->second->body);
3915 }
3916
3917
3918 struct duplicate_function_remover: public functioncall_traversing_visitor
3919 {
3920 systemtap_session& s;
3921 map<functiondecl*, functiondecl*>& duplicate_function_map;
3922
3923 duplicate_function_remover(systemtap_session& sess,
3924 map<functiondecl*, functiondecl*>&dfm):
3925 s(sess), duplicate_function_map(dfm) {};
3926
3927 void visit_functioncall (functioncall* e);
3928 };
3929
3930 void
3931 duplicate_function_remover::visit_functioncall (functioncall *e)
3932 {
3933 functioncall_traversing_visitor::visit_functioncall (e);
3934
3935 // If the current function call reference points to a function that
3936 // is a duplicate, replace it.
3937 if (duplicate_function_map.count(e->referent) != 0)
3938 {
3939 if (s.verbose>2)
3940 clog << _F("Changing %s reference to %s reference\n",
3941 e->referent->name.c_str(), duplicate_function_map[e->referent]->name.c_str());
3942 e->tok = duplicate_function_map[e->referent]->tok;
3943 e->function = duplicate_function_map[e->referent]->name;
3944 e->referent = duplicate_function_map[e->referent];
3945 }
3946 }
3947
3948 static string
3949 get_functionsig (functiondecl* f)
3950 {
3951 ostringstream s;
3952
3953 // Get the "name:args body" of the function in s. We have to
3954 // include the args since the function 'x1(a, b)' is different than
3955 // the function 'x2(b, a)' even if the bodies of the two functions
3956 // are exactly the same.
3957 f->printsig(s);
3958 f->body->print(s);
3959
3960 // printsig puts f->name + ':' on the front. Remove this
3961 // (otherwise, functions would never compare equal).
3962 string str = s.str().erase(0, f->name.size() + 1);
3963
3964 // Return the function signature.
3965 return str;
3966 }
3967
3968 void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p)
3969 {
3970 // Walk through all the functions, looking for duplicates.
3971 map<string, functiondecl*> functionsig_map;
3972 map<functiondecl*, functiondecl*> duplicate_function_map;
3973
3974
3975 vector<functiondecl*> newly_zapped_functions;
3976 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
3977 {
3978 functiondecl *fd = it->second;
3979 string functionsig = get_functionsig(fd);
3980
3981 if (functionsig_map.count(functionsig) == 0)
3982 {
3983 // This function is unique. Remember it.
3984 functionsig_map[functionsig] = fd;
3985 }
3986 else
3987 {
3988 // This function is a duplicate.
3989 duplicate_function_map[fd] = functionsig_map[functionsig];
3990 newly_zapped_functions.push_back (fd);
3991 relaxed_p = false;
3992 }
3993 }
3994 for (unsigned i=0; i<newly_zapped_functions.size(); i++)
3995 {
3996 map<string,functiondecl*>::iterator where = s.functions.find (newly_zapped_functions[i]->name);
3997 assert (where != s.functions.end());
3998 s.functions.erase (where);
3999 }
4000
4001
4002 // If we have duplicate functions, traverse down the tree, replacing
4003 // the appropriate function calls.
4004 // duplicate_function_remover::visit_functioncall() handles the
4005 // details of replacing the function calls.
4006 if (duplicate_function_map.size() != 0)
4007 {
4008 duplicate_function_remover dfr (s, duplicate_function_map);
4009
4010 for (unsigned i=0; i < s.probes.size(); i++)
4011 s.probes[i]->body->visit(&dfr);
4012 }
4013 }
4014
4015
4016 static int
4017 semantic_pass_optimize1 (systemtap_session& s)
4018 {
4019 // In this pass, we attempt to rewrite probe/function bodies to
4020 // eliminate some blatantly unnecessary code. This is run before
4021 // type inference, but after symbol resolution and derived_probe
4022 // creation. We run an outer "relaxation" loop that repeats the
4023 // optimizations until none of them find anything to remove.
4024
4025 int rc = 0;
4026
4027 // Save the old value of suppress_warnings, as we will be changing
4028 // it below.
4029 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
4030
4031 bool relaxed_p = false;
4032 unsigned iterations = 0;
4033 while (! relaxed_p)
4034 {
4035 assert_no_interrupts();
4036
4037 relaxed_p = true; // until proven otherwise
4038
4039 // If the verbosity is high enough, always print warnings (overrides -w),
4040 // or if not, always suppress warnings for every itteration after the first.
4041 if(s.verbose > 2)
4042 s.suppress_warnings = false;
4043 else if (iterations > 0)
4044 s.suppress_warnings = true;
4045
4046 if (!s.unoptimized)
4047 {
4048 semantic_pass_opt1 (s, relaxed_p);
4049 semantic_pass_opt2 (s, relaxed_p, iterations); // produce some warnings only on iteration=0
4050 semantic_pass_opt3 (s, relaxed_p);
4051 semantic_pass_opt4 (s, relaxed_p);
4052 semantic_pass_opt5 (s, relaxed_p);
4053 }
4054
4055 // For listing mode, we need const-folding regardless of optimization so
4056 // that @defined expressions can be properly resolved. PR11360
4057 // We also want it in case variables are used in if/case expressions,
4058 // so enable always. PR11366
4059 semantic_pass_const_fold (s, relaxed_p);
4060
4061 iterations ++;
4062 }
4063
4064 return rc;
4065 }
4066
4067
4068 static int
4069 semantic_pass_optimize2 (systemtap_session& s)
4070 {
4071 // This is run after type inference. We run an outer "relaxation"
4072 // loop that repeats the optimizations until none of them find
4073 // anything to remove.
4074
4075 int rc = 0;
4076
4077 // Save the old value of suppress_warnings, as we will be changing
4078 // it below.
4079 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
4080
4081 bool relaxed_p = false;
4082 unsigned iterations = 0;
4083 while (! relaxed_p)
4084 {
4085 assert_no_interrupts();
4086 relaxed_p = true; // until proven otherwise
4087
4088 // If the verbosity is high enough, always print warnings (overrides -w),
4089 // or if not, always suppress warnings for every itteration after the first.
4090 if(s.verbose > 2)
4091 s.suppress_warnings = false;
4092 else if (iterations > 0)
4093 s.suppress_warnings = true;
4094
4095 if (!s.unoptimized)
4096 semantic_pass_opt6 (s, relaxed_p);
4097
4098 iterations++;
4099 }
4100
4101 return rc;
4102 }
4103
4104
4105
4106 // ------------------------------------------------------------------------
4107 // type resolution
4108
4109
4110 static int
4111 semantic_pass_types (systemtap_session& s)
4112 {
4113 int rc = 0;
4114
4115 // next pass: type inference
4116 unsigned iterations = 0;
4117 typeresolution_info ti (s);
4118
4119 ti.assert_resolvability = false;
4120 // XXX: maybe convert to exception-based error signalling
4121 while (1)
4122 {
4123 assert_no_interrupts();
4124
4125 iterations ++;
4126 ti.num_newly_resolved = 0;
4127 ti.num_still_unresolved = 0;
4128
4129 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
4130 {
4131 assert_no_interrupts();
4132
4133 functiondecl* fd = it->second;
4134 ti.current_probe = 0;
4135 ti.current_function = fd;
4136 ti.t = pe_unknown;
4137 fd->body->visit (& ti);
4138 // NB: we don't have to assert a known type for
4139 // functions here, to permit a "void" function.
4140 // The translator phase will omit the "retvalue".
4141 //
4142 // if (fd->type == pe_unknown)
4143 // ti.unresolved (fd->tok);
4144 for (unsigned i=0; i < fd->locals.size(); ++i)
4145 ti.check_local (fd->locals[i]);
4146 }
4147
4148 for (unsigned j=0; j<s.probes.size(); j++)
4149 {
4150 assert_no_interrupts();
4151
4152 derived_probe* pn = s.probes[j];
4153 ti.current_function = 0;
4154 ti.current_probe = pn;
4155 ti.t = pe_unknown;
4156 pn->body->visit (& ti);
4157 for (unsigned i=0; i < pn->locals.size(); ++i)
4158 ti.check_local (pn->locals[i]);
4159
4160 probe_point* pp = pn->sole_location();
4161 if (pp->condition)
4162 {
4163 ti.current_function = 0;
4164 ti.current_probe = 0;
4165 ti.t = pe_long; // NB: expected type
4166 pp->condition->visit (& ti);
4167 }
4168 }
4169
4170 for (unsigned j=0; j<s.globals.size(); j++)
4171 {
4172 vardecl* gd = s.globals[j];
4173 if (gd->type == pe_unknown)
4174 ti.unresolved (gd->tok);
4175 if(gd->arity == 0 && gd->wrap == true)
4176 {
4177 throw semantic_error (_("wrapping not supported for scalars"), gd->tok);
4178 }
4179 }
4180
4181 if (ti.num_newly_resolved == 0) // converged
4182 {
4183 if (ti.num_still_unresolved == 0)
4184 break; // successfully
4185 else if (! ti.assert_resolvability)
4186 ti.assert_resolvability = true; // last pass, with error msgs
4187 else
4188 { // unsuccessful conclusion
4189 rc ++;
4190 break;
4191 }
4192 }
4193 }
4194
4195 return rc + s.num_errors();
4196 }
4197
4198
4199
4200 typeresolution_info::typeresolution_info (systemtap_session& s):
4201 session(s), num_newly_resolved(0), num_still_unresolved(0),
4202 assert_resolvability(false), current_function(0), current_probe(0),
4203 t(pe_unknown)
4204 {
4205 }
4206
4207
4208 void
4209 typeresolution_info::visit_literal_number (literal_number* e)
4210 {
4211 assert (e->type == pe_long);
4212 if ((t == e->type) || (t == pe_unknown))
4213 return;
4214
4215 mismatch (e->tok, e->type, t);
4216 }
4217
4218
4219 void
4220 typeresolution_info::visit_literal_string (literal_string* e)
4221 {
4222 assert (e->type == pe_string);
4223 if ((t == e->type) || (t == pe_unknown))
4224 return;
4225
4226 mismatch (e->tok, e->type, t);
4227 }
4228
4229
4230 void
4231 typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
4232 {
4233 visit_binary_expression (e);
4234 }
4235
4236
4237 void
4238 typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
4239 {
4240 visit_binary_expression (e);
4241 }
4242
4243 void
4244 typeresolution_info::visit_regex_query (regex_query *e)
4245 {
4246 // NB: result of regex query is an integer!
4247 if (t == pe_stats || t == pe_string)
4248 invalid (e->tok, t);
4249
4250 t = pe_string;
4251 e->left->visit (this);
4252 t = pe_string;
4253 e->right->visit (this); // parser ensures this is a literal known at compile time
4254
4255 if (e->type == pe_unknown)
4256 {
4257 e->type = pe_long;
4258 resolved (e->tok, e->type);
4259 }
4260 }
4261
4262
4263 void
4264 typeresolution_info::visit_comparison (comparison *e)
4265 {
4266 // NB: result of any comparison is an integer!
4267 if (t == pe_stats || t == pe_string)
4268 invalid (e->tok, t);
4269
4270 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
4271 e->left->visit (this);
4272 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
4273 e->right->visit (this);
4274
4275 if (e->left->type != pe_unknown &&
4276 e->right->type != pe_unknown &&
4277 e->left->type != e->right->type)
4278 mismatch (e->tok, e->left->type, e->right->type);
4279
4280 if (e->type == pe_unknown)
4281 {
4282 e->type = pe_long;
4283 resolved (e->tok, e->type);
4284 }
4285 }
4286
4287
4288 void
4289 typeresolution_info::visit_concatenation (concatenation *e)
4290 {
4291 if (t != pe_unknown && t != pe_string)
4292 invalid (e->tok, t);
4293
4294 t = pe_string;
4295 e->left->visit (this);
4296 t = pe_string;
4297 e->right->visit (this);
4298
4299 if (e->type == pe_unknown)
4300 {
4301 e->type = pe_string;
4302 resolved (e->tok, e->type);
4303 }
4304 }
4305
4306
4307 void
4308 typeresolution_info::visit_assignment (assignment *e)
4309 {
4310 if (t == pe_stats)
4311 invalid (e->tok, t);
4312
4313 if (e->op == "<<<") // stats aggregation
4314 {
4315 if (t == pe_string)
4316 invalid (e->tok, t);
4317
4318 t = pe_stats;
4319 e->left->visit (this);
4320 t = pe_long;
4321 e->right->visit (this);
4322 if (e->type == pe_unknown ||
4323 e->type == pe_stats)
4324 {
4325 e->type = pe_long;
4326 resolved (e->tok, e->type);
4327 }
4328 }
4329
4330 else if (e->left->type == pe_stats)
4331 invalid (e->left->tok, e->left->type);
4332
4333 else if (e->right->type == pe_stats)
4334 invalid (e->right->tok, e->right->type);
4335
4336 else if (e->op == "+=" || // numeric only
4337 e->op == "-=" ||
4338 e->op == "*=" ||
4339 e->op == "/=" ||
4340 e->op == "%=" ||
4341 e->op == "&=" ||
4342 e->op == "^=" ||
4343 e->op == "|=" ||
4344 e->op == "<<=" ||
4345 e->op == ">>=" ||
4346 false)
4347 {
4348 visit_binary_expression (e);
4349 }
4350 else if (e->op == ".=" || // string only
4351 false)
4352 {
4353 if (t == pe_long || t == pe_stats)
4354 invalid (e->tok, t);
4355
4356 t = pe_string;
4357 e->left->visit (this);
4358 t = pe_string;
4359 e->right->visit (this);
4360 if (e->type == pe_unknown)
4361 {
4362 e->type = pe_string;
4363 resolved (e->tok, e->type);
4364 }
4365 }
4366 else if (e->op == "=") // overloaded = for string & numeric operands
4367 {
4368 // logic similar to ternary_expression
4369 exp_type sub_type = t;
4370
4371 // Infer types across the l/r values
4372 if (sub_type == pe_unknown && e->type != pe_unknown)
4373 sub_type = e->type;
4374
4375 t = (sub_type != pe_unknown) ? sub_type :
4376 (e->right->type != pe_unknown) ? e->right->type :
4377 pe_unknown;
4378 e->left->visit (this);
4379 t = (sub_type != pe_unknown) ? sub_type :
4380 (e->left->type != pe_unknown) ? e->left->type :
4381 pe_unknown;
4382 e->right->visit (this);
4383
4384 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
4385 {
4386 e->type = sub_type;
4387 resolved (e->tok, e->type);
4388 }
4389 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
4390 {
4391 e->type = e->left->type;
4392 resolved (e->tok, e->type);
4393 }
4394
4395 if (e->left->type != pe_unknown &&
4396 e->right->type != pe_unknown &&
4397 e->left->type != e->right->type)
4398 mismatch (e->tok, e->left->type, e->right->type);
4399
4400 }
4401 else
4402 throw semantic_error (_("unsupported assignment operator ") + e->op);
4403 }
4404
4405
4406 void
4407 typeresolution_info::visit_embedded_expr (embedded_expr *e)
4408 {
4409 if (e->type == pe_unknown)
4410 {
4411 if (e->code.find ("/* string */") != string::npos)
4412 e->type = pe_string;
4413 else // if (e->code.find ("/* long */") != string::npos)
4414 e->type = pe_long;
4415
4416 resolved (e->tok, e->type);
4417 }
4418 }
4419
4420
4421 void
4422 typeresolution_info::visit_binary_expression (binary_expression* e)
4423 {
4424 if (t == pe_stats || t == pe_string)
4425 invalid (e->tok, t);
4426
4427 t = pe_long;
4428 e->left->visit (this);
4429 t = pe_long;
4430 e->right->visit (this);
4431
4432 if (e->left->type != pe_unknown &&
4433 e->right->type != pe_unknown &&
4434 e->left->type != e->right->type)
4435 mismatch (e->tok, e->left->type, e->right->type);
4436
4437 if (e->type == pe_unknown)
4438 {
4439 e->type = pe_long;
4440 resolved (e->tok, e->type);
4441 }
4442 }
4443
4444
4445 void
4446 typeresolution_info::visit_pre_crement (pre_crement *e)
4447 {
4448 visit_unary_expression (e);
4449 }
4450
4451
4452 void
4453 typeresolution_info::visit_post_crement (post_crement *e)
4454 {
4455 visit_unary_expression (e);
4456 }
4457
4458
4459 void
4460 typeresolution_info::visit_unary_expression (unary_expression* e)
4461 {
4462 if (t == pe_stats || t == pe_string)
4463 invalid (e->tok, t);
4464
4465 t = pe_long;
4466 e->operand->visit (this);
4467
4468 if (e->type == pe_unknown)
4469 {
4470 e->type = pe_long;
4471 resolved (e->tok, e->type);
4472 }
4473 }
4474
4475
4476 void
4477 typeresolution_info::visit_ternary_expression (ternary_expression* e)
4478 {
4479 exp_type sub_type = t;
4480
4481 t = pe_long;
4482 e->cond->visit (this);
4483
4484 // Infer types across the true/false arms of the ternary expression.
4485
4486 if (sub_type == pe_unknown && e->type != pe_unknown)
4487 sub_type = e->type;
4488 t = sub_type;
4489 e->truevalue->visit (this);
4490 t = sub_type;
4491 e->falsevalue->visit (this);
4492
4493 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
4494 ; // already resolved
4495 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
4496 {
4497 e->type = sub_type;
4498 resolved (e->tok, e->type);
4499 }
4500 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
4501 {
4502 e->type = e->truevalue->type;
4503 resolved (e->tok, e->type);
4504 }
4505 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
4506 {
4507 e->type = e->falsevalue->type;
4508 resolved (e->tok, e->type);
4509 }
4510 else if (e->type != sub_type)
4511 mismatch (e->tok, sub_type, e->type);
4512 }
4513
4514
4515 template <class Referrer, class Referent>
4516 void resolve_2types (Referrer* referrer, Referent* referent,
4517 typeresolution_info* r, exp_type t, bool accept_unknown = false)
4518 {
4519 exp_type& re_type = referrer->type;
4520 const token* re_tok = referrer->tok;
4521 exp_type& te_type = referent->type;
4522 const token* te_tok = referent->tok;
4523
4524 if (t != pe_unknown && re_type == t && re_type == te_type)
4525 ; // do nothing: all three e->types in agreement
4526 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
4527 ; // do nothing: two known e->types in agreement
4528 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
4529 r->mismatch (re_tok, re_type, te_type);
4530 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
4531 r->mismatch (re_tok, re_type, t);
4532 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
4533 r->mismatch (te_tok, te_type, t);
4534 else if (re_type == pe_unknown && t != pe_unknown)
4535 {
4536 // propagate from upstream
4537 re_type = t;
4538 r->resolved (re_tok, re_type);
4539 // catch re_type/te_type mismatch later
4540 }
4541 else if (re_type == pe_unknown && te_type != pe_unknown)
4542 {
4543 // propagate from referent
4544 re_type = te_type;
4545 r->resolved (re_tok, re_type);
4546 // catch re_type/t mismatch later
4547 }
4548 else if (re_type != pe_unknown && te_type == pe_unknown)
4549 {
4550 // propagate to referent
4551 te_type = re_type;
4552 r->resolved (te_tok, te_type);
4553 // catch re_type/t mismatch later
4554 }
4555 else if (! accept_unknown)
4556 r->unresolved (re_tok);
4557 }
4558
4559
4560 void
4561 typeresolution_info::visit_symbol (symbol* e)
4562 {
4563 assert (e->referent != 0);
4564 resolve_2types (e, e->referent, this, t);
4565 }
4566
4567
4568 void
4569 typeresolution_info::visit_target_symbol (target_symbol* e)
4570 {
4571 // This occurs only if a target symbol was not resolved over in
4572 // tapset.cxx land, that error was properly suppressed, and the
4573 // later unused-expression-elimination pass didn't get rid of it
4574 // either. So we have a target symbol that is believed to be of
4575 // genuine use, yet unresolved by the provider.
4576
4577 if (session.verbose > 2)
4578 {
4579 clog << _("Resolution problem with ");
4580 if (current_function)
4581 {
4582 clog << "function " << current_function->name << endl;
4583 current_function->body->print (clog);
4584 clog << endl;
4585 }
4586 else if (current_probe)
4587 {
4588 clog << "probe " << *current_probe->sole_location() << endl;
4589 current_probe->body->print (clog);
4590 clog << endl;
4591 }
4592 else
4593 //TRANSLATORS: simply saying not an issue with a probe or function
4594 clog << _("other") << endl;
4595 }
4596
4597 if (e->saved_conversion_error)
4598 throw (* (e->saved_conversion_error));
4599 else
4600 throw semantic_error(_("unresolved target-symbol expression"), e->tok);
4601 }
4602
4603
4604 void
4605 typeresolution_info::visit_atvar_op (atvar_op* e)
4606 {
4607 // This occurs only if an @var() was not resolved over in
4608 // tapset.cxx land, that error was properly suppressed, and the
4609 // later unused-expression-elimination pass didn't get rid of it
4610 // either. So we have an @var() that is believed to be of
4611 // genuine use, yet unresolved by the provider.
4612
4613 if (session.verbose > 2)
4614 {
4615 clog << _("Resolution problem with ");
4616 if (current_function)
4617 {
4618 clog << "function " << current_function->name << endl;
4619 current_function->body->print (clog);
4620 clog << endl;
4621 }
4622 else if (current_probe)
4623 {
4624 clog << "probe " << *current_probe->sole_location() << endl;
4625 current_probe->body->print (clog);
4626 clog << endl;
4627 }
4628 else
4629 //TRANSLATORS: simply saying not an issue with a probe or function
4630 clog << _("other") << endl;
4631 }
4632
4633 if (e->saved_conversion_error)
4634 throw (* (e->saved_conversion_error));
4635 else
4636 throw semantic_error(_("unresolved @var() expression"), e->tok);
4637 }
4638
4639
4640 void
4641 typeresolution_info::visit_defined_op (defined_op* e)
4642 {
4643 throw semantic_error(_("unexpected @defined"), e->tok);
4644 }
4645
4646
4647 void
4648 typeresolution_info::visit_entry_op (entry_op* e)
4649 {
4650 throw semantic_error(_("@entry is only valid in .return probes"), e->tok);
4651 }
4652
4653
4654 void
4655 typeresolution_info::visit_cast_op (cast_op* e)
4656 {
4657 // Like target_symbol, a cast_op shouldn't survive this far
4658 // unless it was not resolved and its value is really needed.
4659 if (e->saved_conversion_error)
4660 throw (* (e->saved_conversion_error));
4661 else
4662 throw semantic_error(_F("type definition '%s' not found in '%s'",
4663 e->type_name.c_str(), e->module.c_str()), e->tok);
4664 }
4665
4666
4667 void
4668 typeresolution_info::visit_perf_op (perf_op* e)
4669 {
4670 // A perf_op should already be resolved
4671 if (t == pe_stats || t == pe_string)
4672 invalid (e->tok, t);
4673
4674 e->type = pe_long;
4675
4676 // (There is no real need to visit our operand - by parser
4677 // construction, it's always a string literal, with its type already
4678 // set.)
4679 t = pe_string;
4680 e->operand->visit (this);
4681 }
4682
4683
4684 void
4685 typeresolution_info::visit_arrayindex (arrayindex* e)
4686 {
4687
4688 symbol *array = NULL;
4689 hist_op *hist = NULL;
4690 classify_indexable(e->base, array, hist);
4691
4692 // Every hist_op has type [int]:int, that is to say, every hist_op
4693 // is a pseudo-one-dimensional integer array type indexed by
4694 // integers (bucket numbers).
4695
4696 if (hist)
4697 {
4698 if (e->indexes.size() != 1)
4699 unresolved (e->tok);
4700 t = pe_long;
4701 e->indexes[0]->visit (this);
4702 if (e->indexes[0]->type != pe_long)
4703 unresolved (e->tok);
4704 hist->visit (this);
4705 if (e->type != pe_long)
4706 {
4707 e->type = pe_long;
4708 resolved (e->tok, pe_long);
4709 }
4710 return;
4711 }
4712
4713 // Now we are left with "normal" map inference and index checking.
4714
4715 assert (array);
4716 assert (array->referent != 0);
4717 resolve_2types (e, array->referent, this, t);
4718
4719 // now resolve the array indexes
4720
4721 // if (e->referent->index_types.size() == 0)
4722 // // redesignate referent as array
4723 // e->referent->set_arity (e->indexes.size ());
4724
4725 if (e->indexes.size() != array->referent->index_types.size())
4726 unresolved (e->tok); // symbol resolution should prevent this
4727 else for (unsigned i=0; i<e->indexes.size(); i++)
4728 {
4729 expression* ee = e->indexes[i];
4730 exp_type& ft = array->referent->index_types [i];
4731 t = ft;
4732 ee->visit (this);
4733 exp_type at = ee->type;
4734
4735 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
4736 {
4737 // propagate to formal type
4738 ft = at;
4739 resolved (array->referent->tok, ft);
4740 // uses array decl as there is no token for "formal type"
4741 }
4742 if (at == pe_stats)
4743 invalid (ee->tok, at);
4744 if (ft == pe_stats)
4745 invalid (ee->tok, ft);
4746 if (at != pe_unknown && ft != pe_unknown && ft != at)
4747 mismatch (e->tok, at, ft);
4748 if (at == pe_unknown)
4749 unresolved (ee->tok);
4750 }
4751 }
4752
4753
4754 void
4755 typeresolution_info::visit_functioncall (functioncall* e)
4756 {
4757 assert (e->referent != 0);
4758
4759 resolve_2types (e, e->referent, this, t, true); // accept unknown type
4760
4761 if (e->type == pe_stats)
4762 invalid (e->tok, e->type);
4763
4764 // now resolve the function parameters
4765 if (e->args.size() != e->referent->formal_args.size())
4766 unresolved (e->tok); // symbol resolution should prevent this
4767 else for (unsigned i=0; i<e->args.size(); i++)
4768 {
4769 expression* ee = e->args[i];
4770 exp_type& ft = e->referent->formal_args[i]->type;
4771 const token* fe_tok = e->referent->formal_args[i]->tok;
4772 t = ft;
4773 ee->visit (this);
4774 exp_type at = ee->type;
4775
4776 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
4777 {
4778 // propagate to formal arg
4779 ft = at;
4780 resolved (e->referent->formal_args[i]->tok, ft);
4781 }
4782 if (at == pe_stats)
4783 invalid (e->tok, at);
4784 if (ft == pe_stats)
4785 invalid (fe_tok, ft);
4786 if (at != pe_unknown && ft != pe_unknown && ft != at)
4787 mismatch (e->tok, at, ft);
4788 if (at == pe_unknown)
4789 unresolved (e->tok);
4790 }
4791 }
4792
4793
4794 void
4795 typeresolution_info::visit_block (block* e)
4796 {
4797 for (unsigned i=0; i<e->statements.size(); i++)
4798 {
4799 try
4800 {
4801 t = pe_unknown;
4802 e->statements[i]->visit (this);
4803 }
4804 catch (const semantic_error& e)
4805 {
4806 session.print_error (e);
4807 }
4808 }
4809 }
4810
4811
4812 void
4813 typeresolution_info::visit_try_block (try_block* e)
4814 {
4815 if (e->try_block)
4816 e->try_block->visit (this);
4817 if (e->catch_error_var)
4818 {
4819 t = pe_string;
4820 e->catch_error_var->visit (this);
4821 }
4822 if (e->catch_block)
4823 e->catch_block->visit (this);
4824 }
4825
4826
4827 void
4828 typeresolution_info::visit_embeddedcode (embeddedcode* s)
4829 {
4830 // PR11573. If we have survived thus far with a piece of embedded
4831 // code that requires uprobes, we need to track this.
4832 //
4833 // This is an odd place for this check, as opposed
4834 // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
4835 // over yonder in pass 3. However, we want to do it during pass 2 so
4836 // that cached sessions also get the uprobes treatment.
4837 if (! session.need_uprobes
4838 && s->code.find("/* pragma:uprobes */") != string::npos)
4839 {
4840 if (session.verbose > 2)
4841 clog << _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl;
4842 session.need_uprobes = true;
4843 }
4844
4845 // PR15065. Likewise, we need to detect /* pragma:tagged_dfa */
4846 // before the gen_dfa_table pass. Again, the typechecking part of
4847 // pass 2 is a good place for this.
4848 if (! session.need_tagged_dfa
4849 && s->code.find("/* pragma:tagged_dfa */") != string::npos)
4850 {
4851 // if (session.verbose > 2)
4852 // clog << _F("Turning on DFA subexpressions, pragma:tagged_dfa found in %s",
4853 // current_function->name.c_str()) << endl;
4854 // session.need_tagged_dfa = true;
4855 throw semantic_error (_("Tagged DFA support is not yet available"), s->tok);
4856 }
4857 }
4858
4859
4860 void
4861 typeresolution_info::visit_if_statement (if_statement* e)
4862 {
4863 t = pe_long;
4864 e->condition->visit (this);
4865
4866 t = pe_unknown;
4867 e->thenblock->visit (this);
4868
4869 if (e->elseblock)
4870 {
4871 t = pe_unknown;
4872 e->elseblock->visit (this);
4873 }
4874 }
4875
4876
4877 void
4878 typeresolution_info::visit_for_loop (for_loop* e)
4879 {
4880 t = pe_unknown;
4881 if (e->init) e->init->visit (this);
4882 t = pe_long;
4883 e->cond->visit (this);
4884 t = pe_unknown;
4885 if (e->incr) e->incr->visit (this);
4886 t = pe_unknown;
4887 e->block->visit (this);
4888 }
4889
4890
4891 void
4892 typeresolution_info::visit_foreach_loop (foreach_loop* e)
4893 {
4894 // See also visit_arrayindex.
4895 // This is different in that, being a statement, we can't assign
4896 // a type to the outer array, only propagate to/from the indexes
4897
4898 // if (e->referent->index_types.size() == 0)
4899 // // redesignate referent as array
4900 // e->referent->set_arity (e->indexes.size ());
4901
4902 exp_type wanted_value = pe_unknown;
4903 symbol *array = NULL;
4904 hist_op *hist = NULL;
4905 classify_indexable(e->base, array, hist);
4906
4907 if (hist)
4908 {
4909 if (e->indexes.size() != 1)
4910 unresolved (e->tok);
4911 t = pe_long;
4912 e->indexes[0]->visit (this);
4913 if (e->indexes[0]->type != pe_long)
4914 unresolved (e->tok);
4915 hist->visit (this);
4916 wanted_value = pe_long;
4917 }
4918 else
4919 {
4920 assert (array);
4921 if (e->indexes.size() != array->referent->index_types.size())
4922 unresolved (e->tok); // symbol resolution should prevent this
4923 else for (unsigned i=0; i<e->indexes.size(); i++)
4924 {
4925 expression* ee = e->indexes[i];
4926 exp_type& ft = array->referent->index_types [i];
4927 t = ft;
4928 ee->visit (this);
4929 exp_type at = ee->type;
4930
4931 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
4932 {
4933 // propagate to formal type
4934 ft = at;
4935 resolved (array->referent->tok, ft);
4936 // uses array decl as there is no token for "formal type"
4937 }
4938 if (at == pe_stats)
4939 invalid (ee->tok, at);
4940 if (ft == pe_stats)
4941 invalid (ee->tok, ft);
4942 if (at != pe_unknown && ft != pe_unknown && ft != at)
4943 mismatch (e->tok, at, ft);
4944 if (at == pe_unknown)
4945 unresolved (ee->tok);
4946 }
4947 t = pe_unknown;
4948 array->visit (this);
4949 wanted_value = array->type;
4950 }
4951
4952 if (e->value)
4953 {
4954 if (wanted_value == pe_stats)
4955 invalid(e->value->tok, wanted_value);
4956 else if (wanted_value != pe_unknown)
4957 check_arg_type(wanted_value, e->value);
4958 else
4959 {
4960 t = pe_unknown;
4961 e->value->visit (this);
4962 }
4963 }
4964
4965 /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */
4966 if (wanted_value != pe_unknown)
4967 if (e->sort_aggr != sc_none && wanted_value != pe_stats)
4968 invalid (array->tok, wanted_value);
4969
4970 if (e->limit)
4971 {
4972 t = pe_long;
4973 e->limit->visit (this);
4974 }
4975
4976 t = pe_unknown;
4977 e->block->visit (this);
4978 }
4979
4980
4981 void
4982 typeresolution_info::visit_null_statement (null_statement*)
4983 {
4984 }
4985
4986
4987 void
4988 typeresolution_info::visit_expr_statement (expr_statement* e)
4989 {
4990 t = pe_unknown;
4991 e->value->visit (this);
4992 }
4993
4994
4995 struct delete_statement_typeresolution_info:
4996 public throwing_visitor
4997 {
4998 typeresolution_info *parent;
4999 delete_statement_typeresolution_info (typeresolution_info *p):
5000 throwing_visitor (_("invalid operand of delete expression")),
5001 parent (p)
5002 {}
5003
5004 void visit_arrayindex (arrayindex* e)
5005 {
5006 parent->visit_arrayindex (e);
5007 }
5008
5009 void visit_symbol (symbol* e)
5010 {
5011 exp_type ignored = pe_unknown;
5012 assert (e->referent != 0);
5013 resolve_2types (e, e->referent, parent, ignored);
5014 }
5015 };
5016
5017
5018 void
5019 typeresolution_info::visit_delete_statement (delete_statement* e)
5020 {
5021 delete_statement_typeresolution_info di (this);
5022 t = pe_unknown;
5023 e->value->visit (&di);
5024 }
5025
5026
5027 void
5028 typeresolution_info::visit_next_statement (next_statement*)
5029 {
5030 }
5031
5032
5033 void
5034 typeresolution_info::visit_break_statement (break_statement*)
5035 {
5036 }
5037
5038
5039 void
5040 typeresolution_info::visit_continue_statement (continue_statement*)
5041 {
5042 }
5043
5044
5045 void
5046 typeresolution_info::visit_array_in (array_in* e)
5047 {
5048 // all unary operators only work on numerics
5049 exp_type t1 = t;
5050 t = pe_unknown; // array value can be anything
5051 e->operand->visit (this);
5052
5053 if (t1 == pe_unknown && e->type != pe_unknown)
5054 ; // already resolved
5055 else if (t1 == pe_string || t1 == pe_stats)
5056 mismatch (e->tok, t1, pe_long);
5057 else if (e->type == pe_unknown)
5058 {
5059 e->type = pe_long;
5060 resolved (e->tok, e->type);
5061 }
5062 }
5063
5064
5065 void
5066 typeresolution_info::visit_return_statement (return_statement* e)
5067 {
5068 // This is like symbol, where the referent is
5069 // the return value of the function.
5070
5071 // translation pass will print error
5072 if (current_function == 0)
5073 return;
5074
5075 exp_type& e_type = current_function->type;
5076 t = current_function->type;
5077 e->value->visit (this);
5078
5079 if (e_type != pe_unknown && e->value->type != pe_unknown
5080 && e_type != e->value->type)
5081 mismatch (current_function->tok, e_type, e->value->type);
5082 if (e_type == pe_unknown &&
5083 (e->value->type == pe_long || e->value->type == pe_string))
5084 {
5085 // propagate non-statistics from value
5086 e_type = e->value->type;
5087 resolved (current_function->tok, e->value->type);
5088 }
5089 if (e->value->type == pe_stats)
5090 invalid (e->value->tok, e->value->type);
5091 }
5092
5093 void
5094 typeresolution_info::visit_print_format (print_format* e)
5095 {
5096 size_t unresolved_args = 0;
5097
5098 if (e->hist)
5099 {
5100 e->hist->visit(this);
5101 }
5102
5103 else if (e->print_with_format)
5104 {
5105 // If there's a format string, we can do both inference *and*
5106 // checking.
5107
5108 // First we extract the subsequence of formatting components
5109 // which are conversions (not just literal string components)
5110
5111 unsigned expected_num_args = 0;
5112 std::vector<print_format::format_component> components;
5113 for (size_t i = 0; i < e->components.size(); ++i)
5114 {
5115 if (e->components[i].type == print_format::conv_unspecified)
5116 throw semantic_error (_("Unspecified conversion in print operator format string"),
5117 e->tok);
5118 else if (e->components[i].type == print_format::conv_literal)
5119 continue;
5120 components.push_back(e->components[i]);
5121 ++expected_num_args;
5122 if (e->components[i].widthtype == print_format::width_dynamic)
5123 ++expected_num_args;
5124 if (e->components[i].prectype == print_format::prec_dynamic)
5125 ++expected_num_args;
5126 }
5127
5128 // Then we check that the number of conversions and the number
5129 // of args agree.
5130
5131 if (expected_num_args != e->args.size())
5132 throw semantic_error (_("Wrong number of args to formatted print operator"),
5133 e->tok);
5134
5135 // Then we check that the types of the conversions match the types
5136 // of the args.
5137 unsigned argno = 0;
5138 for (size_t i = 0; i < components.size(); ++i)
5139 {
5140 // Check the dynamic width, if specified
5141 if (components[i].widthtype == print_format::width_dynamic)
5142 {
5143 check_arg_type (pe_long, e->args[argno]);
5144 ++argno;
5145 }
5146
5147 // Check the dynamic precision, if specified
5148 if (components[i].prectype == print_format::prec_dynamic)
5149 {
5150 check_arg_type (pe_long, e->args[argno]);
5151 ++argno;
5152 }
5153
5154 exp_type wanted = pe_unknown;
5155
5156 switch (components[i].type)
5157 {
5158 case print_format::conv_unspecified:
5159 case print_format::conv_literal:
5160 assert (false);
5161 break;
5162
5163 case print_format::conv_pointer:
5164 case print_format::conv_number:
5165 case print_format::conv_binary:
5166 case print_format::conv_char:
5167 case print_format::conv_memory:
5168 case print_format::conv_memory_hex:
5169 wanted = pe_long;
5170 break;
5171
5172 case print_format::conv_string:
5173 wanted = pe_string;
5174 break;
5175 }
5176
5177 assert (wanted != pe_unknown);
5178 check_arg_type (wanted, e->args[argno]);
5179 ++argno;
5180 }
5181 }
5182 else
5183 {
5184 // Without a format string, the best we can do is require that
5185 // each argument resolve to a concrete type.
5186 for (size_t i = 0; i < e->args.size(); ++i)
5187 {
5188 t = pe_unknown;
5189 e->args[i]->visit (this);
5190 if (e->args[i]->type == pe_unknown)
5191 {
5192 unresolved (e->args[i]->tok);
5193 ++unresolved_args;
5194 }
5195 }
5196 }
5197
5198 if (unresolved_args == 0)
5199 {
5200 if (e->type == pe_unknown)
5201 {
5202 if (e->print_to_stream)
5203 e->type = pe_long;
5204 else
5205 e->type = pe_string;
5206 resolved (e->tok, e->type);
5207 }
5208 }
5209 else
5210 {
5211 e->type = pe_unknown;
5212 unresolved (e->tok);
5213 }
5214 }
5215
5216
5217 void
5218 typeresolution_info::visit_stat_op (stat_op* e)
5219 {
5220 t = pe_stats;
5221 e->stat->visit (this);
5222 if (e->type == pe_unknown)
5223 {
5224 e->type = pe_long;
5225 resolved (e->tok, e->type);
5226 }
5227 else if (e->type != pe_long)
5228 mismatch (e->tok, e->type, pe_long);
5229 }
5230
5231 void
5232 typeresolution_info::visit_hist_op (hist_op* e)
5233 {
5234 t = pe_stats;
5235 e->stat->visit (this);
5236 }
5237
5238
5239 void
5240 typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
5241 {
5242 t = wanted;
5243 arg->visit (this);
5244
5245 if (arg->type == pe_unknown)
5246 {
5247 arg->type = wanted;
5248 resolved (arg->tok, wanted);
5249 }
5250 else if (arg->type != wanted)
5251 {
5252 mismatch (arg->tok, arg->type, wanted);
5253 }
5254 }
5255
5256
5257 void
5258 typeresolution_info::check_local (vardecl* v)
5259 {
5260 if (v->arity != 0)
5261 {
5262 num_still_unresolved ++;
5263 if (assert_resolvability)
5264 session.print_error
5265 (semantic_error (_("array locals not supported, missing global declaration? "), v->tok));
5266 }
5267
5268 if (v->type == pe_unknown)
5269 unresolved (v->tok);
5270 else if (v->type == pe_stats)
5271 {
5272 num_still_unresolved ++;
5273 if (assert_resolvability)
5274 session.print_error
5275 (semantic_error (_("stat locals not supported, missing global declaration? "), v->tok));
5276 }
5277 else if (!(v->type == pe_long || v->type == pe_string))
5278 invalid (v->tok, v->type);
5279 }
5280
5281
5282 void
5283 typeresolution_info::unresolved (const token* tok)
5284 {
5285 num_still_unresolved ++;
5286
5287 if (assert_resolvability)
5288 {
5289 stringstream msg;
5290 msg << _("unresolved type ");
5291 session.print_error (semantic_error (msg.str(), tok));
5292 }
5293 }
5294
5295
5296 void
5297 typeresolution_info::invalid (const token* tok, exp_type pe)
5298 {
5299 num_still_unresolved ++;
5300
5301 if (assert_resolvability)
5302 {
5303 stringstream msg;
5304 if (tok && tok->type == tok_operator)
5305 msg << _("invalid operator");
5306 else
5307 msg << _("invalid type ") << pe;
5308 session.print_error (semantic_error (msg.str(), tok));
5309 }
5310 }
5311
5312
5313 void
5314 typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
5315 {
5316 bool tok_resolved = false;
5317 size_t i;
5318 semantic_error* err1 = 0;
5319 num_still_unresolved ++;
5320
5321 //BZ 9719: for improving type mismatch messages, a semantic error is
5322 //generated with the token where type was first resolved. All such
5323 //resolved tokens, stored in a vector, are matched against their
5324 //content. If an error for the matching token hasn't been printed out
5325 //already, it is and the token pushed in another printed_toks vector
5326
5327 if (assert_resolvability)
5328 {
5329 stringstream msg;
5330 for (i=0; i<resolved_toks.size(); i++)
5331 {
5332 if (resolved_toks[i]->content == tok->content)
5333 {
5334 tok_resolved = true;
5335 break;
5336 }
5337 }
5338 if (!tok_resolved)
5339 {
5340 msg << _F("type mismatch (%s vs. %s)",
5341 lex_cast(t1).c_str(), lex_cast(t2).c_str());
5342 }
5343 else
5344 {
5345 bool tok_printed = false;
5346 for (size_t j=0; j<printed_toks.size(); j++)
5347 {
5348 if (printed_toks[j] == resolved_toks[i])
5349 {
5350 tok_printed = true;
5351 break;
5352 }
5353 }
5354 msg << _F("type mismatch (%s vs. %s)",
5355 lex_cast(t1).c_str(), lex_cast(t2).c_str());
5356 if (!tok_printed)
5357 {
5358 //error for possible mismatch in the earlier resolved token
5359 printed_toks.push_back (resolved_toks[i]);
5360 stringstream type_msg;
5361 type_msg << _F("type was first inferred here (%s)", lex_cast(t2).c_str());
5362 err1 = new semantic_error (type_msg.str(), resolved_toks[i]);
5363 }
5364 }
5365 semantic_error err (msg.str(), tok);
5366 err.chain = err1;
5367 session.print_error (err);
5368 }
5369 }
5370
5371
5372 void
5373 typeresolution_info::resolved (const token* tok, exp_type)
5374 {
5375 resolved_toks.push_back (tok);
5376 num_newly_resolved ++;
5377 }
5378
5379 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.297964 seconds and 5 git commands to generate.