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