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