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