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