]> sourceware.org Git - systemtap.git/blame - elaborate.cxx
Add buildok testcase for rcu.stp.
[systemtap.git] / elaborate.cxx
CommitLineData
2b066ec1 1// elaboration functions
ad583484 2// Copyright (C) 2005-2013 Red Hat Inc.
1773fd03 3// Copyright (C) 2008 Intel Corporation
69c68955
FCE
4//
5// This file is part of systemtap, and is free software. You can
6// redistribute it and/or modify it under the terms of the GNU General
7// Public License (GPL); either version 2, or (at your option) any
8// later version.
2b066ec1
FCE
9
10#include "config.h"
11#include "elaborate.h"
2865d17a 12#include "translate.h"
2b066ec1 13#include "parse.h"
20c6c071 14#include "tapsets.h"
dc38c0ae 15#include "session.h"
72dbc915 16#include "util.h"
a057c85c 17#include "task_finder.h"
2b066ec1 18
40ea378c 19#include "re2c-migrate/stapregex.h"
d2548fe7 20
2b066ec1
FCE
21extern "C" {
22#include <sys/utsname.h>
a477f3f1 23#include <fnmatch.h>
4af765b2
LB
24#define __STDC_FORMAT_MACROS
25#include <inttypes.h>
2b066ec1
FCE
26}
27
2b066ec1 28#include <algorithm>
67c0a579
GH
29#include <fstream>
30#include <map>
29e64872 31#include <cassert>
67c0a579
GH
32#include <set>
33#include <vector>
1b07c728
FCE
34#include <algorithm>
35#include <iterator>
f4869658 36#include <climits>
1b07c728 37
2b066ec1 38
2b066ec1
FCE
39using namespace std;
40
41
42// ------------------------------------------------------------------------
43
5d23847d
FCE
44// Used in probe_point condition construction. Either argument may be
45// NULL; if both, return NULL too. Resulting expression is a deep
46// copy for symbol resolution purposes.
47expression* add_condition (expression* a, expression* b)
48{
49 if (!a && !b) return 0;
50 if (! a) return deep_copy_visitor::deep_copy(b);
51 if (! b) return deep_copy_visitor::deep_copy(a);
52 logical_and_expr la;
53 la.op = "&&";
54 la.left = a;
55 la.right = b;
56 la.tok = a->tok; // or could be b->tok
57 return deep_copy_visitor::deep_copy(& la);
58}
59
60// ------------------------------------------------------------------------
61
62
2b066ec1 63
4c5d1300 64derived_probe::derived_probe (probe *p, probe_point *l, bool rewrite_loc):
26e63673 65 base (p), base_pp(l), sdt_semaphore_addr(0), session_index((unsigned)-1)
2b066ec1 66{
5d23847d
FCE
67 assert (p);
68 this->tok = p->tok;
69 this->privileged = p->privileged;
70 this->body = deep_copy_visitor::deep_copy(p->body);
cbbe8080 71
5d23847d 72 assert (l);
4c5d1300
JS
73 // make a copy for subclasses which want to rewrite the location
74 if (rewrite_loc)
75 l = new probe_point(*l);
5d23847d 76 this->locations.push_back (l);
2b066ec1
FCE
77}
78
98afd80e 79
b8da0ad1
FCE
80void
81derived_probe::printsig (ostream& o) const
82{
83 probe::printsig (o);
84 printsig_nested (o);
85}
86
87void
88derived_probe::printsig_nested (ostream& o) const
89{
90 // We'd like to enclose the probe derivation chain in a /* */
91 // comment delimiter. But just printing /* base->printsig() */ is
92 // not enough, since base might itself be a derived_probe. So we,
93 // er, "cleverly" encode our nesting state as a formatting flag for
94 // the ostream.
95 ios::fmtflags f = o.flags (ios::internal);
96 if (f & ios::internal)
97 {
98 // already nested
99 o << " <- ";
100 base->printsig (o);
101 }
102 else
103 {
104 // outermost nesting
105 o << " /* <- ";
106 base->printsig (o);
107 o << " */";
108 }
109 // restore flags
110 (void) o.flags (f);
111}
112
113
c3a3c0c9 114void
d885563b 115derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list) const
c3a3c0c9 116{
d885563b 117 probes_list.push_back(const_cast<derived_probe*>(this));
c3a3c0c9
WC
118 base->collect_derivation_chain(probes_list);
119}
120
121
f1b9a51a 122void
d885563b 123derived_probe::collect_derivation_pp_chain (std::vector<probe_point*> &pp_list) const
f1b9a51a 124{
8159bf55 125 pp_list.push_back(const_cast<probe_point*>(this->sole_location()));
f1b9a51a
JS
126 base->collect_derivation_pp_chain(pp_list);
127}
128
129
26e63673
JS
130string
131derived_probe::derived_locations ()
132{
133 ostringstream o;
134 vector<probe_point*> reference_point;
135 collect_derivation_pp_chain(reference_point);
d885563b
FCE
136 if (reference_point.size() > 0)
137 for(unsigned i=1; i<reference_point.size(); ++i)
138 o << " from: " << reference_point[i]->str(false); // no ?,!,etc
26e63673
JS
139 return o.str();
140}
141
142
b20febf3 143probe_point*
b8da0ad1 144derived_probe::sole_location () const
dc38c0ae 145{
4af765b2 146 if (locations.size() == 0 || locations.size() > 1)
52c2652f 147 throw semantic_error (_N("derived_probe with no locations",
2a89b023 148 "derived_probe with too many locations",
d885563b 149 locations.size()), this->tok);
57148ee7 150 else
b20febf3 151 return locations[0];
dc38c0ae
DS
152}
153
154
c3df9bce
JS
155probe_point*
156derived_probe::script_location () const
157{
d885563b
FCE
158 // This feeds function::pn() in the tapset, which is documented as the
159 // script-level probe point expression, *after wildcard expansion*. If
160 // it were not for wildcard stuff, we'd just return the last item in the
161 // derivation chain. But alas ... we need to search for the last one
162 // that doesn't have a * in the textual representation. Heuristics, eww.
163 vector<probe_point*> chain;
164 collect_derivation_pp_chain (chain);
165
a126c5b1
JS
166 // NB: we actually start looking from the second-to-last item, so the user's
167 // direct input is not considered. Input like 'kernel.function("init_once")'
168 // will thus be listed with the resolved @file:line too, disambiguating the
169 // distinct functions by this name, and matching our historical behavior.
170 for (int i=chain.size()-2; i>=0; i--)
d885563b 171 {
5d9306df
FCE
172 probe_point pp_copy (* chain [i]);
173 // drop any ?/! denotations that would confuse a glob-char search
174 pp_copy.optional = false;
175 pp_copy.sufficient = false;
176 string pp_printed = lex_cast(pp_copy);
177 if (! contains_glob_chars(pp_printed))
d885563b
FCE
178 return chain[i];
179 }
180
8159bf55
FCE
181 // If that didn't work, just fallback to -something-.
182 return sole_location();
c3df9bce
JS
183}
184
185
2865d17a 186void
42e38653 187derived_probe::emit_privilege_assertion (translator_output* o)
2865d17a
DB
188{
189 // Emit code which will cause compilation to fail if it is compiled in
190 // unprivileged mode.
f6be7c06
DB
191 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
192 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
2865d17a
DB
193 o->newline() << "#error Internal Error: Probe ";
194 probe::printsig (o->line());
195 o->line() << " generated in --unprivileged mode";
196 o->newline() << "#endif";
197}
198
199
200void
201derived_probe::emit_process_owner_assertion (translator_output* o)
202{
203 // Emit code which will abort should the current target not belong to the
204 // user in unprivileged mode.
f6be7c06
DB
205 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
206 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
2865d17a
DB
207 o->newline(1) << "if (! is_myproc ()) {";
208 o->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
209 o->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
210 o->newline() << " current->tgid, _stp_uid, c->probe_point);";
211 o->newline() << "c->last_error = c->error_buffer;";
991bd3ba
JS
212 // NB: since this check occurs before probe locking, its exit should
213 // not be a "goto out", which would attempt unlocking.
214 o->newline() << "return;";
2865d17a
DB
215 o->newline(-1) << "}";
216 o->newline(-1) << "#endif";
217}
218
8f6d8c2b
DB
219void
220derived_probe::print_dupe_stamp_unprivileged(ostream& o)
221{
4af765b2 222 o << _("unprivileged users: authorized") << endl;
8f6d8c2b
DB
223}
224
225void
226derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream& o)
227{
4af765b2 228 o << _("unprivileged users: authorized for process owner") << endl;
8f6d8c2b 229}
47dd066d 230
20c6c071 231// ------------------------------------------------------------------------
98afd80e
FCE
232// Members of derived_probe_builder
233
8eb6206c
SM
234void
235derived_probe_builder::build_with_suffix(systemtap_session & sess,
236 probe * use,
237 probe_point * location,
238 std::map<std::string, literal *>
239 const & parameters,
240 std::vector<derived_probe *>
241 & finished_results,
242 std::vector<probe_point::component *>
243 const & suffix) {
244 // XXX perhaps build the probe if suffix is empty?
245 // if (suffix.empty()) {
246 // build (sess, use, location, parameters, finished_results);
247 // return;
248 // }
249 throw semantic_error (_("invalid suffix for probe"));
250}
251
98afd80e
FCE
252bool
253derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
254 const std::string& key,
255 std::string& value)
256{
257 map<string, literal *>::const_iterator i = params.find (key);
258 if (i == params.end())
259 return false;
260 literal_string * ls = dynamic_cast<literal_string *>(i->second);
261 if (!ls)
262 return false;
263 value = ls->value;
264 return true;
265}
266
20c6c071 267
98afd80e
FCE
268bool
269derived_probe_builder::get_param (std::map<std::string, literal*> const & params,
270 const std::string& key,
271 int64_t& value)
272{
273 map<string, literal *>::const_iterator i = params.find (key);
274 if (i == params.end())
275 return false;
276 if (i->second == NULL)
277 return false;
278 literal_number * ln = dynamic_cast<literal_number *>(i->second);
279 if (!ln)
280 return false;
281 value = ln->value;
282 return true;
283}
284
285
888af770
FCE
286bool
287derived_probe_builder::has_null_param (std::map<std::string, literal*> const & params,
288 const std::string& key)
289{
290 map<string, literal *>::const_iterator i = params.find(key);
291 return (i != params.end() && i->second == NULL);
292}
293
294
98afd80e
FCE
295
296// ------------------------------------------------------------------------
20c6c071
GH
297// Members of match_key.
298
57148ee7
FCE
299match_key::match_key(string const & n)
300 : name(n),
301 have_parameter(false),
5d23847d 302 parameter_type(pe_unknown)
20c6c071
GH
303{
304}
305
306match_key::match_key(probe_point::component const & c)
307 : name(c.functor),
308 have_parameter(c.arg != NULL),
5d23847d 309 parameter_type(c.arg ? c.arg->type : pe_unknown)
20c6c071
GH
310{
311}
312
313match_key &
57148ee7 314match_key::with_number()
20c6c071
GH
315{
316 have_parameter = true;
5d23847d 317 parameter_type = pe_long;
20c6c071
GH
318 return *this;
319}
320
321match_key &
57148ee7 322match_key::with_string()
20c6c071
GH
323{
324 have_parameter = true;
5d23847d 325 parameter_type = pe_string;
20c6c071
GH
326 return *this;
327}
328
57148ee7 329string
20c6c071
GH
330match_key::str() const
331{
332 if (have_parameter)
333 switch (parameter_type)
334 {
5d23847d
FCE
335 case pe_string: return name + "(string)";
336 case pe_long: return name + "(number)";
20c6c071
GH
337 default: return name + "(...)";
338 }
339 return name;
340}
341
57148ee7 342bool
20c6c071
GH
343match_key::operator<(match_key const & other) const
344{
345 return ((name < other.name)
57148ee7
FCE
346
347 || (name == other.name
20c6c071 348 && have_parameter < other.have_parameter)
57148ee7
FCE
349
350 || (name == other.name
351 && have_parameter == other.have_parameter
20c6c071
GH
352 && parameter_type < other.parameter_type));
353}
2b066ec1 354
c0c7b466
FCE
355
356// NB: these are only used in the probe point name components, where
357// only "*" is permitted.
358//
359// Within module("bar"), function("foo"), process("baz") strings, real
360// wildcards are permitted too. See also util.h:contains_glob_chars
361
a477f3f1
DS
362static bool
363isglob(string const & str)
364{
365 return(str.find('*') != str.npos);
366}
367
122b4fcd
JS
368static bool
369isdoubleglob(string const & str)
370{
371 return(str.find("**") != str.npos);
372}
373
a477f3f1
DS
374bool
375match_key::globmatch(match_key const & other) const
376{
377 const char *other_str = other.name.c_str();
378 const char *name_str = name.c_str();
379
380 return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0)
57148ee7 381 && have_parameter == other.have_parameter
a477f3f1
DS
382 && parameter_type == other.parameter_type);
383}
384
2b066ec1 385// ------------------------------------------------------------------------
20c6c071
GH
386// Members of match_node
387// ------------------------------------------------------------------------
388
27dc09b1 389match_node::match_node() :
f6be7c06 390 privilege(privilege_t (pr_stapdev | pr_stapsys))
d4935c2f 391{
d4935c2f 392}
20c6c071
GH
393
394match_node *
57148ee7 395match_node::bind(match_key const & k)
20c6c071 396{
b4ceace2 397 if (k.name == "*")
4af765b2 398 throw semantic_error(_("invalid use of wildcard probe point component"));
b4ceace2 399
20c6c071
GH
400 map<match_key, match_node *>::const_iterator i = sub.find(k);
401 if (i != sub.end())
402 return i->second;
403 match_node * n = new match_node();
404 sub.insert(make_pair(k, n));
405 return n;
406}
407
57148ee7 408void
20c6c071
GH
409match_node::bind(derived_probe_builder * e)
410{
2531fc1e 411 ends.push_back (e);
20c6c071
GH
412}
413
57148ee7 414match_node *
20c6c071
GH
415match_node::bind(string const & k)
416{
417 return bind(match_key(k));
418}
419
420match_node *
421match_node::bind_str(string const & k)
422{
423 return bind(match_key(k).with_string());
424}
425
57148ee7 426match_node *
20c6c071
GH
427match_node::bind_num(string const & k)
428{
429 return bind(match_key(k).with_number());
430}
431
27dc09b1 432match_node *
42e38653 433match_node::bind_privilege(privilege_t p)
27dc09b1 434{
42e38653 435 privilege = p;
27dc09b1
DB
436 return this;
437}
438
b4ceace2
FCE
439void
440match_node::find_and_build (systemtap_session& s,
441 probe* p, probe_point *loc, unsigned pos,
442 vector<derived_probe *>& results)
20c6c071 443{
b4ceace2 444 assert (pos <= loc->components.size());
57148ee7 445 if (pos == loc->components.size()) // matched all probe point components so far
20c6c071 446 {
2531fc1e 447 if (ends.empty())
b4ceace2
FCE
448 {
449 string alternatives;
450 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
451 alternatives += string(" ") + i->first.str();
452
8eb6206c
SM
453 throw semantic_error (_F("probe point truncated (follow: %s)",
454 alternatives.c_str()),
4af765b2 455 loc->components.back()->tok);
b4ceace2
FCE
456 }
457
f66bb29a 458 if (! pr_contains (privilege, s.privilege))
27dc09b1 459 {
f66bb29a
DB
460 throw semantic_error (_F("probe point is not allowed for --privilege=%s",
461 pr_name (s.privilege)),
4af765b2 462 loc->components.back()->tok);
27dc09b1
DB
463 }
464
b4ceace2
FCE
465 map<string, literal *> param_map;
466 for (unsigned i=0; i<pos; i++)
467 param_map[loc->components[i]->functor] = loc->components[i]->arg;
468 // maybe 0
469
2531fc1e
FCE
470 // Iterate over all bound builders
471 for (unsigned k=0; k<ends.size(); k++)
472 {
473 derived_probe_builder *b = ends[k];
474 b->build (s, p, loc, param_map, results);
475 }
20c6c071 476 }
122b4fcd
JS
477 else if (isdoubleglob(loc->components[pos]->functor)) // ** wildcard?
478 {
479 unsigned int num_results = results.size();
480
481 // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
482
483 const probe_point::component *comp = loc->components[pos];
484 const string &functor = comp->functor;
485 size_t glob_start = functor.find("**");
486 size_t glob_end = functor.find_first_not_of('*', glob_start);
487 const string prefix = functor.substr(0, glob_start);
488 const string suffix = ((glob_end != string::npos) ?
489 functor.substr(glob_end) : "");
490
491 // Synthesize "foo*bar"
492 probe_point *simple_pp = new probe_point(*loc);
493 probe_point::component *simple_comp = new probe_point::component(*comp);
494 simple_comp->functor = prefix + "*" + suffix;
495 simple_pp->components[pos] = simple_comp;
496 try
497 {
498 find_and_build (s, p, simple_pp, pos, results);
499 }
500 catch (const semantic_error& e)
501 {
502 // Ignore semantic_errors, but cleanup
503 delete simple_pp;
504 delete simple_comp;
505 }
506
507 // Synthesize "foo*.**bar"
508 // NB: any component arg should attach to the latter part only
509 probe_point *expanded_pp = new probe_point(*loc);
510 probe_point::component *expanded_comp_pre = new probe_point::component(*comp);
511 expanded_comp_pre->functor = prefix + "*";
512 expanded_comp_pre->arg = NULL;
513 probe_point::component *expanded_comp_post = new probe_point::component(*comp);
514 expanded_comp_post->functor = "**" + suffix;
515 expanded_pp->components[pos] = expanded_comp_pre;
516 expanded_pp->components.insert(expanded_pp->components.begin() + pos + 1,
517 expanded_comp_post);
518 try
519 {
520 find_and_build (s, p, expanded_pp, pos, results);
521 }
522 catch (const semantic_error& e)
523 {
524 // Ignore semantic_errors, but cleanup
525 delete expanded_pp;
526 delete expanded_comp_pre;
527 delete expanded_comp_post;
528 }
529
8eb6206c
SM
530 // Try suffix expansion only if no matches found:
531 if (num_results == results.size())
532 try
533 {
534 this->try_suffix_expansion (s, p, loc, pos, results);
535 }
536 catch (const recursive_expansion_error &e)
537 {
538 s.print_error(e); return; // Suppress probe mismatch msg.
539 }
540
122b4fcd
JS
541 if (! loc->optional && num_results == results.size())
542 {
543 // We didn't find any wildcard matches (since the size of
544 // the result vector didn't change). Throw an error.
545 string alternatives;
546 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
547 alternatives += string(" ") + i->first.str();
548
8eb6206c
SM
549 throw semantic_error(_F("probe point mismatch (alternatives: %s)",
550 alternatives.c_str()), comp->tok);
122b4fcd
JS
551 }
552 }
a477f3f1 553 else if (isglob(loc->components[pos]->functor)) // wildcard?
20c6c071 554 {
a477f3f1
DS
555 match_key match (* loc->components[pos]);
556
828c3ed5
DS
557 // Call find_and_build for each possible match. Ignore errors -
558 // unless we don't find any match.
559 unsigned int num_results = results.size();
b4ceace2
FCE
560 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
561 {
a477f3f1 562 const match_key& subkey = i->first;
828c3ed5 563 match_node* subnode = i->second;
a477f3f1 564
e19ebcf7 565 assert_no_interrupts();
49abf162 566
a477f3f1 567 if (match.globmatch(subkey))
828c3ed5 568 {
ddfc759e 569 if (s.verbose > 2)
4af765b2
LB
570 clog << _F("wildcard '%s' matched '%s'",
571 loc->components[pos]->functor.c_str(),
572 subkey.name.c_str()) << endl;
ddfc759e
DS
573
574 // When we have a wildcard, we need to create a copy of
575 // the probe point. Then we'll create a copy of the
576 // wildcard component, and substitute the non-wildcard
577 // functor.
578 probe_point *non_wildcard_pp = new probe_point(*loc);
579 probe_point::component *non_wildcard_component
580 = new probe_point::component(*loc->components[pos]);
581 non_wildcard_component->functor = subkey.name;
582 non_wildcard_pp->components[pos] = non_wildcard_component;
583
5d23847d
FCE
584 // NB: probe conditions are not attached at the wildcard
585 // (component/functor) level, but at the overall
586 // probe_point level.
587
ddfc759e 588 // recurse (with the non-wildcard probe point)
a477f3f1
DS
589 try
590 {
ddfc759e
DS
591 subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
592 results);
a477f3f1
DS
593 }
594 catch (const semantic_error& e)
595 {
596 // Ignore semantic_errors while expanding wildcards.
597 // If we get done and nothing was expanded, the code
598 // following the loop will complain.
ddfc759e
DS
599
600 // If this wildcard didn't match, cleanup.
601 delete non_wildcard_pp;
602 delete non_wildcard_component;
a477f3f1 603 }
828c3ed5 604 }
a477f3f1 605 }
8eb6206c
SM
606
607 // Try suffix expansion only if no matches found:
608 if (num_results == results.size())
609 try
610 {
611 this->try_suffix_expansion (s, p, loc, pos, results);
612 }
613 catch (const recursive_expansion_error &e)
614 {
615 s.print_error(e); return; // Suppress probe mismatch msg.
616 }
617
cedd10f4 618 if (! loc->optional && num_results == results.size())
828c3ed5
DS
619 {
620 // We didn't find any wildcard matches (since the size of
621 // the result vector didn't change). Throw an error.
622 string alternatives;
623 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
624 alternatives += string(" ") + i->first.str();
57148ee7 625
8eb6206c 626 throw semantic_error(_F("probe point mismatch %s didn't find any wildcard matches",
4af765b2 627 (alternatives == "" ? "" : _(" (alternatives: ") +
8eb6206c 628 alternatives + ")").c_str()), loc->components[pos]->tok);
828c3ed5 629 }
b4ceace2 630 }
57148ee7 631 else
20c6c071 632 {
b4ceace2
FCE
633 match_key match (* loc->components[pos]);
634 sub_map_iterator_t i = sub.find (match);
8eb6206c
SM
635
636 if (i != sub.end()) // match found
b4ceace2 637 {
8eb6206c
SM
638 match_node* subnode = i->second;
639 // recurse
640 subnode->find_and_build (s, p, loc, pos+1, results);
641 return;
642 }
643
644 unsigned int num_results = results.size();
645
646 try
647 {
648 this->try_suffix_expansion (s, p, loc, pos, results);
649 }
650 catch (const recursive_expansion_error &e)
651 {
652 s.print_error(e); return; // Suppress probe mismatch msg.
653 }
654
655 // XXX: how to correctly report alternatives + position numbers
656 // for alias suffixes? file a separate PR to address the issue
657 if (! loc->optional && num_results == results.size())
658 {
659 // We didn't find any alias suffixes (since the size of the
660 // result vector didn't change). Throw an error.
b4ceace2
FCE
661 string alternatives;
662 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
663 alternatives += string(" ") + i->first.str();
57148ee7 664
8eb6206c 665 throw semantic_error(_F("probe point mismatch %s",
4af765b2 666 (alternatives == "" ? "" : (_(" (alternatives:") + alternatives +
8eb6206c
SM
667 ")").c_str())),
668 loc->components[pos]->tok);
b4ceace2 669 }
8eb6206c
SM
670 }
671}
672
b4ceace2 673
8eb6206c
SM
674void
675match_node::try_suffix_expansion (systemtap_session& s,
676 probe *p, probe_point *loc, unsigned pos,
677 vector<derived_probe *>& results)
678{
679 // PR12210: match alias suffixes. If the components thus far
680 // have been matched, but there is an additional unknown
681 // suffix, we have a potential alias suffix on our hands. We
682 // need to expand the preceding components as probe aliases,
683 // reattach the suffix, and re-run derive_probes() on the
684 // resulting expansion. This is done by the routine
685 // build_with_suffix().
686
687 if (strverscmp(s.compatible.c_str(), "2.0") >= 0)
688 {
689 // XXX: technically, param_map isn't used here. So don't
690 // bother actually assembling it unless some
691 // derived_probe_builder appears that actually takes
692 // suffixes *and* consults parameters (currently no such
693 // builders exist).
694 map<string, literal *> param_map;
695 // for (unsigned i=0; i<pos; i++)
696 // param_map[loc->components[i]->functor] = loc->components[i]->arg;
697 // maybe 0
698
699 vector<probe_point::component *> suffix (loc->components.begin()+pos,
700 loc->components.end());
701
702 // Multiple derived_probe_builders may be bound at a
703 // match_node due to the possibility of multiply defined
704 // aliases.
705 for (unsigned k=0; k < ends.size(); k++)
706 {
707 derived_probe_builder *b = ends[k];
708 try
709 {
710 b->build_with_suffix (s, p, loc, param_map, results, suffix);
711 }
712 catch (const recursive_expansion_error &e)
713 {
714 // Re-throw:
e758508b 715 throw semantic_error(e);
8eb6206c
SM
716 }
717 catch (const semantic_error &e)
718 {
719 // Adjust source coordinate and re-throw:
720 if (! loc->optional)
721 throw semantic_error(e.what(), loc->components[pos]->tok);
722 }
723 }
20c6c071
GH
724 }
725}
726
b4ceace2 727
aa30ccd3
FCE
728void
729match_node::build_no_more (systemtap_session& s)
730{
731 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
732 i->second->build_no_more (s);
2531fc1e
FCE
733 for (unsigned k=0; k<ends.size(); k++)
734 {
735 derived_probe_builder *b = ends[k];
736 b->build_no_more (s);
737 }
aa30ccd3
FCE
738}
739
b82d77b4
DB
740void
741match_node::dump (systemtap_session &s, const string &name)
742{
743 // Dump this node, if it is complete.
744 for (unsigned k=0; k<ends.size(); k++)
745 {
746 // Don't print aliases at all (for now) until we can figure out how to determine whether
747 // the probes they resolve to are ok in unprivileged mode.
748 if (ends[k]->is_alias ())
749 continue;
750
751 // In unprivileged mode, don't show the probes which are not allowed for unprivileged
752 // users.
f66bb29a 753 if (pr_contains (privilege, s.privilege))
b82d77b4
DB
754 {
755 cout << name << endl;
756 break; // we need only print one instance.
757 }
758 }
759
760 // Recursively dump the children of this node
761 string dot;
762 if (! name.empty ())
763 dot = ".";
764 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
765 {
766 i->second->dump (s, name + dot + i->first.str());
767 }
768}
769
aa30ccd3 770
20c6c071
GH
771// ------------------------------------------------------------------------
772// Alias probes
773// ------------------------------------------------------------------------
774
c1d5f3f6
FCE
775struct alias_derived_probe: public derived_probe
776{
8eb6206c
SM
777 alias_derived_probe (probe* base, probe_point *l, const probe_alias *a,
778 const vector<probe_point::component *> *suffix = 0);
c1d5f3f6 779
4af765b2 780 void upchuck () { throw semantic_error (_("inappropriate"), this->tok); }
b20febf3
FCE
781
782 // Alias probes are immediately expanded to other derived_probe
783 // types, and are not themselves emitted or listed in
784 // systemtap_session.probes
dc38c0ae 785
78f6bba6 786 void join_group (systemtap_session&) { upchuck (); }
2c5a19c6
DB
787
788 virtual const probe_alias *get_alias () const { return alias; }
8eb6206c 789 virtual probe_point *get_alias_loc () const { return alias_loc; }
2a89b023 790 virtual probe_point *sole_location () const;
2c5a19c6
DB
791
792private:
793 const probe_alias *alias; // Used to check for recursion
8eb6206c 794 probe_point *alias_loc; // Hack to recover full probe name
c1d5f3f6
FCE
795};
796
8eb6206c
SM
797
798alias_derived_probe::alias_derived_probe(probe *base, probe_point *l,
799 const probe_alias *a,
800 const vector<probe_point::component *>
801 *suffix):
802 derived_probe (base, l), alias(a)
803{
804 // XXX pretty nasty -- this was cribbed from printscript() in main.cxx
805 assert (alias->alias_names.size() >= 1);
806 alias_loc = new probe_point(*alias->alias_names[0]); // XXX: [0] is arbitrary; it would make just as much sense to collect all of the names
807 if (suffix) {
808 alias_loc->components.insert(alias_loc->components.end(),
809 suffix->begin(), suffix->end());
810 }
811}
812
813
2a89b023
FCE
814probe_point*
815alias_derived_probe::sole_location () const
816{
817 return const_cast<probe_point*>(alias_loc);
818}
819
820
c72aa911
JS
821probe*
822probe::create_alias(probe_point* l, probe_point* a)
823{
824 vector<probe_point*> aliases(1, a);
825 probe_alias* p = new probe_alias(aliases);
826 p->tok = tok;
827 p->locations.push_back(l);
828 p->body = body;
d885563b 829 p->base = this;
c72aa911
JS
830 p->privileged = privileged;
831 p->epilogue_style = false;
832 return new alias_derived_probe(this, l, p);
833}
834
c1d5f3f6 835
e2012a7a
DB
836void
837alias_expansion_builder::build(systemtap_session & sess,
838 probe * use,
839 probe_point * location,
8eb6206c
SM
840 std::map<std::string, literal *>
841 const & parameters,
e2012a7a 842 vector<derived_probe *> & finished_results)
8eb6206c
SM
843{
844 vector<probe_point::component *> empty_suffix;
845 build_with_suffix (sess, use, location, parameters,
846 finished_results, empty_suffix);
847}
848
849void
850alias_expansion_builder::build_with_suffix(systemtap_session & sess,
851 probe * use,
852 probe_point * location,
853 std::map<std::string, literal *>
854 const &,
855 vector<derived_probe *>
856 & finished_results,
857 vector<probe_point::component *>
858 const & suffix)
20c6c071 859{
e2012a7a
DB
860 // Don't build the alias expansion if infinite recursion is detected.
861 if (checkForRecursiveExpansion (use)) {
862 stringstream msg;
4af765b2
LB
863 msg << _F("Recursive loop in alias expansion of %s at %s",
864 lex_cast(*location).c_str(), lex_cast(location->components.front()->tok->location).c_str());
8eb6206c
SM
865 // semantic_errors thrown here might be ignored, so we need a special class:
866 throw recursive_expansion_error (msg.str());
867 // XXX The point of throwing this custom error is to suppress a
868 // cascade of "probe mismatch" messages that appear in addition to
869 // the error. The current approach suppresses most of the error
870 // cascade, but leaves one spurious error; in any case, the way
871 // this particular error is reported could be improved.
e2012a7a 872 }
57148ee7 873
e2012a7a
DB
874 // We're going to build a new probe and wrap it up in an
875 // alias_expansion_probe so that the expansion loop recognizes it as
876 // such and re-expands its expansion.
20c6c071 877
8eb6206c 878 alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias, &suffix);
e2012a7a 879 n->body = new block();
5d23847d 880
8eb6206c
SM
881 // The new probe gets a deep copy of the location list of the alias
882 // (with incoming condition joined) plus the suffix (if any),
e2012a7a
DB
883 n->locations.clear();
884 for (unsigned i=0; i<alias->locations.size(); i++)
885 {
886 probe_point *pp = new probe_point(*alias->locations[i]);
8eb6206c 887 pp->components.insert(pp->components.end(), suffix.begin(), suffix.end());
e2012a7a
DB
888 pp->condition = add_condition (pp->condition, location->condition);
889 n->locations.push_back(pp);
890 }
20c6c071 891
e2012a7a
DB
892 // the token location of the alias,
893 n->tok = location->components.front()->tok;
5227f1ea 894
e2012a7a
DB
895 // and statements representing the concatenation of the alias'
896 // body with the use's.
897 //
898 // NB: locals are *not* copied forward, from either alias or
899 // use. The expansion should have its locals re-inferred since
900 // there's concatenated code here and we only want one vardecl per
901 // resulting variable.
57148ee7 902
e2012a7a
DB
903 if (alias->epilogue_style)
904 n->body = new block (use->body, alias->body);
905 else
906 n->body = new block (alias->body, use->body);
a3b4f52c 907
e2012a7a 908 unsigned old_num_results = finished_results.size();
8eb6206c
SM
909 // If expanding for an alias suffix, be sure to pass on any errors
910 // to the caller instead of printing them in derive_probes():
911 derive_probes (sess, n, finished_results, location->optional, !suffix.empty());
2c5a19c6 912
e2012a7a
DB
913 // Check whether we resolved something. If so, put the
914 // whole library into the queue if not already there.
915 if (finished_results.size() > old_num_results)
916 {
917 stapfile *f = alias->tok->location.file;
918 if (find (sess.files.begin(), sess.files.end(), f)
919 == sess.files.end())
920 sess.files.push_back (f);
2c5a19c6 921 }
e2012a7a
DB
922}
923
924bool
925alias_expansion_builder::checkForRecursiveExpansion (probe *use)
926{
927 // Collect the derivation chain of this probe.
928 vector<probe*>derivations;
929 use->collect_derivation_chain (derivations);
930
931 // Check all probe points in the alias expansion against the currently-being-expanded probe point
932 // of each of the probes in the derivation chain, looking for a match. This
933 // indicates infinite recursion.
934 // The first element of the derivation chain will be the derived_probe representing 'use', so
935 // start the search with the second element.
936 assert (derivations.size() > 0);
937 assert (derivations[0] == use);
938 for (unsigned d = 1; d < derivations.size(); ++d) {
939 if (use->get_alias() == derivations[d]->get_alias())
940 return true; // recursion detected
2c5a19c6 941 }
e2012a7a
DB
942 return false;
943}
20c6c071
GH
944
945
946// ------------------------------------------------------------------------
947// Pattern matching
948// ------------------------------------------------------------------------
949
5227f1ea
GH
950static unsigned max_recursion = 100;
951
57148ee7 952struct
5227f1ea
GH
953recursion_guard
954{
955 unsigned & i;
956 recursion_guard(unsigned & i) : i(i)
957 {
958 if (i > max_recursion)
4af765b2 959 throw semantic_error(_("recursion limit reached"));
5227f1ea
GH
960 ++i;
961 }
57148ee7 962 ~recursion_guard()
5227f1ea
GH
963 {
964 --i;
965 }
966};
967
20c6c071
GH
968// The match-and-expand loop.
969void
b4ceace2
FCE
970derive_probes (systemtap_session& s,
971 probe *p, vector<derived_probe*>& dps,
8eb6206c
SM
972 bool optional,
973 bool rethrow_errors)
20c6c071
GH
974{
975 for (unsigned i = 0; i < p->locations.size(); ++i)
976 {
e19ebcf7 977 assert_no_interrupts();
49abf162 978
20c6c071 979 probe_point *loc = p->locations[i];
a971b891 980
d885563b
FCE
981 if (s.verbose > 4)
982 clog << "derive-probes " << *loc << endl;
983
fe3d01fa
FCE
984 try
985 {
fe3d01fa 986 unsigned num_atbegin = dps.size();
d898100a
FCE
987
988 // Pass down optional flag from e.g. alias reference to each
989 // probe_point instance. We do this by temporarily overriding
990 // the probe_point optional flag. We could instead deep-copy
991 // and set a flag on the copy permanently.
992 bool old_loc_opt = loc->optional;
993 loc->optional = loc->optional || optional;
74efda8d
WH
994 try
995 {
996 s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
997 }
998 catch (const semantic_error& e)
999 {
1000 if (!loc->optional)
1001 throw semantic_error(e);
1002 else /* tolerate failure for optional probe */
1003 continue;
1004 }
1005
d898100a 1006 loc->optional = old_loc_opt;
fe3d01fa 1007 unsigned num_atend = dps.size();
d898100a
FCE
1008
1009 if (! (loc->optional||optional) && // something required, but
cedd10f4 1010 num_atbegin == num_atend) // nothing new derived!
4af765b2 1011 throw semantic_error (_("no match"));
d898100a
FCE
1012
1013 if (loc->sufficient && (num_atend > num_atbegin))
1014 {
1015 if (s.verbose > 1)
1016 {
1017 clog << "Probe point ";
1018 p->locations[i]->print(clog);
1019 clog << " sufficient, skipped";
1020 for (unsigned j = i+1; j < p->locations.size(); ++j)
1021 {
1022 clog << " ";
1023 p->locations[j]->print(clog);
1024 }
1025 clog << endl;
1026 }
1027 break; // we need not try to derive for any other locations
1028 }
fe3d01fa
FCE
1029 }
1030 catch (const semantic_error& e)
1031 {
8eb6206c
SM
1032 // The rethrow_errors parameter lets the caller decide an
1033 // alternative to printing the error. This is necessary when
1034 // calling derive_probes() recursively during expansion of
1035 // an alias with suffix -- any message printed here would
1036 // point to the alias declaration and not the invalid suffix
1037 // usage, so the caller needs to catch the error themselves
1038 // and print a more appropriate message.
1039 if (rethrow_errors)
1040 {
e758508b 1041 throw semantic_error(e);
8eb6206c
SM
1042 }
1043 // Only output in listing if -vv is supplied:
1044 else if (!s.listing_mode || (s.listing_mode && s.verbose > 1))
68ac5d0e
FCE
1045 {
1046 // XXX: prefer not to print_error at every nest/unroll level
e26c2f83
FCE
1047 semantic_error* er = new semantic_error (_("while resolving probe point"),
1048 loc->components[0]->tok);
1049 er->chain = & e;
68ac5d0e
FCE
1050 s.print_error (* er);
1051 delete er;
1052 }
fe3d01fa 1053 }
a971b891 1054
20c6c071
GH
1055 }
1056}
1057
b4ceace2
FCE
1058
1059
20c6c071 1060// ------------------------------------------------------------------------
67c0a579 1061//
d02548c0 1062// Indexable usage checks
67c0a579
GH
1063//
1064
d02548c0 1065struct symbol_fetcher
07c17d67 1066 : public throwing_visitor
67c0a579 1067{
d02548c0 1068 symbol *&sym;
67c0a579 1069
57148ee7 1070 symbol_fetcher (symbol *&sym): sym(sym)
67c0a579
GH
1071 {}
1072
d02548c0
GH
1073 void visit_symbol (symbol* e)
1074 {
1075 sym = e;
1076 }
1077
b0be9bdb
FCE
1078 void visit_target_symbol (target_symbol* e)
1079 {
1080 sym = e;
1081 }
1082
d02548c0
GH
1083 void visit_arrayindex (arrayindex* e)
1084 {
d15d767c 1085 e->base->visit (this);
d02548c0
GH
1086 }
1087
9b5af295
JS
1088 void visit_cast_op (cast_op* e)
1089 {
1090 sym = e;
1091 }
1092
d02548c0
GH
1093 void throwone (const token* t)
1094 {
20882639
FCE
1095 if (t->type == tok_operator && t->content == ".") // guess someone misused . in $foo->bar.baz expression
1096 throw semantic_error (_("Expecting symbol or array index expression, try -> instead"), t);
1097 else
1098 throw semantic_error (_("Expecting symbol or array index expression"), t);
d02548c0
GH
1099 }
1100};
1101
07c17d67 1102symbol *
d02548c0
GH
1103get_symbol_within_expression (expression *e)
1104{
1105 symbol *sym = NULL;
1106 symbol_fetcher fetcher(sym);
1107 e->visit (&fetcher);
b0be9bdb 1108 return sym; // NB: may be null!
d02548c0
GH
1109}
1110
1111static symbol *
1112get_symbol_within_indexable (indexable *ix)
1113{
1114 symbol *array = NULL;
1115 hist_op *hist = NULL;
1116 classify_indexable(ix, array, hist);
1117 if (array)
1118 return array;
1119 else
1120 return get_symbol_within_expression (hist->stat);
1121}
1122
1123struct mutated_var_collector
07c17d67 1124 : public traversing_visitor
d02548c0
GH
1125{
1126 set<vardecl *> * mutated_vars;
1127
57148ee7 1128 mutated_var_collector (set<vardecl *> * mm)
d02548c0
GH
1129 : mutated_vars (mm)
1130 {}
1131
1132 void visit_assignment(assignment* e)
1133 {
1134 if (e->type == pe_stats && e->op == "<<<")
1135 {
1136 vardecl *vd = get_symbol_within_expression (e->left)->referent;
1137 if (vd)
1138 mutated_vars->insert (vd);
1139 }
1bbeef03 1140 traversing_visitor::visit_assignment(e);
d02548c0
GH
1141 }
1142
67c0a579
GH
1143 void visit_arrayindex (arrayindex *e)
1144 {
d02548c0
GH
1145 if (is_active_lvalue (e))
1146 {
1147 symbol *sym;
1148 if (e->base->is_symbol (sym))
1149 mutated_vars->insert (sym->referent);
1150 else
4af765b2 1151 throw semantic_error(_("Assignment to read-only histogram bucket"), e->tok);
d02548c0 1152 }
1bbeef03 1153 traversing_visitor::visit_arrayindex (e);
67c0a579
GH
1154 }
1155};
1156
1157
d02548c0 1158struct no_var_mutation_during_iteration_check
07c17d67 1159 : public traversing_visitor
67c0a579
GH
1160{
1161 systemtap_session & session;
d02548c0
GH
1162 map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
1163 vector<vardecl *> vars_being_iterated;
57148ee7
FCE
1164
1165 no_var_mutation_during_iteration_check
67c0a579 1166 (systemtap_session & sess,
d02548c0
GH
1167 map<functiondecl *,set<vardecl *> *> & fmv)
1168 : session(sess), function_mutates_vars (fmv)
67c0a579
GH
1169 {}
1170
1171 void visit_arrayindex (arrayindex *e)
1172 {
d7f3e0c5 1173 if (is_active_lvalue(e))
67c0a579 1174 {
d02548c0
GH
1175 vardecl *vd = get_symbol_within_indexable (e->base)->referent;
1176 if (vd)
67c0a579 1177 {
d02548c0 1178 for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
67c0a579 1179 {
d02548c0
GH
1180 vardecl *v = vars_being_iterated[i];
1181 if (v == vd)
1182 {
4af765b2
LB
1183 string err = _F("variable '%s' modified during 'foreach' iteration",
1184 v->name.c_str());
d02548c0
GH
1185 session.print_error (semantic_error (err, e->tok));
1186 }
67c0a579
GH
1187 }
1188 }
1189 }
1bbeef03 1190 traversing_visitor::visit_arrayindex (e);
67c0a579
GH
1191 }
1192
1193 void visit_functioncall (functioncall* e)
1194 {
57148ee7 1195 map<functiondecl *,set<vardecl *> *>::const_iterator i
d02548c0 1196 = function_mutates_vars.find (e->referent);
67c0a579 1197
d02548c0 1198 if (i != function_mutates_vars.end())
67c0a579 1199 {
d02548c0 1200 for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
67c0a579 1201 {
d02548c0 1202 vardecl *m = vars_being_iterated[j];
67c0a579
GH
1203 if (i->second->find (m) != i->second->end())
1204 {
4af765b2
LB
1205 string err = _F("function call modifies var '%s' during 'foreach' iteration",
1206 m->name.c_str());
67c0a579
GH
1207 session.print_error (semantic_error (err, e->tok));
1208 }
1209 }
1210 }
1211
1bbeef03 1212 traversing_visitor::visit_functioncall (e);
67c0a579
GH
1213 }
1214
1215 void visit_foreach_loop(foreach_loop* s)
1216 {
d02548c0
GH
1217 vardecl *vd = get_symbol_within_indexable (s->base)->referent;
1218
1219 if (vd)
1220 vars_being_iterated.push_back (vd);
57148ee7 1221
1bbeef03 1222 traversing_visitor::visit_foreach_loop (s);
d02548c0
GH
1223
1224 if (vd)
1225 vars_being_iterated.pop_back();
67c0a579
GH
1226 }
1227};
20c6c071 1228
2b066ec1 1229
67c0a579
GH
1230// ------------------------------------------------------------------------
1231
07c17d67
GH
1232struct stat_decl_collector
1233 : public traversing_visitor
1234{
1235 systemtap_session & session;
57148ee7 1236
07c17d67
GH
1237 stat_decl_collector(systemtap_session & sess)
1238 : session(sess)
1239 {}
1240
1241 void visit_stat_op (stat_op* e)
1242 {
1243 symbol *sym = get_symbol_within_expression (e->stat);
1244 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1245 session.stat_decls[sym->name] = statistic_decl();
1246 }
1247
1248 void visit_assignment (assignment* e)
1249 {
1250 if (e->op == "<<<")
1251 {
1252 symbol *sym = get_symbol_within_expression (e->left);
1253 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1254 session.stat_decls[sym->name] = statistic_decl();
1255 }
1256 else
1257 traversing_visitor::visit_assignment(e);
1258 }
1259
1260 void visit_hist_op (hist_op* e)
1261 {
1262 symbol *sym = get_symbol_within_expression (e->stat);
1263 statistic_decl new_stat;
1264
1265 if (e->htype == hist_linear)
1266 {
1267 new_stat.type = statistic_decl::linear;
1268 assert (e->params.size() == 3);
1269 new_stat.linear_low = e->params[0];
1270 new_stat.linear_high = e->params[1];
1271 new_stat.linear_step = e->params[2];
1272 }
1273 else
1274 {
1275 assert (e->htype == hist_log);
1276 new_stat.type = statistic_decl::logarithmic;
e38723d2 1277 assert (e->params.size() == 0);
07c17d67
GH
1278 }
1279
1280 map<string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
1281 if (i == session.stat_decls.end())
1282 session.stat_decls[sym->name] = new_stat;
1283 else
1284 {
1285 statistic_decl & old_stat = i->second;
1286 if (!(old_stat == new_stat))
1287 {
1288 if (old_stat.type == statistic_decl::none)
1289 i->second = new_stat;
1290 else
1291 {
1292 // FIXME: Support multiple co-declared histogram types
4af765b2 1293 semantic_error se(_F("multiple histogram types declared on '%s'", sym->name.c_str()), e->tok);
07c17d67
GH
1294 session.print_error (se);
1295 }
1296 }
57148ee7 1297 }
07c17d67
GH
1298 }
1299
1300};
1301
1302static int
1303semantic_pass_stats (systemtap_session & sess)
1304{
1305 stat_decl_collector sdc(sess);
1306
f76427a2
FCE
1307 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
1308 it->second->body->visit (&sdc);
07c17d67 1309
57148ee7 1310 for (unsigned i = 0; i < sess.probes.size(); ++i)
07c17d67
GH
1311 sess.probes[i]->body->visit (&sdc);
1312
1313 for (unsigned i = 0; i < sess.globals.size(); ++i)
1314 {
1315 vardecl *v = sess.globals[i];
1316 if (v->type == pe_stats)
1317 {
57148ee7 1318
07c17d67
GH
1319 if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
1320 {
4af765b2 1321 semantic_error se(_F("unable to infer statistic parameters for global '%s'", v->name.c_str()));
07c17d67
GH
1322 sess.print_error (se);
1323 }
1324 }
1325 }
57148ee7 1326
7e41d3dc 1327 return sess.num_errors();
07c17d67
GH
1328}
1329
5d23847d
FCE
1330// ------------------------------------------------------------------------
1331
1332// Enforce variable-related invariants: no modification of
1333// a foreach()-iterated array.
1334static int
1335semantic_pass_vars (systemtap_session & sess)
1336{
57148ee7 1337
5d23847d
FCE
1338 map<functiondecl *, set<vardecl *> *> fmv;
1339 no_var_mutation_during_iteration_check chk(sess, fmv);
57148ee7 1340
f76427a2 1341 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
5d23847d 1342 {
f76427a2 1343 functiondecl * fn = it->second;
5d23847d
FCE
1344 if (fn->body)
1345 {
1346 set<vardecl *> * m = new set<vardecl *>();
1347 mutated_var_collector mc (m);
1348 fn->body->visit (&mc);
1349 fmv[fn] = m;
1350 }
1351 }
1352
f76427a2 1353 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
5d23847d 1354 {
f76427a2
FCE
1355 functiondecl * fn = it->second;
1356 if (fn->body) fn->body->visit (&chk);
5d23847d
FCE
1357 }
1358
1359 for (unsigned i = 0; i < sess.probes.size(); ++i)
1360 {
1361 if (sess.probes[i]->body)
1362 sess.probes[i]->body->visit (&chk);
57148ee7 1363 }
5d23847d
FCE
1364
1365 return sess.num_errors();
1366}
1367
1368
1369// ------------------------------------------------------------------------
1370
1371// Rewrite probe condition expressions into probe bodies. Tricky and
1372// exciting business, this. This:
1373//
1374// probe foo if (g1 || g2) { ... }
1375// probe bar { ... g1 ++ ... }
1376//
1377// becomes:
1378//
1379// probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1380// probe foo { if (! (g1 || g2)) next; ... }
57148ee7 1381// probe bar { ... g1 ++ ...;
5d23847d
FCE
1382// if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1383// }
1384//
1385// XXX: As a first cut, do only the "inline probe condition" part of the
1386// transform.
1387
1388static int
1389semantic_pass_conditions (systemtap_session & sess)
1390{
1391 for (unsigned i = 0; i < sess.probes.size(); ++i)
1392 {
1393 derived_probe* p = sess.probes[i];
1394 expression* e = p->sole_location()->condition;
1395 if (e)
1396 {
313db8e6 1397 varuse_collecting_visitor vut(sess);
5d23847d
FCE
1398 e->visit (& vut);
1399
1400 if (! vut.written.empty())
1401 {
4af765b2 1402 string err = (_("probe condition must not modify any variables"));
5d23847d
FCE
1403 sess.print_error (semantic_error (err, e->tok));
1404 }
1405 else if (vut.embedded_seen)
1406 {
4af765b2 1407 sess.print_error (semantic_error (_("probe condition must not include impure embedded-C"), e->tok));
5d23847d
FCE
1408 }
1409
1410 // Add the condition expression to the front of the
1411 // derived_probe body.
1412 if_statement *ifs = new if_statement ();
1413 ifs->tok = e->tok;
1414 ifs->thenblock = new next_statement ();
1415 ifs->thenblock->tok = e->tok;
1416 ifs->elseblock = NULL;
1417 unary_expression *notex = new unary_expression ();
1418 notex->op = "!";
1419 notex->tok = e->tok;
1420 notex->operand = e;
1421 ifs->condition = notex;
ba6f838d 1422 p->body = new block (ifs, p->body);
5d23847d 1423 }
57148ee7 1424 }
5d23847d
FCE
1425
1426 return sess.num_errors();
1427}
1428
ac9ca50a
MW
1429// ------------------------------------------------------------------------
1430
1431
1432// Simple visitor that just goes through all embedded code blocks that
1433// are available at the end all the optimizations to register any
1434// relevant pragmas or other indicators found, so that session flags can
1435// be set that can be inspected at translation time to trigger any
1436// necessary initialization of code needed by the embedded code functions.
1437
1438// This is only for pragmas that don't have any other side-effect than
8af41ec2
MW
1439// needing some initialization at module init time. Currently handles
1440// /* pragma:vma */ /* pragma:unwind */ /* pragma:symbol */
ac9ca50a
MW
1441
1442// /* pragma:uprobes */ is handled during the typeresolution_info pass.
2363d2a5
DB
1443// /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */
1444// are handled by the varuse_collecting_visitor.
ac9ca50a
MW
1445
1446struct embeddedcode_info: public functioncall_traversing_visitor
1447{
1448protected:
1449 systemtap_session& session;
1450
1451public:
1452 embeddedcode_info (systemtap_session& s): session(s) { }
1453
1454 void visit_embeddedcode (embeddedcode* c)
1455 {
a057c85c 1456 if (! vma_tracker_enabled(session)
ac9ca50a
MW
1457 && c->code.find("/* pragma:vma */") != string::npos)
1458 {
a057c85c 1459 enable_vma_tracker(session);
ac9ca50a 1460 if (session.verbose > 2)
4af765b2
LB
1461 clog << _F("Turning on task_finder vma_tracker, pragma:vma found in %s",
1462 current_function->name.c_str()) << endl;
ac9ca50a 1463 }
08badca8
MW
1464
1465 if (! session.need_unwind
1466 && c->code.find("/* pragma:unwind */") != string::npos)
1467 {
1468 if (session.verbose > 2)
1469 clog << _F("Turning on unwind support, pragma:unwind found in %s",
1470 current_function->name.c_str()) << endl;
8af41ec2
MW
1471 session.need_unwind = true;
1472 }
1473
1474 if (! session.need_symbols
1475 && c->code.find("/* pragma:symbols */") != string::npos)
1476 {
1477 if (session.verbose > 2)
1478 clog << _F("Turning on symbol data collecting, pragma:symbols found in %s",
1479 current_function->name.c_str()) << endl;
1480 session.need_symbols = true;
1481 }
ac9ca50a
MW
1482 }
1483};
1484
1485void embeddedcode_info_pass (systemtap_session& s)
1486{
1487 embeddedcode_info eci (s);
1488 for (unsigned i=0; i<s.probes.size(); i++)
1489 s.probes[i]->body->visit (& eci);
1490}
5d23847d 1491
07c17d67
GH
1492// ------------------------------------------------------------------------
1493
2b066ec1 1494
d2548fe7
SM
1495// Simple visitor that collects all the regular expressions in the
1496// file and adds them to the session DFA table.
1497
1498struct regex_collecting_visitor: public functioncall_traversing_visitor
1499{
1500protected:
1501 systemtap_session& session;
1502
1503public:
1504 regex_collecting_visitor (systemtap_session& s): session(s) { }
1505
1506 void visit_regex_query (regex_query *q) {
1507 functioncall_traversing_visitor::visit_regex_query (q); // TODOXXX test necessity
1508
d24f1ff4 1509 string re = q->re->value;
5a14b9b8
SM
1510 try
1511 {
1512 regex_to_stapdfa (&session, re, session.dfa_counter);
1513 }
1514 catch (const semantic_error &e)
1515 {
1516 throw semantic_error(e.what(), q->right->tok);
1517 }
d2548fe7
SM
1518 }
1519};
1520
1521// Go through the regex match invocations and generate corresponding DFAs.
1522void gen_dfa_table (systemtap_session& s)
1523{
1524 regex_collecting_visitor rcv(s); // TODOXXX
1525
1526 for (unsigned i=0; i<s.probes.size(); i++)
1527 {
1528 s.probes[i]->body->visit (& rcv);
1529
1530 if (s.probes[i]->sole_location()->condition)
1531 s.probes[i]->sole_location()->condition->visit (& rcv);
1532 }
1533}
1534
1535// ------------------------------------------------------------------------
1536
1537
2b066ec1 1538static int semantic_pass_symbols (systemtap_session&);
c214bd6a
DS
1539static int semantic_pass_optimize1 (systemtap_session&);
1540static int semantic_pass_optimize2 (systemtap_session&);
2b066ec1 1541static int semantic_pass_types (systemtap_session&);
d02548c0 1542static int semantic_pass_vars (systemtap_session&);
07c17d67 1543static int semantic_pass_stats (systemtap_session&);
5d23847d 1544static int semantic_pass_conditions (systemtap_session&);
2b066ec1
FCE
1545
1546
1547// Link up symbols to their declarations. Set the session's
1548// files/probes/functions/globals vectors from the transitively
1549// reached set of stapfiles in s.library_files, starting from
20c6c071 1550// s.user_file. Perform automatic tapset inclusion and probe
2b066ec1
FCE
1551// alias expansion.
1552static int
1553semantic_pass_symbols (systemtap_session& s)
1554{
1555 symresolution_info sym (s);
1556
1557 // NB: s.files can grow during this iteration, so size() can
1558 // return gradually increasing numbers.
1559 s.files.push_back (s.user_file);
1560 for (unsigned i = 0; i < s.files.size(); i++)
1561 {
e19ebcf7 1562 assert_no_interrupts();
2b066ec1
FCE
1563 stapfile* dome = s.files[i];
1564
1565 // Pass 1: add globals and functions to systemtap-session master list,
1566 // so the find_* functions find them
e26c2f83
FCE
1567 //
1568 // NB: tapset global/function definitions may duplicate or conflict
1569 // with those already in s.globals/functions. We need to deconflict
1570 // here.
2b066ec1
FCE
1571
1572 for (unsigned i=0; i<dome->globals.size(); i++)
e26c2f83
FCE
1573 {
1574 vardecl* g = dome->globals[i];
1575 for (unsigned j=0; j<s.globals.size(); j++)
1576 {
1577 vardecl* g2 = s.globals[j];
1578 if (g->name == g2->name)
1579 {
1580 s.print_error (semantic_error (_("conflicting global variables"),
1581 g->tok, g2->tok));
1582 }
1583 }
1584 s.globals.push_back (g);
1585 }
2b066ec1
FCE
1586
1587 for (unsigned i=0; i<dome->functions.size(); i++)
e26c2f83
FCE
1588 {
1589 functiondecl* f = dome->functions[i];
1590 functiondecl* f2 = s.functions[f->name];
1591 if (f2 && f != f2)
1592 {
1593 s.print_error (semantic_error (_("conflicting functions"),
1594 f->tok, f2->tok));
1595 }
1596 s.functions[f->name] = f;
1597 }
2b066ec1 1598
e26c2f83 1599 // NB: embeds don't conflict with each other
54dfabe9
FCE
1600 for (unsigned i=0; i<dome->embeds.size(); i++)
1601 s.embeds.push_back (dome->embeds[i]);
1602
f8809d54 1603 // Pass 2: derive probes and resolve any further symbols in the
57148ee7 1604 // derived results.
2b066ec1
FCE
1605
1606 for (unsigned i=0; i<dome->probes.size(); i++)
1607 {
e19ebcf7 1608 assert_no_interrupts();
2b066ec1
FCE
1609 probe* p = dome->probes [i];
1610 vector<derived_probe*> dps;
1611
a971b891
FCE
1612 // much magic happens here: probe alias expansion, wildcard
1613 // matching, low-level derived_probe construction.
b4ceace2 1614 derive_probes (s, p, dps);
2b066ec1
FCE
1615
1616 for (unsigned j=0; j<dps.size(); j++)
1617 {
e19ebcf7 1618 assert_no_interrupts();
2b066ec1 1619 derived_probe* dp = dps[j];
b20febf3
FCE
1620 s.probes.push_back (dp);
1621 dp->join_group (s);
2b066ec1 1622
57148ee7 1623 try
2b066ec1 1624 {
f80d9004 1625 for (unsigned k=0; k<s.code_filters.size(); k++)
8b095b45 1626 s.code_filters[k]->replace (dp->body);
f80d9004 1627
2b066ec1 1628 sym.current_function = 0;
5227f1ea 1629 sym.current_probe = dp;
2b066ec1 1630 dp->body->visit (& sym);
5d23847d
FCE
1631
1632 // Process the probe-point condition expression.
1633 sym.current_function = 0;
1634 sym.current_probe = 0;
1635 if (dp->sole_location()->condition)
1636 dp->sole_location()->condition->visit (& sym);
2b066ec1
FCE
1637 }
1638 catch (const semantic_error& e)
1639 {
1640 s.print_error (e);
1641 }
1642 }
1643 }
f8809d54
JS
1644
1645 // Pass 3: process functions
1646
1647 for (unsigned i=0; i<dome->functions.size(); i++)
1648 {
e19ebcf7 1649 assert_no_interrupts();
f8809d54
JS
1650 functiondecl* fd = dome->functions[i];
1651
1652 try
1653 {
1654 for (unsigned j=0; j<s.code_filters.size(); j++)
1655 s.code_filters[j]->replace (fd->body);
1656
1657 sym.current_function = fd;
1658 sym.current_probe = 0;
1659 fd->body->visit (& sym);
1660 }
1661 catch (const semantic_error& e)
1662 {
1663 s.print_error (e);
1664 }
1665 }
2b066ec1 1666 }
aa30ccd3
FCE
1667
1668 // Inform all derived_probe builders that we're done with
1669 // all resolution, so it's time to release caches.
1670 s.pattern_root->build_no_more (s);
57148ee7 1671
a07a2c28
LB
1672 if(s.systemtap_v_check){
1673 for(unsigned i=0;i<s.globals.size();i++){
1674 if(s.globals[i]->systemtap_v_conditional)
4af765b2 1675 s.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s.globals[i]->tok);
a07a2c28
LB
1676 }
1677
1678 for(map<string, functiondecl*>::const_iterator i=s.functions.begin();i != s.functions.end();++i){
1679 if(i->second->systemtap_v_conditional)
4af765b2 1680 s.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i->second->tok);
a07a2c28
LB
1681 }
1682
1683 for(unsigned i=0;i<s.probes.size();i++){
1684 vector<probe*> sysvc;
1685 s.probes[i]->collect_derivation_chain(sysvc);
1686 for(unsigned j=0;j<sysvc.size();j++){
1687 if(sysvc[j]->systemtap_v_conditional)
4af765b2 1688 s.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc[j]->tok);
a07a2c28 1689 if(sysvc[j]->get_alias() && sysvc[j]->get_alias()->systemtap_v_conditional)
4af765b2 1690 s.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc[j]->get_alias()->tok);
a07a2c28
LB
1691 }
1692 }
1693 }
1694
7e41d3dc 1695 return s.num_errors(); // all those print_error calls
2b066ec1
FCE
1696}
1697
1698
0a102c82
SC
1699// Keep unread global variables for probe end value display.
1700void add_global_var_display (systemtap_session& s)
1701{
5ae31731
FCE
1702 // Don't generate synthetic end probes when in listings mode;
1703 // it would clutter up the list of probe points with "end ...".
1704 if (s.listing_mode) return;
3438f38f 1705
313db8e6 1706 varuse_collecting_visitor vut(s);
9d8a6ba3 1707
0a102c82
SC
1708 for (unsigned i=0; i<s.probes.size(); i++)
1709 {
1710 s.probes[i]->body->visit (& vut);
1711
1712 if (s.probes[i]->sole_location()->condition)
1713 s.probes[i]->sole_location()->condition->visit (& vut);
1714 }
1715
1716 for (unsigned g=0; g < s.globals.size(); g++)
1717 {
1718 vardecl* l = s.globals[g];
9d8a6ba3
SC
1719 if ((vut.read.find (l) != vut.read.end()
1720 && vut.used.find (l) != vut.used.end())
e491a713 1721 || vut.written.find (l) == vut.written.end())
0a102c82
SC
1722 continue;
1723
b5852334 1724 // Don't generate synthetic end probes for unread globals
5ae31731
FCE
1725 // declared only within tapsets. (RHBZ 468139), but rather
1726 // only within the end-user script.
1727
7584f162
RA
1728 bool tapset_global = false;
1729 for (size_t m=0; m < s.library_files.size(); m++)
1730 {
1731 for (size_t n=0; n < s.library_files[m]->globals.size(); n++)
1732 {
1733 if (l->name == s.library_files[m]->globals[n]->name)
1734 {tapset_global = true; break;}
1735 }
1736 }
1737 if (tapset_global)
1738 continue;
5ae31731 1739
0a102c82 1740 probe_point::component* c = new probe_point::component("end");
d5e178c1
JS
1741 probe_point* pl = new probe_point;
1742 pl->components.push_back (c);
1743
0a102c82 1744 vector<derived_probe*> dps;
6d2685fe 1745 block *b = new block;
ead25cf5 1746 b->tok = l->tok;
0a102c82 1747
d5e178c1 1748 probe* p = new probe;
db48cbe9 1749 p->tok = l->tok;
0a102c82 1750 p->locations.push_back (pl);
0a102c82
SC
1751
1752 // Create a symbol
1753 symbol* g_sym = new symbol;
1754 g_sym->name = l->name;
1755 g_sym->tok = l->tok;
1756 g_sym->type = l->type;
57148ee7 1757 g_sym->referent = l;
0a102c82 1758
ead25cf5 1759 token* print_tok = new token(*l->tok);
d5e178c1
JS
1760 print_tok->type = tok_identifier;
1761 print_tok->content = "printf";
1762
1763 print_format* pf = print_format::create(print_tok);
0a102c82 1764 pf->raw_components += l->name;
0a102c82
SC
1765
1766 if (l->index_types.size() == 0) // Scalar
1767 {
e071e49b 1768 if (l->type == pe_stats)
49060244
WC
1769 if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
1770 pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1771 else
1772 pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
e071e49b 1773 else if (l->type == pe_string)
0a102c82
SC
1774 pf->raw_components += "=\"%#s\"\\n";
1775 else
1776 pf->raw_components += "=%#x\\n";
0a102c82
SC
1777 pf->components = print_format::string_to_components(pf->raw_components);
1778 expr_statement* feb = new expr_statement;
1779 feb->value = pf;
1780 feb->tok = print_tok;
e071e49b
SC
1781 if (l->type == pe_stats)
1782 {
1783 struct stat_op* so [5];
1784 const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
1785
1786 for (unsigned si = 0;
1787 si < (sizeof(so)/sizeof(struct stat_op*));
1788 si++)
1789 {
1790 so[si]= new stat_op;
1791 so[si]->ctype = stypes[si];
1792 so[si]->type = pe_long;
1793 so[si]->stat = g_sym;
1794 so[si]->tok = l->tok;
1795 pf->args.push_back(so[si]);
1796 }
1797 }
1798 else
1799 pf->args.push_back(g_sym);
271d408e
WH
1800
1801 /* PR7053: Checking empty aggregate for global variable */
1802 if (l->type == pe_stats) {
1803 stat_op *so= new stat_op;
1804 so->ctype = sc_count;
1805 so->type = pe_long;
1806 so->stat = g_sym;
1807 so->tok = l->tok;
1808 comparison *be = new comparison;
1809 be->op = ">";
1810 be->tok = l->tok;
1811 be->left = so;
1812 be->right = new literal_number(0);
1813
1814 /* Create printf @count=0x0 in else block */
d5e178c1 1815 print_format* pf_0 = print_format::create(print_tok);
271d408e
WH
1816 pf_0->raw_components += l->name;
1817 pf_0->raw_components += " @count=0x0\\n";
271d408e
WH
1818 pf_0->components = print_format::string_to_components(pf_0->raw_components);
1819 expr_statement* feb_else = new expr_statement;
1820 feb_else->value = pf_0;
1821 feb_else->tok = print_tok;
1822 if_statement *ifs = new if_statement;
1823 ifs->tok = l->tok;
1824 ifs->condition = be;
1825 ifs->thenblock = feb ;
1826 ifs->elseblock = feb_else;
1827 b->statements.push_back(ifs);
1828 }
1829 else /* other non-stat cases */
1830 b->statements.push_back(feb);
0a102c82
SC
1831 }
1832 else // Array
1833 {
1834 int idx_count = l->index_types.size();
0a102c82
SC
1835 symbol* idx_sym[idx_count];
1836 vardecl* idx_v[idx_count];
1837 // Create a foreach loop
0a102c82 1838 foreach_loop* fe = new foreach_loop;
e91b23bc
FCE
1839 fe->sort_direction = -1; // imply decreasing sort on value
1840 fe->sort_column = 0; // as in foreach ([a,b,c] in array-) { }
1cdda92d 1841 fe->sort_aggr = sc_none; // as in default @count
c261711d 1842 fe->value = NULL;
0a102c82 1843 fe->limit = NULL;
ead25cf5 1844 fe->tok = l->tok;
0a102c82
SC
1845
1846 // Create indices for the foreach loop
1847 for (int i=0; i < idx_count; i++)
1848 {
0a102c82 1849 char *idx_name;
4310926e
LB
1850 if (asprintf (&idx_name, "idx%d", i) < 0) {
1851 delete pf;
1852 delete b;
1853 delete p;
1854 delete g_sym;
1855 delete fe;
1856 return;
1857 }
0a102c82 1858 idx_sym[i] = new symbol;
0a102c82 1859 idx_sym[i]->name = idx_name;
db48cbe9 1860 idx_sym[i]->tok = l->tok;
0a102c82
SC
1861 idx_v[i] = new vardecl;
1862 idx_v[i]->name = idx_name;
0a102c82 1863 idx_v[i]->type = l->index_types[i];
db48cbe9 1864 idx_v[i]->tok = l->tok;
0a102c82
SC
1865 idx_sym[i]->referent = idx_v[i];
1866 fe->indexes.push_back (idx_sym[i]);
1867 }
1868
1869 // Create a printf for the foreach loop
ead25cf5 1870 pf->raw_components += "[";
0a102c82 1871 for (int i=0; i < idx_count; i++)
ead25cf5
JS
1872 {
1873 if (i > 0)
1874 pf->raw_components += ",";
1875 if (l->index_types[i] == pe_string)
1876 pf->raw_components += "\"%#s\"";
1877 else
1878 pf->raw_components += "%#d";
1879 }
1880 pf->raw_components += "]";
e491a713 1881 if (l->type == pe_stats)
49060244
WC
1882 if (strverscmp(s.compatible.c_str(), "1.4") >= 0)
1883 pf->raw_components += " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1884 else
1885 pf->raw_components += " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
e491a713 1886 else if (l->type == pe_string)
0a102c82
SC
1887 pf->raw_components += "=\"%#s\"\\n";
1888 else
1889 pf->raw_components += "=%#x\\n";
1890
1891 // Create an index for the array
1892 struct arrayindex* ai = new arrayindex;
1893 ai->tok = l->tok;
1894 ai->base = g_sym;
e491a713 1895
0a102c82
SC
1896 for (int i=0; i < idx_count; i++)
1897 {
1898 ai->indexes.push_back (idx_sym[i]);
1899 pf->args.push_back(idx_sym[i]);
1900 }
e491a713
SC
1901 if (l->type == pe_stats)
1902 {
1903 struct stat_op* so [5];
e491a713 1904 const stat_component_type stypes[] = {sc_count, sc_min, sc_max, sc_sum, sc_average};
e071e49b
SC
1905
1906 ai->type = pe_stats;
db48cbe9
SC
1907 for (unsigned si = 0;
1908 si < (sizeof(so)/sizeof(struct stat_op*));
1909 si++)
e491a713
SC
1910 {
1911 so[si]= new stat_op;
1912 so[si]->ctype = stypes[si];
1913 so[si]->type = pe_long;
1914 so[si]->stat = ai;
db48cbe9 1915 so[si]->tok = l->tok;
e071e49b 1916 pf->args.push_back(so[si]);
e491a713 1917 }
e491a713
SC
1918 }
1919 else
c261711d
JS
1920 {
1921 // Create value for the foreach loop
1922 fe->value = new symbol;
1923 fe->value->name = "val";
1924 fe->value->tok = l->tok;
1925 pf->args.push_back(fe->value);
1926 }
57148ee7 1927
0a102c82
SC
1928 pf->components = print_format::string_to_components(pf->raw_components);
1929 expr_statement* feb = new expr_statement;
1930 feb->value = pf;
ead25cf5 1931 feb->tok = l->tok;
0a102c82
SC
1932 fe->base = g_sym;
1933 fe->block = (statement*)feb;
1934 b->statements.push_back(fe);
0a102c82
SC
1935 }
1936
0a102c82 1937 // Add created probe
6d2685fe
SC
1938 p->body = b;
1939 derive_probes (s, p, dps);
0a102c82
SC
1940 for (unsigned i = 0; i < dps.size(); i++)
1941 {
1942 derived_probe* dp = dps[i];
1943 s.probes.push_back (dp);
1944 dp->join_group (s);
1945 }
6d2685fe
SC
1946 // Repopulate symbol and type info
1947 symresolution_info sym (s);
1948 sym.current_function = 0;
1949 sym.current_probe = dps[0];
1950 dps[0]->body->visit (& sym);
0a102c82 1951
6d2685fe
SC
1952 semantic_pass_types(s);
1953 // Mark that variable is read
0a102c82
SC
1954 vut.read.insert (l);
1955 }
1956}
2b066ec1
FCE
1957
1958int
1959semantic_pass (systemtap_session& s)
1960{
59bafbe8 1961 int rc = 0;
20c6c071 1962
57148ee7 1963 try
59bafbe8
FCE
1964 {
1965 s.register_library_aliases();
1966 register_standard_tapsets(s);
57148ee7 1967
5d23847d
FCE
1968 if (rc == 0) rc = semantic_pass_symbols (s);
1969 if (rc == 0) rc = semantic_pass_conditions (s);
c0f56268 1970 if (rc == 0) rc = semantic_pass_optimize1 (s);
59bafbe8 1971 if (rc == 0) rc = semantic_pass_types (s);
d2548fe7 1972 if (rc == 0) gen_dfa_table(s); // TODOXXX set rc?
0a102c82 1973 if (rc == 0) add_global_var_display (s);
c0f56268 1974 if (rc == 0) rc = semantic_pass_optimize2 (s);
d02548c0 1975 if (rc == 0) rc = semantic_pass_vars (s);
07c17d67 1976 if (rc == 0) rc = semantic_pass_stats (s);
7b8548ee 1977 if (rc == 0) embeddedcode_info_pass (s);
57148ee7 1978
8c938ec7 1979 if (s.num_errors() == 0 && s.probes.size() == 0 && !s.listing_mode)
4af765b2 1980 throw semantic_error (_("no probes found"));
59bafbe8
FCE
1981 }
1982 catch (const semantic_error& e)
1983 {
1984 s.print_error (e);
21beacc9 1985 rc ++;
59bafbe8 1986 }
57148ee7 1987
f119a57f 1988 // PR11443
f5b1b8bc
JS
1989 // NB: listing mode only cares whether we have any probes,
1990 // so all previous error conditions are disregarded.
1991 if (s.listing_mode)
1992 rc = s.probes.empty();
f119a57f 1993
2b066ec1
FCE
1994 return rc;
1995}
1996
1997
2b066ec1
FCE
1998// ------------------------------------------------------------------------
1999// semantic processing: symbol resolution
2000
2001
2002symresolution_info::symresolution_info (systemtap_session& s):
5227f1ea 2003 session (s), current_function (0), current_probe (0)
2b066ec1
FCE
2004{
2005}
2006
2007
2008void
2009symresolution_info::visit_block (block* e)
2010{
2011 for (unsigned i=0; i<e->statements.size(); i++)
2012 {
57148ee7 2013 try
2b066ec1
FCE
2014 {
2015 e->statements[i]->visit (this);
2016 }
2017 catch (const semantic_error& e)
2018 {
2019 session.print_error (e);
2020 }
2021 }
2022}
2023
2024
69c68955
FCE
2025void
2026symresolution_info::visit_foreach_loop (foreach_loop* e)
2027{
2028 for (unsigned i=0; i<e->indexes.size(); i++)
2029 e->indexes[i]->visit (this);
2030
57148ee7 2031 symbol *array = NULL;
d02548c0
GH
2032 hist_op *hist = NULL;
2033 classify_indexable (e->base, array, hist);
69c68955 2034
d02548c0
GH
2035 if (array)
2036 {
2037 if (!array->referent)
57148ee7 2038 {
2e526dab 2039 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
d02548c0
GH
2040 if (d)
2041 array->referent = d;
2042 else
60bebf58
JS
2043 {
2044 stringstream msg;
4af765b2
LB
2045 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
2046 e->indexes.size(), array->name.c_str());
60bebf58
JS
2047 throw semantic_error (msg.str(), e->tok);
2048 }
d02548c0
GH
2049 }
2050 }
57148ee7 2051 else
d02548c0
GH
2052 {
2053 assert (hist);
2054 hist->visit (this);
2055 }
69c68955 2056
c261711d
JS
2057 if (e->value)
2058 e->value->visit (this);
2059
27f21e8c
DS
2060 if (e->limit)
2061 e->limit->visit (this);
2062
69c68955
FCE
2063 e->block->visit (this);
2064}
2065
d02548c0 2066
57148ee7 2067struct
d98d459c
GH
2068delete_statement_symresolution_info:
2069 public traversing_visitor
2070{
2071 symresolution_info *parent;
2072
2073 delete_statement_symresolution_info (symresolution_info *p):
2074 parent(p)
2075 {}
2076
2077 void visit_arrayindex (arrayindex* e)
2078 {
2079 parent->visit_arrayindex (e);
2080 }
2081 void visit_functioncall (functioncall* e)
2082 {
2083 parent->visit_functioncall (e);
2084 }
2085
2086 void visit_symbol (symbol* e)
2087 {
2088 if (e->referent)
2089 return;
57148ee7 2090
2e526dab 2091 vardecl* d = parent->find_var (e->name, -1, e->tok);
d98d459c
GH
2092 if (d)
2093 e->referent = d;
2094 else
4af765b2 2095 throw semantic_error (_("unresolved array in delete statement"), e->tok);
d98d459c
GH
2096 }
2097};
2098
57148ee7 2099void
d98d459c
GH
2100symresolution_info::visit_delete_statement (delete_statement* s)
2101{
2102 delete_statement_symresolution_info di (this);
2103 s->value->visit (&di);
2104}
2105
69c68955 2106
2b066ec1
FCE
2107void
2108symresolution_info::visit_symbol (symbol* e)
2109{
2110 if (e->referent)
2111 return;
2112
2e526dab 2113 vardecl* d = find_var (e->name, 0, e->tok);
2b066ec1
FCE
2114 if (d)
2115 e->referent = d;
2116 else
2117 {
2118 // new local
2119 vardecl* v = new vardecl;
2120 v->name = e->name;
2121 v->tok = e->tok;
58701b78 2122 v->set_arity(0, e->tok);
2b066ec1
FCE
2123 if (current_function)
2124 current_function->locals.push_back (v);
2125 else if (current_probe)
2126 current_probe->locals.push_back (v);
2127 else
5d23847d 2128 // must be probe-condition expression
4af765b2 2129 throw semantic_error (_("probe condition must not reference undeclared global"), e->tok);
2b066ec1
FCE
2130 e->referent = v;
2131 }
2132}
2133
2134
2135void
2136symresolution_info::visit_arrayindex (arrayindex* e)
2137{
2138 for (unsigned i=0; i<e->indexes.size(); i++)
2139 e->indexes[i]->visit (this);
2140
57148ee7 2141 symbol *array = NULL;
d02548c0
GH
2142 hist_op *hist = NULL;
2143 classify_indexable(e->base, array, hist);
2b066ec1 2144
d02548c0 2145 if (array)
313b2f74 2146 {
d02548c0
GH
2147 if (array->referent)
2148 return;
2149
2e526dab 2150 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
d02548c0
GH
2151 if (d)
2152 array->referent = d;
313b2f74 2153 else
d02548c0 2154 {
60bebf58 2155 stringstream msg;
4af765b2
LB
2156 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
2157 e->indexes.size(), array->name.c_str());
60bebf58 2158 throw semantic_error (msg.str(), e->tok);
57148ee7 2159 }
d02548c0
GH
2160 }
2161 else
2162 {
2163 assert (hist);
2164 hist->visit (this);
313b2f74 2165 }
2b066ec1
FCE
2166}
2167
2168
2169void
2170symresolution_info::visit_functioncall (functioncall* e)
2171{
5d23847d
FCE
2172 // XXX: we could relax this, if we're going to examine the
2173 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
2174 if (! (current_function || current_probe))
2175 {
2176 // must be probe-condition expression
4af765b2 2177 throw semantic_error (_("probe condition must not reference function"), e->tok);
5d23847d
FCE
2178 }
2179
2b066ec1
FCE
2180 for (unsigned i=0; i<e->args.size(); i++)
2181 e->args[i]->visit (this);
2182
2183 if (e->referent)
2184 return;
2185
2186 functiondecl* d = find_function (e->function, e->args.size ());
2187 if (d)
2188 e->referent = d;
2189 else
2a99f48f 2190 {
7e41d3dc 2191 stringstream msg;
4af765b2 2192 msg << _F("unresolved arity-%zu function", e->args.size());
7e41d3dc 2193 throw semantic_error (msg.str(), e->tok);
2a99f48f 2194 }
2b066ec1
FCE
2195}
2196
a07a2c28
LB
2197/*find_var will return an argument other than zero if the name matches the var
2198 * name ie, if the current local name matches the name passed to find_var*/
57148ee7 2199vardecl*
2e526dab 2200symresolution_info::find_var (const string& name, int arity, const token* tok)
2b066ec1 2201{
5d23847d
FCE
2202 if (current_function || current_probe)
2203 {
2204 // search locals
57148ee7 2205 vector<vardecl*>& locals = (current_function ?
5d23847d
FCE
2206 current_function->locals :
2207 current_probe->locals);
57148ee7
FCE
2208
2209
5d23847d 2210 for (unsigned i=0; i<locals.size(); i++)
60bebf58 2211 if (locals[i]->name == name)
5d23847d 2212 {
58701b78 2213 locals[i]->set_arity (arity, tok);
5d23847d
FCE
2214 return locals[i];
2215 }
2216 }
2b066ec1 2217
313b2f74
GH
2218 // search function formal parameters (for scalars)
2219 if (arity == 0 && current_function)
2b066ec1
FCE
2220 for (unsigned i=0; i<current_function->formal_args.size(); i++)
2221 if (current_function->formal_args[i]->name == name)
8846477c
FCE
2222 {
2223 // NB: no need to check arity here: formal args always scalar
58701b78 2224 current_function->formal_args[i]->set_arity (0, tok);
8846477c
FCE
2225 return current_function->formal_args[i];
2226 }
2b066ec1 2227
313b2f74 2228 // search processed globals
2b066ec1 2229 for (unsigned i=0; i<session.globals.size(); i++)
60bebf58 2230 if (session.globals[i]->name == name)
8846477c 2231 {
2e526dab
FCE
2232 if (! session.suppress_warnings)
2233 {
2234 vardecl* v = session.globals[i];
2235 // clog << "resolved " << *tok << " to global " << *v->tok << endl;
2236 if (v->tok->location.file != tok->location.file)
2237 {
4af765b2
LB
2238 session.print_warning (_F("cross-file global variable reference to %s from",
2239 lex_cast(*v->tok).c_str()), tok);
2e526dab
FCE
2240 }
2241 }
2a7153bf
JS
2242 session.globals[i]->set_arity (arity, tok);
2243 return session.globals[i];
8846477c 2244 }
57148ee7 2245
2b066ec1
FCE
2246 // search library globals
2247 for (unsigned i=0; i<session.library_files.size(); i++)
2248 {
2249 stapfile* f = session.library_files[i];
2250 for (unsigned j=0; j<f->globals.size(); j++)
84e5ea0f
FCE
2251 {
2252 vardecl* g = f->globals[j];
60bebf58 2253 if (g->name == name)
84e5ea0f 2254 {
58701b78 2255 g->set_arity (arity, tok);
57148ee7
FCE
2256
2257 // put library into the queue if not already there
2258 if (find (session.files.begin(), session.files.end(), f)
84e5ea0f
FCE
2259 == session.files.end())
2260 session.files.push_back (f);
57148ee7 2261
84e5ea0f
FCE
2262 return g;
2263 }
2264 }
2b066ec1
FCE
2265 }
2266
2b066ec1 2267 return 0;
2b066ec1
FCE
2268}
2269
2270
57148ee7 2271functiondecl*
2b066ec1
FCE
2272symresolution_info::find_function (const string& name, unsigned arity)
2273{
f76427a2
FCE
2274 // the common path
2275 if (session.functions.find(name) != session.functions.end())
2b066ec1 2276 {
f76427a2
FCE
2277 functiondecl* fd = session.functions[name];
2278 assert (fd->name == name);
2279 if (fd->formal_args.size() == arity)
2b066ec1 2280 return fd;
e26c2f83
FCE
2281
2282 session.print_warning (_F("mismatched arity-%zu function found", fd->formal_args.size()),
2283 fd->tok);
2284 // and some semantic_error will shortly follow
2b066ec1
FCE
2285 }
2286
e26c2f83 2287 // search library functions
2b066ec1
FCE
2288 for (unsigned i=0; i<session.library_files.size(); i++)
2289 {
2290 stapfile* f = session.library_files[i];
2291 for (unsigned j=0; j<f->functions.size(); j++)
2292 if (f->functions[j]->name == name &&
2293 f->functions[j]->formal_args.size() == arity)
2294 {
2295 // put library into the queue if not already there
2296 if (0) // session.verbose_resolution
4af765b2
LB
2297 cerr << _F(" function %s is defined from %s",
2298 name.c_str(), f->name.c_str()) << endl;
2b066ec1 2299
57148ee7 2300 if (find (session.files.begin(), session.files.end(), f)
2b066ec1
FCE
2301 == session.files.end())
2302 session.files.push_back (f);
2303 // else .. print different message?
2304
2305 return f->functions[j];
2306 }
2307 }
2308
2309 return 0;
2b066ec1
FCE
2310}
2311
2312
cbfbbf69
FCE
2313
2314// ------------------------------------------------------------------------
2315// optimization
2316
2317
2318// Do away with functiondecls that are never (transitively) called
2319// from probes.
2320void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
2321{
2322 functioncall_traversing_visitor ftv;
2323 for (unsigned i=0; i<s.probes.size(); i++)
5d23847d
FCE
2324 {
2325 s.probes[i]->body->visit (& ftv);
2326 if (s.probes[i]->sole_location()->condition)
2327 s.probes[i]->sole_location()->condition->visit (& ftv);
2328 }
f76427a2
FCE
2329 vector<functiondecl*> new_unused_functions;
2330 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
cbfbbf69 2331 {
f76427a2
FCE
2332 functiondecl* fd = it->second;
2333 if (ftv.traversed.find(fd) == ftv.traversed.end())
cbfbbf69 2334 {
bad814e8 2335 if (fd->tok->location.file->name == s.user_file->name && ! fd->synthetic)// !tapset
4af765b2 2336 s.print_warning (_F("Eliding unused function '%s'", fd->name.c_str()), fd->tok);
f76427a2
FCE
2337 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
2338 new_unused_functions.push_back (fd);
cbfbbf69 2339 relaxed_p = false;
cbfbbf69 2340 }
f76427a2
FCE
2341 }
2342 for (unsigned i=0; i<new_unused_functions.size(); i++)
2343 {
2344 map<string,functiondecl*>::iterator where = s.functions.find (new_unused_functions[i]->name);
2345 assert (where != s.functions.end());
2346 s.functions.erase (where);
2347 if (s.tapset_compile_coverage)
2348 s.unused_functions.push_back (new_unused_functions[i]);
cbfbbf69
FCE
2349 }
2350}
2351
2352
2353// ------------------------------------------------------------------------
2354
2355// Do away with local & global variables that are never
2356// written nor read.
cfd621bc 2357void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations)
cbfbbf69 2358{
313db8e6 2359 varuse_collecting_visitor vut(s);
cfd621bc 2360
cbfbbf69 2361 for (unsigned i=0; i<s.probes.size(); i++)
5d23847d
FCE
2362 {
2363 s.probes[i]->body->visit (& vut);
2364
2365 if (s.probes[i]->sole_location()->condition)
2366 s.probes[i]->sole_location()->condition->visit (& vut);
2367 }
2368
cbfbbf69
FCE
2369 // NB: Since varuse_collecting_visitor also traverses down
2370 // actually called functions, we don't need to explicitly
2371 // iterate over them. Uncalled ones should have been pruned
2372 // in _opt1 above.
2373 //
2374 // for (unsigned i=0; i<s.functions.size(); i++)
2375 // s.functions[i]->body->visit (& vut);
57148ee7 2376
cbfbbf69 2377 // Now in vut.read/written, we have a mixture of all locals, globals
57148ee7
FCE
2378
2379 for (unsigned i=0; i<s.probes.size(); i++)
cbfbbf69
FCE
2380 for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
2381 {
2382 vardecl* l = s.probes[i]->locals[j];
a9e8f7e0 2383
a45664f4 2384 // skip over "special" locals
69aa668e 2385 if (l->synthetic) { j++; continue; }
a45664f4 2386
cbfbbf69
FCE
2387 if (vut.read.find (l) == vut.read.end() &&
2388 vut.written.find (l) == vut.written.end())
2389 {
bad814e8 2390 if (l->tok->location.file->name == s.user_file->name) // !tapset
4af765b2 2391 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
c3a3c0c9
WC
2392 if (s.tapset_compile_coverage) {
2393 s.probes[i]->unused_locals.push_back
2394 (s.probes[i]->locals[j]);
2395 }
cbfbbf69
FCE
2396 s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
2397 relaxed_p = false;
2398 // don't increment j
2399 }
2400 else
27d24ae2
FCE
2401 {
2402 if (vut.written.find (l) == vut.written.end())
cfd621bc 2403 if (iterations == 0 && ! s.suppress_warnings)
6643650d
SC
2404 {
2405 stringstream o;
2406 vector<vardecl*>::iterator it;
cfd621bc
FCE
2407 for (it = s.probes[i]->locals.begin(); it != s.probes[i]->locals.end(); it++)
2408 if (l->name != (*it)->name)
2409 o << " " << (*it)->name;
2410 for (it = s.globals.begin(); it != s.globals.end(); it++)
2411 if (l->name != (*it)->name)
2412 o << " " << (*it)->name;
2413
4af765b2
LB
2414 s.print_warning (_F("never-assigned local variable '%s' %s",
2415 l->name.c_str(), (o.str() == "" ? "" :
2416 (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
6643650d 2417 }
27d24ae2
FCE
2418 j++;
2419 }
cbfbbf69 2420 }
57148ee7 2421
f76427a2
FCE
2422 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2423 {
2424 functiondecl *fd = it->second;
2425 for (unsigned j=0; j<fd->locals.size(); /* see below */)
2426 {
2427 vardecl* l = fd->locals[j];
2428 if (vut.read.find (l) == vut.read.end() &&
2429 vut.written.find (l) == vut.written.end())
2430 {
bad814e8 2431 if (l->tok->location.file->name == s.user_file->name) // !tapset
4af765b2 2432 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
f76427a2
FCE
2433 if (s.tapset_compile_coverage) {
2434 fd->unused_locals.push_back (fd->locals[j]);
2435 }
2436 fd->locals.erase(fd->locals.begin() + j);
2437 relaxed_p = false;
2438 // don't increment j
2439 }
2440 else
2441 {
2442 if (vut.written.find (l) == vut.written.end())
2443 if (iterations == 0 && ! s.suppress_warnings)
2444 {
2445 stringstream o;
2446 vector<vardecl*>::iterator it;
2447 for (it = fd->formal_args.begin() ;
2448 it != fd->formal_args.end(); it++)
2449 if (l->name != (*it)->name)
2450 o << " " << (*it)->name;
2451 for (it = fd->locals.begin(); it != fd->locals.end(); it++)
2452 if (l->name != (*it)->name)
2453 o << " " << (*it)->name;
2454 for (it = s.globals.begin(); it != s.globals.end(); it++)
2455 if (l->name != (*it)->name)
2456 o << " " << (*it)->name;
2457
4af765b2
LB
2458 s.print_warning (_F("never-assigned local variable '%s' %s",
2459 l->name.c_str(), (o.str() == "" ? "" :
2460 (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
f76427a2 2461 }
cfd621bc 2462
f76427a2
FCE
2463 j++;
2464 }
2465 }
2466 }
cbfbbf69
FCE
2467 for (unsigned i=0; i<s.globals.size(); /* see below */)
2468 {
2469 vardecl* l = s.globals[i];
2470 if (vut.read.find (l) == vut.read.end() &&
2471 vut.written.find (l) == vut.written.end())
2472 {
bad814e8 2473 if (l->tok->location.file->name == s.user_file->name) // !tapset
4af765b2 2474 s.print_warning (_F("Eliding unused variable '%s'", l->name.c_str()), l->tok);
c3a3c0c9 2475 if (s.tapset_compile_coverage) {
0a102c82 2476 s.unused_globals.push_back(s.globals[i]);
c3a3c0c9 2477 }
0a102c82
SC
2478 s.globals.erase(s.globals.begin() + i);
2479 relaxed_p = false;
2480 // don't increment i
cbfbbf69
FCE
2481 }
2482 else
27d24ae2 2483 {
cfd621bc
FCE
2484 if (vut.written.find (l) == vut.written.end() && ! l->init) // no initializer
2485 if (iterations == 0 && ! s.suppress_warnings)
2486 {
2487 stringstream o;
2488 vector<vardecl*>::iterator it;
2489 for (it = s.globals.begin(); it != s.globals.end(); it++)
2490 if (l->name != (*it)->name)
2491 o << " " << (*it)->name;
57148ee7 2492
4af765b2
LB
2493 s.print_warning (_F("never assigned global variable '%s' %s", l->name.c_str(),
2494 (o.str() == "" ? "" : (_("(alternatives:") + o.str() + ")")).c_str()), l->tok);
cfd621bc
FCE
2495 }
2496
27d24ae2
FCE
2497 i++;
2498 }
cbfbbf69
FCE
2499 }
2500}
2501
2502
2503// ------------------------------------------------------------------------
2504
8bda6498 2505struct dead_assignment_remover: public update_visitor
cbfbbf69
FCE
2506{
2507 systemtap_session& session;
2508 bool& relaxed_p;
2509 const varuse_collecting_visitor& vut;
cbfbbf69
FCE
2510
2511 dead_assignment_remover(systemtap_session& s, bool& r,
57148ee7 2512 const varuse_collecting_visitor& v):
8bda6498 2513 session(s), relaxed_p(r), vut(v) {}
cbfbbf69
FCE
2514
2515 void visit_assignment (assignment* e);
f4fe2e93 2516 void visit_try_block (try_block *s);
cbfbbf69
FCE
2517};
2518
2519
cbfbbf69
FCE
2520void
2521dead_assignment_remover::visit_assignment (assignment* e)
2522{
8b095b45
JS
2523 replace (e->left);
2524 replace (e->right);
8bda6498 2525
cbfbbf69 2526 symbol* left = get_symbol_within_expression (e->left);
b0be9bdb 2527 vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
8bda6498 2528 if (leftvar) // not unresolved $target, so intended sideeffect may be elided
cbfbbf69 2529 {
cbfbbf69
FCE
2530 if (vut.read.find(leftvar) == vut.read.end()) // var never read?
2531 {
cf9ff341
FCE
2532 // NB: Not so fast! The left side could be an array whose
2533 // index expressions may have side-effects. This would be
57148ee7 2534 // OK if we could replace the array assignment with a
cf9ff341
FCE
2535 // statement-expression containing all the index expressions
2536 // and the rvalue... but we can't.
0a102c82
SC
2537 // Another possibility is that we have an unread global variable
2538 // which are kept for probe end value display.
2539
2540 bool is_global = false;
2541 vector<vardecl*>::iterator it;
2542 for (it = session.globals.begin(); it != session.globals.end(); it++)
2543 if (leftvar->name == (*it)->name)
2544 {
2545 is_global = true;
2546 break;
2547 }
cf9ff341 2548
313db8e6 2549 varuse_collecting_visitor lvut(session);
8bda6498 2550 e->left->visit (& lvut);
df16cbea 2551 if (lvut.side_effect_free () && !is_global // XXX: use _wrt() once we track focal_vars
69aa668e 2552 && !leftvar->synthetic) // don't elide assignment to synthetic $context variables
cf9ff341 2553 {
a9e8f7e0
FCE
2554 /* PR 1119: NB: This is not necessary here. A write-only
2555 variable will also be elided soon at the next _opt2 iteration.
bad814e8
CM
2556 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
2557 session.print_warning("eliding write-only ", *e->left->tok);
a9e8f7e0
FCE
2558 else
2559 */
bad814e8 2560 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
df16cbea 2561 session.print_warning(_F("Eliding assignment to %s at %s", leftvar->name.c_str(), lex_cast(*e->tok).c_str()));
8bda6498 2562 provide (e->right); // goodbye assignment*
cf9ff341 2563 relaxed_p = false;
8bda6498 2564 return;
cf9ff341 2565 }
cbfbbf69
FCE
2566 }
2567 }
8bda6498 2568 provide (e);
e7625481 2569}
cbfbbf69 2570
f4fe2e93
FCE
2571
2572void
2573dead_assignment_remover::visit_try_block (try_block *s)
2574{
2575 replace (s->try_block);
2576 if (s->catch_error_var)
2577 {
2578 vardecl* errvar = s->catch_error_var->referent;
2579 if (vut.read.find(errvar) == vut.read.end()) // never read?
2580 {
2581 if (session.verbose>2)
4af765b2
LB
2582 clog << _F("Eliding unused error string catcher %s at %s",
2583 errvar->name.c_str(), lex_cast(*s->tok).c_str()) << endl;
f4fe2e93
FCE
2584 s->catch_error_var = 0;
2585 }
2586 }
2587 replace (s->catch_block);
2588 provide (s);
2589}
2590
2591
cbfbbf69
FCE
2592// Let's remove assignments to variables that are never read. We
2593// rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2594// be optimized away as an unused variable, and expr a candidate to be
2595// removed as a side-effect-free statement expression. Wahoo!
2596void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
2597{
2598 // Recompute the varuse data, which will probably match the opt2
2599 // copy of the computation, except for those totally unused
2600 // variables that opt2 removed.
313db8e6 2601 varuse_collecting_visitor vut(s);
cbfbbf69
FCE
2602 for (unsigned i=0; i<s.probes.size(); i++)
2603 s.probes[i]->body->visit (& vut); // includes reachable functions too
2604
2605 dead_assignment_remover dar (s, relaxed_p, vut);
2606 // This instance may be reused for multiple probe/function body trims.
2607
2608 for (unsigned i=0; i<s.probes.size(); i++)
8b095b45 2609 dar.replace (s.probes[i]->body);
8bda6498
JS
2610 for (map<string,functiondecl*>::iterator it = s.functions.begin();
2611 it != s.functions.end(); it++)
8b095b45 2612 dar.replace (it->second->body);
cbfbbf69 2613 // The rewrite operation is performed within the visitor.
27d24ae2
FCE
2614
2615 // XXX: we could also zap write-only globals here
cbfbbf69
FCE
2616}
2617
2618
2619// ------------------------------------------------------------------------
2620
1cd151d5 2621struct dead_stmtexpr_remover: public update_visitor
cbfbbf69
FCE
2622{
2623 systemtap_session& session;
2624 bool& relaxed_p;
1b07c728 2625 set<vardecl*> focal_vars; // vars considered subject to side-effects
cbfbbf69 2626
57148ee7 2627 dead_stmtexpr_remover(systemtap_session& s, bool& r):
1cd151d5 2628 session(s), relaxed_p(r) {}
cbfbbf69
FCE
2629
2630 void visit_block (block *s);
f4fe2e93 2631 void visit_try_block (try_block *s);
ba6f838d 2632 void visit_null_statement (null_statement *s);
739a3e81
FCE
2633 void visit_if_statement (if_statement* s);
2634 void visit_foreach_loop (foreach_loop *s);
2635 void visit_for_loop (for_loop *s);
cbfbbf69
FCE
2636 // XXX: and other places where stmt_expr's might be nested
2637
2638 void visit_expr_statement (expr_statement *s);
2639};
2640
2641
ba6f838d
FCE
2642void
2643dead_stmtexpr_remover::visit_null_statement (null_statement *s)
2644{
2645 // easy!
2646 if (session.verbose>2)
4af765b2 2647 clog << _("Eliding side-effect-free null statement ") << *s->tok << endl;
1cd151d5
JS
2648 s = 0;
2649 provide (s);
ba6f838d
FCE
2650}
2651
2652
cbfbbf69
FCE
2653void
2654dead_stmtexpr_remover::visit_block (block *s)
2655{
ba6f838d
FCE
2656 vector<statement*> new_stmts;
2657 for (unsigned i=0; i<s->statements.size(); i++ )
cbfbbf69 2658 {
1cd151d5
JS
2659 statement* new_stmt = require (s->statements[i], true);
2660 if (new_stmt != 0)
bea72737
JS
2661 {
2662 // flatten nested blocks into this one
1cd151d5 2663 block *b = dynamic_cast<block *>(new_stmt);
bea72737
JS
2664 if (b)
2665 {
2666 if (session.verbose>2)
4af765b2 2667 clog << _("Flattening nested block ") << *b->tok << endl;
bea72737
JS
2668 new_stmts.insert(new_stmts.end(),
2669 b->statements.begin(), b->statements.end());
2670 relaxed_p = false;
2671 }
2672 else
1cd151d5 2673 new_stmts.push_back (new_stmt);
bea72737 2674 }
cbfbbf69 2675 }
ba6f838d
FCE
2676 if (new_stmts.size() == 0)
2677 {
2678 if (session.verbose>2)
4af765b2 2679 clog << _("Eliding side-effect-free empty block ") << *s->tok << endl;
1cd151d5 2680 s = 0;
ba6f838d
FCE
2681 }
2682 else if (new_stmts.size() == 1)
2683 {
2684 if (session.verbose>2)
4af765b2 2685 clog << _("Eliding side-effect-free singleton block ") << *s->tok << endl;
1cd151d5
JS
2686 provide (new_stmts[0]);
2687 return;
ba6f838d
FCE
2688 }
2689 else
1cd151d5
JS
2690 s->statements = new_stmts;
2691 provide (s);
cbfbbf69
FCE
2692}
2693
f4fe2e93
FCE
2694
2695void
2696dead_stmtexpr_remover::visit_try_block (try_block *s)
2697{
2698 replace (s->try_block, true);
2699 replace (s->catch_block, true); // null catch{} is ok and useful
2700 if (s->try_block == 0)
2701 {
2702 if (session.verbose>2)
4af765b2 2703 clog << _("Eliding empty try {} block ") << *s->tok << endl;
f4fe2e93
FCE
2704 s = 0;
2705 }
2706 provide (s);
2707}
2708
2709
739a3e81
FCE
2710void
2711dead_stmtexpr_remover::visit_if_statement (if_statement *s)
2712{
8b095b45
JS
2713 replace (s->thenblock, true);
2714 replace (s->elseblock, true);
ba6f838d 2715
bea72737 2716 if (s->thenblock == 0)
ba6f838d 2717 {
bea72737
JS
2718 if (s->elseblock == 0)
2719 {
2720 // We may be able to elide this statement, if the condition
2721 // expression is side-effect-free.
313db8e6 2722 varuse_collecting_visitor vct(session);
bea72737
JS
2723 s->condition->visit(& vct);
2724 if (vct.side_effect_free ())
2725 {
2726 if (session.verbose>2)
4af765b2 2727 clog << _("Eliding side-effect-free if statement ")
bea72737 2728 << *s->tok << endl;
1cd151d5 2729 s = 0; // yeah, baby
bea72737
JS
2730 }
2731 else
2732 {
2733 // We can still turn it into a simple expr_statement though...
2734 if (session.verbose>2)
4af765b2 2735 clog << _("Creating simple evaluation from if statement ")
bea72737
JS
2736 << *s->tok << endl;
2737 expr_statement *es = new expr_statement;
2738 es->value = s->condition;
2739 es->tok = es->value->tok;
1cd151d5
JS
2740 provide (es);
2741 return;
bea72737
JS
2742 }
2743 }
2744 else
ba6f838d 2745 {
bea72737
JS
2746 // For an else without a then, we can invert the condition logic to
2747 // avoid having a null statement in the thenblock
ba6f838d 2748 if (session.verbose>2)
4af765b2 2749 clog << _("Inverting the condition of if statement ")
bea72737
JS
2750 << *s->tok << endl;
2751 unary_expression *ue = new unary_expression;
2752 ue->operand = s->condition;
2753 ue->tok = ue->operand->tok;
2754 ue->op = "!";
2755 s->condition = ue;
2756 s->thenblock = s->elseblock;
2757 s->elseblock = 0;
ba6f838d
FCE
2758 }
2759 }
1cd151d5 2760 provide (s);
739a3e81
FCE
2761}
2762
2763void
2764dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
2765{
8b095b45 2766 replace (s->block, true);
ba6f838d
FCE
2767
2768 if (s->block == 0)
2769 {
10328bcf 2770 // XXX what if s->limit has side effects?
c261711d 2771 // XXX what about s->indexes or s->value used outside the loop?
bad814e8 2772 if(session.verbose > 2)
4af765b2 2773 clog << _("Eliding side-effect-free foreach statement ") << *s->tok << endl;
1cd151d5 2774 s = 0; // yeah, baby
ba6f838d 2775 }
1cd151d5 2776 provide (s);
739a3e81
FCE
2777}
2778
2779void
2780dead_stmtexpr_remover::visit_for_loop (for_loop *s)
2781{
8b095b45 2782 replace (s->block, true);
ba6f838d
FCE
2783
2784 if (s->block == 0)
2785 {
2786 // We may be able to elide this statement, if the condition
2787 // expression is side-effect-free.
313db8e6 2788 varuse_collecting_visitor vct(session);
ba6f838d
FCE
2789 if (s->init) s->init->visit(& vct);
2790 s->cond->visit(& vct);
2791 if (s->incr) s->incr->visit(& vct);
2792 if (vct.side_effect_free ())
2793 {
2794 if (session.verbose>2)
4af765b2 2795 clog << _("Eliding side-effect-free for statement ") << *s->tok << endl;
1cd151d5
JS
2796 s = 0; // yeah, baby
2797 }
2798 else
2799 {
2800 // Can't elide this whole statement; put a null in there.
f946b10f 2801 s->block = new null_statement(s->tok);
ba6f838d 2802 }
ba6f838d 2803 }
1cd151d5 2804 provide (s);
739a3e81
FCE
2805}
2806
2807
cbfbbf69
FCE
2808
2809void
2810dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
2811{
2812 // Run a varuse query against the operand expression. If it has no
2813 // side-effects, replace the entire statement expression by a null
1cd151d5 2814 // statement with the provide() call.
cbfbbf69
FCE
2815 //
2816 // Unlike many other visitors, we do *not* traverse this outermost
2817 // one into the expression subtrees. There is no need - no
2818 // expr_statement nodes will be found there. (Function bodies
2819 // need to be visited explicitly by our caller.)
2820 //
2821 // NB. While we don't share nodes in the parse tree, let's not
2822 // deallocate *s anyway, just in case...
2823
313db8e6 2824 varuse_collecting_visitor vut(session);
cbfbbf69 2825 s->value->visit (& vut);
57148ee7 2826
1cd151d5 2827 if (vut.side_effect_free_wrt (focal_vars))
cbfbbf69 2828 {
a9e8f7e0
FCE
2829 /* PR 1119: NB: this message is not a good idea here. It can
2830 name some arbitrary RHS expression of an assignment.
bad814e8
CM
2831 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
2832 session.print_warning("eliding never-assigned ", *s->value->tok);
57148ee7 2833 else
a9e8f7e0 2834 */
bad814e8
CM
2835 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
2836 session.print_warning("Eliding side-effect-free expression ", s->tok);
cbfbbf69 2837
ba6f838d
FCE
2838 // NB: this 0 pointer is invalid to leave around for any length of
2839 // time, but the parent parse tree objects above handle it.
1cd151d5 2840 s = 0;
cbfbbf69
FCE
2841 relaxed_p = false;
2842 }
1cd151d5 2843 provide (s);
cbfbbf69
FCE
2844}
2845
2846
2847void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
2848{
2849 // Finally, let's remove some statement-expressions that have no
2850 // side-effect. These should be exactly those whose private varuse
2851 // visitors come back with an empty "written" and "embedded" lists.
57148ee7 2852
cbfbbf69
FCE
2853 dead_stmtexpr_remover duv (s, relaxed_p);
2854 // This instance may be reused for multiple probe/function body trims.
2855
2856 for (unsigned i=0; i<s.probes.size(); i++)
1b07c728 2857 {
e19ebcf7 2858 assert_no_interrupts();
f76427a2 2859
ba6f838d
FCE
2860 derived_probe* p = s.probes[i];
2861
1b07c728
FCE
2862 duv.focal_vars.clear ();
2863 duv.focal_vars.insert (s.globals.begin(),
2864 s.globals.end());
ba6f838d
FCE
2865 duv.focal_vars.insert (p->locals.begin(),
2866 p->locals.end());
2867
8b095b45 2868 duv.replace (p->body, true);
ba6f838d
FCE
2869 if (p->body == 0)
2870 {
bad814e8 2871 if (! s.timing) // PR10070
4af765b2 2872 s.print_warning (_F("side-effect-free probe '%s'", p->name.c_str()), p->tok);
ba6f838d 2873
f946b10f 2874 p->body = new null_statement(p->tok);
27d24ae2
FCE
2875
2876 // XXX: possible duplicate warnings; see below
ba6f838d 2877 }
1b07c728 2878 }
f76427a2 2879 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
1b07c728 2880 {
e19ebcf7 2881 assert_no_interrupts();
f76427a2
FCE
2882
2883 functiondecl* fn = it->second;
1b07c728 2884 duv.focal_vars.clear ();
ba6f838d
FCE
2885 duv.focal_vars.insert (fn->locals.begin(),
2886 fn->locals.end());
2887 duv.focal_vars.insert (fn->formal_args.begin(),
2888 fn->formal_args.end());
1b07c728
FCE
2889 duv.focal_vars.insert (s.globals.begin(),
2890 s.globals.end());
ba6f838d 2891
8b095b45 2892 duv.replace (fn->body, true);
ba6f838d
FCE
2893 if (fn->body == 0)
2894 {
bad814e8 2895 s.print_warning (_F("side-effect-free function '%s'", fn->name.c_str()), fn->tok);
ba6f838d 2896
f946b10f 2897 fn->body = new null_statement(fn->tok);
27d24ae2
FCE
2898
2899 // XXX: the next iteration of the outer optimization loop may
2900 // take this new null_statement away again, and thus give us a
2901 // fresh warning. It would be better if this fixup was performed
2902 // only after the relaxation iterations.
2903 // XXX: or else see bug #6469.
ba6f838d 2904 }
1b07c728 2905 }
cbfbbf69
FCE
2906}
2907
bea72737
JS
2908
2909// ------------------------------------------------------------------------
2910
2911// The goal of this visitor is to reduce top-level expressions in void context
2912// into separate statements that evaluate each subcomponent of the expression.
2913// The dead-statement-remover can later remove some parts if they have no side
2914// effects.
9f9873df
JS
2915//
2916// All expressions must be overridden here so we never visit their subexpressions
2917// accidentally. Thus, the only visited expressions should be value of an
2918// expr_statement.
2919//
2920// For an expression to replace its expr_statement with something else, it will
2921// let the new statement provide(), and then provide(0) for itself. The
2922// expr_statement will take this as a sign that it's been replaced.
2923struct void_statement_reducer: public update_visitor
bea72737
JS
2924{
2925 systemtap_session& session;
2926 bool& relaxed_p;
bea72737
JS
2927 set<vardecl*> focal_vars; // vars considered subject to side-effects
2928
2929 void_statement_reducer(systemtap_session& s, bool& r):
9f9873df 2930 session(s), relaxed_p(r) {}
bea72737 2931
133c7b1d 2932 void visit_expr_statement (expr_statement* s);
9f9873df
JS
2933
2934 // expressions in conditional / loop controls are definitely a side effect,
2935 // but still recurse into the child statements
bea72737
JS
2936 void visit_if_statement (if_statement* s);
2937 void visit_for_loop (for_loop* s);
2938 void visit_foreach_loop (foreach_loop* s);
2939
2940 // these expressions get rewritten into their statement equivalents
2941 void visit_logical_or_expr (logical_or_expr* e);
2942 void visit_logical_and_expr (logical_and_expr* e);
2943 void visit_ternary_expression (ternary_expression* e);
2944
93daaca8 2945 // all of these can (usually) be reduced into simpler statements
bea72737
JS
2946 void visit_binary_expression (binary_expression* e);
2947 void visit_unary_expression (unary_expression* e);
93daaca8 2948 void visit_regex_query (regex_query* e); // TODOXXX may or may not be reducible
bea72737
JS
2949 void visit_comparison (comparison* e);
2950 void visit_concatenation (concatenation* e);
2951 void visit_functioncall (functioncall* e);
2952 void visit_print_format (print_format* e);
6fda2dff 2953 void visit_target_symbol (target_symbol* e);
9b5af295 2954 void visit_cast_op (cast_op* e);
30263a73 2955 void visit_defined_op (defined_op* e);
bea72737
JS
2956
2957 // these are a bit hairy to grok due to the intricacies of indexables and
2958 // stats, so I'm chickening out and skipping them...
9f9873df
JS
2959 void visit_array_in (array_in* e) { provide (e); }
2960 void visit_arrayindex (arrayindex* e) { provide (e); }
2961 void visit_stat_op (stat_op* e) { provide (e); }
2962 void visit_hist_op (hist_op* e) { provide (e); }
bea72737
JS
2963
2964 // these can't be reduced because they always have an effect
9f9873df
JS
2965 void visit_return_statement (return_statement* s) { provide (s); }
2966 void visit_delete_statement (delete_statement* s) { provide (s); }
2967 void visit_pre_crement (pre_crement* e) { provide (e); }
2968 void visit_post_crement (post_crement* e) { provide (e); }
2969 void visit_assignment (assignment* e) { provide (e); }
bea72737
JS
2970};
2971
2972
133c7b1d
JS
2973void
2974void_statement_reducer::visit_expr_statement (expr_statement* s)
2975{
8b095b45 2976 replace (s->value, true);
133c7b1d 2977
9f9873df
JS
2978 // if the expression provides 0, that's our signal that a new
2979 // statement has been provided, so we shouldn't provide this one.
2980 if (s->value != 0)
2981 provide(s);
bea72737
JS
2982}
2983
2984void
2985void_statement_reducer::visit_if_statement (if_statement* s)
2986{
9f9873df 2987 // s->condition is never void
8b095b45
JS
2988 replace (s->thenblock);
2989 replace (s->elseblock);
9f9873df 2990 provide (s);
bea72737
JS
2991}
2992
2993void
2994void_statement_reducer::visit_for_loop (for_loop* s)
2995{
9f9873df 2996 // s->init/cond/incr are never void
8b095b45 2997 replace (s->block);
9f9873df 2998 provide (s);
bea72737
JS
2999}
3000
3001void
3002void_statement_reducer::visit_foreach_loop (foreach_loop* s)
3003{
c261711d 3004 // s->indexes/base/value/limit are never void
8b095b45 3005 replace (s->block);
9f9873df 3006 provide (s);
bea72737
JS
3007}
3008
3009void
3010void_statement_reducer::visit_logical_or_expr (logical_or_expr* e)
3011{
3012 // In void context, the evaluation of "a || b" is exactly like
3013 // "if (!a) b", so let's do that instead.
3014
bea72737 3015 if (session.verbose>2)
4af765b2 3016 clog << _("Creating if statement from unused logical-or ")
bea72737
JS
3017 << *e->tok << endl;
3018
3019 if_statement *is = new if_statement;
3020 is->tok = e->tok;
3021 is->elseblock = 0;
bea72737
JS
3022
3023 unary_expression *ue = new unary_expression;
3024 ue->operand = e->left;
3025 ue->tok = e->tok;
3026 ue->op = "!";
3027 is->condition = ue;
3028
133c7b1d 3029 expr_statement *es = new expr_statement;
bea72737
JS
3030 es->value = e->right;
3031 es->tok = es->value->tok;
3032 is->thenblock = es;
3033
3034 is->visit(this);
3035 relaxed_p = false;
9f9873df
JS
3036 e = 0;
3037 provide (e);
bea72737
JS
3038}
3039
3040void
3041void_statement_reducer::visit_logical_and_expr (logical_and_expr* e)
3042{
3043 // In void context, the evaluation of "a && b" is exactly like
3044 // "if (a) b", so let's do that instead.
3045
bea72737 3046 if (session.verbose>2)
4af765b2 3047 clog << _("Creating if statement from unused logical-and ")
bea72737
JS
3048 << *e->tok << endl;
3049
3050 if_statement *is = new if_statement;
3051 is->tok = e->tok;
3052 is->elseblock = 0;
3053 is->condition = e->left;
bea72737 3054
133c7b1d 3055 expr_statement *es = new expr_statement;
bea72737
JS
3056 es->value = e->right;
3057 es->tok = es->value->tok;
3058 is->thenblock = es;
3059
3060 is->visit(this);
3061 relaxed_p = false;
9f9873df
JS
3062 e = 0;
3063 provide (e);
bea72737
JS
3064}
3065
3066void
3067void_statement_reducer::visit_ternary_expression (ternary_expression* e)
3068{
3069 // In void context, the evaluation of "a ? b : c" is exactly like
3070 // "if (a) b else c", so let's do that instead.
3071
bea72737 3072 if (session.verbose>2)
4af765b2 3073 clog << _("Creating if statement from unused ternary expression ")
bea72737
JS
3074 << *e->tok << endl;
3075
3076 if_statement *is = new if_statement;
3077 is->tok = e->tok;
3078 is->condition = e->cond;
bea72737 3079
133c7b1d 3080 expr_statement *es = new expr_statement;
bea72737
JS
3081 es->value = e->truevalue;
3082 es->tok = es->value->tok;
3083 is->thenblock = es;
3084
3085 es = new expr_statement;
3086 es->value = e->falsevalue;
3087 es->tok = es->value->tok;
3088 is->elseblock = es;
3089
3090 is->visit(this);
3091 relaxed_p = false;
9f9873df
JS
3092 e = 0;
3093 provide (e);
bea72737
JS
3094}
3095
3096void
3097void_statement_reducer::visit_binary_expression (binary_expression* e)
3098{
3099 // When the result of a binary operation isn't needed, it's just as good to
3100 // evaluate the operands as sequential statements in a block.
3101
bea72737 3102 if (session.verbose>2)
4af765b2 3103 clog << _("Eliding unused binary ") << *e->tok << endl;
bea72737
JS
3104
3105 block *b = new block;
9f9873df 3106 b->tok = e->tok;
bea72737 3107
133c7b1d 3108 expr_statement *es = new expr_statement;
bea72737
JS
3109 es->value = e->left;
3110 es->tok = es->value->tok;
3111 b->statements.push_back(es);
3112
3113 es = new expr_statement;
3114 es->value = e->right;
3115 es->tok = es->value->tok;
3116 b->statements.push_back(es);
3117
3118 b->visit(this);
3119 relaxed_p = false;
9f9873df
JS
3120 e = 0;
3121 provide (e);
bea72737
JS
3122}
3123
3124void
3125void_statement_reducer::visit_unary_expression (unary_expression* e)
3126{
3127 // When the result of a unary operation isn't needed, it's just as good to
3128 // evaluate the operand directly
3129
bea72737 3130 if (session.verbose>2)
4af765b2 3131 clog << _("Eliding unused unary ") << *e->tok << endl;
bea72737 3132
bea72737 3133 relaxed_p = false;
9f9873df 3134 e->operand->visit(this);
bea72737
JS
3135}
3136
93daaca8
SM
3137void
3138void_statement_reducer::visit_regex_query (regex_query* e)
3139{
3140 // Whether we need to run a regex query depends on whether
3141 // subexpression extraction is enabled, as in:
3142 //
3143 // str =~ "pat";
3144 // println(matched(0)); // NOTE: not totally nice -- are we SURE it matched?
3145 // TODOXXX it's debatable whether we should allow this, though
3146
3147 // TODOXXX since subexpression extraction is not yet implemented,
3148 // just treat it as a unary expression wrt the left operand -- since
3149 // the right hand side must be a literal (verified by the parses),
3150 // evaluating it never has side effects.
3151
3152 if (session.verbose>2)
3153 clog << _("Eliding regex query ") << *e->tok << endl;
3154
3155 relaxed_p = false;
3156 e->left->visit(this);
3157}
3158
bea72737
JS
3159void
3160void_statement_reducer::visit_comparison (comparison* e)
3161{
3162 visit_binary_expression(e);
3163}
3164
3165void
3166void_statement_reducer::visit_concatenation (concatenation* e)
3167{
3168 visit_binary_expression(e);
3169}
3170
3171void
3172void_statement_reducer::visit_functioncall (functioncall* e)
3173{
3174 // If a function call is pure and its result ignored, we can elide the call
c7d47935 3175 // and just evaluate the arguments in sequence
bea72737
JS
3176
3177 if (!e->args.size())
9f9873df
JS
3178 {
3179 provide (e);
3180 return;
3181 }
bea72737 3182
313db8e6 3183 varuse_collecting_visitor vut(session);
bea72737
JS
3184 vut.traversed.insert (e->referent);
3185 vut.current_function = e->referent;
3186 e->referent->body->visit (& vut);
3187 if (!vut.side_effect_free_wrt (focal_vars))
9f9873df
JS
3188 {
3189 provide (e);
3190 return;
3191 }
bea72737
JS
3192
3193 if (session.verbose>2)
4af765b2 3194 clog << _("Eliding side-effect-free function call ") << *e->tok << endl;
bea72737 3195
133c7b1d
JS
3196 block *b = new block;
3197 b->tok = e->tok;
bea72737 3198
133c7b1d 3199 for (unsigned i=0; i<e->args.size(); i++ )
bea72737 3200 {
133c7b1d
JS
3201 expr_statement *es = new expr_statement;
3202 es->value = e->args[i];
3203 es->tok = es->value->tok;
bea72737 3204 b->statements.push_back(es);
bea72737
JS
3205 }
3206
133c7b1d 3207 b->visit(this);
bea72737 3208 relaxed_p = false;
9f9873df
JS
3209 e = 0;
3210 provide (e);
bea72737
JS
3211}
3212
3213void
3214void_statement_reducer::visit_print_format (print_format* e)
3215{
3216 // When an sprint's return value is ignored, we can simply evaluate the
3217 // arguments in sequence
3218
3219 if (e->print_to_stream || !e->args.size())
9f9873df
JS
3220 {
3221 provide (e);
3222 return;
3223 }
bea72737
JS
3224
3225 if (session.verbose>2)
4af765b2 3226 clog << _("Eliding unused print ") << *e->tok << endl;
bea72737 3227
133c7b1d
JS
3228 block *b = new block;
3229 b->tok = e->tok;
bea72737 3230
133c7b1d 3231 for (unsigned i=0; i<e->args.size(); i++ )
bea72737 3232 {
133c7b1d
JS
3233 expr_statement *es = new expr_statement;
3234 es->value = e->args[i];
3235 es->tok = es->value->tok;
bea72737 3236 b->statements.push_back(es);
bea72737
JS
3237 }
3238
133c7b1d 3239 b->visit(this);
bea72737 3240 relaxed_p = false;
9f9873df
JS
3241 e = 0;
3242 provide (e);
bea72737
JS
3243}
3244
6fda2dff
JS
3245void
3246void_statement_reducer::visit_target_symbol (target_symbol* e)
3247{
3248 // When target_symbol isn't needed, it's just as good to
3249 // evaluate any array indexes directly
3250
3251 block *b = new block;
3252 b->tok = e->tok;
3253
3254 for (unsigned i=0; i<e->components.size(); i++ )
3255 {
3256 if (e->components[i].type != target_symbol::comp_expression_array_index)
3257 continue;
3258
3259 expr_statement *es = new expr_statement;
3260 es->value = e->components[i].expr_index;
3261 es->tok = es->value->tok;
3262 b->statements.push_back(es);
3263 }
3264
3265 if (b->statements.empty())
3266 {
3267 delete b;
3268 provide (e);
3269 return;
3270 }
3271
3272 if (session.verbose>2)
4af765b2 3273 clog << _("Eliding unused target symbol ") << *e->tok << endl;
6fda2dff
JS
3274
3275 b->visit(this);
3276 relaxed_p = false;
3277 e = 0;
3278 provide (e);
3279}
3280
9b5af295
JS
3281void
3282void_statement_reducer::visit_cast_op (cast_op* e)
3283{
3284 // When the result of a cast operation isn't needed, it's just as good to
6fda2dff
JS
3285 // evaluate the operand and any array indexes directly
3286
3287 block *b = new block;
3288 b->tok = e->tok;
3289
3290 expr_statement *es = new expr_statement;
3291 es->value = e->operand;
3292 es->tok = es->value->tok;
3293 b->statements.push_back(es);
3294
3295 for (unsigned i=0; i<e->components.size(); i++ )
3296 {
3297 if (e->components[i].type != target_symbol::comp_expression_array_index)
3298 continue;
3299
3300 es = new expr_statement;
3301 es->value = e->components[i].expr_index;
3302 es->tok = es->value->tok;
3303 b->statements.push_back(es);
3304 }
9b5af295
JS
3305
3306 if (session.verbose>2)
4af765b2 3307 clog << _("Eliding unused typecast ") << *e->tok << endl;
9b5af295 3308
6fda2dff 3309 b->visit(this);
9b5af295 3310 relaxed_p = false;
6fda2dff
JS
3311 e = 0;
3312 provide (e);
9b5af295
JS
3313}
3314
bea72737 3315
30263a73
FCE
3316void
3317void_statement_reducer::visit_defined_op (defined_op* e)
3318{
3319 // When the result of a @defined operation isn't needed, just elide
3320 // it entirely. Its operand $expression must already be
3321 // side-effect-free.
3322
3323 if (session.verbose>2)
4af765b2 3324 clog << _("Eliding unused check ") << *e->tok << endl;
30263a73
FCE
3325
3326 relaxed_p = false;
3327 e = 0;
3328 provide (e);
3329}
3330
3331
3332
bea72737
JS
3333void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
3334{
3335 // Let's simplify statements with unused computed values.
3336
3337 void_statement_reducer vuv (s, relaxed_p);
3338 // This instance may be reused for multiple probe/function body trims.
3339
3340 vuv.focal_vars.insert (s.globals.begin(), s.globals.end());
3341
3342 for (unsigned i=0; i<s.probes.size(); i++)
8b095b45 3343 vuv.replace (s.probes[i]->body);
9f9873df
JS
3344 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3345 it != s.functions.end(); it++)
8b095b45 3346 vuv.replace (it->second->body);
bea72737
JS
3347}
3348
3349
10328bcf
JS
3350struct const_folder: public update_visitor
3351{
3352 systemtap_session& session;
3353 bool& relaxed_p;
3354
3355 const_folder(systemtap_session& s, bool& r):
3356 session(s), relaxed_p(r), last_number(0), last_string(0) {}
3357
3358 literal_number* last_number;
3359 literal_number* get_number(expression*& e);
3360 void visit_literal_number (literal_number* e);
3361
3362 literal_string* last_string;
3363 literal_string* get_string(expression*& e);
3364 void visit_literal_string (literal_string* e);
3365
f4869658
JS
3366 void get_literal(expression*& e, literal_number*& n, literal_string*& s);
3367
10328bcf
JS
3368 void visit_if_statement (if_statement* s);
3369 void visit_for_loop (for_loop* s);
3370 void visit_foreach_loop (foreach_loop* s);
3371 void visit_binary_expression (binary_expression* e);
3372 void visit_unary_expression (unary_expression* e);
3373 void visit_logical_or_expr (logical_or_expr* e);
3374 void visit_logical_and_expr (logical_and_expr* e);
93daaca8 3375 // TODOXXX visit_regex_query could be done if we could run dfa at compiletime
10328bcf
JS
3376 void visit_comparison (comparison* e);
3377 void visit_concatenation (concatenation* e);
3378 void visit_ternary_expression (ternary_expression* e);
b7aedf26 3379 void visit_defined_op (defined_op* e);
9fab2262 3380 void visit_target_symbol (target_symbol* e);
10328bcf
JS
3381};
3382
f4869658
JS
3383void
3384const_folder::get_literal(expression*& e,
3385 literal_number*& n,
3386 literal_string*& s)
3387{
3388 replace (e);
3389 n = (e == last_number) ? last_number : NULL;
3390 s = (e == last_string) ? last_string : NULL;
3391}
3392
10328bcf
JS
3393literal_number*
3394const_folder::get_number(expression*& e)
3395{
3396 replace (e);
3397 return (e == last_number) ? last_number : NULL;
3398}
3399
3400void
3401const_folder::visit_literal_number (literal_number* e)
3402{
3403 last_number = e;
3404 provide (e);
3405}
3406
3407literal_string*
3408const_folder::get_string(expression*& e)
3409{
3410 replace (e);
3411 return (e == last_string) ? last_string : NULL;
3412}
3413
3414void
3415const_folder::visit_literal_string (literal_string* e)
3416{
3417 last_string = e;
3418 provide (e);
3419}
3420
3421void
3422const_folder::visit_if_statement (if_statement* s)
3423{
3424 literal_number* cond = get_number (s->condition);
3425 if (!cond)
3426 {
3427 replace (s->thenblock);
3428 replace (s->elseblock);
3429 provide (s);
3430 }
3431 else
3432 {
3433 if (session.verbose>2)
4af765b2
LB
3434 clog << _F("Collapsing constant-%" PRIi64 " if-statement %s",
3435 cond->value, lex_cast(*s->tok).c_str()) << endl;
10328bcf
JS
3436 relaxed_p = false;
3437
3438 statement* n = cond->value ? s->thenblock : s->elseblock;
3439 if (n)
3440 n->visit (this);
3441 else
3442 provide (new null_statement (s->tok));
3443 }
3444}
3445
3446void
3447const_folder::visit_for_loop (for_loop* s)
3448{
3449 literal_number* cond = get_number (s->cond);
3450 if (!cond || cond->value)
3451 {
3452 replace (s->init);
3453 replace (s->incr);
3454 replace (s->block);
3455 provide (s);
3456 }
3457 else
3458 {
3459 if (session.verbose>2)
4af765b2 3460 clog << _("Collapsing constantly-false for-loop ") << *s->tok << endl;
10328bcf
JS
3461 relaxed_p = false;
3462
3463 if (s->init)
3464 s->init->visit (this);
3465 else
3466 provide (new null_statement (s->tok));
3467 }
3468}
3469
3470void
3471const_folder::visit_foreach_loop (foreach_loop* s)
3472{
3473 literal_number* limit = get_number (s->limit);
3474 if (!limit || limit->value > 0)
3475 {
3476 for (unsigned i = 0; i < s->indexes.size(); ++i)
3477 replace (s->indexes[i]);
3478 replace (s->base);
c261711d 3479 replace (s->value);
10328bcf
JS
3480 replace (s->block);
3481 provide (s);
3482 }
3483 else
3484 {
3485 if (session.verbose>2)
4af765b2 3486 clog << _("Collapsing constantly-limited foreach-loop ") << *s->tok << endl;
10328bcf
JS
3487 relaxed_p = false;
3488
3489 provide (new null_statement (s->tok));
3490 }
3491}
3492
3493void
3494const_folder::visit_binary_expression (binary_expression* e)
3495{
e7227e90
JS
3496 int64_t value;
3497 literal_number* left = get_number (e->left);
3498 literal_number* right = get_number (e->right);
3499
3500 if (right && !right->value && (e->op == "/" || e->op == "%"))
3501 {
3502 // Give divide-by-zero a chance to be optimized out elsewhere,
3503 // and if not it will be a runtime error anyway...
3504 provide (e);
3505 return;
3506 }
3507
3508 if (left && right)
3509 {
3510 if (e->op == "+")
3511 value = left->value + right->value;
3512 else if (e->op == "-")
3513 value = left->value - right->value;
3514 else if (e->op == "*")
3515 value = left->value * right->value;
3516 else if (e->op == "&")
3517 value = left->value & right->value;
3518 else if (e->op == "|")
3519 value = left->value | right->value;
3520 else if (e->op == "^")
3521 value = left->value ^ right->value;
3522 else if (e->op == ">>")
3523 value = left->value >> max(min(right->value, (int64_t)64), (int64_t)0);
3524 else if (e->op == "<<")
3525 value = left->value << max(min(right->value, (int64_t)64), (int64_t)0);
3526 else if (e->op == "/")
3527 value = (left->value == LLONG_MIN && right->value == -1) ? LLONG_MIN :
3528 left->value / right->value;
3529 else if (e->op == "%")
3530 value = (left->value == LLONG_MIN && right->value == -1) ? 0 :
3531 left->value % right->value;
3532 else
4af765b2 3533 throw semantic_error (_("unsupported binary operator ") + e->op);
e7227e90
JS
3534 }
3535
3536 else if ((left && ((left->value == 0 && (e->op == "*" || e->op == "&" ||
3537 e->op == ">>" || e->op == "<<" )) ||
3538 (left->value ==-1 && (e->op == "|" || e->op == ">>"))))
3539 ||
3540 (right && ((right->value == 0 && (e->op == "*" || e->op == "&")) ||
3541 (right->value == 1 && (e->op == "%")) ||
3542 (right->value ==-1 && (e->op == "%" || e->op == "|")))))
3543 {
3544 expression* other = left ? e->right : e->left;
3545 varuse_collecting_visitor vu(session);
3546 other->visit(&vu);
3547 if (!vu.side_effect_free())
3548 {
3549 provide (e);
3550 return;
3551 }
3552
3553 if (left)
3554 value = left->value;
3555 else if (e->op == "%")
3556 value = 0;
3557 else
3558 value = right->value;
3559 }
3560
3561 else if ((left && ((left->value == 0 && (e->op == "+" || e->op == "|" ||
3562 e->op == "^")) ||
3563 (left->value == 1 && (e->op == "*")) ||
3564 (left->value ==-1 && (e->op == "&"))))
3565 ||
3566 (right && ((right->value == 0 && (e->op == "+" || e->op == "-" ||
3567 e->op == "|" || e->op == "^")) ||
3568 (right->value == 1 && (e->op == "*" || e->op == "/")) ||
3569 (right->value ==-1 && (e->op == "&")) ||
3570 (right->value <= 0 && (e->op == ">>" || e->op == "<<")))))
3571 {
3572 if (session.verbose>2)
4af765b2 3573 clog << _("Collapsing constant-identity binary operator ") << *e->tok << endl;
e7227e90
JS
3574 relaxed_p = false;
3575
3576 provide (left ? e->right : e->left);
3577 return;
3578 }
3579
3580 else
3581 {
3582 provide (e);
3583 return;
3584 }
3585
3586 if (session.verbose>2)
4af765b2
LB
3587 clog << _F("Collapsing constant-%" PRIi64 " binary operator %s",
3588 value, lex_cast(*e->tok).c_str()) << endl;
e7227e90
JS
3589 relaxed_p = false;
3590
3591 literal_number* n = new literal_number(value);
3592 n->tok = e->tok;
3593 n->visit (this);
10328bcf
JS
3594}
3595
3596void
3597const_folder::visit_unary_expression (unary_expression* e)
3598{
3599 literal_number* operand = get_number (e->operand);
3600 if (!operand)
3601 provide (e);
3602 else
3603 {
3604 if (session.verbose>2)
4af765b2 3605 clog << _("Collapsing constant unary ") << *e->tok << endl;
10328bcf
JS
3606 relaxed_p = false;
3607
3608 literal_number* n = new literal_number (*operand);
3609 n->tok = e->tok;
3610 if (e->op == "+")
3611 ; // nothing to do
3612 else if (e->op == "-")
3613 n->value = -n->value;
3614 else if (e->op == "!")
3615 n->value = !n->value;
3616 else if (e->op == "~")
3617 n->value = ~n->value;
3618 else
4af765b2 3619 throw semantic_error (_("unsupported unary operator ") + e->op);
10328bcf
JS
3620 n->visit (this);
3621 }
3622}
3623
3624void
3625const_folder::visit_logical_or_expr (logical_or_expr* e)
3626{
a7e58d4c
JS
3627 int64_t value;
3628 literal_number* left = get_number (e->left);
3629 literal_number* right = get_number (e->right);
3630
3631 if (left && right)
3632 value = left->value || right->value;
3633
3634 else if ((left && left->value) || (right && right->value))
3635 {
3636 // If the const is on the left, we get to short-circuit the right
3637 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3638 if (right)
3639 {
3640 varuse_collecting_visitor vu(session);
3641 e->left->visit(&vu);
3642 if (!vu.side_effect_free())
3643 {
3644 provide (e);
3645 return;
3646 }
3647 }
3648
3649 value = 1;
3650 }
3651
3652 // We might also get rid of useless "0||x" and "x||0", except it does
3653 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3654 // that this would gain us much.
3655
3656 else
3657 {
3658 provide (e);
3659 return;
3660 }
3661
3662 if (session.verbose>2)
4af765b2 3663 clog << _("Collapsing constant logical-OR ") << *e->tok << endl;
a7e58d4c
JS
3664 relaxed_p = false;
3665
3666 literal_number* n = new literal_number(value);
3667 n->tok = e->tok;
3668 n->visit (this);
10328bcf
JS
3669}
3670
3671void
3672const_folder::visit_logical_and_expr (logical_and_expr* e)
3673{
a7e58d4c
JS
3674 int64_t value;
3675 literal_number* left = get_number (e->left);
3676 literal_number* right = get_number (e->right);
3677
3678 if (left && right)
3679 value = left->value && right->value;
3680
3681 else if ((left && !left->value) || (right && !right->value))
3682 {
3683 // If the const is on the left, we get to short-circuit the right
3684 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3685 if (right)
3686 {
3687 varuse_collecting_visitor vu(session);
3688 e->left->visit(&vu);
3689 if (!vu.side_effect_free())
3690 {
3691 provide (e);
3692 return;
3693 }
3694 }
3695
3696 value = 0;
3697 }
3698
3699 // We might also get rid of useless "1&&x" and "x&&1", except it does
3700 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3701 // that this would gain us much.
3702
3703 else
3704 {
3705 provide (e);
3706 return;
3707 }
3708
3709 if (session.verbose>2)
4af765b2 3710 clog << _("Collapsing constant logical-AND ") << *e->tok << endl;
a7e58d4c
JS
3711 relaxed_p = false;
3712
3713 literal_number* n = new literal_number(value);
3714 n->tok = e->tok;
3715 n->visit (this);
10328bcf
JS
3716}
3717
3718void
3719const_folder::visit_comparison (comparison* e)
3720{
f4869658
JS
3721 int comp;
3722
3723 literal_number *left_num, *right_num;
3724 literal_string *left_str, *right_str;
3725 get_literal(e->left, left_num, left_str);
3726 get_literal(e->right, right_num, right_str);
3727
3728 if (left_str && right_str)
3729 comp = left_str->value.compare(right_str->value);
3730
3731 else if (left_num && right_num)
3732 comp = left_num->value < right_num->value ? -1 :
3733 left_num->value > right_num->value ? 1 : 0;
3734
3735 else if ((left_num && ((left_num->value == LLONG_MIN &&
3736 (e->op == "<=" || e->op == ">")) ||
3737 (left_num->value == LLONG_MAX &&
3738 (e->op == ">=" || e->op == "<"))))
3739 ||
3740 (right_num && ((right_num->value == LLONG_MIN &&
3741 (e->op == ">=" || e->op == "<")) ||
3742 (right_num->value == LLONG_MAX &&
3743 (e->op == "<=" || e->op == ">")))))
3744 {
3745 expression* other = left_num ? e->right : e->left;
3746 varuse_collecting_visitor vu(session);
3747 other->visit(&vu);
3748 if (!vu.side_effect_free())
3749 provide (e);
3750 else
3751 {
3752 if (session.verbose>2)
4af765b2 3753 clog << _("Collapsing constant-boundary comparison ") << *e->tok << endl;
f4869658
JS
3754 relaxed_p = false;
3755
3756 // ops <= and >= are true, < and > are false
3757 literal_number* n = new literal_number( e->op.length() == 2 );
3758 n->tok = e->tok;
3759 n->visit (this);
3760 }
3761 return;
3762 }
3763
3764 else
3765 {
3766 provide (e);
3767 return;
3768 }
3769
3770 if (session.verbose>2)
4af765b2 3771 clog << _("Collapsing constant comparison ") << *e->tok << endl;
f4869658
JS
3772 relaxed_p = false;
3773
3774 int64_t value;
3775 if (e->op == "==")
3776 value = comp == 0;
3777 else if (e->op == "!=")
3778 value = comp != 0;
3779 else if (e->op == "<")
3780 value = comp < 0;
3781 else if (e->op == ">")
3782 value = comp > 0;
3783 else if (e->op == "<=")
3784 value = comp <= 0;
3785 else if (e->op == ">=")
3786 value = comp >= 0;
3787 else
4af765b2 3788 throw semantic_error (_("unsupported comparison operator ") + e->op);
f4869658
JS
3789
3790 literal_number* n = new literal_number(value);
3791 n->tok = e->tok;
3792 n->visit (this);
10328bcf
JS
3793}
3794
3795void
3796const_folder::visit_concatenation (concatenation* e)
3797{
29b1a9b7
JS
3798 literal_string* left = get_string (e->left);
3799 literal_string* right = get_string (e->right);
3800
3801 if (left && right)
3802 {
3803 if (session.verbose>2)
4af765b2 3804 clog << _("Collapsing constant concatenation ") << *e->tok << endl;
29b1a9b7
JS
3805 relaxed_p = false;
3806
3807 literal_string* n = new literal_string (*left);
3808 n->tok = e->tok;
3809 n->value.append(right->value);
3810 n->visit (this);
3811 }
3812 else if ((left && left->value.empty()) ||
3813 (right && right->value.empty()))
3814 {
3815 if (session.verbose>2)
4af765b2 3816 clog << _("Collapsing identity concatenation ") << *e->tok << endl;
29b1a9b7
JS
3817 relaxed_p = false;
3818 provide(left ? e->right : e->left);
3819 }
3820 else
3821 provide (e);
10328bcf
JS
3822}
3823
3824void
3825const_folder::visit_ternary_expression (ternary_expression* e)
3826{
3827 literal_number* cond = get_number (e->cond);
3828 if (!cond)
3829 {
3830 replace (e->truevalue);
3831 replace (e->falsevalue);
3832 provide (e);
3833 }
3834 else
3835 {
3836 if (session.verbose>2)
4af765b2
LB
3837 clog << _F("Collapsing constant-%" PRIi64 " ternary %s",
3838 cond->value, lex_cast(*e->tok).c_str()) << endl;
10328bcf
JS
3839 relaxed_p = false;
3840
3841 expression* n = cond->value ? e->truevalue : e->falsevalue;
3842 n->visit (this);
3843 }
3844}
3845
b7aedf26
JS
3846void
3847const_folder::visit_defined_op (defined_op* e)
3848{
3849 // If a @defined makes it this far, then it is, de facto, undefined.
3850
3851 if (session.verbose>2)
4af765b2 3852 clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
b7aedf26
JS
3853 relaxed_p = false;
3854
3855 literal_number* n = new literal_number (0);
3856 n->tok = e->tok;
3857 n->visit (this);
3858}
3859
9fab2262
JS
3860void
3861const_folder::visit_target_symbol (target_symbol* e)
3862{
a45664f4 3863 if (session.skip_badvars)
9fab2262
JS
3864 {
3865 // Upon user request for ignoring context, the symbol is replaced
3866 // with a literal 0 and a warning message displayed
3867 // XXX this ignores possible side-effects, e.g. in array indexes
3868 literal_number* ln_zero = new literal_number (0);
3869 ln_zero->tok = e->tok;
3870 provide (ln_zero);
bad814e8 3871 session.print_warning (_("Bad $context variable being substituted with literal 0"),
9fab2262 3872 e->tok);
9fab2262
JS
3873 relaxed_p = false;
3874 }
3875 else
3876 update_visitor::visit_target_symbol (e);
3877}
3878
10328bcf
JS
3879static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p)
3880{
3881 // Let's simplify statements with constant values.
3882
3883 const_folder cf (s, relaxed_p);
3884 // This instance may be reused for multiple probe/function body trims.
3885
3886 for (unsigned i=0; i<s.probes.size(); i++)
3887 cf.replace (s.probes[i]->body);
3888 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3889 it != s.functions.end(); it++)
3890 cf.replace (it->second->body);
3891}
3892
3893
88bbd60d
DS
3894struct duplicate_function_remover: public functioncall_traversing_visitor
3895{
3896 systemtap_session& s;
88bbd60d
DS
3897 map<functiondecl*, functiondecl*>& duplicate_function_map;
3898
c214bd6a 3899 duplicate_function_remover(systemtap_session& sess,
88bbd60d 3900 map<functiondecl*, functiondecl*>&dfm):
c214bd6a 3901 s(sess), duplicate_function_map(dfm) {};
88bbd60d
DS
3902
3903 void visit_functioncall (functioncall* e);
3904};
3905
3906void
3907duplicate_function_remover::visit_functioncall (functioncall *e)
3908{
3909 functioncall_traversing_visitor::visit_functioncall (e);
3910
3911 // If the current function call reference points to a function that
3912 // is a duplicate, replace it.
3913 if (duplicate_function_map.count(e->referent) != 0)
3914 {
3915 if (s.verbose>2)
4af765b2
LB
3916 clog << _F("Changing %s reference to %s reference\n",
3917 e->referent->name.c_str(), duplicate_function_map[e->referent]->name.c_str());
88bbd60d
DS
3918 e->tok = duplicate_function_map[e->referent]->tok;
3919 e->function = duplicate_function_map[e->referent]->name;
3920 e->referent = duplicate_function_map[e->referent];
88bbd60d
DS
3921 }
3922}
3923
3924static string
3925get_functionsig (functiondecl* f)
3926{
3927 ostringstream s;
3928
3929 // Get the "name:args body" of the function in s. We have to
3930 // include the args since the function 'x1(a, b)' is different than
3931 // the function 'x2(b, a)' even if the bodies of the two functions
3932 // are exactly the same.
3933 f->printsig(s);
3934 f->body->print(s);
3935
3936 // printsig puts f->name + ':' on the front. Remove this
3937 // (otherwise, functions would never compare equal).
3938 string str = s.str().erase(0, f->name.size() + 1);
3939
3940 // Return the function signature.
3941 return str;
3942}
3943
bea72737 3944void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p)
88bbd60d
DS
3945{
3946 // Walk through all the functions, looking for duplicates.
3947 map<string, functiondecl*> functionsig_map;
3948 map<functiondecl*, functiondecl*> duplicate_function_map;
f76427a2
FCE
3949
3950
3951 vector<functiondecl*> newly_zapped_functions;
3952 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
88bbd60d 3953 {
f76427a2
FCE
3954 functiondecl *fd = it->second;
3955 string functionsig = get_functionsig(fd);
88bbd60d
DS
3956
3957 if (functionsig_map.count(functionsig) == 0)
c214bd6a
DS
3958 {
3959 // This function is unique. Remember it.
f76427a2 3960 functionsig_map[functionsig] = fd;
c214bd6a 3961 }
88bbd60d 3962 else
c214bd6a
DS
3963 {
3964 // This function is a duplicate.
f76427a2
FCE
3965 duplicate_function_map[fd] = functionsig_map[functionsig];
3966 newly_zapped_functions.push_back (fd);
c214bd6a 3967 relaxed_p = false;
c214bd6a 3968 }
88bbd60d 3969 }
f76427a2
FCE
3970 for (unsigned i=0; i<newly_zapped_functions.size(); i++)
3971 {
3972 map<string,functiondecl*>::iterator where = s.functions.find (newly_zapped_functions[i]->name);
3973 assert (where != s.functions.end());
3974 s.functions.erase (where);
3975 }
3976
88bbd60d
DS
3977
3978 // If we have duplicate functions, traverse down the tree, replacing
3979 // the appropriate function calls.
3980 // duplicate_function_remover::visit_functioncall() handles the
c214bd6a 3981 // details of replacing the function calls.
88bbd60d
DS
3982 if (duplicate_function_map.size() != 0)
3983 {
c214bd6a 3984 duplicate_function_remover dfr (s, duplicate_function_map);
88bbd60d
DS
3985
3986 for (unsigned i=0; i < s.probes.size(); i++)
3987 s.probes[i]->body->visit(&dfr);
3988 }
3989}
3990
cbfbbf69
FCE
3991
3992static int
c214bd6a 3993semantic_pass_optimize1 (systemtap_session& s)
cbfbbf69
FCE
3994{
3995 // In this pass, we attempt to rewrite probe/function bodies to
3996 // eliminate some blatantly unnecessary code. This is run before
3997 // type inference, but after symbol resolution and derived_probe
3998 // creation. We run an outer "relaxation" loop that repeats the
3999 // optimizations until none of them find anything to remove.
4000
4001 int rc = 0;
4002
bad814e8
CM
4003 // Save the old value of suppress_warnings, as we will be changing
4004 // it below.
4005 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
4006
cbfbbf69 4007 bool relaxed_p = false;
cfd621bc 4008 unsigned iterations = 0;
cbfbbf69
FCE
4009 while (! relaxed_p)
4010 {
e19ebcf7 4011 assert_no_interrupts();
49abf162 4012
cbfbbf69
FCE
4013 relaxed_p = true; // until proven otherwise
4014
bad814e8
CM
4015 // If the verbosity is high enough, always print warnings (overrides -w),
4016 // or if not, always suppress warnings for every itteration after the first.
4017 if(s.verbose > 2)
4018 s.suppress_warnings = false;
4019 else if (iterations > 0)
4020 s.suppress_warnings = true;
4021
c0f56268
JS
4022 if (!s.unoptimized)
4023 {
4024 semantic_pass_opt1 (s, relaxed_p);
4025 semantic_pass_opt2 (s, relaxed_p, iterations); // produce some warnings only on iteration=0
4026 semantic_pass_opt3 (s, relaxed_p);
4027 semantic_pass_opt4 (s, relaxed_p);
4028 semantic_pass_opt5 (s, relaxed_p);
4029 }
4030
4031 // For listing mode, we need const-folding regardless of optimization so
4032 // that @defined expressions can be properly resolved. PR11360
ad12c592
MW
4033 // We also want it in case variables are used in if/case expressions,
4034 // so enable always. PR11366
4035 semantic_pass_const_fold (s, relaxed_p);
cfd621bc
FCE
4036
4037 iterations ++;
c214bd6a
DS
4038 }
4039
c214bd6a
DS
4040 return rc;
4041}
4042
4043
4044static int
4045semantic_pass_optimize2 (systemtap_session& s)
4046{
4047 // This is run after type inference. We run an outer "relaxation"
4048 // loop that repeats the optimizations until none of them find
4049 // anything to remove.
4050
4051 int rc = 0;
4052
bad814e8
CM
4053 // Save the old value of suppress_warnings, as we will be changing
4054 // it below.
4055 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
4056
c214bd6a 4057 bool relaxed_p = false;
bad814e8 4058 unsigned iterations = 0;
c214bd6a
DS
4059 while (! relaxed_p)
4060 {
e19ebcf7 4061 assert_no_interrupts();
c214bd6a
DS
4062 relaxed_p = true; // until proven otherwise
4063
bad814e8
CM
4064 // If the verbosity is high enough, always print warnings (overrides -w),
4065 // or if not, always suppress warnings for every itteration after the first.
4066 if(s.verbose > 2)
4067 s.suppress_warnings = false;
4068 else if (iterations > 0)
4069 s.suppress_warnings = true;
4070
c0f56268
JS
4071 if (!s.unoptimized)
4072 semantic_pass_opt6 (s, relaxed_p);
bad814e8
CM
4073
4074 iterations++;
cbfbbf69
FCE
4075 }
4076
cbfbbf69
FCE
4077 return rc;
4078}
4079
4080
4081
2b066ec1
FCE
4082// ------------------------------------------------------------------------
4083// type resolution
4084
4085
4086static int
4087semantic_pass_types (systemtap_session& s)
4088{
4089 int rc = 0;
4090
4091 // next pass: type inference
4092 unsigned iterations = 0;
4093 typeresolution_info ti (s);
57148ee7 4094
2b066ec1
FCE
4095 ti.assert_resolvability = false;
4096 // XXX: maybe convert to exception-based error signalling
4097 while (1)
4098 {
e19ebcf7 4099 assert_no_interrupts();
49abf162 4100
2b066ec1 4101 iterations ++;
2b066ec1
FCE
4102 ti.num_newly_resolved = 0;
4103 ti.num_still_unresolved = 0;
4104
f76427a2 4105 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2b066ec1 4106 {
e19ebcf7 4107 assert_no_interrupts();
49abf162 4108
f76427a2 4109 functiondecl* fd = it->second;
bdef2583 4110 ti.current_probe = 0;
f76427a2 4111 ti.current_function = fd;
8a43522c 4112 ti.t = pe_unknown;
f76427a2 4113 fd->body->visit (& ti);
8a43522c
GH
4114 // NB: we don't have to assert a known type for
4115 // functions here, to permit a "void" function.
4116 // The translator phase will omit the "retvalue".
4117 //
f76427a2
FCE
4118 // if (fd->type == pe_unknown)
4119 // ti.unresolved (fd->tok);
5abd364d
JS
4120 for (unsigned i=0; i < fd->locals.size(); ++i)
4121 ti.check_local (fd->locals[i]);
57148ee7 4122 }
2b066ec1
FCE
4123
4124 for (unsigned j=0; j<s.probes.size(); j++)
4125 {
e19ebcf7 4126 assert_no_interrupts();
49abf162 4127
2b066ec1
FCE
4128 derived_probe* pn = s.probes[j];
4129 ti.current_function = 0;
bdef2583 4130 ti.current_probe = pn;
2b066ec1
FCE
4131 ti.t = pe_unknown;
4132 pn->body->visit (& ti);
5abd364d
JS
4133 for (unsigned i=0; i < pn->locals.size(); ++i)
4134 ti.check_local (pn->locals[i]);
5d23847d
FCE
4135
4136 probe_point* pp = pn->sole_location();
4137 if (pp->condition)
4138 {
4139 ti.current_function = 0;
4140 ti.current_probe = 0;
4141 ti.t = pe_long; // NB: expected type
4142 pp->condition->visit (& ti);
4143 }
2b066ec1
FCE
4144 }
4145
4146 for (unsigned j=0; j<s.globals.size(); j++)
4147 {
4148 vardecl* gd = s.globals[j];
4149 if (gd->type == pe_unknown)
4150 ti.unresolved (gd->tok);
bc889c8d
CM
4151 if(gd->arity == 0 && gd->wrap == true)
4152 {
4153 throw semantic_error (_("wrapping not supported for scalars"), gd->tok);
4154 }
2b066ec1 4155 }
57148ee7 4156
2b066ec1 4157 if (ti.num_newly_resolved == 0) // converged
78f6bba6
FCE
4158 {
4159 if (ti.num_still_unresolved == 0)
4160 break; // successfully
4161 else if (! ti.assert_resolvability)
4162 ti.assert_resolvability = true; // last pass, with error msgs
4163 else
4164 { // unsuccessful conclusion
4165 rc ++;
4166 break;
4167 }
4168 }
2b066ec1 4169 }
57148ee7 4170
7e41d3dc 4171 return rc + s.num_errors();
2b066ec1
FCE
4172}
4173
4174
bdef2583
FCE
4175
4176typeresolution_info::typeresolution_info (systemtap_session& s):
74fe61bc
LB
4177 session(s), num_newly_resolved(0), num_still_unresolved(0),
4178 assert_resolvability(false), current_function(0), current_probe(0),
4179 t(pe_unknown)
bdef2583
FCE
4180{
4181}
4182
4183
2b066ec1
FCE
4184void
4185typeresolution_info::visit_literal_number (literal_number* e)
4186{
4187 assert (e->type == pe_long);
4188 if ((t == e->type) || (t == pe_unknown))
4189 return;
4190
4191 mismatch (e->tok, e->type, t);
4192}
4193
4194
4195void
4196typeresolution_info::visit_literal_string (literal_string* e)
4197{
4198 assert (e->type == pe_string);
4199 if ((t == e->type) || (t == pe_unknown))
4200 return;
4201
4202 mismatch (e->tok, e->type, t);
4203}
4204
4205
4206void
4207typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
4208{
4209 visit_binary_expression (e);
4210}
4211
4212
4213void
4214typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
4215{
4216 visit_binary_expression (e);
4217}
4218
93daaca8
SM
4219void
4220typeresolution_info::visit_regex_query (regex_query *e)
4221{
4222 // NB: result of regex query is an integer!
4223 if (t == pe_stats || t == pe_string)
4224 invalid (e->tok, t);
4225
4226 t = pe_string;
4227 e->left->visit (this);
4228 t = pe_string;
4229 e->right->visit (this); // parser ensures this is a literal known at compile time
4230
4231 if (e->type == pe_unknown)
4232 {
4233 e->type = pe_long;
4234 resolved (e->tok, e->type);
4235 }
4236}
4237
2b066ec1
FCE
4238
4239void
4240typeresolution_info::visit_comparison (comparison *e)
4241{
d5d7c2cc 4242 // NB: result of any comparison is an integer!
553d27a5
FCE
4243 if (t == pe_stats || t == pe_string)
4244 invalid (e->tok, t);
4245
4246 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
4247 e->left->visit (this);
4248 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
4249 e->right->visit (this);
57148ee7 4250
553d27a5
FCE
4251 if (e->left->type != pe_unknown &&
4252 e->right->type != pe_unknown &&
4253 e->left->type != e->right->type)
4254 mismatch (e->tok, e->left->type, e->right->type);
57148ee7 4255
553d27a5
FCE
4256 if (e->type == pe_unknown)
4257 {
4258 e->type = pe_long;
4259 resolved (e->tok, e->type);
4260 }
2b066ec1
FCE
4261}
4262
4263
4264void
4265typeresolution_info::visit_concatenation (concatenation *e)
4266{
553d27a5
FCE
4267 if (t != pe_unknown && t != pe_string)
4268 invalid (e->tok, t);
4269
4270 t = pe_string;
4271 e->left->visit (this);
4272 t = pe_string;
4273 e->right->visit (this);
4274
4275 if (e->type == pe_unknown)
4276 {
4277 e->type = pe_string;
4278 resolved (e->tok, e->type);
4279 }
2b066ec1
FCE
4280}
4281
4282
2b066ec1
FCE
4283void
4284typeresolution_info::visit_assignment (assignment *e)
4285{
553d27a5
FCE
4286 if (t == pe_stats)
4287 invalid (e->tok, t);
2b066ec1 4288
2b066ec1
FCE
4289 if (e->op == "<<<") // stats aggregation
4290 {
553d27a5
FCE
4291 if (t == pe_string)
4292 invalid (e->tok, t);
4293
2b066ec1
FCE
4294 t = pe_stats;
4295 e->left->visit (this);
4296 t = pe_long;
4297 e->right->visit (this);
57b73400
GH
4298 if (e->type == pe_unknown ||
4299 e->type == pe_stats)
2b066ec1
FCE
4300 {
4301 e->type = pe_long;
4302 resolved (e->tok, e->type);
4303 }
4304 }
57b73400
GH
4305
4306 else if (e->left->type == pe_stats)
4307 invalid (e->left->tok, e->left->type);
4308
4309 else if (e->right->type == pe_stats)
4310 invalid (e->right->tok, e->right->type);
4311
553d27a5 4312 else if (e->op == "+=" || // numeric only
d5d7c2cc
FCE
4313 e->op == "-=" ||
4314 e->op == "*=" ||
4315 e->op == "/=" ||
4316 e->op == "%=" ||
4317 e->op == "&=" ||
4318 e->op == "^=" ||
4319 e->op == "|=" ||
4320 e->op == "<<=" ||
4321 e->op == ">>=" ||
553d27a5 4322 false)
2b066ec1 4323 {
553d27a5 4324 visit_binary_expression (e);
2b066ec1 4325 }
d5d7c2cc
FCE
4326 else if (e->op == ".=" || // string only
4327 false)
4328 {
4329 if (t == pe_long || t == pe_stats)
4330 invalid (e->tok, t);
4331
4332 t = pe_string;
4333 e->left->visit (this);
4334 t = pe_string;
4335 e->right->visit (this);
4336 if (e->type == pe_unknown)
4337 {
4338 e->type = pe_string;
4339 resolved (e->tok, e->type);
4340 }
4341 }
4342 else if (e->op == "=") // overloaded = for string & numeric operands
2b066ec1 4343 {
553d27a5 4344 // logic similar to ternary_expression
2b066ec1 4345 exp_type sub_type = t;
553d27a5
FCE
4346
4347 // Infer types across the l/r values
4348 if (sub_type == pe_unknown && e->type != pe_unknown)
2b066ec1 4349 sub_type = e->type;
553d27a5
FCE
4350
4351 t = (sub_type != pe_unknown) ? sub_type :
4352 (e->right->type != pe_unknown) ? e->right->type :
4353 pe_unknown;
2b066ec1 4354 e->left->visit (this);
553d27a5
FCE
4355 t = (sub_type != pe_unknown) ? sub_type :
4356 (e->left->type != pe_unknown) ? e->left->type :
4357 pe_unknown;
2b066ec1 4358 e->right->visit (this);
57148ee7 4359
553d27a5 4360 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2b066ec1
FCE
4361 {
4362 e->type = sub_type;
4363 resolved (e->tok, e->type);
4364 }
553d27a5 4365 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
2b066ec1
FCE
4366 {
4367 e->type = e->left->type;
4368 resolved (e->tok, e->type);
4369 }
553d27a5
FCE
4370
4371 if (e->left->type != pe_unknown &&
4372 e->right->type != pe_unknown &&
4373 e->left->type != e->right->type)
4374 mismatch (e->tok, e->left->type, e->right->type);
d02548c0 4375
553d27a5 4376 }
d5d7c2cc 4377 else
4af765b2 4378 throw semantic_error (_("unsupported assignment operator ") + e->op);
553d27a5
FCE
4379}
4380
4381
7d902887
FCE
4382void
4383typeresolution_info::visit_embedded_expr (embedded_expr *e)
4384{
4385 if (e->type == pe_unknown)
4386 {
4387 if (e->code.find ("/* string */") != string::npos)
4388 e->type = pe_string;
4389 else // if (e->code.find ("/* long */") != string::npos)
4390 e->type = pe_long;
4391
4392 resolved (e->tok, e->type);
4393 }
4394}
4395
4396
553d27a5
FCE
4397void
4398typeresolution_info::visit_binary_expression (binary_expression* e)
4399{
4400 if (t == pe_stats || t == pe_string)
4401 invalid (e->tok, t);
4402
4403 t = pe_long;
4404 e->left->visit (this);
4405 t = pe_long;
4406 e->right->visit (this);
4407
4408 if (e->left->type != pe_unknown &&
4409 e->right->type != pe_unknown &&
4410 e->left->type != e->right->type)
4411 mismatch (e->tok, e->left->type, e->right->type);
57148ee7 4412
553d27a5
FCE
4413 if (e->type == pe_unknown)
4414 {
4415 e->type = pe_long;
4416 resolved (e->tok, e->type);
2b066ec1
FCE
4417 }
4418}
4419
4420
4421void
4422typeresolution_info::visit_pre_crement (pre_crement *e)
4423{
4424 visit_unary_expression (e);
4425}
4426
4427
4428void
4429typeresolution_info::visit_post_crement (post_crement *e)
4430{
4431 visit_unary_expression (e);
4432}
4433
4434
4435void
4436typeresolution_info::visit_unary_expression (unary_expression* e)
4437{
553d27a5
FCE
4438 if (t == pe_stats || t == pe_string)
4439 invalid (e->tok, t);
4440
2b066ec1
FCE
4441 t = pe_long;
4442 e->operand->visit (this);
4443
553d27a5 4444 if (e->type == pe_unknown)
2b066ec1
FCE
4445 {
4446 e->type = pe_long;
4447 resolved (e->tok, e->type);
4448 }
4449}
4450
4451
2b066ec1
FCE
4452void
4453typeresolution_info::visit_ternary_expression (ternary_expression* e)
4454{
4455 exp_type sub_type = t;
4456
4457 t = pe_long;
4458 e->cond->visit (this);
4459
553d27a5 4460 // Infer types across the true/false arms of the ternary expression.
2b066ec1
FCE
4461
4462 if (sub_type == pe_unknown && e->type != pe_unknown)
4463 sub_type = e->type;
4464 t = sub_type;
4465 e->truevalue->visit (this);
4466 t = sub_type;
4467 e->falsevalue->visit (this);
4468
4469 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
4470 ; // already resolved
4471 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
4472 {
4473 e->type = sub_type;
4474 resolved (e->tok, e->type);
4475 }
4476 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
4477 {
4478 e->type = e->truevalue->type;
4479 resolved (e->tok, e->type);
4480 }
4481 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
4482 {
4483 e->type = e->falsevalue->type;
4484 resolved (e->tok, e->type);
4485 }
4486 else if (e->type != sub_type)
4487 mismatch (e->tok, sub_type, e->type);
4488}
4489
4490
4491template <class Referrer, class Referent>
4492void resolve_2types (Referrer* referrer, Referent* referent,
31966088 4493 typeresolution_info* r, exp_type t, bool accept_unknown = false)
2b066ec1
FCE
4494{
4495 exp_type& re_type = referrer->type;
4496 const token* re_tok = referrer->tok;
4497 exp_type& te_type = referent->type;
4498 const token* te_tok = referent->tok;
4499
4500 if (t != pe_unknown && re_type == t && re_type == te_type)
4501 ; // do nothing: all three e->types in agreement
4502 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
4503 ; // do nothing: two known e->types in agreement
4504 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
4505 r->mismatch (re_tok, re_type, te_type);
4506 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
4507 r->mismatch (re_tok, re_type, t);
4508 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
4509 r->mismatch (te_tok, te_type, t);
4510 else if (re_type == pe_unknown && t != pe_unknown)
4511 {
4512 // propagate from upstream
4513 re_type = t;
4514 r->resolved (re_tok, re_type);
4515 // catch re_type/te_type mismatch later
4516 }
4517 else if (re_type == pe_unknown && te_type != pe_unknown)
4518 {
4519 // propagate from referent
4520 re_type = te_type;
4521 r->resolved (re_tok, re_type);
4522 // catch re_type/t mismatch later
4523 }
4524 else if (re_type != pe_unknown && te_type == pe_unknown)
4525 {
4526 // propagate to referent
4527 te_type = re_type;
4528 r->resolved (te_tok, te_type);
4529 // catch re_type/t mismatch later
4530 }
31966088 4531 else if (! accept_unknown)
2b066ec1
FCE
4532 r->unresolved (re_tok);
4533}
4534
4535
4536void
4537typeresolution_info::visit_symbol (symbol* e)
4538{
4539 assert (e->referent != 0);
d02548c0 4540 resolve_2types (e, e->referent, this, t);
2b066ec1
FCE
4541}
4542
4543
d7f3e0c5
GH
4544void
4545typeresolution_info::visit_target_symbol (target_symbol* e)
4546{
cbfbbf69
FCE
4547 // This occurs only if a target symbol was not resolved over in
4548 // tapset.cxx land, that error was properly suppressed, and the
4549 // later unused-expression-elimination pass didn't get rid of it
4550 // either. So we have a target symbol that is believed to be of
4551 // genuine use, yet unresolved by the provider.
ba6f838d
FCE
4552
4553 if (session.verbose > 2)
4554 {
4af765b2 4555 clog << _("Resolution problem with ");
ba6f838d
FCE
4556 if (current_function)
4557 {
4558 clog << "function " << current_function->name << endl;
4559 current_function->body->print (clog);
4560 clog << endl;
4561 }
4562 else if (current_probe)
4563 {
da2df842 4564 clog << "probe " << *current_probe->sole_location() << endl;
ba6f838d
FCE
4565 current_probe->body->print (clog);
4566 clog << endl;
4567 }
57148ee7 4568 else
4af765b2
LB
4569 //TRANSLATORS: simply saying not an issue with a probe or function
4570 clog << _("other") << endl;
ba6f838d
FCE
4571 }
4572
9b48ce88
FCE
4573 if (e->saved_conversion_error)
4574 throw (* (e->saved_conversion_error));
4575 else
4af765b2 4576 throw semantic_error(_("unresolved target-symbol expression"), e->tok);
d7f3e0c5
GH
4577}
4578
4579
30263a73
FCE
4580void
4581typeresolution_info::visit_defined_op (defined_op* e)
4582{
4af765b2 4583 throw semantic_error(_("unexpected @defined"), e->tok);
30263a73
FCE
4584}
4585
4586
8cc799a5
JS
4587void
4588typeresolution_info::visit_entry_op (entry_op* e)
4589{
4af765b2 4590 throw semantic_error(_("@entry is only valid in .return probes"), e->tok);
8cc799a5
JS
4591}
4592
4593
9b5af295
JS
4594void
4595typeresolution_info::visit_cast_op (cast_op* e)
4596{
4597 // Like target_symbol, a cast_op shouldn't survive this far
4598 // unless it was not resolved and its value is really needed.
4599 if (e->saved_conversion_error)
4600 throw (* (e->saved_conversion_error));
4601 else
4583161b
JS
4602 throw semantic_error(_F("type definition '%s' not found in '%s'",
4603 e->type_name.c_str(), e->module.c_str()), e->tok);
9b5af295
JS
4604}
4605
4606
3689db05
SC
4607void
4608typeresolution_info::visit_perf_op (perf_op* e)
4609{
4610 // A perf_op should already be resolved
4611 if (t == pe_stats || t == pe_string)
4612 invalid (e->tok, t);
4613
ad583484
FCE
4614 e->type = pe_long;
4615
4616 // (There is no real need to visit our operand - by parser
4617 // construction, it's always a string literal, with its type already
4618 // set.)
4619 t = pe_string;
3689db05
SC
4620 e->operand->visit (this);
4621}
4622
4623
2b066ec1
FCE
4624void
4625typeresolution_info::visit_arrayindex (arrayindex* e)
4626{
2b066ec1 4627
d02548c0
GH
4628 symbol *array = NULL;
4629 hist_op *hist = NULL;
4630 classify_indexable(e->base, array, hist);
57148ee7 4631
d02548c0
GH
4632 // Every hist_op has type [int]:int, that is to say, every hist_op
4633 // is a pseudo-one-dimensional integer array type indexed by
4634 // integers (bucket numbers).
4635
4636 if (hist)
4637 {
4638 if (e->indexes.size() != 1)
4639 unresolved (e->tok);
4640 t = pe_long;
4641 e->indexes[0]->visit (this);
4642 if (e->indexes[0]->type != pe_long)
4643 unresolved (e->tok);
a4636912 4644 hist->visit (this);
1bbeef03
GH
4645 if (e->type != pe_long)
4646 {
4647 e->type = pe_long;
4648 resolved (e->tok, pe_long);
4649 }
d02548c0
GH
4650 return;
4651 }
4652
4653 // Now we are left with "normal" map inference and index checking.
4654
4655 assert (array);
4656 assert (array->referent != 0);
4657 resolve_2types (e, array->referent, this, t);
2b066ec1
FCE
4658
4659 // now resolve the array indexes
69c68955
FCE
4660
4661 // if (e->referent->index_types.size() == 0)
4662 // // redesignate referent as array
4663 // e->referent->set_arity (e->indexes.size ());
2b066ec1 4664
d02548c0 4665 if (e->indexes.size() != array->referent->index_types.size())
2b066ec1
FCE
4666 unresolved (e->tok); // symbol resolution should prevent this
4667 else for (unsigned i=0; i<e->indexes.size(); i++)
4668 {
4669 expression* ee = e->indexes[i];
d02548c0 4670 exp_type& ft = array->referent->index_types [i];
2b066ec1
FCE
4671 t = ft;
4672 ee->visit (this);
4673 exp_type at = ee->type;
4674
4675 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
4676 {
4677 // propagate to formal type
4678 ft = at;
d02548c0 4679 resolved (array->referent->tok, ft);
2b066ec1
FCE
4680 // uses array decl as there is no token for "formal type"
4681 }
4682 if (at == pe_stats)
4683 invalid (ee->tok, at);
4684 if (ft == pe_stats)
4685 invalid (ee->tok, ft);
4686 if (at != pe_unknown && ft != pe_unknown && ft != at)
4687 mismatch (e->tok, at, ft);
4688 if (at == pe_unknown)
313b2f74 4689 unresolved (ee->tok);
2b066ec1
FCE
4690 }
4691}
4692
4693
4694void
4695typeresolution_info::visit_functioncall (functioncall* e)
4696{
4697 assert (e->referent != 0);
4698
57148ee7 4699 resolve_2types (e, e->referent, this, t, true); // accept unknown type
2b066ec1
FCE
4700
4701 if (e->type == pe_stats)
4702 invalid (e->tok, e->type);
4703
2b066ec1
FCE
4704 // now resolve the function parameters
4705 if (e->args.size() != e->referent->formal_args.size())
4706 unresolved (e->tok); // symbol resolution should prevent this
4707 else for (unsigned i=0; i<e->args.size(); i++)
4708 {
4709 expression* ee = e->args[i];
4710 exp_type& ft = e->referent->formal_args[i]->type;
4711 const token* fe_tok = e->referent->formal_args[i]->tok;
4712 t = ft;
4713 ee->visit (this);
4714 exp_type at = ee->type;
57148ee7 4715
2b066ec1
FCE
4716 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
4717 {
4718 // propagate to formal arg
4719 ft = at;
4720 resolved (e->referent->formal_args[i]->tok, ft);
4721 }
4722 if (at == pe_stats)
4723 invalid (e->tok, at);
4724 if (ft == pe_stats)
4725 invalid (fe_tok, ft);
4726 if (at != pe_unknown && ft != pe_unknown && ft != at)
4727 mismatch (e->tok, at, ft);
4728 if (at == pe_unknown)
4729 unresolved (e->tok);
4730 }
4731}
4732
4733
4734void
4735typeresolution_info::visit_block (block* e)
4736{
4737 for (unsigned i=0; i<e->statements.size(); i++)
4738 {
57148ee7 4739 try
2b066ec1
FCE
4740 {
4741 t = pe_unknown;
4742 e->statements[i]->visit (this);
4743 }
4744 catch (const semantic_error& e)
4745 {
4746 session.print_error (e);
4747 }
4748 }
4749}
4750
4751
f4fe2e93
FCE
4752void
4753typeresolution_info::visit_try_block (try_block* e)
4754{
4755 if (e->try_block)
4756 e->try_block->visit (this);
4757 if (e->catch_error_var)
4758 {
4759 t = pe_string;
4760 e->catch_error_var->visit (this);
4761 }
4762 if (e->catch_block)
4763 e->catch_block->visit (this);
4764}
4765
4766
54dfabe9 4767void
6a80494e 4768typeresolution_info::visit_embeddedcode (embeddedcode* s)
54dfabe9 4769{
6a80494e
FCE
4770 // PR11573. If we have survived thus far with a piece of embedded
4771 // code that requires uprobes, we need to track this.
4772 //
4773 // This is an odd place for this check, as opposed
4774 // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
4775 // over yonder in pass 3. However, we want to do it during pass 2 so
4776 // that cached sessions also get the uprobes treatment.
4777 if (!session.need_uprobes && s->code.find("/* pragma:uprobes */") != string::npos)
4778 {
4779 if (session.verbose > 2)
4af765b2 4780 clog << _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl;
6a80494e
FCE
4781 session.need_uprobes = true;
4782 }
54dfabe9
FCE
4783}
4784
4785
2b066ec1
FCE
4786void
4787typeresolution_info::visit_if_statement (if_statement* e)
4788{
4789 t = pe_long;
4790 e->condition->visit (this);
4791
4792 t = pe_unknown;
4793 e->thenblock->visit (this);
4794
4795 if (e->elseblock)
4796 {
4797 t = pe_unknown;
4798 e->elseblock->visit (this);
4799 }
4800}
4801
4802
4803void
4804typeresolution_info::visit_for_loop (for_loop* e)
4805{
4806 t = pe_unknown;
cbfbbf69 4807 if (e->init) e->init->visit (this);
2b066ec1
FCE
4808 t = pe_long;
4809 e->cond->visit (this);
4810 t = pe_unknown;
57148ee7 4811 if (e->incr) e->incr->visit (this);
2b066ec1 4812 t = pe_unknown;
57148ee7 4813 e->block->visit (this);
2b066ec1
FCE
4814}
4815
4816
69c68955
FCE
4817void
4818typeresolution_info::visit_foreach_loop (foreach_loop* e)
4819{
4820 // See also visit_arrayindex.
4821 // This is different in that, being a statement, we can't assign
4822 // a type to the outer array, only propagate to/from the indexes
4823
4824 // if (e->referent->index_types.size() == 0)
4825 // // redesignate referent as array
4826 // e->referent->set_arity (e->indexes.size ());
4827
c261711d 4828 exp_type wanted_value = pe_unknown;
d02548c0
GH
4829 symbol *array = NULL;
4830 hist_op *hist = NULL;
4831 classify_indexable(e->base, array, hist);
69c68955 4832
d02548c0 4833 if (hist)
57148ee7 4834 {
d02548c0
GH
4835 if (e->indexes.size() != 1)
4836 unresolved (e->tok);
4837 t = pe_long;
4838 e->indexes[0]->visit (this);
4839 if (e->indexes[0]->type != pe_long)
4840 unresolved (e->tok);
a4636912 4841 hist->visit (this);
c261711d 4842 wanted_value = pe_long;
d02548c0
GH
4843 }
4844 else
4845 {
57148ee7 4846 assert (array);
d02548c0
GH
4847 if (e->indexes.size() != array->referent->index_types.size())
4848 unresolved (e->tok); // symbol resolution should prevent this
4849 else for (unsigned i=0; i<e->indexes.size(); i++)
4850 {
4851 expression* ee = e->indexes[i];
4852 exp_type& ft = array->referent->index_types [i];
4853 t = ft;
4854 ee->visit (this);
4855 exp_type at = ee->type;
57148ee7 4856
d02548c0
GH
4857 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
4858 {
4859 // propagate to formal type
4860 ft = at;
4861 resolved (array->referent->tok, ft);
4862 // uses array decl as there is no token for "formal type"
4863 }
4864 if (at == pe_stats)
4865 invalid (ee->tok, at);
4866 if (ft == pe_stats)
4867 invalid (ee->tok, ft);
4868 if (at != pe_unknown && ft != pe_unknown && ft != at)
4869 mismatch (e->tok, at, ft);
4870 if (at == pe_unknown)
4871 unresolved (ee->tok);
4872 }
c261711d
JS
4873 t = pe_unknown;
4874 array->visit (this);
4875 wanted_value = array->type;
4876 }
4877
4878 if (e->value)
4879 {
4880 if (wanted_value == pe_stats)
4881 invalid(e->value->tok, wanted_value);
4882 else if (wanted_value != pe_unknown)
4883 check_arg_type(wanted_value, e->value);
4884 else
4885 {
4886 t = pe_unknown;
4887 e->value->visit (this);
4888 }
69c68955
FCE
4889 }
4890
fd5689dc
FCE
4891 /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */
4892 if (wanted_value != pe_unknown)
4893 if (e->sort_aggr != sc_none && wanted_value != pe_stats)
4894 invalid (array->tok, wanted_value);
4895
27f21e8c
DS
4896 if (e->limit)
4897 {
4898 t = pe_long;
4899 e->limit->visit (this);
4900 }
4901
69c68955 4902 t = pe_unknown;
57148ee7 4903 e->block->visit (this);
69c68955
FCE
4904}
4905
4906
2b066ec1 4907void
78f6bba6 4908typeresolution_info::visit_null_statement (null_statement*)
2b066ec1
FCE
4909{
4910}
4911
4912
4913void
4914typeresolution_info::visit_expr_statement (expr_statement* e)
4915{
4916 t = pe_unknown;
4917 e->value->visit (this);
4918}
4919
4920
57148ee7 4921struct delete_statement_typeresolution_info:
d98d459c
GH
4922 public throwing_visitor
4923{
4924 typeresolution_info *parent;
4925 delete_statement_typeresolution_info (typeresolution_info *p):
4af765b2 4926 throwing_visitor (_("invalid operand of delete expression")),
d98d459c
GH
4927 parent (p)
4928 {}
4929
4930 void visit_arrayindex (arrayindex* e)
4931 {
4932 parent->visit_arrayindex (e);
4933 }
57148ee7 4934
d98d459c
GH
4935 void visit_symbol (symbol* e)
4936 {
4937 exp_type ignored = pe_unknown;
57148ee7 4938 assert (e->referent != 0);
d98d459c
GH
4939 resolve_2types (e, e->referent, parent, ignored);
4940 }
4941};
4942
4943
2b066ec1
FCE
4944void
4945typeresolution_info::visit_delete_statement (delete_statement* e)
4946{
d98d459c
GH
4947 delete_statement_typeresolution_info di (this);
4948 t = pe_unknown;
4949 e->value->visit (&di);
2b066ec1
FCE
4950}
4951
4952
f3c26ea5 4953void
78f6bba6 4954typeresolution_info::visit_next_statement (next_statement*)
f3c26ea5
FCE
4955{
4956}
4957
4958
4959void
78f6bba6 4960typeresolution_info::visit_break_statement (break_statement*)
f3c26ea5
FCE
4961{
4962}
4963
4964
4965void
78f6bba6 4966typeresolution_info::visit_continue_statement (continue_statement*)
f3c26ea5
FCE
4967{
4968}
4969
4970
2b066ec1
FCE
4971void
4972typeresolution_info::visit_array_in (array_in* e)
4973{
ce10591c
FCE
4974 // all unary operators only work on numerics
4975 exp_type t1 = t;
4976 t = pe_unknown; // array value can be anything
4977 e->operand->visit (this);
4978
4979 if (t1 == pe_unknown && e->type != pe_unknown)
4980 ; // already resolved
4981 else if (t1 == pe_string || t1 == pe_stats)
4982 mismatch (e->tok, t1, pe_long);
4983 else if (e->type == pe_unknown)
4984 {
4985 e->type = pe_long;
4986 resolved (e->tok, e->type);
4987 }
2b066ec1
FCE
4988}
4989
4990
4991void
4992typeresolution_info::visit_return_statement (return_statement* e)
4993{
4994 // This is like symbol, where the referent is
4995 // the return value of the function.
4996
57148ee7 4997 // translation pass will print error
2b066ec1 4998 if (current_function == 0)
22f46231 4999 return;
2b066ec1
FCE
5000
5001 exp_type& e_type = current_function->type;
5002 t = current_function->type;
5003 e->value->visit (this);
5004
5005 if (e_type != pe_unknown && e->value->type != pe_unknown
5006 && e_type != e->value->type)
5007 mismatch (current_function->tok, e_type, e->value->type);
57148ee7 5008 if (e_type == pe_unknown &&
2b066ec1
FCE
5009 (e->value->type == pe_long || e->value->type == pe_string))
5010 {
5011 // propagate non-statistics from value
5012 e_type = e->value->type;
5013 resolved (current_function->tok, e->value->type);
5014 }
5015 if (e->value->type == pe_stats)
5016 invalid (e->value->tok, e->value->type);
5017}
5018
57148ee7 5019void
d02548c0
GH
5020typeresolution_info::visit_print_format (print_format* e)
5021{
5022 size_t unresolved_args = 0;
5023
1bbeef03
GH
5024 if (e->hist)
5025 {
5026 e->hist->visit(this);
5027 }
5028
5029 else if (e->print_with_format)
d02548c0
GH
5030 {
5031 // If there's a format string, we can do both inference *and*
5032 // checking.
5033
5034 // First we extract the subsequence of formatting components
5035 // which are conversions (not just literal string components)
5036
34201621 5037 unsigned expected_num_args = 0;
d02548c0
GH
5038 std::vector<print_format::format_component> components;
5039 for (size_t i = 0; i < e->components.size(); ++i)
5040 {
5041 if (e->components[i].type == print_format::conv_unspecified)
4af765b2 5042 throw semantic_error (_("Unspecified conversion in print operator format string"),
d02548c0 5043 e->tok);
b5852334 5044 else if (e->components[i].type == print_format::conv_literal)
d02548c0
GH
5045 continue;
5046 components.push_back(e->components[i]);
34201621
DB
5047 ++expected_num_args;
5048 if (e->components[i].widthtype == print_format::width_dynamic)
5049 ++expected_num_args;
5050 if (e->components[i].prectype == print_format::prec_dynamic)
5051 ++expected_num_args;
d02548c0
GH
5052 }
5053
5054 // Then we check that the number of conversions and the number
5055 // of args agree.
5056
34201621 5057 if (expected_num_args != e->args.size())
4af765b2 5058 throw semantic_error (_("Wrong number of args to formatted print operator"),
d02548c0
GH
5059 e->tok);
5060
5061 // Then we check that the types of the conversions match the types
5062 // of the args.
34201621 5063 unsigned argno = 0;
d02548c0
GH
5064 for (size_t i = 0; i < components.size(); ++i)
5065 {
34201621
DB
5066 // Check the dynamic width, if specified
5067 if (components[i].widthtype == print_format::width_dynamic)
5068 {
5069 check_arg_type (pe_long, e->args[argno]);
5070 ++argno;
5071 }
5072
5073 // Check the dynamic precision, if specified
5074 if (components[i].prectype == print_format::prec_dynamic)
5075 {
5076 check_arg_type (pe_long, e->args[argno]);
5077 ++argno;
5078 }
5079
d02548c0
GH
5080 exp_type wanted = pe_unknown;
5081
5082 switch (components[i].type)
5083 {
d02548c0
GH
5084 case print_format::conv_unspecified:
5085 case print_format::conv_literal:
5086 assert (false);
5087 break;
5088
929eb962
JS
5089 case print_format::conv_pointer:
5090 case print_format::conv_number:
dc0b623a 5091 case print_format::conv_binary:
fecccf83 5092 case print_format::conv_char:
ec03bd4b 5093 case print_format::conv_memory:
30c94a80 5094 case print_format::conv_memory_hex:
d02548c0
GH
5095 wanted = pe_long;
5096 break;
5097
5098 case print_format::conv_string:
5099 wanted = pe_string;
5100 break;
5101 }
5102
5103 assert (wanted != pe_unknown);
34201621
DB
5104 check_arg_type (wanted, e->args[argno]);
5105 ++argno;
d02548c0
GH
5106 }
5107 }
5108 else
5109 {
5110 // Without a format string, the best we can do is require that
5111 // each argument resolve to a concrete type.
5112 for (size_t i = 0; i < e->args.size(); ++i)
5113 {
5114 t = pe_unknown;
5115 e->args[i]->visit (this);
5116 if (e->args[i]->type == pe_unknown)
5117 {
5118 unresolved (e->args[i]->tok);
5119 ++unresolved_args;
5120 }
5121 }
5122 }
57148ee7 5123
d02548c0
GH
5124 if (unresolved_args == 0)
5125 {
5126 if (e->type == pe_unknown)
5127 {
5128 if (e->print_to_stream)
5129 e->type = pe_long;
5130 else
57148ee7 5131 e->type = pe_string;
d02548c0
GH
5132 resolved (e->tok, e->type);
5133 }
5134 }
5135 else
5136 {
5137 e->type = pe_unknown;
5138 unresolved (e->tok);
5139 }
5140}
5141
5142
57148ee7 5143void
d02548c0
GH
5144typeresolution_info::visit_stat_op (stat_op* e)
5145{
5146 t = pe_stats;
5147 e->stat->visit (this);
5148 if (e->type == pe_unknown)
5149 {
5150 e->type = pe_long;
5151 resolved (e->tok, e->type);
5152 }
07c17d67 5153 else if (e->type != pe_long)
d02548c0
GH
5154 mismatch (e->tok, e->type, pe_long);
5155}
5156
57148ee7 5157void
d02548c0
GH
5158typeresolution_info::visit_hist_op (hist_op* e)
5159{
5160 t = pe_stats;
5161 e->stat->visit (this);
5162}
5163
2b066ec1 5164
34201621
DB
5165void
5166typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
5167{
5168 t = wanted;
5169 arg->visit (this);
5170
5171 if (arg->type == pe_unknown)
5172 {
5173 arg->type = wanted;
5174 resolved (arg->tok, wanted);
5175 }
5176 else if (arg->type != wanted)
5177 {
5178 mismatch (arg->tok, arg->type, wanted);
5179 }
5180}
5181
5182
5abd364d
JS
5183void
5184typeresolution_info::check_local (vardecl* v)
5185{
5186 if (v->arity != 0)
5187 {
5188 num_still_unresolved ++;
5189 if (assert_resolvability)
5190 session.print_error
4af765b2 5191 (semantic_error (_("array locals not supported, missing global declaration? "), v->tok));
5abd364d
JS
5192 }
5193
5194 if (v->type == pe_unknown)
5195 unresolved (v->tok);
5196 else if (v->type == pe_stats)
5197 {
5198 num_still_unresolved ++;
5199 if (assert_resolvability)
5200 session.print_error
4af765b2 5201 (semantic_error (_("stat locals not supported, missing global declaration? "), v->tok));
5abd364d
JS
5202 }
5203 else if (!(v->type == pe_long || v->type == pe_string))
5204 invalid (v->tok, v->type);
5205}
5206
5207
2b066ec1
FCE
5208void
5209typeresolution_info::unresolved (const token* tok)
5210{
5211 num_still_unresolved ++;
5212
5213 if (assert_resolvability)
5214 {
6c543717 5215 stringstream msg;
4af765b2 5216 msg << _("unresolved type ");
6c543717 5217 session.print_error (semantic_error (msg.str(), tok));
2b066ec1
FCE
5218 }
5219}
5220
5221
5222void
5223typeresolution_info::invalid (const token* tok, exp_type pe)
5224{
5225 num_still_unresolved ++;
5226
5227 if (assert_resolvability)
5228 {
6c543717 5229 stringstream msg;
022b623f 5230 if (tok && tok->type == tok_operator)
4af765b2 5231 msg << _("invalid operator");
2b066ec1 5232 else
4af765b2 5233 msg << _("invalid type ") << pe;
6c543717 5234 session.print_error (semantic_error (msg.str(), tok));
2b066ec1
FCE
5235 }
5236}
5237
5238
5239void
5240typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
5241{
d784c94d 5242 bool tok_resolved = false;
d5f0c423
RA
5243 size_t i;
5244 semantic_error* err1 = 0;
2b066ec1
FCE
5245 num_still_unresolved ++;
5246
d5f0c423
RA
5247 //BZ 9719: for improving type mismatch messages, a semantic error is
5248 //generated with the token where type was first resolved. All such
5249 //resolved tokens, stored in a vector, are matched against their
5250 //content. If an error for the matching token hasn't been printed out
5251 //already, it is and the token pushed in another printed_toks vector
5252
2b066ec1
FCE
5253 if (assert_resolvability)
5254 {
6c543717 5255 stringstream msg;
d5f0c423
RA
5256 for (i=0; i<resolved_toks.size(); i++)
5257 {
5258 if (resolved_toks[i]->content == tok->content)
5259 {
5260 tok_resolved = true;
5261 break;
5262 }
5263 }
5264 if (!tok_resolved)
5265 {
3c5dc934 5266 msg << _F("type mismatch (%s vs. %s)",
4af765b2 5267 lex_cast(t1).c_str(), lex_cast(t2).c_str());
d5f0c423
RA
5268 }
5269 else
5270 {
d784c94d 5271 bool tok_printed = false;
d5f0c423
RA
5272 for (size_t j=0; j<printed_toks.size(); j++)
5273 {
5274 if (printed_toks[j] == resolved_toks[i])
5275 {
5276 tok_printed = true;
5277 break;
5278 }
5279 }
3c5dc934 5280 msg << _F("type mismatch (%s vs. %s)",
4af765b2 5281 lex_cast(t1).c_str(), lex_cast(t2).c_str());
d5f0c423
RA
5282 if (!tok_printed)
5283 {
5284 //error for possible mismatch in the earlier resolved token
5285 printed_toks.push_back (resolved_toks[i]);
5286 stringstream type_msg;
3c5dc934 5287 type_msg << _F("type was first inferred here (%s)", lex_cast(t2).c_str());
d5f0c423
RA
5288 err1 = new semantic_error (type_msg.str(), resolved_toks[i]);
5289 }
5290 }
5291 semantic_error err (msg.str(), tok);
5292 err.chain = err1;
5293 session.print_error (err);
2b066ec1
FCE
5294 }
5295}
5296
5297
5298void
d5f0c423 5299typeresolution_info::resolved (const token* tok, exp_type)
2b066ec1 5300{
d5f0c423 5301 resolved_toks.push_back (tok);
2b066ec1 5302 num_newly_resolved ++;
2b066ec1
FCE
5303}
5304
73267b89 5305/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.800962 seconds and 5 git commands to generate.