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