]> sourceware.org Git - systemtap.git/blob - elaborate.cxx
Bug 6611: read-only variable typo warnings should list alternatives.
[systemtap.git] / elaborate.cxx
1 // elaboration functions
2 // Copyright (C) 2005-2008 Red Hat Inc.
3 //
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
7 // later version.
8
9 #include "config.h"
10 #include "elaborate.h"
11 #include "parse.h"
12 #include "tapsets.h"
13 #include "session.h"
14 #include "util.h"
15
16 extern "C" {
17 #include <sys/utsname.h>
18 #include <fnmatch.h>
19 }
20
21 #include <algorithm>
22 #include <fstream>
23 #include <map>
24 #include <cassert>
25 #include <set>
26 #include <vector>
27 #include <algorithm>
28 #include <iterator>
29
30
31 using namespace std;
32
33
34 // ------------------------------------------------------------------------
35
36 // Used in probe_point condition construction. Either argument may be
37 // NULL; if both, return NULL too. Resulting expression is a deep
38 // copy for symbol resolution purposes.
39 expression* add_condition (expression* a, expression* b)
40 {
41 if (!a && !b) return 0;
42 if (! a) return deep_copy_visitor::deep_copy(b);
43 if (! b) return deep_copy_visitor::deep_copy(a);
44 logical_and_expr la;
45 la.op = "&&";
46 la.left = a;
47 la.right = b;
48 la.tok = a->tok; // or could be b->tok
49 return deep_copy_visitor::deep_copy(& la);
50 }
51
52 // ------------------------------------------------------------------------
53
54
55
56 derived_probe::derived_probe (probe *p):
57 base (p)
58 {
59 assert (p);
60 this->locations = p->locations;
61 this->tok = p->tok;
62 this->privileged = p->privileged;
63 this->body = deep_copy_visitor::deep_copy(p->body);
64 }
65
66
67 derived_probe::derived_probe (probe *p, probe_point *l):
68 base (p)
69 {
70 assert (p);
71 this->tok = p->tok;
72 this->privileged = p->privileged;
73 this->body = deep_copy_visitor::deep_copy(p->body);
74
75 assert (l);
76 this->locations.push_back (l);
77 }
78
79
80 void
81 derived_probe::printsig (ostream& o) const
82 {
83 probe::printsig (o);
84 printsig_nested (o);
85 }
86
87 void
88 derived_probe::printsig_nested (ostream& o) const
89 {
90 // We'd like to enclose the probe derivation chain in a /* */
91 // comment delimiter. But just printing /* base->printsig() */ is
92 // not enough, since base might itself be a derived_probe. So we,
93 // er, "cleverly" encode our nesting state as a formatting flag for
94 // the ostream.
95 ios::fmtflags f = o.flags (ios::internal);
96 if (f & ios::internal)
97 {
98 // already nested
99 o << " <- ";
100 base->printsig (o);
101 }
102 else
103 {
104 // outermost nesting
105 o << " /* <- ";
106 base->printsig (o);
107 o << " */";
108 }
109 // restore flags
110 (void) o.flags (f);
111 }
112
113
114 void
115 derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list)
116 {
117 probes_list.push_back(this);
118 base->collect_derivation_chain(probes_list);
119 }
120
121
122 probe_point*
123 derived_probe::sole_location () const
124 {
125 if (locations.size() == 0)
126 throw semantic_error ("derived_probe with no locations", this->tok);
127 else if (locations.size() > 1)
128 throw semantic_error ("derived_probe with too many locations", this->tok);
129 else
130 return locations[0];
131 }
132
133
134
135 // ------------------------------------------------------------------------
136 // Members of derived_probe_builder
137
138 bool
139 derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
140 const std::string& key,
141 std::string& value)
142 {
143 map<string, literal *>::const_iterator i = params.find (key);
144 if (i == params.end())
145 return false;
146 literal_string * ls = dynamic_cast<literal_string *>(i->second);
147 if (!ls)
148 return false;
149 value = ls->value;
150 return true;
151 }
152
153
154 bool
155 derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
156 const std::string& key,
157 int64_t& value)
158 {
159 map<string, literal *>::const_iterator i = params.find (key);
160 if (i == params.end())
161 return false;
162 if (i->second == NULL)
163 return false;
164 literal_number * ln = dynamic_cast<literal_number *>(i->second);
165 if (!ln)
166 return false;
167 value = ln->value;
168 return true;
169 }
170
171
172 bool
173 derived_probe_builder::has_null_param (std::map<std::string, literal*> const & params,
174 const std::string& key)
175 {
176 map<string, literal *>::const_iterator i = params.find(key);
177 return (i != params.end() && i->second == NULL);
178 }
179
180
181
182 // ------------------------------------------------------------------------
183 // Members of match_key.
184
185 match_key::match_key(string const & n)
186 : name(n),
187 have_parameter(false),
188 parameter_type(pe_unknown)
189 {
190 }
191
192 match_key::match_key(probe_point::component const & c)
193 : name(c.functor),
194 have_parameter(c.arg != NULL),
195 parameter_type(c.arg ? c.arg->type : pe_unknown)
196 {
197 }
198
199 match_key &
200 match_key::with_number()
201 {
202 have_parameter = true;
203 parameter_type = pe_long;
204 return *this;
205 }
206
207 match_key &
208 match_key::with_string()
209 {
210 have_parameter = true;
211 parameter_type = pe_string;
212 return *this;
213 }
214
215 string
216 match_key::str() const
217 {
218 if (have_parameter)
219 switch (parameter_type)
220 {
221 case pe_string: return name + "(string)";
222 case pe_long: return name + "(number)";
223 default: return name + "(...)";
224 }
225 return name;
226 }
227
228 bool
229 match_key::operator<(match_key const & other) const
230 {
231 return ((name < other.name)
232
233 || (name == other.name
234 && have_parameter < other.have_parameter)
235
236 || (name == other.name
237 && have_parameter == other.have_parameter
238 && parameter_type < other.parameter_type));
239 }
240
241 static bool
242 isglob(string const & str)
243 {
244 return(str.find('*') != str.npos);
245 }
246
247 bool
248 match_key::globmatch(match_key const & other) const
249 {
250 const char *other_str = other.name.c_str();
251 const char *name_str = name.c_str();
252
253 return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0)
254 && have_parameter == other.have_parameter
255 && parameter_type == other.parameter_type);
256 }
257
258 // ------------------------------------------------------------------------
259 // Members of match_node
260 // ------------------------------------------------------------------------
261
262 match_node::match_node()
263 : end(NULL)
264 {}
265
266 match_node *
267 match_node::bind(match_key const & k)
268 {
269 if (k.name == "*")
270 throw semantic_error("invalid use of wildcard probe point component");
271
272 map<match_key, match_node *>::const_iterator i = sub.find(k);
273 if (i != sub.end())
274 return i->second;
275 match_node * n = new match_node();
276 sub.insert(make_pair(k, n));
277 return n;
278 }
279
280 void
281 match_node::bind(derived_probe_builder * e)
282 {
283 if (end)
284 throw semantic_error("duplicate probe point pattern");
285 end = 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
307 void
308 match_node::find_and_build (systemtap_session& s,
309 probe* p, probe_point *loc, unsigned pos,
310 vector<derived_probe *>& results)
311 {
312 assert (pos <= loc->components.size());
313 if (pos == loc->components.size()) // matched all probe point components so far
314 {
315 derived_probe_builder *b = end; // may be 0 if only nested names are bound
316
317 if (! b)
318 {
319 string alternatives;
320 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
321 alternatives += string(" ") + i->first.str();
322
323 throw semantic_error (string("probe point truncated at position ") +
324 lex_cast<string> (pos) +
325 " (follow:" + alternatives + ")");
326 }
327
328 map<string, literal *> param_map;
329 for (unsigned i=0; i<pos; i++)
330 param_map[loc->components[i]->functor] = loc->components[i]->arg;
331 // maybe 0
332
333 b->build (s, p, loc, param_map, results);
334 }
335 else if (isglob(loc->components[pos]->functor)) // wildcard?
336 {
337 match_key match (* loc->components[pos]);
338
339 // Call find_and_build for each possible match. Ignore errors -
340 // unless we don't find any match.
341 unsigned int num_results = results.size();
342 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
343 {
344 const match_key& subkey = i->first;
345 match_node* subnode = i->second;
346
347 if (pending_interrupts) break;
348
349 if (match.globmatch(subkey))
350 {
351 if (s.verbose > 2)
352 clog << "wildcard '" << loc->components[pos]->functor
353 << "' matched '" << subkey.name << "'" << endl;
354
355 // When we have a wildcard, we need to create a copy of
356 // the probe point. Then we'll create a copy of the
357 // wildcard component, and substitute the non-wildcard
358 // functor.
359 probe_point *non_wildcard_pp = new probe_point(*loc);
360 probe_point::component *non_wildcard_component
361 = new probe_point::component(*loc->components[pos]);
362 non_wildcard_component->functor = subkey.name;
363 non_wildcard_pp->components[pos] = non_wildcard_component;
364
365 // NB: probe conditions are not attached at the wildcard
366 // (component/functor) level, but at the overall
367 // probe_point level.
368
369 // recurse (with the non-wildcard probe point)
370 try
371 {
372 subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
373 results);
374 }
375 catch (const semantic_error& e)
376 {
377 // Ignore semantic_errors while expanding wildcards.
378 // If we get done and nothing was expanded, the code
379 // following the loop will complain.
380
381 // If this wildcard didn't match, cleanup.
382 delete non_wildcard_pp;
383 delete non_wildcard_component;
384 }
385 }
386 }
387 if (! loc->optional && num_results == results.size())
388 {
389 // We didn't find any wildcard matches (since the size of
390 // the result vector didn't change). Throw an error.
391 string alternatives;
392 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
393 alternatives += string(" ") + i->first.str();
394
395 throw semantic_error(string("probe point mismatch at position ") +
396 lex_cast<string> (pos) +
397 " (alternatives:" + alternatives + ")");
398 }
399 }
400 else
401 {
402 match_key match (* loc->components[pos]);
403 sub_map_iterator_t i = sub.find (match);
404 if (i == sub.end()) // no match
405 {
406 string alternatives;
407 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
408 alternatives += string(" ") + i->first.str();
409
410 throw semantic_error (string("probe point mismatch at position ") +
411 lex_cast<string> (pos) +
412 " (alternatives:" + alternatives + ")");
413 }
414
415 match_node* subnode = i->second;
416 // recurse
417 subnode->find_and_build (s, p, loc, pos+1, results);
418 }
419 }
420
421
422 void
423 match_node::build_no_more (systemtap_session& s)
424 {
425 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
426 i->second->build_no_more (s);
427 if (end) end->build_no_more (s);
428 }
429
430
431 // ------------------------------------------------------------------------
432 // Alias probes
433 // ------------------------------------------------------------------------
434
435 struct alias_derived_probe: public derived_probe
436 {
437 alias_derived_probe (probe* base, probe_point *l, const probe_alias *a):
438 derived_probe (base, l), alias(a) {}
439
440 void upchuck () { throw semantic_error ("inappropriate", this->tok); }
441
442 // Alias probes are immediately expanded to other derived_probe
443 // types, and are not themselves emitted or listed in
444 // systemtap_session.probes
445
446 void join_group (systemtap_session&) { upchuck (); }
447
448 virtual const probe_alias *get_alias () const { return alias; }
449
450 private:
451 const probe_alias *alias; // Used to check for recursion
452 };
453
454
455 struct
456 alias_expansion_builder
457 : public derived_probe_builder
458 {
459 probe_alias * alias;
460
461 alias_expansion_builder(probe_alias * a)
462 : alias(a)
463 {}
464
465 virtual void build(systemtap_session & sess,
466 probe * use,
467 probe_point * location,
468 std::map<std::string, literal *> const &,
469 vector<derived_probe *> & finished_results)
470 {
471 // Don't build the alias expansion if infinite recursion is detected.
472 if (checkForRecursiveExpansion (use)) {
473 stringstream msg;
474 msg << "Recursive loop in alias expansion of " << *location << " at " << location->tok->location;
475 // semantic_errors thrown here are ignored.
476 sess.print_error (semantic_error (msg.str()));
477 return;
478 }
479
480 // We're going to build a new probe and wrap it up in an
481 // alias_expansion_probe so that the expansion loop recognizes it as
482 // such and re-expands its expansion.
483
484 alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias);
485 n->body = new block();
486
487 // The new probe gets the location list of the alias (with incoming condition joined)
488 n->locations = alias->locations;
489 for (unsigned i=0; i<n->locations.size(); i++)
490 n->locations[i]->condition = add_condition (n->locations[i]->condition,
491 location->condition);
492
493 // the token location of the alias,
494 n->tok = location->tok;
495
496 // and statements representing the concatenation of the alias'
497 // body with the use's.
498 //
499 // NB: locals are *not* copied forward, from either alias or
500 // use. The expansion should have its locals re-inferred since
501 // there's concatenated code here and we only want one vardecl per
502 // resulting variable.
503
504 if (alias->epilogue_style)
505 n->body = new block (use->body, alias->body);
506 else
507 n->body = new block (alias->body, use->body);
508
509 derive_probes (sess, n, finished_results, location->optional);
510 }
511
512 bool checkForRecursiveExpansion (probe *use)
513 {
514 // Collect the derivation chain of this probe.
515 vector<probe*>derivations;
516 use->collect_derivation_chain (derivations);
517
518 // Check all probe points in the alias expansion against the currently-being-expanded probe point
519 // of each of the probes in the derivation chain, looking for a match. This
520 // indicates infinite recursion.
521 // The first element of the derivation chain will be the derived_probe representing 'use', so
522 // start the search with the second element.
523 assert (derivations.size() > 0);
524 assert (derivations[0] == use);
525 for (unsigned d = 1; d < derivations.size(); ++d) {
526 if (use->get_alias() == derivations[d]->get_alias())
527 return true; // recursion detected
528 }
529 return false;
530 }
531 };
532
533
534 // ------------------------------------------------------------------------
535 // Pattern matching
536 // ------------------------------------------------------------------------
537
538
539 // Register all the aliases we've seen in library files, and the user
540 // file, as patterns.
541
542 void
543 systemtap_session::register_library_aliases()
544 {
545 vector<stapfile*> files(library_files);
546 files.push_back(user_file);
547
548 for (unsigned f = 0; f < files.size(); ++f)
549 {
550 stapfile * file = files[f];
551 for (unsigned a = 0; a < file->aliases.size(); ++a)
552 {
553 probe_alias * alias = file->aliases[a];
554 try
555 {
556 for (unsigned n = 0; n < alias->alias_names.size(); ++n)
557 {
558 probe_point * name = alias->alias_names[n];
559 match_node * n = pattern_root;
560 for (unsigned c = 0; c < name->components.size(); ++c)
561 {
562 probe_point::component * comp = name->components[c];
563 // XXX: alias parameters
564 if (comp->arg)
565 throw semantic_error("alias component "
566 + comp->functor
567 + " contains illegal parameter");
568 n = n->bind(comp->functor);
569 }
570 n->bind(new alias_expansion_builder(alias));
571 }
572 }
573 catch (const semantic_error& e)
574 {
575 semantic_error* er = new semantic_error (e); // copy it
576 stringstream msg;
577 msg << e.msg2;
578 msg << " while registering probe alias ";
579 alias->printsig(msg);
580 er->msg2 = msg.str();
581 print_error (* er);
582 delete er;
583 }
584 }
585 }
586 }
587
588
589 static unsigned max_recursion = 100;
590
591 struct
592 recursion_guard
593 {
594 unsigned & i;
595 recursion_guard(unsigned & i) : i(i)
596 {
597 if (i > max_recursion)
598 throw semantic_error("recursion limit reached");
599 ++i;
600 }
601 ~recursion_guard()
602 {
603 --i;
604 }
605 };
606
607 // The match-and-expand loop.
608 void
609 derive_probes (systemtap_session& s,
610 probe *p, vector<derived_probe*>& dps,
611 bool optional)
612 {
613 for (unsigned i = 0; i < p->locations.size(); ++i)
614 {
615 if (pending_interrupts) break;
616
617 probe_point *loc = p->locations[i];
618
619 try
620 {
621 unsigned num_atbegin = dps.size();
622
623 // Pass down optional flag from e.g. alias reference to each
624 // probe_point instance. We do this by temporarily overriding
625 // the probe_point optional flag. We could instead deep-copy
626 // and set a flag on the copy permanently.
627 bool old_loc_opt = loc->optional;
628 loc->optional = loc->optional || optional;
629 s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
630 loc->optional = old_loc_opt;
631 unsigned num_atend = dps.size();
632
633 if (! (loc->optional||optional) && // something required, but
634 num_atbegin == num_atend) // nothing new derived!
635 throw semantic_error ("no match");
636
637 if (loc->sufficient && (num_atend > num_atbegin))
638 {
639 if (s.verbose > 1)
640 {
641 clog << "Probe point ";
642 p->locations[i]->print(clog);
643 clog << " sufficient, skipped";
644 for (unsigned j = i+1; j < p->locations.size(); ++j)
645 {
646 clog << " ";
647 p->locations[j]->print(clog);
648 }
649 clog << endl;
650 }
651 break; // we need not try to derive for any other locations
652 }
653 }
654 catch (const semantic_error& e)
655 {
656 // XXX: prefer not to print_error at every nest/unroll level
657
658 semantic_error* er = new semantic_error (e); // copy it
659 stringstream msg;
660 msg << e.msg2;
661 msg << " while resolving probe point " << *loc;
662 er->msg2 = msg.str();
663 s.print_error (* er);
664 delete er;
665 }
666
667 }
668 }
669
670
671
672 // ------------------------------------------------------------------------
673 //
674 // Indexable usage checks
675 //
676
677 struct symbol_fetcher
678 : public throwing_visitor
679 {
680 symbol *&sym;
681
682 symbol_fetcher (symbol *&sym): sym(sym)
683 {}
684
685 void visit_symbol (symbol* e)
686 {
687 sym = e;
688 }
689
690 void visit_target_symbol (target_symbol* e)
691 {
692 sym = e;
693 }
694
695 void visit_arrayindex (arrayindex* e)
696 {
697 e->base->visit_indexable (this);
698 }
699
700 void throwone (const token* t)
701 {
702 throw semantic_error ("Expecting symbol or array index expression", t);
703 }
704 };
705
706 symbol *
707 get_symbol_within_expression (expression *e)
708 {
709 symbol *sym = NULL;
710 symbol_fetcher fetcher(sym);
711 e->visit (&fetcher);
712 return sym; // NB: may be null!
713 }
714
715 static symbol *
716 get_symbol_within_indexable (indexable *ix)
717 {
718 symbol *array = NULL;
719 hist_op *hist = NULL;
720 classify_indexable(ix, array, hist);
721 if (array)
722 return array;
723 else
724 return get_symbol_within_expression (hist->stat);
725 }
726
727 struct mutated_var_collector
728 : public traversing_visitor
729 {
730 set<vardecl *> * mutated_vars;
731
732 mutated_var_collector (set<vardecl *> * mm)
733 : mutated_vars (mm)
734 {}
735
736 void visit_assignment(assignment* e)
737 {
738 if (e->type == pe_stats && e->op == "<<<")
739 {
740 vardecl *vd = get_symbol_within_expression (e->left)->referent;
741 if (vd)
742 mutated_vars->insert (vd);
743 }
744 traversing_visitor::visit_assignment(e);
745 }
746
747 void visit_arrayindex (arrayindex *e)
748 {
749 if (is_active_lvalue (e))
750 {
751 symbol *sym;
752 if (e->base->is_symbol (sym))
753 mutated_vars->insert (sym->referent);
754 else
755 throw semantic_error("Assignment to read-only histogram bucket", e->tok);
756 }
757 traversing_visitor::visit_arrayindex (e);
758 }
759 };
760
761
762 struct no_var_mutation_during_iteration_check
763 : public traversing_visitor
764 {
765 systemtap_session & session;
766 map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
767 vector<vardecl *> vars_being_iterated;
768
769 no_var_mutation_during_iteration_check
770 (systemtap_session & sess,
771 map<functiondecl *,set<vardecl *> *> & fmv)
772 : session(sess), function_mutates_vars (fmv)
773 {}
774
775 void visit_arrayindex (arrayindex *e)
776 {
777 if (is_active_lvalue(e))
778 {
779 vardecl *vd = get_symbol_within_indexable (e->base)->referent;
780 if (vd)
781 {
782 for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
783 {
784 vardecl *v = vars_being_iterated[i];
785 if (v == vd)
786 {
787 string err = ("variable '" + v->name +
788 "' modified during 'foreach' iteration");
789 session.print_error (semantic_error (err, e->tok));
790 }
791 }
792 }
793 }
794 traversing_visitor::visit_arrayindex (e);
795 }
796
797 void visit_functioncall (functioncall* e)
798 {
799 map<functiondecl *,set<vardecl *> *>::const_iterator i
800 = function_mutates_vars.find (e->referent);
801
802 if (i != function_mutates_vars.end())
803 {
804 for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
805 {
806 vardecl *m = vars_being_iterated[j];
807 if (i->second->find (m) != i->second->end())
808 {
809 string err = ("function call modifies var '" + m->name +
810 "' during 'foreach' iteration");
811 session.print_error (semantic_error (err, e->tok));
812 }
813 }
814 }
815
816 traversing_visitor::visit_functioncall (e);
817 }
818
819 void visit_foreach_loop(foreach_loop* s)
820 {
821 vardecl *vd = get_symbol_within_indexable (s->base)->referent;
822
823 if (vd)
824 vars_being_iterated.push_back (vd);
825
826 traversing_visitor::visit_foreach_loop (s);
827
828 if (vd)
829 vars_being_iterated.pop_back();
830 }
831 };
832
833
834 // ------------------------------------------------------------------------
835
836 struct stat_decl_collector
837 : public traversing_visitor
838 {
839 systemtap_session & session;
840
841 stat_decl_collector(systemtap_session & sess)
842 : session(sess)
843 {}
844
845 void visit_stat_op (stat_op* e)
846 {
847 symbol *sym = get_symbol_within_expression (e->stat);
848 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
849 session.stat_decls[sym->name] = statistic_decl();
850 }
851
852 void visit_assignment (assignment* e)
853 {
854 if (e->op == "<<<")
855 {
856 symbol *sym = get_symbol_within_expression (e->left);
857 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
858 session.stat_decls[sym->name] = statistic_decl();
859 }
860 else
861 traversing_visitor::visit_assignment(e);
862 }
863
864 void visit_hist_op (hist_op* e)
865 {
866 symbol *sym = get_symbol_within_expression (e->stat);
867 statistic_decl new_stat;
868
869 if (e->htype == hist_linear)
870 {
871 new_stat.type = statistic_decl::linear;
872 assert (e->params.size() == 3);
873 new_stat.linear_low = e->params[0];
874 new_stat.linear_high = e->params[1];
875 new_stat.linear_step = e->params[2];
876 }
877 else
878 {
879 assert (e->htype == hist_log);
880 new_stat.type = statistic_decl::logarithmic;
881 assert (e->params.size() == 0);
882 }
883
884 map<string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
885 if (i == session.stat_decls.end())
886 session.stat_decls[sym->name] = new_stat;
887 else
888 {
889 statistic_decl & old_stat = i->second;
890 if (!(old_stat == new_stat))
891 {
892 if (old_stat.type == statistic_decl::none)
893 i->second = new_stat;
894 else
895 {
896 // FIXME: Support multiple co-declared histogram types
897 semantic_error se("multiple histogram types declared on '" + sym->name + "'",
898 e->tok);
899 session.print_error (se);
900 }
901 }
902 }
903 }
904
905 };
906
907 static int
908 semantic_pass_stats (systemtap_session & sess)
909 {
910 stat_decl_collector sdc(sess);
911
912 for (unsigned i = 0; i < sess.functions.size(); ++i)
913 sess.functions[i]->body->visit (&sdc);
914
915 for (unsigned i = 0; i < sess.probes.size(); ++i)
916 sess.probes[i]->body->visit (&sdc);
917
918 for (unsigned i = 0; i < sess.globals.size(); ++i)
919 {
920 vardecl *v = sess.globals[i];
921 if (v->type == pe_stats)
922 {
923
924 if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
925 {
926 semantic_error se("unable to infer statistic parameters for global '" + v->name + "'");
927 sess.print_error (se);
928 }
929 }
930 }
931
932 return sess.num_errors();
933 }
934
935 // ------------------------------------------------------------------------
936
937 // Enforce variable-related invariants: no modification of
938 // a foreach()-iterated array.
939 static int
940 semantic_pass_vars (systemtap_session & sess)
941 {
942
943 map<functiondecl *, set<vardecl *> *> fmv;
944 no_var_mutation_during_iteration_check chk(sess, fmv);
945
946 for (unsigned i = 0; i < sess.functions.size(); ++i)
947 {
948 functiondecl * fn = sess.functions[i];
949 if (fn->body)
950 {
951 set<vardecl *> * m = new set<vardecl *>();
952 mutated_var_collector mc (m);
953 fn->body->visit (&mc);
954 fmv[fn] = m;
955 }
956 }
957
958 for (unsigned i = 0; i < sess.functions.size(); ++i)
959 {
960 if (sess.functions[i]->body)
961 sess.functions[i]->body->visit (&chk);
962 }
963
964 for (unsigned i = 0; i < sess.probes.size(); ++i)
965 {
966 if (sess.probes[i]->body)
967 sess.probes[i]->body->visit (&chk);
968 }
969
970 return sess.num_errors();
971 }
972
973
974 // ------------------------------------------------------------------------
975
976 // Rewrite probe condition expressions into probe bodies. Tricky and
977 // exciting business, this. This:
978 //
979 // probe foo if (g1 || g2) { ... }
980 // probe bar { ... g1 ++ ... }
981 //
982 // becomes:
983 //
984 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
985 // probe foo { if (! (g1 || g2)) next; ... }
986 // probe bar { ... g1 ++ ...;
987 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
988 // }
989 //
990 // XXX: As a first cut, do only the "inline probe condition" part of the
991 // transform.
992
993 static int
994 semantic_pass_conditions (systemtap_session & sess)
995 {
996 for (unsigned i = 0; i < sess.probes.size(); ++i)
997 {
998 derived_probe* p = sess.probes[i];
999 expression* e = p->sole_location()->condition;
1000 if (e)
1001 {
1002 varuse_collecting_visitor vut;
1003 e->visit (& vut);
1004
1005 if (! vut.written.empty())
1006 {
1007 string err = ("probe condition must not modify any variables");
1008 sess.print_error (semantic_error (err, e->tok));
1009 }
1010 else if (vut.embedded_seen)
1011 {
1012 sess.print_error (semantic_error ("probe condition must not include impure embedded-C", e->tok));
1013 }
1014
1015 // Add the condition expression to the front of the
1016 // derived_probe body.
1017 if_statement *ifs = new if_statement ();
1018 ifs->tok = e->tok;
1019 ifs->thenblock = new next_statement ();
1020 ifs->thenblock->tok = e->tok;
1021 ifs->elseblock = NULL;
1022 unary_expression *notex = new unary_expression ();
1023 notex->op = "!";
1024 notex->tok = e->tok;
1025 notex->operand = e;
1026 ifs->condition = notex;
1027 p->body = new block (ifs, p->body);
1028 }
1029 }
1030
1031 return sess.num_errors();
1032 }
1033
1034
1035 // ------------------------------------------------------------------------
1036
1037
1038 static int semantic_pass_symbols (systemtap_session&);
1039 static int semantic_pass_optimize1 (systemtap_session&);
1040 static int semantic_pass_optimize2 (systemtap_session&);
1041 static int semantic_pass_types (systemtap_session&);
1042 static int semantic_pass_vars (systemtap_session&);
1043 static int semantic_pass_stats (systemtap_session&);
1044 static int semantic_pass_conditions (systemtap_session&);
1045
1046
1047 // Link up symbols to their declarations. Set the session's
1048 // files/probes/functions/globals vectors from the transitively
1049 // reached set of stapfiles in s.library_files, starting from
1050 // s.user_file. Perform automatic tapset inclusion and probe
1051 // alias expansion.
1052 static int
1053 semantic_pass_symbols (systemtap_session& s)
1054 {
1055 symresolution_info sym (s);
1056
1057 // NB: s.files can grow during this iteration, so size() can
1058 // return gradually increasing numbers.
1059 s.files.push_back (s.user_file);
1060 for (unsigned i = 0; i < s.files.size(); i++)
1061 {
1062 if (pending_interrupts) break;
1063 stapfile* dome = s.files[i];
1064
1065 // Pass 1: add globals and functions to systemtap-session master list,
1066 // so the find_* functions find them
1067
1068 for (unsigned i=0; i<dome->globals.size(); i++)
1069 s.globals.push_back (dome->globals[i]);
1070
1071 for (unsigned i=0; i<dome->functions.size(); i++)
1072 s.functions.push_back (dome->functions[i]);
1073
1074 for (unsigned i=0; i<dome->embeds.size(); i++)
1075 s.embeds.push_back (dome->embeds[i]);
1076
1077 // Pass 2: process functions
1078
1079 for (unsigned i=0; i<dome->functions.size(); i++)
1080 {
1081 if (pending_interrupts) break;
1082 functiondecl* fd = dome->functions[i];
1083
1084 try
1085 {
1086 sym.current_function = fd;
1087 sym.current_probe = 0;
1088 fd->body->visit (& sym);
1089 }
1090 catch (const semantic_error& e)
1091 {
1092 s.print_error (e);
1093 }
1094 }
1095
1096 // Pass 3: derive probes and resolve any further symbols in the
1097 // derived results.
1098
1099 for (unsigned i=0; i<dome->probes.size(); i++)
1100 {
1101 if (pending_interrupts) break;
1102 probe* p = dome->probes [i];
1103 vector<derived_probe*> dps;
1104
1105 // much magic happens here: probe alias expansion, wildcard
1106 // matching, low-level derived_probe construction.
1107 derive_probes (s, p, dps);
1108
1109 for (unsigned j=0; j<dps.size(); j++)
1110 {
1111 if (pending_interrupts) break;
1112 derived_probe* dp = dps[j];
1113 s.probes.push_back (dp);
1114 dp->join_group (s);
1115
1116 try
1117 {
1118 sym.current_function = 0;
1119 sym.current_probe = dp;
1120 dp->body->visit (& sym);
1121
1122 // Process the probe-point condition expression.
1123 sym.current_function = 0;
1124 sym.current_probe = 0;
1125 if (dp->sole_location()->condition)
1126 dp->sole_location()->condition->visit (& sym);
1127 }
1128 catch (const semantic_error& e)
1129 {
1130 s.print_error (e);
1131 }
1132 }
1133 }
1134 }
1135
1136 // Inform all derived_probe builders that we're done with
1137 // all resolution, so it's time to release caches.
1138 s.pattern_root->build_no_more (s);
1139
1140 return s.num_errors(); // all those print_error calls
1141 }
1142
1143
1144
1145 int
1146 semantic_pass (systemtap_session& s)
1147 {
1148 int rc = 0;
1149
1150 try
1151 {
1152 s.register_library_aliases();
1153 register_standard_tapsets(s);
1154
1155 if (rc == 0) rc = semantic_pass_symbols (s);
1156 if (rc == 0) rc = semantic_pass_conditions (s);
1157 if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize1 (s);
1158 if (rc == 0) rc = semantic_pass_types (s);
1159 if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize2 (s);
1160 if (rc == 0) rc = semantic_pass_vars (s);
1161 if (rc == 0) rc = semantic_pass_stats (s);
1162
1163 if (s.probes.size() == 0 && !s.listing_mode)
1164 throw semantic_error ("no probes found");
1165 }
1166 catch (const semantic_error& e)
1167 {
1168 s.print_error (e);
1169 rc ++;
1170 }
1171
1172 return rc;
1173 }
1174
1175
1176 // ------------------------------------------------------------------------
1177
1178
1179 systemtap_session::systemtap_session ():
1180 // NB: pointer members must be manually initialized!
1181 pattern_root(new match_node),
1182 user_file (0),
1183 be_derived_probes(0),
1184 dwarf_derived_probes(0),
1185 uprobe_derived_probes(0),
1186 utrace_derived_probes(0),
1187 task_finder_derived_probes(0),
1188 timer_derived_probes(0),
1189 profile_derived_probes(0),
1190 mark_derived_probes(0),
1191 hrtimer_derived_probes(0),
1192 perfmon_derived_probes(0),
1193 procfs_derived_probes(0),
1194 op (0), up (0),
1195 sym_kprobes_text_start (0),
1196 sym_kprobes_text_end (0),
1197 sym_stext (0)
1198 {
1199 }
1200
1201
1202 void
1203 systemtap_session::print_error (const semantic_error& e)
1204 {
1205 string message_str;
1206 stringstream message;
1207
1208 // NB: we don't print error messages during listing mode.
1209 if (listing_mode) return;
1210
1211 message << "semantic error: " << e.what ();
1212 if (e.tok1 || e.tok2)
1213 message << ": ";
1214 if (e.tok1) message << *e.tok1;
1215 message << e.msg2;
1216 if (e.tok2) message << *e.tok2;
1217 message << endl;
1218 message_str = message.str();
1219
1220 // Duplicate elimination
1221 if (seen_errors.find (message_str) == seen_errors.end())
1222 {
1223 seen_errors.insert (message_str);
1224 cerr << message_str;
1225 }
1226
1227 if (e.chain)
1228 print_error (* e.chain);
1229 }
1230
1231 void
1232 systemtap_session::print_warning (const string& message_str, string optional_str = "")
1233 {
1234 // Duplicate elimination
1235 if (seen_warnings.find (message_str) == seen_warnings.end())
1236 {
1237 seen_warnings.insert (message_str);
1238 clog << "WARNING: " << message_str << optional_str << endl;
1239 }
1240 }
1241
1242
1243 // ------------------------------------------------------------------------
1244 // semantic processing: symbol resolution
1245
1246
1247 symresolution_info::symresolution_info (systemtap_session& s):
1248 session (s), current_function (0), current_probe (0)
1249 {
1250 }
1251
1252
1253 void
1254 symresolution_info::visit_block (block* e)
1255 {
1256 for (unsigned i=0; i<e->statements.size(); i++)
1257 {
1258 try
1259 {
1260 e->statements[i]->visit (this);
1261 }
1262 catch (const semantic_error& e)
1263 {
1264 session.print_error (e);
1265 }
1266 }
1267 }
1268
1269
1270 void
1271 symresolution_info::visit_foreach_loop (foreach_loop* e)
1272 {
1273 for (unsigned i=0; i<e->indexes.size(); i++)
1274 e->indexes[i]->visit (this);
1275
1276 symbol *array = NULL;
1277 hist_op *hist = NULL;
1278 classify_indexable (e->base, array, hist);
1279
1280 if (array)
1281 {
1282 if (!array->referent)
1283 {
1284 vardecl* d = find_var (array->name, e->indexes.size ());
1285 if (d)
1286 array->referent = d;
1287 else
1288 {
1289 stringstream msg;
1290 msg << "unresolved arity-" << e->indexes.size()
1291 << " global array " << array->name;
1292 throw semantic_error (msg.str(), e->tok);
1293 }
1294 }
1295 }
1296 else
1297 {
1298 assert (hist);
1299 hist->visit (this);
1300 }
1301
1302 if (e->limit)
1303 e->limit->visit (this);
1304
1305 e->block->visit (this);
1306 }
1307
1308
1309 struct
1310 delete_statement_symresolution_info:
1311 public traversing_visitor
1312 {
1313 symresolution_info *parent;
1314
1315 delete_statement_symresolution_info (symresolution_info *p):
1316 parent(p)
1317 {}
1318
1319 void visit_arrayindex (arrayindex* e)
1320 {
1321 parent->visit_arrayindex (e);
1322 }
1323 void visit_functioncall (functioncall* e)
1324 {
1325 parent->visit_functioncall (e);
1326 }
1327
1328 void visit_symbol (symbol* e)
1329 {
1330 if (e->referent)
1331 return;
1332
1333 vardecl* d = parent->find_var (e->name, -1);
1334 if (d)
1335 e->referent = d;
1336 else
1337 throw semantic_error ("unresolved array in delete statement", e->tok);
1338 }
1339 };
1340
1341 void
1342 symresolution_info::visit_delete_statement (delete_statement* s)
1343 {
1344 delete_statement_symresolution_info di (this);
1345 s->value->visit (&di);
1346 }
1347
1348
1349 void
1350 symresolution_info::visit_symbol (symbol* e)
1351 {
1352 if (e->referent)
1353 return;
1354
1355 vardecl* d = find_var (e->name, 0);
1356 if (d)
1357 e->referent = d;
1358 else
1359 {
1360 // new local
1361 vardecl* v = new vardecl;
1362 v->name = e->name;
1363 v->tok = e->tok;
1364 if (current_function)
1365 current_function->locals.push_back (v);
1366 else if (current_probe)
1367 current_probe->locals.push_back (v);
1368 else
1369 // must be probe-condition expression
1370 throw semantic_error ("probe condition must not reference undeclared global", e->tok);
1371 e->referent = v;
1372 }
1373 }
1374
1375
1376 void
1377 symresolution_info::visit_arrayindex (arrayindex* e)
1378 {
1379 for (unsigned i=0; i<e->indexes.size(); i++)
1380 e->indexes[i]->visit (this);
1381
1382 symbol *array = NULL;
1383 hist_op *hist = NULL;
1384 classify_indexable(e->base, array, hist);
1385
1386 if (array)
1387 {
1388 if (array->referent)
1389 return;
1390
1391 vardecl* d = find_var (array->name, e->indexes.size ());
1392 if (d)
1393 array->referent = d;
1394 else
1395 {
1396 // new local
1397 vardecl* v = new vardecl;
1398 v->set_arity(e->indexes.size());
1399 v->name = array->name;
1400 v->tok = array->tok;
1401 if (current_function)
1402 current_function->locals.push_back (v);
1403 else if (current_probe)
1404 current_probe->locals.push_back (v);
1405 else
1406 // must not happen
1407 throw semantic_error ("no current probe/function", e->tok);
1408 array->referent = v;
1409 }
1410 }
1411 else
1412 {
1413 assert (hist);
1414 hist->visit (this);
1415 }
1416 }
1417
1418
1419 void
1420 symresolution_info::visit_functioncall (functioncall* e)
1421 {
1422 // XXX: we could relax this, if we're going to examine the
1423 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1424 if (! (current_function || current_probe))
1425 {
1426 // must be probe-condition expression
1427 throw semantic_error ("probe condition must not reference function", e->tok);
1428 }
1429
1430 for (unsigned i=0; i<e->args.size(); i++)
1431 e->args[i]->visit (this);
1432
1433 if (e->referent)
1434 return;
1435
1436 functiondecl* d = find_function (e->function, e->args.size ());
1437 if (d)
1438 e->referent = d;
1439 else
1440 {
1441 stringstream msg;
1442 msg << "unresolved arity-" << e->args.size()
1443 << " function";
1444 throw semantic_error (msg.str(), e->tok);
1445 }
1446 }
1447
1448
1449 vardecl*
1450 symresolution_info::find_var (const string& name, int arity)
1451 {
1452 if (current_function || current_probe)
1453 {
1454 // search locals
1455 vector<vardecl*>& locals = (current_function ?
1456 current_function->locals :
1457 current_probe->locals);
1458
1459
1460 for (unsigned i=0; i<locals.size(); i++)
1461 if (locals[i]->name == name
1462 && locals[i]->compatible_arity(arity))
1463 {
1464 locals[i]->set_arity (arity);
1465 return locals[i];
1466 }
1467 }
1468
1469 // search function formal parameters (for scalars)
1470 if (arity == 0 && current_function)
1471 for (unsigned i=0; i<current_function->formal_args.size(); i++)
1472 if (current_function->formal_args[i]->name == name)
1473 {
1474 // NB: no need to check arity here: formal args always scalar
1475 current_function->formal_args[i]->set_arity (0);
1476 return current_function->formal_args[i];
1477 }
1478
1479 // search processed globals
1480 for (unsigned i=0; i<session.globals.size(); i++)
1481 if (session.globals[i]->name == name
1482 && session.globals[i]->compatible_arity(arity))
1483 {
1484 session.globals[i]->set_arity (arity);
1485 return session.globals[i];
1486 }
1487
1488 // search library globals
1489 for (unsigned i=0; i<session.library_files.size(); i++)
1490 {
1491 stapfile* f = session.library_files[i];
1492 for (unsigned j=0; j<f->globals.size(); j++)
1493 {
1494 vardecl* g = f->globals[j];
1495 if (g->name == name && g->compatible_arity (arity))
1496 {
1497 g->set_arity (arity);
1498
1499 // put library into the queue if not already there
1500 if (find (session.files.begin(), session.files.end(), f)
1501 == session.files.end())
1502 session.files.push_back (f);
1503
1504 return g;
1505 }
1506 }
1507 }
1508
1509 return 0;
1510 }
1511
1512
1513 functiondecl*
1514 symresolution_info::find_function (const string& name, unsigned arity)
1515 {
1516 for (unsigned j = 0; j < session.functions.size(); j++)
1517 {
1518 functiondecl* fd = session.functions[j];
1519 if (fd->name == name &&
1520 fd->formal_args.size() == arity)
1521 return fd;
1522 }
1523
1524 // search library globals
1525 for (unsigned i=0; i<session.library_files.size(); i++)
1526 {
1527 stapfile* f = session.library_files[i];
1528 for (unsigned j=0; j<f->functions.size(); j++)
1529 if (f->functions[j]->name == name &&
1530 f->functions[j]->formal_args.size() == arity)
1531 {
1532 // put library into the queue if not already there
1533 if (0) // session.verbose_resolution
1534 cerr << " function " << name << " "
1535 << "is defined from " << f->name << endl;
1536
1537 if (find (session.files.begin(), session.files.end(), f)
1538 == session.files.end())
1539 session.files.push_back (f);
1540 // else .. print different message?
1541
1542 return f->functions[j];
1543 }
1544 }
1545
1546 return 0;
1547 }
1548
1549
1550
1551 // ------------------------------------------------------------------------
1552 // optimization
1553
1554
1555 // Do away with functiondecls that are never (transitively) called
1556 // from probes.
1557 void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
1558 {
1559 functioncall_traversing_visitor ftv;
1560 for (unsigned i=0; i<s.probes.size(); i++)
1561 {
1562 s.probes[i]->body->visit (& ftv);
1563 if (s.probes[i]->sole_location()->condition)
1564 s.probes[i]->sole_location()->condition->visit (& ftv);
1565 }
1566 for (unsigned i=0; i<s.functions.size(); /* see below */)
1567 {
1568 if (ftv.traversed.find(s.functions[i]) == ftv.traversed.end())
1569 {
1570 if (s.functions[i]->tok->location.file == s.user_file->name && // !tapset
1571 ! s.suppress_warnings)
1572 s.print_warning ("eliding unused function " + stringify(*s.functions[i]->tok));
1573 else if (s.verbose>2)
1574 clog << "Eliding unused function " << s.functions[i]->name
1575 << endl;
1576 if (s.tapset_compile_coverage) {
1577 s.unused_functions.push_back (s.functions[i]);
1578 }
1579 s.functions.erase (s.functions.begin() + i);
1580 relaxed_p = false;
1581 // NB: don't increment i
1582 }
1583 else
1584 i++;
1585 }
1586 }
1587
1588
1589 // ------------------------------------------------------------------------
1590
1591 // Do away with local & global variables that are never
1592 // written nor read.
1593 void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p)
1594 {
1595 varuse_collecting_visitor vut;
1596
1597 for (unsigned i=0; i<s.probes.size(); i++)
1598 {
1599 s.probes[i]->body->visit (& vut);
1600
1601 if (s.probes[i]->sole_location()->condition)
1602 s.probes[i]->sole_location()->condition->visit (& vut);
1603 }
1604
1605 // NB: Since varuse_collecting_visitor also traverses down
1606 // actually called functions, we don't need to explicitly
1607 // iterate over them. Uncalled ones should have been pruned
1608 // in _opt1 above.
1609 //
1610 // for (unsigned i=0; i<s.functions.size(); i++)
1611 // s.functions[i]->body->visit (& vut);
1612
1613 // Now in vut.read/written, we have a mixture of all locals, globals
1614
1615 for (unsigned i=0; i<s.probes.size(); i++)
1616 for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
1617 {
1618 vardecl* l = s.probes[i]->locals[j];
1619
1620 if (vut.read.find (l) == vut.read.end() &&
1621 vut.written.find (l) == vut.written.end())
1622 {
1623 if (l->tok->location.file == s.user_file->name && // !tapset
1624 ! s.suppress_warnings)
1625 s.print_warning ("eliding unused variable " + stringify(*l->tok));
1626 else if (s.verbose>2)
1627 clog << "Eliding unused local variable "
1628 << l->name << " in " << s.probes[i]->name << endl;
1629 if (s.tapset_compile_coverage) {
1630 s.probes[i]->unused_locals.push_back
1631 (s.probes[i]->locals[j]);
1632 }
1633 s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
1634 relaxed_p = false;
1635 // don't increment j
1636 }
1637 else
1638 {
1639 if (vut.written.find (l) == vut.written.end())
1640 if (! s.suppress_warnings)
1641 {
1642 stringstream o;
1643 vector<vardecl*>::iterator it;
1644 for ( it = s.probes[i]->locals.begin() ;
1645 it != s.probes[i]->locals.end(); it++ )
1646 if (l->name.compare(((vardecl*)*it)->name) != 0)
1647 o << " " << ((vardecl*)*it)->name;
1648 for ( it = s.globals.begin() ;
1649 it != s.globals.end() ; it++ )
1650 if (l->name.compare(((vardecl*)*it)->name) != 0)
1651 o << " " << ((vardecl*)*it)->name;
1652
1653 s.print_warning ("read-only local variable "
1654 + stringify(*l->tok),
1655 " (alternatives: " + o.str () + ")");
1656 }
1657
1658 j++;
1659 }
1660 }
1661
1662 for (unsigned i=0; i<s.functions.size(); i++)
1663 for (unsigned j=0; j<s.functions[i]->locals.size(); /* see below */)
1664 {
1665 vardecl* l = s.functions[i]->locals[j];
1666 if (vut.read.find (l) == vut.read.end() &&
1667 vut.written.find (l) == vut.written.end())
1668 {
1669 if (l->tok->location.file == s.user_file->name && // !tapset
1670 ! s.suppress_warnings)
1671 s.print_warning ("eliding unused variable " + stringify(*l->tok));
1672 else if (s.verbose>2)
1673 clog << "Eliding unused local variable "
1674 << l->name << " in function " << s.functions[i]->name
1675 << endl;
1676 if (s.tapset_compile_coverage) {
1677 s.functions[i]->unused_locals.push_back
1678 (s.functions[i]->locals[j]);
1679 }
1680 s.functions[i]->locals.erase(s.functions[i]->locals.begin() + j);
1681 relaxed_p = false;
1682 // don't increment j
1683 }
1684 else
1685 {
1686 stringstream o;
1687 vector<vardecl*>::iterator it;
1688 for ( it = s.functions[i]->formal_args.begin() ;
1689 it != s.functions[i]->formal_args.end(); it++ )
1690 if (l->name.compare(((vardecl*)*it)->name) != 0)
1691 o << " " << ((vardecl*)*it)->name;
1692 for ( it = s.functions[i]->locals.begin() ;
1693 it != s.functions[i]->locals.end(); it++ )
1694 if (l->name.compare(((vardecl*)*it)->name) != 0)
1695 o << " " << ((vardecl*)*it)->name;
1696 for ( it = s.globals.begin() ;
1697 it != s.globals.end() ; it++ )
1698 if (l->name.compare(((vardecl*)*it)->name) != 0)
1699 o << " " << ((vardecl*)*it)->name;
1700
1701 if (vut.written.find (l) == vut.written.end())
1702 if (! s.suppress_warnings)
1703 s.print_warning ("read-only local variable "
1704 + stringify(*l->tok),
1705 " (alternatives:" + o.str () + ")");
1706
1707 j++;
1708 }
1709 }
1710 for (unsigned i=0; i<s.globals.size(); /* see below */)
1711 {
1712 vardecl* l = s.globals[i];
1713 if (vut.read.find (l) == vut.read.end() &&
1714 vut.written.find (l) == vut.written.end())
1715 {
1716 if (l->tok->location.file == s.user_file->name && // !tapset
1717 ! s.suppress_warnings)
1718 s.print_warning ("eliding unused variable " + stringify(*l->tok));
1719 else if (s.verbose>2)
1720 clog << "Eliding unused global variable "
1721 << l->name << endl;
1722 if (s.tapset_compile_coverage) {
1723 s.unused_globals.push_back(s.globals[i]);
1724 }
1725 s.globals.erase(s.globals.begin() + i);
1726 relaxed_p = false;
1727 // don't increment i
1728 }
1729 else
1730 {
1731 if (vut.written.find (l) == vut.written.end() &&
1732 ! l->init) // no initializer
1733 if (! s.suppress_warnings)
1734 s.print_warning ("read-only global variable " + stringify(*l->tok));
1735 i++;
1736 }
1737 }
1738 }
1739
1740
1741 // ------------------------------------------------------------------------
1742
1743 struct dead_assignment_remover: public traversing_visitor
1744 {
1745 systemtap_session& session;
1746 bool& relaxed_p;
1747 const varuse_collecting_visitor& vut;
1748 expression** current_expr;
1749
1750 dead_assignment_remover(systemtap_session& s, bool& r,
1751 const varuse_collecting_visitor& v):
1752 session(s), relaxed_p(r), vut(v), current_expr(0) {}
1753
1754 void visit_expr_statement (expr_statement* s);
1755 // XXX: other places where an assignment may be nested should be
1756 // handled too (e.g., loop/if conditionals, array indexes, function
1757 // parameters). Until then, they result in visit_assignment() being
1758 // called with null current_expr.
1759
1760 void visit_assignment (assignment* e);
1761 void visit_binary_expression (binary_expression* e);
1762 void visit_arrayindex (arrayindex* e);
1763 void visit_functioncall (functioncall* e);
1764 void visit_if_statement (if_statement* e);
1765 void visit_for_loop (for_loop* e);
1766 };
1767
1768
1769 void
1770 dead_assignment_remover::visit_expr_statement (expr_statement* s)
1771 {
1772 expression** last_expr = current_expr;
1773 current_expr = & s->value;
1774 s->value->visit (this);
1775 s->tok = s->value->tok; // in case it was replaced
1776 current_expr = last_expr;
1777 }
1778
1779
1780 void
1781 dead_assignment_remover::visit_assignment (assignment* e)
1782 {
1783 symbol* left = get_symbol_within_expression (e->left);
1784 vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
1785 if (current_expr && // see XXX above: this case represents a missed
1786 // optimization opportunity
1787 *current_expr == e && // we're not nested any deeper than expected
1788 leftvar) // not unresolved $target; intended sideeffect cannot be elided
1789 {
1790 expression** last_expr = current_expr;
1791 e->left->visit (this);
1792 current_expr = &e->right;
1793 e->right->visit (this);
1794 current_expr = last_expr;
1795 if (vut.read.find(leftvar) == vut.read.end()) // var never read?
1796 {
1797 // NB: Not so fast! The left side could be an array whose
1798 // index expressions may have side-effects. This would be
1799 // OK if we could replace the array assignment with a
1800 // statement-expression containing all the index expressions
1801 // and the rvalue... but we can't.
1802
1803 varuse_collecting_visitor vut;
1804 e->left->visit (& vut);
1805 if (vut.side_effect_free ()) // XXX: use _wrt() once we track focal_vars
1806 {
1807 /* PR 1119: NB: This is not necessary here. A write-only
1808 variable will also be elided soon at the next _opt2 iteration.
1809 if (e->left->tok->location.file == session.user_file->name && // !tapset
1810 ! session.suppress_warnings)
1811 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
1812 else
1813 */
1814 if (session.verbose>2)
1815 clog << "Eliding assignment to " << leftvar->name
1816 << " at " << *e->tok << endl;
1817
1818 *current_expr = e->right; // goodbye assignment*
1819 relaxed_p = false;
1820 }
1821 }
1822 }
1823 }
1824
1825 void
1826 dead_assignment_remover::visit_binary_expression (binary_expression* e)
1827 {
1828 expression** last_expr = current_expr;
1829 current_expr = &e->left;
1830 e->left->visit (this);
1831 current_expr = &e->right;
1832 e->right->visit (this);
1833 current_expr = last_expr;
1834 }
1835
1836 void
1837 dead_assignment_remover::visit_arrayindex (arrayindex *e)
1838 {
1839 symbol *array = NULL;
1840 hist_op *hist = NULL;
1841 classify_indexable(e->base, array, hist);
1842
1843 if (array)
1844 {
1845 expression** last_expr = current_expr;
1846 for (unsigned i=0; i < e->indexes.size(); i++)
1847 {
1848 current_expr = & e->indexes[i];
1849 e->indexes[i]->visit (this);
1850 }
1851 current_expr = last_expr;
1852 }
1853 }
1854
1855 void
1856 dead_assignment_remover::visit_functioncall (functioncall* e)
1857 {
1858 expression** last_expr = current_expr;
1859 for (unsigned i=0; i<e->args.size(); i++)
1860 {
1861 current_expr = & e->args[i];
1862 e->args[i]->visit (this);
1863 }
1864 current_expr = last_expr;
1865 }
1866
1867 void
1868 dead_assignment_remover::visit_if_statement (if_statement* s)
1869 {
1870 expression** last_expr = current_expr;
1871 current_expr = & s->condition;
1872 s->condition->visit (this);
1873 s->thenblock->visit (this);
1874 if (s->elseblock)
1875 s->elseblock->visit (this);
1876 current_expr = last_expr;
1877 }
1878
1879 void
1880 dead_assignment_remover::visit_for_loop (for_loop* s)
1881 {
1882 expression** last_expr = current_expr;
1883 if (s->init) s->init->visit (this);
1884 current_expr = & s->cond;
1885 s->cond->visit (this);
1886 if (s->incr) s->incr->visit (this);
1887 s->block->visit (this);
1888 current_expr = last_expr;
1889 }
1890
1891 // Let's remove assignments to variables that are never read. We
1892 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
1893 // be optimized away as an unused variable, and expr a candidate to be
1894 // removed as a side-effect-free statement expression. Wahoo!
1895 void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
1896 {
1897 // Recompute the varuse data, which will probably match the opt2
1898 // copy of the computation, except for those totally unused
1899 // variables that opt2 removed.
1900 varuse_collecting_visitor vut;
1901 for (unsigned i=0; i<s.probes.size(); i++)
1902 s.probes[i]->body->visit (& vut); // includes reachable functions too
1903
1904 dead_assignment_remover dar (s, relaxed_p, vut);
1905 // This instance may be reused for multiple probe/function body trims.
1906
1907 for (unsigned i=0; i<s.probes.size(); i++)
1908 s.probes[i]->body->visit (& dar);
1909 for (unsigned i=0; i<s.functions.size(); i++)
1910 s.functions[i]->body->visit (& dar);
1911 // The rewrite operation is performed within the visitor.
1912
1913 // XXX: we could also zap write-only globals here
1914 }
1915
1916
1917 // ------------------------------------------------------------------------
1918
1919 struct dead_stmtexpr_remover: public traversing_visitor
1920 {
1921 systemtap_session& session;
1922 bool& relaxed_p;
1923 statement** current_stmt; // pointer to current stmt* being iterated
1924 set<vardecl*> focal_vars; // vars considered subject to side-effects
1925
1926 dead_stmtexpr_remover(systemtap_session& s, bool& r):
1927 session(s), relaxed_p(r), current_stmt(0) {}
1928
1929 void visit_block (block *s);
1930 void visit_null_statement (null_statement *s);
1931 void visit_if_statement (if_statement* s);
1932 void visit_foreach_loop (foreach_loop *s);
1933 void visit_for_loop (for_loop *s);
1934 // XXX: and other places where stmt_expr's might be nested
1935
1936 void visit_expr_statement (expr_statement *s);
1937 };
1938
1939
1940 void
1941 dead_stmtexpr_remover::visit_null_statement (null_statement *s)
1942 {
1943 // easy!
1944 if (session.verbose>2)
1945 clog << "Eliding side-effect-free null statement " << *s->tok << endl;
1946 *current_stmt = 0;
1947 }
1948
1949
1950 void
1951 dead_stmtexpr_remover::visit_block (block *s)
1952 {
1953 vector<statement*> new_stmts;
1954 for (unsigned i=0; i<s->statements.size(); i++ )
1955 {
1956 statement** last_stmt = current_stmt;
1957 current_stmt = & s->statements[i];
1958 s->statements[i]->visit (this);
1959 if (*current_stmt != 0)
1960 new_stmts.push_back (*current_stmt);
1961 current_stmt = last_stmt;
1962 }
1963 if (new_stmts.size() == 0)
1964 {
1965 if (session.verbose>2)
1966 clog << "Eliding side-effect-free empty block " << *s->tok << endl;
1967 *current_stmt = 0;
1968 }
1969 else if (new_stmts.size() == 1)
1970 {
1971 if (session.verbose>2)
1972 clog << "Eliding side-effect-free singleton block " << *s->tok << endl;
1973 *current_stmt = new_stmts[0];
1974 }
1975 else
1976 {
1977 s->statements = new_stmts;
1978 }
1979 }
1980
1981 void
1982 dead_stmtexpr_remover::visit_if_statement (if_statement *s)
1983 {
1984 statement** last_stmt = current_stmt;
1985 current_stmt = & s->thenblock;
1986 s->thenblock->visit (this);
1987
1988 if (s->elseblock)
1989 {
1990 current_stmt = & s->elseblock;
1991 s->elseblock->visit (this);
1992 // null *current_stmt is OK here.
1993 }
1994 current_stmt = last_stmt;
1995
1996 if (s->elseblock == 0 && s->thenblock == 0)
1997 {
1998 // We may be able to elide this statement, if the condition
1999 // expression is side-effect-free.
2000 varuse_collecting_visitor vct;
2001 s->condition->visit(& vct);
2002 if (vct.side_effect_free ())
2003 {
2004 if (session.verbose>2)
2005 clog << "Eliding side-effect-free if statement " << *s->tok << endl;
2006 *current_stmt = 0; // yeah, baby
2007 return;
2008 }
2009 }
2010
2011 if (s->thenblock == 0)
2012 {
2013 // Can't elide this whole if/else statement; put a null in there.
2014 s->thenblock = new null_statement();
2015 s->thenblock->tok = s->tok;
2016 }
2017 }
2018
2019 void
2020 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
2021 {
2022 statement** last_stmt = current_stmt;
2023 current_stmt = & s->block;
2024 s->block->visit (this);
2025 current_stmt = last_stmt;
2026
2027 if (s->block == 0)
2028 {
2029 if (session.verbose>2)
2030 clog << "Eliding side-effect-free foreach statement " << *s->tok << endl;
2031 *current_stmt = 0; // yeah, baby
2032 }
2033 }
2034
2035 void
2036 dead_stmtexpr_remover::visit_for_loop (for_loop *s)
2037 {
2038 statement** last_stmt = current_stmt;
2039 current_stmt = & s->block;
2040 s->block->visit (this);
2041 current_stmt = last_stmt;
2042
2043 if (s->block == 0)
2044 {
2045 // We may be able to elide this statement, if the condition
2046 // expression is side-effect-free.
2047 varuse_collecting_visitor vct;
2048 if (s->init) s->init->visit(& vct);
2049 s->cond->visit(& vct);
2050 if (s->incr) s->incr->visit(& vct);
2051 if (vct.side_effect_free ())
2052 {
2053 if (session.verbose>2)
2054 clog << "Eliding side-effect-free for statement " << *s->tok << endl;
2055 *current_stmt = 0; // yeah, baby
2056 return;
2057 }
2058
2059 // Can't elide this whole statement; put a null in there.
2060 s->block = new null_statement();
2061 s->block->tok = s->tok;
2062 }
2063 }
2064
2065
2066
2067 void
2068 dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
2069 {
2070 // Run a varuse query against the operand expression. If it has no
2071 // side-effects, replace the entire statement expression by a null
2072 // statement. This replacement is done by overwriting the
2073 // current_stmt pointer.
2074 //
2075 // Unlike many other visitors, we do *not* traverse this outermost
2076 // one into the expression subtrees. There is no need - no
2077 // expr_statement nodes will be found there. (Function bodies
2078 // need to be visited explicitly by our caller.)
2079 //
2080 // NB. While we don't share nodes in the parse tree, let's not
2081 // deallocate *s anyway, just in case...
2082
2083 varuse_collecting_visitor vut;
2084 s->value->visit (& vut);
2085 if (vut.side_effect_free_wrt (focal_vars) &&
2086 *current_stmt == s) // we're not nested any deeper than expected
2087 {
2088 /* PR 1119: NB: this message is not a good idea here. It can
2089 name some arbitrary RHS expression of an assignment.
2090 if (s->value->tok->location.file == session.user_file->name && // not tapset
2091 ! session.suppress_warnings)
2092 clog << "WARNING: eliding read-only " << *s->value->tok << endl;
2093 else
2094 */
2095 if (session.verbose>2)
2096 clog << "Eliding side-effect-free expression "
2097 << *s->tok << endl;
2098
2099 // NB: this 0 pointer is invalid to leave around for any length of
2100 // time, but the parent parse tree objects above handle it.
2101 * current_stmt = 0;
2102
2103 relaxed_p = false;
2104 }
2105 }
2106
2107
2108 void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
2109 {
2110 // Finally, let's remove some statement-expressions that have no
2111 // side-effect. These should be exactly those whose private varuse
2112 // visitors come back with an empty "written" and "embedded" lists.
2113
2114 dead_stmtexpr_remover duv (s, relaxed_p);
2115 // This instance may be reused for multiple probe/function body trims.
2116
2117 for (unsigned i=0; i<s.probes.size(); i++)
2118 {
2119 derived_probe* p = s.probes[i];
2120
2121 duv.focal_vars.clear ();
2122 duv.focal_vars.insert (s.globals.begin(),
2123 s.globals.end());
2124 duv.focal_vars.insert (p->locals.begin(),
2125 p->locals.end());
2126
2127 duv.current_stmt = & p->body;
2128 p->body->visit (& duv);
2129 if (p->body == 0)
2130 {
2131 if (! s.suppress_warnings)
2132 s.print_warning ("side-effect-free probe '" + p->name + "' "
2133 + stringify(*p->tok));
2134
2135 p->body = new null_statement();
2136 p->body->tok = p->tok;
2137
2138 // XXX: possible duplicate warnings; see below
2139 }
2140 }
2141 for (unsigned i=0; i<s.functions.size(); i++)
2142 {
2143 functiondecl* fn = s.functions[i];
2144 duv.focal_vars.clear ();
2145 duv.focal_vars.insert (fn->locals.begin(),
2146 fn->locals.end());
2147 duv.focal_vars.insert (fn->formal_args.begin(),
2148 fn->formal_args.end());
2149 duv.focal_vars.insert (s.globals.begin(),
2150 s.globals.end());
2151
2152 duv.current_stmt = & fn->body;
2153 fn->body->visit (& duv);
2154 if (fn->body == 0)
2155 {
2156 if (! s.suppress_warnings)
2157 s.print_warning ("side-effect-free function '" + fn->name + "' "
2158 + stringify(*fn->tok));
2159
2160 fn->body = new null_statement();
2161 fn->body->tok = fn->tok;
2162
2163 // XXX: the next iteration of the outer optimization loop may
2164 // take this new null_statement away again, and thus give us a
2165 // fresh warning. It would be better if this fixup was performed
2166 // only after the relaxation iterations.
2167 // XXX: or else see bug #6469.
2168 }
2169 }
2170 }
2171
2172 struct duplicate_function_remover: public functioncall_traversing_visitor
2173 {
2174 systemtap_session& s;
2175 map<functiondecl*, functiondecl*>& duplicate_function_map;
2176
2177 duplicate_function_remover(systemtap_session& sess,
2178 map<functiondecl*, functiondecl*>&dfm):
2179 s(sess), duplicate_function_map(dfm) {};
2180
2181 void visit_functioncall (functioncall* e);
2182 };
2183
2184 void
2185 duplicate_function_remover::visit_functioncall (functioncall *e)
2186 {
2187 functioncall_traversing_visitor::visit_functioncall (e);
2188
2189 // If the current function call reference points to a function that
2190 // is a duplicate, replace it.
2191 if (duplicate_function_map.count(e->referent) != 0)
2192 {
2193 if (s.verbose>2)
2194 clog << "Changing " << e->referent->name
2195 << " reference to "
2196 << duplicate_function_map[e->referent]->name
2197 << " reference\n";
2198 e->tok = duplicate_function_map[e->referent]->tok;
2199 e->function = duplicate_function_map[e->referent]->name;
2200 e->referent = duplicate_function_map[e->referent];
2201 }
2202 }
2203
2204 static string
2205 get_functionsig (functiondecl* f)
2206 {
2207 ostringstream s;
2208
2209 // Get the "name:args body" of the function in s. We have to
2210 // include the args since the function 'x1(a, b)' is different than
2211 // the function 'x2(b, a)' even if the bodies of the two functions
2212 // are exactly the same.
2213 f->printsig(s);
2214 f->body->print(s);
2215
2216 // printsig puts f->name + ':' on the front. Remove this
2217 // (otherwise, functions would never compare equal).
2218 string str = s.str().erase(0, f->name.size() + 1);
2219
2220 // Return the function signature.
2221 return str;
2222 }
2223
2224 void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
2225 {
2226 // Walk through all the functions, looking for duplicates.
2227 map<string, functiondecl*> functionsig_map;
2228 map<functiondecl*, functiondecl*> duplicate_function_map;
2229 for (unsigned i=0; i < s.functions.size(); /* see below */)
2230 {
2231 string functionsig = get_functionsig(s.functions[i]);
2232
2233 if (functionsig_map.count(functionsig) == 0)
2234 {
2235 // This function is unique. Remember it.
2236 functionsig_map[functionsig] = s.functions[i];
2237 i++;
2238 }
2239 else
2240 {
2241 // This function is a duplicate.
2242 duplicate_function_map[s.functions[i]]
2243 = functionsig_map[functionsig];
2244
2245 // Remove the duplicate function (since we don't need it
2246 // anymore).
2247 s.functions.erase (s.functions.begin() + i);
2248
2249 relaxed_p = false;
2250 // NB: don't increment i
2251 }
2252 }
2253
2254 // If we have duplicate functions, traverse down the tree, replacing
2255 // the appropriate function calls.
2256 // duplicate_function_remover::visit_functioncall() handles the
2257 // details of replacing the function calls.
2258 if (duplicate_function_map.size() != 0)
2259 {
2260 duplicate_function_remover dfr (s, duplicate_function_map);
2261
2262 for (unsigned i=0; i < s.probes.size(); i++)
2263 s.probes[i]->body->visit(&dfr);
2264 }
2265 }
2266
2267
2268 static int
2269 semantic_pass_optimize1 (systemtap_session& s)
2270 {
2271 // In this pass, we attempt to rewrite probe/function bodies to
2272 // eliminate some blatantly unnecessary code. This is run before
2273 // type inference, but after symbol resolution and derived_probe
2274 // creation. We run an outer "relaxation" loop that repeats the
2275 // optimizations until none of them find anything to remove.
2276
2277 int rc = 0;
2278
2279 bool relaxed_p = false;
2280 while (! relaxed_p)
2281 {
2282 if (pending_interrupts) break;
2283
2284 relaxed_p = true; // until proven otherwise
2285
2286 semantic_pass_opt1 (s, relaxed_p);
2287 semantic_pass_opt2 (s, relaxed_p);
2288 semantic_pass_opt3 (s, relaxed_p);
2289 semantic_pass_opt4 (s, relaxed_p);
2290 }
2291
2292 return rc;
2293 }
2294
2295
2296 static int
2297 semantic_pass_optimize2 (systemtap_session& s)
2298 {
2299 // This is run after type inference. We run an outer "relaxation"
2300 // loop that repeats the optimizations until none of them find
2301 // anything to remove.
2302
2303 int rc = 0;
2304
2305 bool relaxed_p = false;
2306 while (! relaxed_p)
2307 {
2308 if (pending_interrupts) break;
2309 relaxed_p = true; // until proven otherwise
2310
2311 semantic_pass_opt5 (s, relaxed_p);
2312 }
2313
2314 return rc;
2315 }
2316
2317
2318
2319 // ------------------------------------------------------------------------
2320 // type resolution
2321
2322
2323 static int
2324 semantic_pass_types (systemtap_session& s)
2325 {
2326 int rc = 0;
2327
2328 // next pass: type inference
2329 unsigned iterations = 0;
2330 typeresolution_info ti (s);
2331
2332 ti.assert_resolvability = false;
2333 // XXX: maybe convert to exception-based error signalling
2334 while (1)
2335 {
2336 if (pending_interrupts) break;
2337
2338 iterations ++;
2339 ti.num_newly_resolved = 0;
2340 ti.num_still_unresolved = 0;
2341
2342 for (unsigned j=0; j<s.functions.size(); j++)
2343 {
2344 if (pending_interrupts) break;
2345
2346 functiondecl* fn = s.functions[j];
2347 ti.current_probe = 0;
2348 ti.current_function = fn;
2349 ti.t = pe_unknown;
2350 fn->body->visit (& ti);
2351 // NB: we don't have to assert a known type for
2352 // functions here, to permit a "void" function.
2353 // The translator phase will omit the "retvalue".
2354 //
2355 // if (fn->type == pe_unknown)
2356 // ti.unresolved (fn->tok);
2357 }
2358
2359 for (unsigned j=0; j<s.probes.size(); j++)
2360 {
2361 if (pending_interrupts) break;
2362
2363 derived_probe* pn = s.probes[j];
2364 ti.current_function = 0;
2365 ti.current_probe = pn;
2366 ti.t = pe_unknown;
2367 pn->body->visit (& ti);
2368
2369 probe_point* pp = pn->sole_location();
2370 if (pp->condition)
2371 {
2372 ti.current_function = 0;
2373 ti.current_probe = 0;
2374 ti.t = pe_long; // NB: expected type
2375 pp->condition->visit (& ti);
2376 }
2377 }
2378
2379 for (unsigned j=0; j<s.globals.size(); j++)
2380 {
2381 vardecl* gd = s.globals[j];
2382 if (gd->type == pe_unknown)
2383 ti.unresolved (gd->tok);
2384 }
2385
2386 if (ti.num_newly_resolved == 0) // converged
2387 {
2388 if (ti.num_still_unresolved == 0)
2389 break; // successfully
2390 else if (! ti.assert_resolvability)
2391 ti.assert_resolvability = true; // last pass, with error msgs
2392 else
2393 { // unsuccessful conclusion
2394 rc ++;
2395 break;
2396 }
2397 }
2398 }
2399
2400 return rc + s.num_errors();
2401 }
2402
2403
2404
2405 typeresolution_info::typeresolution_info (systemtap_session& s):
2406 session(s), current_function(0), current_probe(0)
2407 {
2408 }
2409
2410
2411 void
2412 typeresolution_info::visit_literal_number (literal_number* e)
2413 {
2414 assert (e->type == pe_long);
2415 if ((t == e->type) || (t == pe_unknown))
2416 return;
2417
2418 mismatch (e->tok, e->type, t);
2419 }
2420
2421
2422 void
2423 typeresolution_info::visit_literal_string (literal_string* e)
2424 {
2425 assert (e->type == pe_string);
2426 if ((t == e->type) || (t == pe_unknown))
2427 return;
2428
2429 mismatch (e->tok, e->type, t);
2430 }
2431
2432
2433 void
2434 typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
2435 {
2436 visit_binary_expression (e);
2437 }
2438
2439
2440 void
2441 typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
2442 {
2443 visit_binary_expression (e);
2444 }
2445
2446
2447 void
2448 typeresolution_info::visit_comparison (comparison *e)
2449 {
2450 // NB: result of any comparison is an integer!
2451 if (t == pe_stats || t == pe_string)
2452 invalid (e->tok, t);
2453
2454 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
2455 e->left->visit (this);
2456 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
2457 e->right->visit (this);
2458
2459 if (e->left->type != pe_unknown &&
2460 e->right->type != pe_unknown &&
2461 e->left->type != e->right->type)
2462 mismatch (e->tok, e->left->type, e->right->type);
2463
2464 if (e->type == pe_unknown)
2465 {
2466 e->type = pe_long;
2467 resolved (e->tok, e->type);
2468 }
2469 }
2470
2471
2472 void
2473 typeresolution_info::visit_concatenation (concatenation *e)
2474 {
2475 if (t != pe_unknown && t != pe_string)
2476 invalid (e->tok, t);
2477
2478 t = pe_string;
2479 e->left->visit (this);
2480 t = pe_string;
2481 e->right->visit (this);
2482
2483 if (e->type == pe_unknown)
2484 {
2485 e->type = pe_string;
2486 resolved (e->tok, e->type);
2487 }
2488 }
2489
2490
2491 void
2492 typeresolution_info::visit_assignment (assignment *e)
2493 {
2494 if (t == pe_stats)
2495 invalid (e->tok, t);
2496
2497 if (e->op == "<<<") // stats aggregation
2498 {
2499 if (t == pe_string)
2500 invalid (e->tok, t);
2501
2502 t = pe_stats;
2503 e->left->visit (this);
2504 t = pe_long;
2505 e->right->visit (this);
2506 if (e->type == pe_unknown ||
2507 e->type == pe_stats)
2508 {
2509 e->type = pe_long;
2510 resolved (e->tok, e->type);
2511 }
2512 }
2513
2514 else if (e->left->type == pe_stats)
2515 invalid (e->left->tok, e->left->type);
2516
2517 else if (e->right->type == pe_stats)
2518 invalid (e->right->tok, e->right->type);
2519
2520 else if (e->op == "+=" || // numeric only
2521 e->op == "-=" ||
2522 e->op == "*=" ||
2523 e->op == "/=" ||
2524 e->op == "%=" ||
2525 e->op == "&=" ||
2526 e->op == "^=" ||
2527 e->op == "|=" ||
2528 e->op == "<<=" ||
2529 e->op == ">>=" ||
2530 false)
2531 {
2532 visit_binary_expression (e);
2533 }
2534 else if (e->op == ".=" || // string only
2535 false)
2536 {
2537 if (t == pe_long || t == pe_stats)
2538 invalid (e->tok, t);
2539
2540 t = pe_string;
2541 e->left->visit (this);
2542 t = pe_string;
2543 e->right->visit (this);
2544 if (e->type == pe_unknown)
2545 {
2546 e->type = pe_string;
2547 resolved (e->tok, e->type);
2548 }
2549 }
2550 else if (e->op == "=") // overloaded = for string & numeric operands
2551 {
2552 // logic similar to ternary_expression
2553 exp_type sub_type = t;
2554
2555 // Infer types across the l/r values
2556 if (sub_type == pe_unknown && e->type != pe_unknown)
2557 sub_type = e->type;
2558
2559 t = (sub_type != pe_unknown) ? sub_type :
2560 (e->right->type != pe_unknown) ? e->right->type :
2561 pe_unknown;
2562 e->left->visit (this);
2563 t = (sub_type != pe_unknown) ? sub_type :
2564 (e->left->type != pe_unknown) ? e->left->type :
2565 pe_unknown;
2566 e->right->visit (this);
2567
2568 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2569 {
2570 e->type = sub_type;
2571 resolved (e->tok, e->type);
2572 }
2573 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
2574 {
2575 e->type = e->left->type;
2576 resolved (e->tok, e->type);
2577 }
2578
2579 if (e->left->type != pe_unknown &&
2580 e->right->type != pe_unknown &&
2581 e->left->type != e->right->type)
2582 mismatch (e->tok, e->left->type, e->right->type);
2583
2584 }
2585 else
2586 throw semantic_error ("unsupported assignment operator " + e->op);
2587 }
2588
2589
2590 void
2591 typeresolution_info::visit_binary_expression (binary_expression* e)
2592 {
2593 if (t == pe_stats || t == pe_string)
2594 invalid (e->tok, t);
2595
2596 t = pe_long;
2597 e->left->visit (this);
2598 t = pe_long;
2599 e->right->visit (this);
2600
2601 if (e->left->type != pe_unknown &&
2602 e->right->type != pe_unknown &&
2603 e->left->type != e->right->type)
2604 mismatch (e->tok, e->left->type, e->right->type);
2605
2606 if (e->type == pe_unknown)
2607 {
2608 e->type = pe_long;
2609 resolved (e->tok, e->type);
2610 }
2611 }
2612
2613
2614 void
2615 typeresolution_info::visit_pre_crement (pre_crement *e)
2616 {
2617 visit_unary_expression (e);
2618 }
2619
2620
2621 void
2622 typeresolution_info::visit_post_crement (post_crement *e)
2623 {
2624 visit_unary_expression (e);
2625 }
2626
2627
2628 void
2629 typeresolution_info::visit_unary_expression (unary_expression* e)
2630 {
2631 if (t == pe_stats || t == pe_string)
2632 invalid (e->tok, t);
2633
2634 t = pe_long;
2635 e->operand->visit (this);
2636
2637 if (e->type == pe_unknown)
2638 {
2639 e->type = pe_long;
2640 resolved (e->tok, e->type);
2641 }
2642 }
2643
2644
2645 void
2646 typeresolution_info::visit_ternary_expression (ternary_expression* e)
2647 {
2648 exp_type sub_type = t;
2649
2650 t = pe_long;
2651 e->cond->visit (this);
2652
2653 // Infer types across the true/false arms of the ternary expression.
2654
2655 if (sub_type == pe_unknown && e->type != pe_unknown)
2656 sub_type = e->type;
2657 t = sub_type;
2658 e->truevalue->visit (this);
2659 t = sub_type;
2660 e->falsevalue->visit (this);
2661
2662 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
2663 ; // already resolved
2664 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2665 {
2666 e->type = sub_type;
2667 resolved (e->tok, e->type);
2668 }
2669 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
2670 {
2671 e->type = e->truevalue->type;
2672 resolved (e->tok, e->type);
2673 }
2674 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
2675 {
2676 e->type = e->falsevalue->type;
2677 resolved (e->tok, e->type);
2678 }
2679 else if (e->type != sub_type)
2680 mismatch (e->tok, sub_type, e->type);
2681 }
2682
2683
2684 template <class Referrer, class Referent>
2685 void resolve_2types (Referrer* referrer, Referent* referent,
2686 typeresolution_info* r, exp_type t, bool accept_unknown = false)
2687 {
2688 exp_type& re_type = referrer->type;
2689 const token* re_tok = referrer->tok;
2690 exp_type& te_type = referent->type;
2691 const token* te_tok = referent->tok;
2692
2693 if (t != pe_unknown && re_type == t && re_type == te_type)
2694 ; // do nothing: all three e->types in agreement
2695 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
2696 ; // do nothing: two known e->types in agreement
2697 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
2698 r->mismatch (re_tok, re_type, te_type);
2699 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
2700 r->mismatch (re_tok, re_type, t);
2701 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
2702 r->mismatch (te_tok, te_type, t);
2703 else if (re_type == pe_unknown && t != pe_unknown)
2704 {
2705 // propagate from upstream
2706 re_type = t;
2707 r->resolved (re_tok, re_type);
2708 // catch re_type/te_type mismatch later
2709 }
2710 else if (re_type == pe_unknown && te_type != pe_unknown)
2711 {
2712 // propagate from referent
2713 re_type = te_type;
2714 r->resolved (re_tok, re_type);
2715 // catch re_type/t mismatch later
2716 }
2717 else if (re_type != pe_unknown && te_type == pe_unknown)
2718 {
2719 // propagate to referent
2720 te_type = re_type;
2721 r->resolved (te_tok, te_type);
2722 // catch re_type/t mismatch later
2723 }
2724 else if (! accept_unknown)
2725 r->unresolved (re_tok);
2726 }
2727
2728
2729 void
2730 typeresolution_info::visit_symbol (symbol* e)
2731 {
2732 assert (e->referent != 0);
2733 resolve_2types (e, e->referent, this, t);
2734 }
2735
2736
2737 void
2738 typeresolution_info::visit_target_symbol (target_symbol* e)
2739 {
2740 // This occurs only if a target symbol was not resolved over in
2741 // tapset.cxx land, that error was properly suppressed, and the
2742 // later unused-expression-elimination pass didn't get rid of it
2743 // either. So we have a target symbol that is believed to be of
2744 // genuine use, yet unresolved by the provider.
2745
2746 if (session.verbose > 2)
2747 {
2748 clog << "Resolution problem with ";
2749 if (current_function)
2750 {
2751 clog << "function " << current_function->name << endl;
2752 current_function->body->print (clog);
2753 clog << endl;
2754 }
2755 else if (current_probe)
2756 {
2757 clog << "probe " << current_probe->name << endl;
2758 current_probe->body->print (clog);
2759 clog << endl;
2760 }
2761 else
2762 clog << "other" << endl;
2763 }
2764
2765 if (e->saved_conversion_error)
2766 throw (* (e->saved_conversion_error));
2767 else
2768 throw semantic_error("unresolved target-symbol expression", e->tok);
2769 }
2770
2771
2772 void
2773 typeresolution_info::visit_arrayindex (arrayindex* e)
2774 {
2775
2776 symbol *array = NULL;
2777 hist_op *hist = NULL;
2778 classify_indexable(e->base, array, hist);
2779
2780 // Every hist_op has type [int]:int, that is to say, every hist_op
2781 // is a pseudo-one-dimensional integer array type indexed by
2782 // integers (bucket numbers).
2783
2784 if (hist)
2785 {
2786 if (e->indexes.size() != 1)
2787 unresolved (e->tok);
2788 t = pe_long;
2789 e->indexes[0]->visit (this);
2790 if (e->indexes[0]->type != pe_long)
2791 unresolved (e->tok);
2792 hist->visit (this);
2793 if (e->type != pe_long)
2794 {
2795 e->type = pe_long;
2796 resolved (e->tok, pe_long);
2797 }
2798 return;
2799 }
2800
2801 // Now we are left with "normal" map inference and index checking.
2802
2803 assert (array);
2804 assert (array->referent != 0);
2805 resolve_2types (e, array->referent, this, t);
2806
2807 // now resolve the array indexes
2808
2809 // if (e->referent->index_types.size() == 0)
2810 // // redesignate referent as array
2811 // e->referent->set_arity (e->indexes.size ());
2812
2813 if (e->indexes.size() != array->referent->index_types.size())
2814 unresolved (e->tok); // symbol resolution should prevent this
2815 else for (unsigned i=0; i<e->indexes.size(); i++)
2816 {
2817 expression* ee = e->indexes[i];
2818 exp_type& ft = array->referent->index_types [i];
2819 t = ft;
2820 ee->visit (this);
2821 exp_type at = ee->type;
2822
2823 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
2824 {
2825 // propagate to formal type
2826 ft = at;
2827 resolved (array->referent->tok, ft);
2828 // uses array decl as there is no token for "formal type"
2829 }
2830 if (at == pe_stats)
2831 invalid (ee->tok, at);
2832 if (ft == pe_stats)
2833 invalid (ee->tok, ft);
2834 if (at != pe_unknown && ft != pe_unknown && ft != at)
2835 mismatch (e->tok, at, ft);
2836 if (at == pe_unknown)
2837 unresolved (ee->tok);
2838 }
2839 }
2840
2841
2842 void
2843 typeresolution_info::visit_functioncall (functioncall* e)
2844 {
2845 assert (e->referent != 0);
2846
2847 resolve_2types (e, e->referent, this, t, true); // accept unknown type
2848
2849 if (e->type == pe_stats)
2850 invalid (e->tok, e->type);
2851
2852 // now resolve the function parameters
2853 if (e->args.size() != e->referent->formal_args.size())
2854 unresolved (e->tok); // symbol resolution should prevent this
2855 else for (unsigned i=0; i<e->args.size(); i++)
2856 {
2857 expression* ee = e->args[i];
2858 exp_type& ft = e->referent->formal_args[i]->type;
2859 const token* fe_tok = e->referent->formal_args[i]->tok;
2860 t = ft;
2861 ee->visit (this);
2862 exp_type at = ee->type;
2863
2864 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
2865 {
2866 // propagate to formal arg
2867 ft = at;
2868 resolved (e->referent->formal_args[i]->tok, ft);
2869 }
2870 if (at == pe_stats)
2871 invalid (e->tok, at);
2872 if (ft == pe_stats)
2873 invalid (fe_tok, ft);
2874 if (at != pe_unknown && ft != pe_unknown && ft != at)
2875 mismatch (e->tok, at, ft);
2876 if (at == pe_unknown)
2877 unresolved (e->tok);
2878 }
2879 }
2880
2881
2882 void
2883 typeresolution_info::visit_block (block* e)
2884 {
2885 for (unsigned i=0; i<e->statements.size(); i++)
2886 {
2887 try
2888 {
2889 t = pe_unknown;
2890 e->statements[i]->visit (this);
2891 }
2892 catch (const semantic_error& e)
2893 {
2894 session.print_error (e);
2895 }
2896 }
2897 }
2898
2899
2900 void
2901 typeresolution_info::visit_embeddedcode (embeddedcode*)
2902 {
2903 }
2904
2905
2906 void
2907 typeresolution_info::visit_if_statement (if_statement* e)
2908 {
2909 t = pe_long;
2910 e->condition->visit (this);
2911
2912 t = pe_unknown;
2913 e->thenblock->visit (this);
2914
2915 if (e->elseblock)
2916 {
2917 t = pe_unknown;
2918 e->elseblock->visit (this);
2919 }
2920 }
2921
2922
2923 void
2924 typeresolution_info::visit_for_loop (for_loop* e)
2925 {
2926 t = pe_unknown;
2927 if (e->init) e->init->visit (this);
2928 t = pe_long;
2929 e->cond->visit (this);
2930 t = pe_unknown;
2931 if (e->incr) e->incr->visit (this);
2932 t = pe_unknown;
2933 e->block->visit (this);
2934 }
2935
2936
2937 void
2938 typeresolution_info::visit_foreach_loop (foreach_loop* e)
2939 {
2940 // See also visit_arrayindex.
2941 // This is different in that, being a statement, we can't assign
2942 // a type to the outer array, only propagate to/from the indexes
2943
2944 // if (e->referent->index_types.size() == 0)
2945 // // redesignate referent as array
2946 // e->referent->set_arity (e->indexes.size ());
2947
2948 symbol *array = NULL;
2949 hist_op *hist = NULL;
2950 classify_indexable(e->base, array, hist);
2951
2952 if (hist)
2953 {
2954 if (e->indexes.size() != 1)
2955 unresolved (e->tok);
2956 t = pe_long;
2957 e->indexes[0]->visit (this);
2958 if (e->indexes[0]->type != pe_long)
2959 unresolved (e->tok);
2960 hist->visit (this);
2961 }
2962 else
2963 {
2964 assert (array);
2965 if (e->indexes.size() != array->referent->index_types.size())
2966 unresolved (e->tok); // symbol resolution should prevent this
2967 else for (unsigned i=0; i<e->indexes.size(); i++)
2968 {
2969 expression* ee = e->indexes[i];
2970 exp_type& ft = array->referent->index_types [i];
2971 t = ft;
2972 ee->visit (this);
2973 exp_type at = ee->type;
2974
2975 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
2976 {
2977 // propagate to formal type
2978 ft = at;
2979 resolved (array->referent->tok, ft);
2980 // uses array decl as there is no token for "formal type"
2981 }
2982 if (at == pe_stats)
2983 invalid (ee->tok, at);
2984 if (ft == pe_stats)
2985 invalid (ee->tok, ft);
2986 if (at != pe_unknown && ft != pe_unknown && ft != at)
2987 mismatch (e->tok, at, ft);
2988 if (at == pe_unknown)
2989 unresolved (ee->tok);
2990 }
2991 }
2992
2993 if (e->limit)
2994 {
2995 t = pe_long;
2996 e->limit->visit (this);
2997 }
2998
2999 t = pe_unknown;
3000 e->block->visit (this);
3001 }
3002
3003
3004 void
3005 typeresolution_info::visit_null_statement (null_statement*)
3006 {
3007 }
3008
3009
3010 void
3011 typeresolution_info::visit_expr_statement (expr_statement* e)
3012 {
3013 t = pe_unknown;
3014 e->value->visit (this);
3015 }
3016
3017
3018 struct delete_statement_typeresolution_info:
3019 public throwing_visitor
3020 {
3021 typeresolution_info *parent;
3022 delete_statement_typeresolution_info (typeresolution_info *p):
3023 throwing_visitor ("invalid operand of delete expression"),
3024 parent (p)
3025 {}
3026
3027 void visit_arrayindex (arrayindex* e)
3028 {
3029 parent->visit_arrayindex (e);
3030 }
3031
3032 void visit_symbol (symbol* e)
3033 {
3034 exp_type ignored = pe_unknown;
3035 assert (e->referent != 0);
3036 resolve_2types (e, e->referent, parent, ignored);
3037 }
3038 };
3039
3040
3041 void
3042 typeresolution_info::visit_delete_statement (delete_statement* e)
3043 {
3044 delete_statement_typeresolution_info di (this);
3045 t = pe_unknown;
3046 e->value->visit (&di);
3047 }
3048
3049
3050 void
3051 typeresolution_info::visit_next_statement (next_statement*)
3052 {
3053 }
3054
3055
3056 void
3057 typeresolution_info::visit_break_statement (break_statement*)
3058 {
3059 }
3060
3061
3062 void
3063 typeresolution_info::visit_continue_statement (continue_statement*)
3064 {
3065 }
3066
3067
3068 void
3069 typeresolution_info::visit_array_in (array_in* e)
3070 {
3071 // all unary operators only work on numerics
3072 exp_type t1 = t;
3073 t = pe_unknown; // array value can be anything
3074 e->operand->visit (this);
3075
3076 if (t1 == pe_unknown && e->type != pe_unknown)
3077 ; // already resolved
3078 else if (t1 == pe_string || t1 == pe_stats)
3079 mismatch (e->tok, t1, pe_long);
3080 else if (e->type == pe_unknown)
3081 {
3082 e->type = pe_long;
3083 resolved (e->tok, e->type);
3084 }
3085 }
3086
3087
3088 void
3089 typeresolution_info::visit_return_statement (return_statement* e)
3090 {
3091 // This is like symbol, where the referent is
3092 // the return value of the function.
3093
3094 // translation pass will print error
3095 if (current_function == 0)
3096 return;
3097
3098 exp_type& e_type = current_function->type;
3099 t = current_function->type;
3100 e->value->visit (this);
3101
3102 if (e_type != pe_unknown && e->value->type != pe_unknown
3103 && e_type != e->value->type)
3104 mismatch (current_function->tok, e_type, e->value->type);
3105 if (e_type == pe_unknown &&
3106 (e->value->type == pe_long || e->value->type == pe_string))
3107 {
3108 // propagate non-statistics from value
3109 e_type = e->value->type;
3110 resolved (current_function->tok, e->value->type);
3111 }
3112 if (e->value->type == pe_stats)
3113 invalid (e->value->tok, e->value->type);
3114 }
3115
3116 void
3117 typeresolution_info::visit_print_format (print_format* e)
3118 {
3119 size_t unresolved_args = 0;
3120
3121 if (e->hist)
3122 {
3123 e->hist->visit(this);
3124 }
3125
3126 else if (e->print_with_format)
3127 {
3128 // If there's a format string, we can do both inference *and*
3129 // checking.
3130
3131 // First we extract the subsequence of formatting components
3132 // which are conversions (not just literal string components)
3133
3134 unsigned expected_num_args = 0;
3135 std::vector<print_format::format_component> components;
3136 for (size_t i = 0; i < e->components.size(); ++i)
3137 {
3138 if (e->components[i].type == print_format::conv_unspecified)
3139 throw semantic_error ("Unspecified conversion in print operator format string",
3140 e->tok);
3141 else if (e->components[i].type == print_format::conv_literal
3142 || e->components[i].type == print_format::conv_size)
3143 continue;
3144 components.push_back(e->components[i]);
3145 ++expected_num_args;
3146 if (e->components[i].widthtype == print_format::width_dynamic)
3147 ++expected_num_args;
3148 if (e->components[i].prectype == print_format::prec_dynamic)
3149 ++expected_num_args;
3150 }
3151
3152 // Then we check that the number of conversions and the number
3153 // of args agree.
3154
3155 if (expected_num_args != e->args.size())
3156 throw semantic_error ("Wrong number of args to formatted print operator",
3157 e->tok);
3158
3159 // Then we check that the types of the conversions match the types
3160 // of the args.
3161 unsigned argno = 0;
3162 for (size_t i = 0; i < components.size(); ++i)
3163 {
3164 // Check the dynamic width, if specified
3165 if (components[i].widthtype == print_format::width_dynamic)
3166 {
3167 check_arg_type (pe_long, e->args[argno]);
3168 ++argno;
3169 }
3170
3171 // Check the dynamic precision, if specified
3172 if (components[i].prectype == print_format::prec_dynamic)
3173 {
3174 check_arg_type (pe_long, e->args[argno]);
3175 ++argno;
3176 }
3177
3178 exp_type wanted = pe_unknown;
3179
3180 switch (components[i].type)
3181 {
3182 case print_format::conv_unspecified:
3183 case print_format::conv_literal:
3184 case print_format::conv_size:
3185 assert (false);
3186 break;
3187
3188 case print_format::conv_signed_decimal:
3189 case print_format::conv_unsigned_decimal:
3190 case print_format::conv_unsigned_octal:
3191 case print_format::conv_unsigned_ptr:
3192 case print_format::conv_unsigned_uppercase_hex:
3193 case print_format::conv_unsigned_lowercase_hex:
3194 case print_format::conv_binary:
3195 case print_format::conv_memory:
3196 wanted = pe_long;
3197 break;
3198
3199 case print_format::conv_string:
3200 wanted = pe_string;
3201 break;
3202 }
3203
3204 assert (wanted != pe_unknown);
3205 check_arg_type (wanted, e->args[argno]);
3206 ++argno;
3207 }
3208 }
3209 else
3210 {
3211 // Without a format string, the best we can do is require that
3212 // each argument resolve to a concrete type.
3213 for (size_t i = 0; i < e->args.size(); ++i)
3214 {
3215 t = pe_unknown;
3216 e->args[i]->visit (this);
3217 if (e->args[i]->type == pe_unknown)
3218 {
3219 unresolved (e->args[i]->tok);
3220 ++unresolved_args;
3221 }
3222 }
3223 }
3224
3225 if (unresolved_args == 0)
3226 {
3227 if (e->type == pe_unknown)
3228 {
3229 if (e->print_to_stream)
3230 e->type = pe_long;
3231 else
3232 e->type = pe_string;
3233 resolved (e->tok, e->type);
3234 }
3235 }
3236 else
3237 {
3238 e->type = pe_unknown;
3239 unresolved (e->tok);
3240 }
3241 }
3242
3243
3244 void
3245 typeresolution_info::visit_stat_op (stat_op* e)
3246 {
3247 t = pe_stats;
3248 e->stat->visit (this);
3249 if (e->type == pe_unknown)
3250 {
3251 e->type = pe_long;
3252 resolved (e->tok, e->type);
3253 }
3254 else if (e->type != pe_long)
3255 mismatch (e->tok, e->type, pe_long);
3256 }
3257
3258 void
3259 typeresolution_info::visit_hist_op (hist_op* e)
3260 {
3261 t = pe_stats;
3262 e->stat->visit (this);
3263 }
3264
3265
3266 void
3267 typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
3268 {
3269 t = wanted;
3270 arg->visit (this);
3271
3272 if (arg->type == pe_unknown)
3273 {
3274 arg->type = wanted;
3275 resolved (arg->tok, wanted);
3276 }
3277 else if (arg->type != wanted)
3278 {
3279 mismatch (arg->tok, arg->type, wanted);
3280 }
3281 }
3282
3283
3284 void
3285 typeresolution_info::unresolved (const token* tok)
3286 {
3287 num_still_unresolved ++;
3288
3289 if (assert_resolvability)
3290 {
3291 stringstream msg;
3292 string nm = (current_function ? current_function->name :
3293 current_probe ? current_probe->name :
3294 "probe condition");
3295 msg << nm + " with unresolved type";
3296 session.print_error (semantic_error (msg.str(), tok));
3297 }
3298 }
3299
3300
3301 void
3302 typeresolution_info::invalid (const token* tok, exp_type pe)
3303 {
3304 num_still_unresolved ++;
3305
3306 if (assert_resolvability)
3307 {
3308 stringstream msg;
3309 string nm = (current_function ? current_function->name :
3310 current_probe ? current_probe->name :
3311 "probe condition");
3312 if (tok && tok->type == tok_operator)
3313 msg << nm + " uses invalid operator";
3314 else
3315 msg << nm + " with invalid type " << pe;
3316 session.print_error (semantic_error (msg.str(), tok));
3317 }
3318 }
3319
3320
3321 void
3322 typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
3323 {
3324 num_still_unresolved ++;
3325
3326 if (assert_resolvability)
3327 {
3328 stringstream msg;
3329 string nm = (current_function ? current_function->name :
3330 current_probe ? current_probe->name :
3331 "probe condition");
3332 msg << nm + " with type mismatch (" << t1 << " vs. " << t2 << ")";
3333 session.print_error (semantic_error (msg.str(), tok));
3334 }
3335 }
3336
3337
3338 void
3339 typeresolution_info::resolved (const token*, exp_type)
3340 {
3341 num_newly_resolved ++;
3342 }
3343
This page took 0.198173 seconds and 6 git commands to generate.