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