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