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