]> sourceware.org Git - systemtap.git/blame - elaborate.cxx
Fix PR19954 by avoiding "suspicious RCU usage" message.
[systemtap.git] / elaborate.cxx
CommitLineData
2b066ec1 1// elaboration functions
3e3756f8 2// Copyright (C) 2005-2016 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"
60cf5fae 18#include "stapregex.h"
a3e980f9 19#include "stringtable.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):
ca6d3b0f
JL
65 base (p), base_pp(l), group(NULL), sdt_semaphore_addr(0),
66 session_index((unsigned)-1)
2b066ec1 67{
5d23847d
FCE
68 assert (p);
69 this->tok = p->tok;
70 this->privileged = p->privileged;
71 this->body = deep_copy_visitor::deep_copy(p->body);
cbbe8080 72
5d23847d 73 assert (l);
4c5d1300
JS
74 // make a copy for subclasses which want to rewrite the location
75 if (rewrite_loc)
76 l = new probe_point(*l);
5d23847d 77 this->locations.push_back (l);
2b066ec1
FCE
78}
79
98afd80e 80
b8da0ad1
FCE
81void
82derived_probe::printsig (ostream& o) const
83{
84 probe::printsig (o);
85 printsig_nested (o);
86}
87
88void
89derived_probe::printsig_nested (ostream& o) const
90{
91 // We'd like to enclose the probe derivation chain in a /* */
92 // comment delimiter. But just printing /* base->printsig() */ is
93 // not enough, since base might itself be a derived_probe. So we,
94 // er, "cleverly" encode our nesting state as a formatting flag for
95 // the ostream.
96 ios::fmtflags f = o.flags (ios::internal);
97 if (f & ios::internal)
98 {
99 // already nested
100 o << " <- ";
101 base->printsig (o);
102 }
103 else
104 {
105 // outermost nesting
106 o << " /* <- ";
107 base->printsig (o);
108 o << " */";
109 }
110 // restore flags
111 (void) o.flags (f);
112}
113
114
c3a3c0c9 115void
d885563b 116derived_probe::collect_derivation_chain (std::vector<probe*> &probes_list) const
c3a3c0c9 117{
d885563b 118 probes_list.push_back(const_cast<derived_probe*>(this));
c3a3c0c9
WC
119 base->collect_derivation_chain(probes_list);
120}
121
122
f1b9a51a 123void
d885563b 124derived_probe::collect_derivation_pp_chain (std::vector<probe_point*> &pp_list) const
f1b9a51a 125{
8159bf55 126 pp_list.push_back(const_cast<probe_point*>(this->sole_location()));
f1b9a51a
JS
127 base->collect_derivation_pp_chain(pp_list);
128}
129
130
26e63673 131string
96c7f494 132derived_probe::derived_locations (bool firstFrom)
26e63673
JS
133{
134 ostringstream o;
135 vector<probe_point*> reference_point;
136 collect_derivation_pp_chain(reference_point);
d885563b
FCE
137 if (reference_point.size() > 0)
138 for(unsigned i=1; i<reference_point.size(); ++i)
96c7f494
FCE
139 {
140 if (firstFrom || i>1)
141 o << " from: ";
142 o << reference_point[i]->str(false); // no ?,!,etc
143 }
26e63673
JS
144 return o.str();
145}
146
147
b20febf3 148probe_point*
b8da0ad1 149derived_probe::sole_location () const
dc38c0ae 150{
4af765b2 151 if (locations.size() == 0 || locations.size() > 1)
dc09353a 152 throw SEMANTIC_ERROR (_N("derived_probe with no locations",
2a89b023 153 "derived_probe with too many locations",
d885563b 154 locations.size()), this->tok);
57148ee7 155 else
b20febf3 156 return locations[0];
dc38c0ae
DS
157}
158
159
c3df9bce
JS
160probe_point*
161derived_probe::script_location () const
162{
d885563b 163 // This feeds function::pn() in the tapset, which is documented as the
e2fee59d 164 // script-level probe point expression, *after wildcard expansion*.
d885563b
FCE
165 vector<probe_point*> chain;
166 collect_derivation_pp_chain (chain);
167
e2fee59d
JL
168 // Go backwards until we hit the first well-formed probe point
169 for (int i=chain.size()-1; i>=0; i--)
170 if (chain[i]->well_formed)
171 return chain[i];
d885563b 172
8159bf55
FCE
173 // If that didn't work, just fallback to -something-.
174 return sole_location();
c3df9bce
JS
175}
176
177
2865d17a 178void
42e38653 179derived_probe::emit_privilege_assertion (translator_output* o)
2865d17a
DB
180{
181 // Emit code which will cause compilation to fail if it is compiled in
182 // unprivileged mode.
f6be7c06
DB
183 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
184 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
2865d17a
DB
185 o->newline() << "#error Internal Error: Probe ";
186 probe::printsig (o->line());
187 o->line() << " generated in --unprivileged mode";
188 o->newline() << "#endif";
189}
190
191
192void
193derived_probe::emit_process_owner_assertion (translator_output* o)
194{
195 // Emit code which will abort should the current target not belong to the
196 // user in unprivileged mode.
f6be7c06
DB
197 o->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
198 o->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
2865d17a
DB
199 o->newline(1) << "if (! is_myproc ()) {";
200 o->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
201 o->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
202 o->newline() << " current->tgid, _stp_uid, c->probe_point);";
203 o->newline() << "c->last_error = c->error_buffer;";
991bd3ba
JS
204 // NB: since this check occurs before probe locking, its exit should
205 // not be a "goto out", which would attempt unlocking.
206 o->newline() << "return;";
2865d17a
DB
207 o->newline(-1) << "}";
208 o->newline(-1) << "#endif";
209}
210
8f6d8c2b
DB
211void
212derived_probe::print_dupe_stamp_unprivileged(ostream& o)
213{
4af765b2 214 o << _("unprivileged users: authorized") << endl;
8f6d8c2b
DB
215}
216
217void
218derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream& o)
219{
4af765b2 220 o << _("unprivileged users: authorized for process owner") << endl;
8f6d8c2b 221}
47dd066d 222
20c6c071 223// ------------------------------------------------------------------------
98afd80e
FCE
224// Members of derived_probe_builder
225
8eb6206c 226void
dabd71bb
MW
227derived_probe_builder::build_with_suffix(systemtap_session &,
228 probe *,
229 probe_point *,
230 literal_map_t const &,
231 std::vector<derived_probe *> &,
8eb6206c 232 std::vector<probe_point::component *>
dabd71bb 233 const &) {
8eb6206c
SM
234 // XXX perhaps build the probe if suffix is empty?
235 // if (suffix.empty()) {
236 // build (sess, use, location, parameters, finished_results);
237 // return;
238 // }
dc09353a 239 throw SEMANTIC_ERROR (_("invalid suffix for probe"));
8eb6206c
SM
240}
241
98afd80e 242bool
45a63356
FCE
243derived_probe_builder::get_param (literal_map_t const & params,
244 interned_string key,
245 interned_string& value)
98afd80e 246{
45a63356 247 literal_map_t::const_iterator i = params.find (key);
98afd80e
FCE
248 if (i == params.end())
249 return false;
250 literal_string * ls = dynamic_cast<literal_string *>(i->second);
251 if (!ls)
252 return false;
47d349b1 253 value = ls->value;
98afd80e
FCE
254 return true;
255}
256
20c6c071 257
98afd80e 258bool
45a63356
FCE
259derived_probe_builder::get_param (literal_map_t const & params,
260 interned_string key,
98afd80e
FCE
261 int64_t& value)
262{
45a63356 263 literal_map_t::const_iterator i = params.find (key);
98afd80e
FCE
264 if (i == params.end())
265 return false;
266 if (i->second == NULL)
267 return false;
268 literal_number * ln = dynamic_cast<literal_number *>(i->second);
269 if (!ln)
270 return false;
271 value = ln->value;
272 return true;
273}
274
275
888af770 276bool
45a63356
FCE
277derived_probe_builder::has_null_param (literal_map_t const & params,
278 interned_string key)
888af770 279{
45a63356 280 literal_map_t::const_iterator i = params.find(key);
888af770
FCE
281 return (i != params.end() && i->second == NULL);
282}
283
5c6f9e92 284bool
45a63356
FCE
285derived_probe_builder::has_param (literal_map_t const & params,
286 interned_string key)
5c6f9e92
AJ
287{
288 return (params.find(key) != params.end());
289}
98afd80e
FCE
290
291// ------------------------------------------------------------------------
20c6c071
GH
292// Members of match_key.
293
45a63356 294match_key::match_key(interned_string n)
47d349b1 295 : name(n),
57148ee7 296 have_parameter(false),
5d23847d 297 parameter_type(pe_unknown)
20c6c071
GH
298{
299}
300
301match_key::match_key(probe_point::component const & c)
302 : name(c.functor),
303 have_parameter(c.arg != NULL),
5d23847d 304 parameter_type(c.arg ? c.arg->type : pe_unknown)
20c6c071
GH
305{
306}
307
308match_key &
57148ee7 309match_key::with_number()
20c6c071
GH
310{
311 have_parameter = true;
5d23847d 312 parameter_type = pe_long;
20c6c071
GH
313 return *this;
314}
315
316match_key &
57148ee7 317match_key::with_string()
20c6c071
GH
318{
319 have_parameter = true;
5d23847d 320 parameter_type = pe_string;
20c6c071
GH
321 return *this;
322}
323
57148ee7 324string
20c6c071
GH
325match_key::str() const
326{
47d349b1 327 string n = name;
20c6c071
GH
328 if (have_parameter)
329 switch (parameter_type)
330 {
a3e980f9
FCE
331 case pe_string: return n + "(string)";
332 case pe_long: return n + "(number)";
333 default: return n + "(...)";
20c6c071 334 }
a3e980f9 335 return n;
20c6c071
GH
336}
337
57148ee7 338bool
20c6c071
GH
339match_key::operator<(match_key const & other) const
340{
341 return ((name < other.name)
57148ee7
FCE
342
343 || (name == other.name
20c6c071 344 && have_parameter < other.have_parameter)
57148ee7
FCE
345
346 || (name == other.name
347 && have_parameter == other.have_parameter
20c6c071
GH
348 && parameter_type < other.parameter_type));
349}
2b066ec1 350
c0c7b466
FCE
351
352// NB: these are only used in the probe point name components, where
353// only "*" is permitted.
354//
355// Within module("bar"), function("foo"), process("baz") strings, real
356// wildcards are permitted too. See also util.h:contains_glob_chars
357
a477f3f1 358static bool
47d349b1 359isglob(interned_string str)
a477f3f1
DS
360{
361 return(str.find('*') != str.npos);
362}
363
122b4fcd 364static bool
47d349b1 365isdoubleglob(interned_string str)
122b4fcd
JS
366{
367 return(str.find("**") != str.npos);
368}
369
a477f3f1
DS
370bool
371match_key::globmatch(match_key const & other) const
372{
7371cd19
JS
373 const string & name_str = name;
374 const string & other_str = other.name;
a477f3f1 375
7371cd19 376 return ((fnmatch(name_str.c_str(), other_str.c_str(), FNM_NOESCAPE) == 0)
57148ee7 377 && have_parameter == other.have_parameter
a477f3f1
DS
378 && parameter_type == other.parameter_type);
379}
380
2b066ec1 381// ------------------------------------------------------------------------
20c6c071
GH
382// Members of match_node
383// ------------------------------------------------------------------------
384
27dc09b1 385match_node::match_node() :
f6be7c06 386 privilege(privilege_t (pr_stapdev | pr_stapsys))
d4935c2f 387{
d4935c2f 388}
20c6c071
GH
389
390match_node *
57148ee7 391match_node::bind(match_key const & k)
20c6c071 392{
b4ceace2 393 if (k.name == "*")
dc09353a 394 throw SEMANTIC_ERROR(_("invalid use of wildcard probe point component"));
b4ceace2 395
20c6c071
GH
396 map<match_key, match_node *>::const_iterator i = sub.find(k);
397 if (i != sub.end())
398 return i->second;
399 match_node * n = new match_node();
400 sub.insert(make_pair(k, n));
401 return n;
402}
403
57148ee7 404void
20c6c071
GH
405match_node::bind(derived_probe_builder * e)
406{
2531fc1e 407 ends.push_back (e);
20c6c071
GH
408}
409
57148ee7 410match_node *
45a63356 411match_node::bind(interned_string k)
20c6c071
GH
412{
413 return bind(match_key(k));
414}
415
416match_node *
417match_node::bind_str(string const & k)
418{
419 return bind(match_key(k).with_string());
420}
421
57148ee7 422match_node *
20c6c071
GH
423match_node::bind_num(string const & k)
424{
425 return bind(match_key(k).with_number());
426}
427
27dc09b1 428match_node *
42e38653 429match_node::bind_privilege(privilege_t p)
27dc09b1 430{
42e38653 431 privilege = p;
27dc09b1
DB
432 return this;
433}
434
b4ceace2
FCE
435void
436match_node::find_and_build (systemtap_session& s,
437 probe* p, probe_point *loc, unsigned pos,
438 vector<derived_probe *>& results)
20c6c071 439{
b4ceace2 440 assert (pos <= loc->components.size());
57148ee7 441 if (pos == loc->components.size()) // matched all probe point components so far
20c6c071 442 {
2531fc1e 443 if (ends.empty())
b4ceace2
FCE
444 {
445 string alternatives;
446 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
447 alternatives += string(" ") + i->first.str();
448
dc09353a 449 throw SEMANTIC_ERROR (_F("probe point truncated (follow: %s)",
8eb6206c 450 alternatives.c_str()),
4af765b2 451 loc->components.back()->tok);
b4ceace2
FCE
452 }
453
f66bb29a 454 if (! pr_contains (privilege, s.privilege))
27dc09b1 455 {
dc09353a 456 throw SEMANTIC_ERROR (_F("probe point is not allowed for --privilege=%s",
f66bb29a 457 pr_name (s.privilege)),
4af765b2 458 loc->components.back()->tok);
27dc09b1
DB
459 }
460
45a63356 461 literal_map_t param_map;
b4ceace2 462 for (unsigned i=0; i<pos; i++)
47d349b1 463 param_map[loc->components[i]->functor] = loc->components[i]->arg;
b4ceace2
FCE
464 // maybe 0
465
2531fc1e
FCE
466 // Iterate over all bound builders
467 for (unsigned k=0; k<ends.size(); k++)
468 {
469 derived_probe_builder *b = ends[k];
470 b->build (s, p, loc, param_map, results);
471 }
20c6c071 472 }
122b4fcd
JS
473 else if (isdoubleglob(loc->components[pos]->functor)) // ** wildcard?
474 {
475 unsigned int num_results = results.size();
476
477 // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
478
479 const probe_point::component *comp = loc->components[pos];
47d349b1 480 string functor = comp->functor;
122b4fcd
JS
481 size_t glob_start = functor.find("**");
482 size_t glob_end = functor.find_first_not_of('*', glob_start);
a3e980f9
FCE
483 string prefix = functor.substr(0, glob_start);
484 string suffix = ((glob_end != string::npos) ?
485 functor.substr(glob_end) : "");
122b4fcd
JS
486
487 // Synthesize "foo*bar"
488 probe_point *simple_pp = new probe_point(*loc);
489 probe_point::component *simple_comp = new probe_point::component(*comp);
47d349b1 490 simple_comp->functor = prefix + "*" + suffix;
d2eaa03b 491 simple_comp->from_glob = true;
122b4fcd
JS
492 simple_pp->components[pos] = simple_comp;
493 try
494 {
495 find_and_build (s, p, simple_pp, pos, results);
496 }
497 catch (const semantic_error& e)
498 {
601db063
JL
499 // Ignore semantic_errors.
500 }
501
502 // Cleanup if we didn't find anything
503 if (results.size() == num_results)
504 {
122b4fcd
JS
505 delete simple_pp;
506 delete simple_comp;
507 }
508
601db063
JL
509 num_results = results.size();
510
122b4fcd
JS
511 // Synthesize "foo*.**bar"
512 // NB: any component arg should attach to the latter part only
513 probe_point *expanded_pp = new probe_point(*loc);
514 probe_point::component *expanded_comp_pre = new probe_point::component(*comp);
47d349b1 515 expanded_comp_pre->functor = prefix + "*";
d2eaa03b 516 expanded_comp_pre->from_glob = true;
122b4fcd
JS
517 expanded_comp_pre->arg = NULL;
518 probe_point::component *expanded_comp_post = new probe_point::component(*comp);
47d349b1 519 expanded_comp_post->functor = string("**") + suffix;
122b4fcd
JS
520 expanded_pp->components[pos] = expanded_comp_pre;
521 expanded_pp->components.insert(expanded_pp->components.begin() + pos + 1,
522 expanded_comp_post);
523 try
524 {
525 find_and_build (s, p, expanded_pp, pos, results);
526 }
527 catch (const semantic_error& e)
528 {
601db063
JL
529 // Ignore semantic_errors.
530 }
531
532 // Cleanup if we didn't find anything
533 if (results.size() == num_results)
534 {
122b4fcd
JS
535 delete expanded_pp;
536 delete expanded_comp_pre;
537 delete expanded_comp_post;
538 }
539
8eb6206c
SM
540 // Try suffix expansion only if no matches found:
541 if (num_results == results.size())
7f557fa7 542 this->try_suffix_expansion (s, p, loc, pos, results);
8eb6206c 543
122b4fcd
JS
544 if (! loc->optional && num_results == results.size())
545 {
546 // We didn't find any wildcard matches (since the size of
547 // the result vector didn't change). Throw an error.
cff6336b 548 string sugs = suggest_functors(s, functor);
5bcb7b4e
JL
549 throw SEMANTIC_ERROR (_F("probe point mismatch: didn't find any wildcard matches%s",
550 sugs.empty() ? "" : (" (similar: " + sugs + ")").c_str()),
551 comp->tok);
122b4fcd
JS
552 }
553 }
a477f3f1 554 else if (isglob(loc->components[pos]->functor)) // wildcard?
20c6c071 555 {
a477f3f1
DS
556 match_key match (* loc->components[pos]);
557
828c3ed5
DS
558 // Call find_and_build for each possible match. Ignore errors -
559 // unless we don't find any match.
560 unsigned int num_results = results.size();
b4ceace2
FCE
561 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
562 {
a477f3f1 563 const match_key& subkey = i->first;
828c3ed5 564 match_node* subnode = i->second;
a477f3f1 565
e19ebcf7 566 assert_no_interrupts();
49abf162 567
a477f3f1 568 if (match.globmatch(subkey))
828c3ed5 569 {
ddfc759e 570 if (s.verbose > 2)
47d349b1 571 clog << _F("wildcard '%s' matched '%s'",
7371cd19
JS
572 loc->components[pos]->functor.to_string().c_str(),
573 subkey.name.to_string().c_str()) << endl;
a3e980f9 574
ddfc759e
DS
575 // When we have a wildcard, we need to create a copy of
576 // the probe point. Then we'll create a copy of the
577 // wildcard component, and substitute the non-wildcard
578 // functor.
579 probe_point *non_wildcard_pp = new probe_point(*loc);
580 probe_point::component *non_wildcard_component
581 = new probe_point::component(*loc->components[pos]);
582 non_wildcard_component->functor = subkey.name;
d2eaa03b 583 non_wildcard_component->from_glob = true;
ddfc759e
DS
584 non_wildcard_pp->components[pos] = non_wildcard_component;
585
5d23847d
FCE
586 // NB: probe conditions are not attached at the wildcard
587 // (component/functor) level, but at the overall
588 // probe_point level.
589
601db063
JL
590 unsigned int inner_results = results.size();
591
ddfc759e 592 // recurse (with the non-wildcard probe point)
a477f3f1
DS
593 try
594 {
ddfc759e
DS
595 subnode->find_and_build (s, p, non_wildcard_pp, pos+1,
596 results);
a477f3f1
DS
597 }
598 catch (const semantic_error& e)
599 {
600 // Ignore semantic_errors while expanding wildcards.
601 // If we get done and nothing was expanded, the code
602 // following the loop will complain.
601db063 603 }
ddfc759e 604
601db063
JL
605 if (results.size() == inner_results)
606 {
ddfc759e
DS
607 // If this wildcard didn't match, cleanup.
608 delete non_wildcard_pp;
609 delete non_wildcard_component;
601db063 610 }
828c3ed5 611 }
a477f3f1 612 }
8eb6206c
SM
613
614 // Try suffix expansion only if no matches found:
615 if (num_results == results.size())
7f557fa7 616 this->try_suffix_expansion (s, p, loc, pos, results);
8eb6206c 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.
47d349b1 622 string sugs = suggest_functors(s, loc->components[pos]->functor);
5bcb7b4e
JL
623 throw SEMANTIC_ERROR (_F("probe point mismatch: didn't find any wildcard matches%s",
624 sugs.empty() ? "" : (" (similar: " + sugs + ")").c_str()),
625 loc->components[pos]->tok);
828c3ed5 626 }
b4ceace2 627 }
57148ee7 628 else
20c6c071 629 {
b4ceace2
FCE
630 match_key match (* loc->components[pos]);
631 sub_map_iterator_t i = sub.find (match);
8eb6206c
SM
632
633 if (i != sub.end()) // match found
b4ceace2 634 {
8eb6206c
SM
635 match_node* subnode = i->second;
636 // recurse
637 subnode->find_and_build (s, p, loc, pos+1, results);
638 return;
639 }
640
641 unsigned int num_results = results.size();
7f557fa7 642 this->try_suffix_expansion (s, p, loc, pos, results);
601db063 643
8eb6206c
SM
644 // XXX: how to correctly report alternatives + position numbers
645 // for alias suffixes? file a separate PR to address the issue
646 if (! loc->optional && num_results == results.size())
647 {
648 // We didn't find any alias suffixes (since the size of the
649 // result vector didn't change). Throw an error.
47d349b1 650 string sugs = suggest_functors(s, loc->components[pos]->functor);
5bcb7b4e
JL
651 throw SEMANTIC_ERROR (_F("probe point mismatch%s",
652 sugs.empty() ? "" : (" (similar: " + sugs + ")").c_str()),
653 loc->components[pos]->tok);
b4ceace2 654 }
8eb6206c
SM
655 }
656}
657
5bcb7b4e 658string
cff6336b 659match_node::suggest_functors(systemtap_session& s, string functor)
5bcb7b4e
JL
660{
661 // only use prefix if globby (and prefix is non-empty)
662 size_t glob = functor.find('*');
663 if (glob != string::npos && glob != 0)
664 functor.erase(glob);
665 if (functor.empty())
666 return "";
667
cff6336b
DS
668 // PR18577: There isn't any point in generating a suggestion list if
669 // we're not going to display it.
670 if ((s.dump_mode == systemtap_session::dump_matched_probes
671 || s.dump_mode == systemtap_session::dump_matched_probes_vars)
672 && s.verbose < 2)
673 return "";
674
5bcb7b4e
JL
675 set<string> functors;
676 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
677 {
678 string ftor = i->first.str();
679 if (ftor.find('(') != string::npos) // trim any parameter
680 ftor.erase(ftor.find('('));
681 functors.insert(ftor);
682 }
683 return levenshtein_suggest(functor, functors, 5); // print top 5
684}
b4ceace2 685
8eb6206c
SM
686void
687match_node::try_suffix_expansion (systemtap_session& s,
688 probe *p, probe_point *loc, unsigned pos,
689 vector<derived_probe *>& results)
690{
691 // PR12210: match alias suffixes. If the components thus far
692 // have been matched, but there is an additional unknown
693 // suffix, we have a potential alias suffix on our hands. We
694 // need to expand the preceding components as probe aliases,
695 // reattach the suffix, and re-run derive_probes() on the
696 // resulting expansion. This is done by the routine
697 // build_with_suffix().
698
699 if (strverscmp(s.compatible.c_str(), "2.0") >= 0)
700 {
701 // XXX: technically, param_map isn't used here. So don't
702 // bother actually assembling it unless some
703 // derived_probe_builder appears that actually takes
704 // suffixes *and* consults parameters (currently no such
705 // builders exist).
45a63356 706 literal_map_t param_map;
8eb6206c
SM
707 // for (unsigned i=0; i<pos; i++)
708 // param_map[loc->components[i]->functor] = loc->components[i]->arg;
709 // maybe 0
710
711 vector<probe_point::component *> suffix (loc->components.begin()+pos,
712 loc->components.end());
713
714 // Multiple derived_probe_builders may be bound at a
715 // match_node due to the possibility of multiply defined
716 // aliases.
717 for (unsigned k=0; k < ends.size(); k++)
718 {
719 derived_probe_builder *b = ends[k];
7f557fa7 720 try
8eb6206c
SM
721 {
722 b->build_with_suffix (s, p, loc, param_map, results, suffix);
7f557fa7 723 }
8eb6206c
SM
724 catch (const recursive_expansion_error &e)
725 {
726 // Re-throw:
e758508b 727 throw semantic_error(e);
8eb6206c
SM
728 }
729 catch (const semantic_error &e)
730 {
731 // Adjust source coordinate and re-throw:
732 if (! loc->optional)
dc09353a 733 throw semantic_error(e.errsrc, e.what(), loc->components[pos]->tok);
8eb6206c
SM
734 }
735 }
20c6c071
GH
736 }
737}
738
b4ceace2 739
aa30ccd3
FCE
740void
741match_node::build_no_more (systemtap_session& s)
742{
743 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
744 i->second->build_no_more (s);
2531fc1e
FCE
745 for (unsigned k=0; k<ends.size(); k++)
746 {
747 derived_probe_builder *b = ends[k];
748 b->build_no_more (s);
749 }
aa30ccd3
FCE
750}
751
b82d77b4
DB
752void
753match_node::dump (systemtap_session &s, const string &name)
754{
755 // Dump this node, if it is complete.
756 for (unsigned k=0; k<ends.size(); k++)
757 {
758 // Don't print aliases at all (for now) until we can figure out how to determine whether
759 // the probes they resolve to are ok in unprivileged mode.
760 if (ends[k]->is_alias ())
761 continue;
762
763 // In unprivileged mode, don't show the probes which are not allowed for unprivileged
764 // users.
f66bb29a 765 if (pr_contains (privilege, s.privilege))
b82d77b4
DB
766 {
767 cout << name << endl;
768 break; // we need only print one instance.
769 }
770 }
771
772 // Recursively dump the children of this node
773 string dot;
774 if (! name.empty ())
775 dot = ".";
776 for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++)
777 {
778 i->second->dump (s, name + dot + i->first.str());
779 }
780}
781
aa30ccd3 782
20c6c071
GH
783// ------------------------------------------------------------------------
784// Alias probes
785// ------------------------------------------------------------------------
786
c1d5f3f6
FCE
787struct alias_derived_probe: public derived_probe
788{
8eb6206c
SM
789 alias_derived_probe (probe* base, probe_point *l, const probe_alias *a,
790 const vector<probe_point::component *> *suffix = 0);
1e2efea5 791 ~alias_derived_probe();
c1d5f3f6 792
dc09353a 793 void upchuck () { throw SEMANTIC_ERROR (_("inappropriate"), this->tok); }
b20febf3
FCE
794
795 // Alias probes are immediately expanded to other derived_probe
796 // types, and are not themselves emitted or listed in
797 // systemtap_session.probes
dc38c0ae 798
78f6bba6 799 void join_group (systemtap_session&) { upchuck (); }
2c5a19c6
DB
800
801 virtual const probe_alias *get_alias () const { return alias; }
8eb6206c 802 virtual probe_point *get_alias_loc () const { return alias_loc; }
2a89b023 803 virtual probe_point *sole_location () const;
2c5a19c6
DB
804
805private:
806 const probe_alias *alias; // Used to check for recursion
8eb6206c 807 probe_point *alias_loc; // Hack to recover full probe name
c1d5f3f6
FCE
808};
809
8eb6206c
SM
810
811alias_derived_probe::alias_derived_probe(probe *base, probe_point *l,
812 const probe_alias *a,
813 const vector<probe_point::component *>
814 *suffix):
815 derived_probe (base, l), alias(a)
816{
817 // XXX pretty nasty -- this was cribbed from printscript() in main.cxx
818 assert (alias->alias_names.size() >= 1);
819 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
da631035
JL
820 alias_loc->well_formed = true;
821 vector<probe_point::component*>::const_iterator it;
822 for (it = suffix->begin(); it != suffix->end(); ++it)
823 {
824 alias_loc->components.push_back(*it);
825 if (isglob((*it)->functor))
826 alias_loc->well_formed = false; // needs further derivation
827 }
8eb6206c
SM
828}
829
1e2efea5
SM
830alias_derived_probe::~alias_derived_probe ()
831{
832 delete alias_loc;
833}
834
8eb6206c 835
2a89b023
FCE
836probe_point*
837alias_derived_probe::sole_location () const
838{
839 return const_cast<probe_point*>(alias_loc);
840}
841
842
e2012a7a
DB
843void
844alias_expansion_builder::build(systemtap_session & sess,
845 probe * use,
846 probe_point * location,
45a63356 847 literal_map_t const & parameters,
e2012a7a 848 vector<derived_probe *> & finished_results)
8eb6206c
SM
849{
850 vector<probe_point::component *> empty_suffix;
851 build_with_suffix (sess, use, location, parameters,
852 finished_results, empty_suffix);
853}
854
855void
856alias_expansion_builder::build_with_suffix(systemtap_session & sess,
857 probe * use,
858 probe_point * location,
45a63356 859 literal_map_t const &,
8eb6206c
SM
860 vector<derived_probe *>
861 & finished_results,
862 vector<probe_point::component *>
863 const & suffix)
20c6c071 864{
e2012a7a
DB
865 // Don't build the alias expansion if infinite recursion is detected.
866 if (checkForRecursiveExpansion (use)) {
867 stringstream msg;
7f557fa7 868 msg << _F("recursive loop in alias expansion of %s at %s",
4af765b2 869 lex_cast(*location).c_str(), lex_cast(location->components.front()->tok->location).c_str());
8eb6206c
SM
870 // semantic_errors thrown here might be ignored, so we need a special class:
871 throw recursive_expansion_error (msg.str());
872 // XXX The point of throwing this custom error is to suppress a
873 // cascade of "probe mismatch" messages that appear in addition to
874 // the error. The current approach suppresses most of the error
875 // cascade, but leaves one spurious error; in any case, the way
876 // this particular error is reported could be improved.
e2012a7a 877 }
57148ee7 878
e2012a7a
DB
879 // We're going to build a new probe and wrap it up in an
880 // alias_expansion_probe so that the expansion loop recognizes it as
881 // such and re-expands its expansion.
20c6c071 882
8eb6206c 883 alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias, &suffix);
e2012a7a 884 n->body = new block();
5d23847d 885
8eb6206c
SM
886 // The new probe gets a deep copy of the location list of the alias
887 // (with incoming condition joined) plus the suffix (if any),
e2012a7a
DB
888 n->locations.clear();
889 for (unsigned i=0; i<alias->locations.size(); i++)
890 {
891 probe_point *pp = new probe_point(*alias->locations[i]);
8eb6206c 892 pp->components.insert(pp->components.end(), suffix.begin(), suffix.end());
e2012a7a
DB
893 pp->condition = add_condition (pp->condition, location->condition);
894 n->locations.push_back(pp);
895 }
20c6c071 896
e2012a7a
DB
897 // the token location of the alias,
898 n->tok = location->components.front()->tok;
5227f1ea 899
e2012a7a
DB
900 // and statements representing the concatenation of the alias'
901 // body with the use's.
902 //
903 // NB: locals are *not* copied forward, from either alias or
904 // use. The expansion should have its locals re-inferred since
905 // there's concatenated code here and we only want one vardecl per
906 // resulting variable.
57148ee7 907
e2012a7a
DB
908 if (alias->epilogue_style)
909 n->body = new block (use->body, alias->body);
910 else
911 n->body = new block (alias->body, use->body);
a3b4f52c 912
e2012a7a 913 unsigned old_num_results = finished_results.size();
8eb6206c
SM
914 // If expanding for an alias suffix, be sure to pass on any errors
915 // to the caller instead of printing them in derive_probes():
916 derive_probes (sess, n, finished_results, location->optional, !suffix.empty());
2c5a19c6 917
e2012a7a
DB
918 // Check whether we resolved something. If so, put the
919 // whole library into the queue if not already there.
920 if (finished_results.size() > old_num_results)
921 {
922 stapfile *f = alias->tok->location.file;
923 if (find (sess.files.begin(), sess.files.end(), f)
924 == sess.files.end())
925 sess.files.push_back (f);
2c5a19c6 926 }
e2012a7a
DB
927}
928
929bool
930alias_expansion_builder::checkForRecursiveExpansion (probe *use)
931{
932 // Collect the derivation chain of this probe.
933 vector<probe*>derivations;
934 use->collect_derivation_chain (derivations);
935
936 // Check all probe points in the alias expansion against the currently-being-expanded probe point
937 // of each of the probes in the derivation chain, looking for a match. This
938 // indicates infinite recursion.
939 // The first element of the derivation chain will be the derived_probe representing 'use', so
940 // start the search with the second element.
941 assert (derivations.size() > 0);
942 assert (derivations[0] == use);
943 for (unsigned d = 1; d < derivations.size(); ++d) {
944 if (use->get_alias() == derivations[d]->get_alias())
945 return true; // recursion detected
2c5a19c6 946 }
e2012a7a
DB
947 return false;
948}
20c6c071
GH
949
950
951// ------------------------------------------------------------------------
952// Pattern matching
953// ------------------------------------------------------------------------
954
5227f1ea
GH
955static unsigned max_recursion = 100;
956
57148ee7 957struct
5227f1ea
GH
958recursion_guard
959{
960 unsigned & i;
961 recursion_guard(unsigned & i) : i(i)
962 {
963 if (i > max_recursion)
dc09353a 964 throw SEMANTIC_ERROR(_("recursion limit reached"));
5227f1ea
GH
965 ++i;
966 }
57148ee7 967 ~recursion_guard()
5227f1ea
GH
968 {
969 --i;
970 }
971};
972
20c6c071
GH
973// The match-and-expand loop.
974void
b4ceace2
FCE
975derive_probes (systemtap_session& s,
976 probe *p, vector<derived_probe*>& dps,
8eb6206c
SM
977 bool optional,
978 bool rethrow_errors)
20c6c071 979{
168e2ef5
JL
980 // We need a static to track whether the current probe is optional so that
981 // even if we recurse into derive_probes with optional = false, errors will
982 // still be ignored. The undo_parent_optional bool ensures we reset the
983 // static at the same level we had it set.
984 static bool parent_optional = false;
985 bool undo_parent_optional = false;
986
987 if (optional && !parent_optional)
988 {
989 parent_optional = true;
990 undo_parent_optional = true;
991 }
992
4f31fb82
JL
993 vector <semantic_error> optional_errs;
994
20c6c071
GH
995 for (unsigned i = 0; i < p->locations.size(); ++i)
996 {
e19ebcf7 997 assert_no_interrupts();
49abf162 998
20c6c071 999 probe_point *loc = p->locations[i];
a971b891 1000
d885563b
FCE
1001 if (s.verbose > 4)
1002 clog << "derive-probes " << *loc << endl;
1003
fe3d01fa
FCE
1004 try
1005 {
fe3d01fa 1006 unsigned num_atbegin = dps.size();
d898100a 1007
74efda8d
WH
1008 try
1009 {
1010 s.pattern_root->find_and_build (s, p, loc, 0, dps); // <-- actual derivation!
1011 }
1012 catch (const semantic_error& e)
1013 {
168e2ef5 1014 if (!loc->optional && !parent_optional)
74efda8d
WH
1015 throw semantic_error(e);
1016 else /* tolerate failure for optional probe */
4f31fb82
JL
1017 {
1018 // remember err, we will print it (in catch block) if any
1019 // non-optional loc fails to resolve
1020 semantic_error err(ERR_SRC, _("while resolving probe point"),
1021 loc->components[0]->tok, NULL, &e);
1022 optional_errs.push_back(err);
1023 continue;
1024 }
74efda8d
WH
1025 }
1026
fe3d01fa 1027 unsigned num_atend = dps.size();
d898100a 1028
168e2ef5 1029 if (! (loc->optional||parent_optional) && // something required, but
cedd10f4 1030 num_atbegin == num_atend) // nothing new derived!
dc09353a 1031 throw SEMANTIC_ERROR (_("no match"));
d898100a
FCE
1032
1033 if (loc->sufficient && (num_atend > num_atbegin))
1034 {
1035 if (s.verbose > 1)
1036 {
1037 clog << "Probe point ";
1038 p->locations[i]->print(clog);
1039 clog << " sufficient, skipped";
1040 for (unsigned j = i+1; j < p->locations.size(); ++j)
1041 {
1042 clog << " ";
1043 p->locations[j]->print(clog);
1044 }
1045 clog << endl;
1046 }
1047 break; // we need not try to derive for any other locations
1048 }
fe3d01fa
FCE
1049 }
1050 catch (const semantic_error& e)
1051 {
8eb6206c
SM
1052 // The rethrow_errors parameter lets the caller decide an
1053 // alternative to printing the error. This is necessary when
1054 // calling derive_probes() recursively during expansion of
1055 // an alias with suffix -- any message printed here would
1056 // point to the alias declaration and not the invalid suffix
1057 // usage, so the caller needs to catch the error themselves
1058 // and print a more appropriate message.
1059 if (rethrow_errors)
1060 {
e758508b 1061 throw semantic_error(e);
8eb6206c 1062 }
bba368c5
JL
1063 // Only output in dump mode if -vv is supplied:
1064 else if (!s.dump_mode || (s.verbose > 1))
68ac5d0e 1065 {
4f31fb82
JL
1066 // print this one manually first because it's more important than
1067 // the optional errs
1068 semantic_error err(ERR_SRC, _("while resolving probe point"),
1069 loc->components[0]->tok, NULL, &e);
1070 s.print_error(err);
1071
1072 // print optional errs accumulated while visiting other probe points
1073 for (vector<semantic_error>::const_iterator it = optional_errs.begin();
1074 it != optional_errs.end(); ++it)
1075 {
1076 s.print_error(*it);
1077 }
68ac5d0e 1078 }
fe3d01fa 1079 }
20c6c071 1080 }
168e2ef5
JL
1081
1082 if (undo_parent_optional)
1083 parent_optional = false;
20c6c071
GH
1084}
1085
b4ceace2
FCE
1086
1087
20c6c071 1088// ------------------------------------------------------------------------
67c0a579 1089//
d02548c0 1090// Indexable usage checks
67c0a579
GH
1091//
1092
d02548c0 1093struct symbol_fetcher
07c17d67 1094 : public throwing_visitor
67c0a579 1095{
d02548c0 1096 symbol *&sym;
67c0a579 1097
57148ee7 1098 symbol_fetcher (symbol *&sym): sym(sym)
67c0a579
GH
1099 {}
1100
d02548c0
GH
1101 void visit_symbol (symbol* e)
1102 {
1103 sym = e;
1104 }
1105
1106 void visit_arrayindex (arrayindex* e)
1107 {
d15d767c 1108 e->base->visit (this);
d02548c0
GH
1109 }
1110
1111 void throwone (const token* t)
1112 {
bd70b999 1113 throw SEMANTIC_ERROR (_("Expecting symbol or array index expression"), t);
d02548c0
GH
1114 }
1115};
1116
07c17d67 1117symbol *
d02548c0
GH
1118get_symbol_within_expression (expression *e)
1119{
1120 symbol *sym = NULL;
1121 symbol_fetcher fetcher(sym);
1122 e->visit (&fetcher);
b0be9bdb 1123 return sym; // NB: may be null!
d02548c0
GH
1124}
1125
1126static symbol *
1127get_symbol_within_indexable (indexable *ix)
1128{
1129 symbol *array = NULL;
1130 hist_op *hist = NULL;
1131 classify_indexable(ix, array, hist);
1132 if (array)
1133 return array;
1134 else
1135 return get_symbol_within_expression (hist->stat);
1136}
1137
1138struct mutated_var_collector
07c17d67 1139 : public traversing_visitor
d02548c0
GH
1140{
1141 set<vardecl *> * mutated_vars;
1142
57148ee7 1143 mutated_var_collector (set<vardecl *> * mm)
d02548c0
GH
1144 : mutated_vars (mm)
1145 {}
1146
1147 void visit_assignment(assignment* e)
1148 {
1149 if (e->type == pe_stats && e->op == "<<<")
1150 {
1151 vardecl *vd = get_symbol_within_expression (e->left)->referent;
1152 if (vd)
1153 mutated_vars->insert (vd);
1154 }
1bbeef03 1155 traversing_visitor::visit_assignment(e);
d02548c0
GH
1156 }
1157
67c0a579
GH
1158 void visit_arrayindex (arrayindex *e)
1159 {
d02548c0
GH
1160 if (is_active_lvalue (e))
1161 {
1162 symbol *sym;
1163 if (e->base->is_symbol (sym))
1164 mutated_vars->insert (sym->referent);
1165 else
dc09353a 1166 throw SEMANTIC_ERROR(_("Assignment to read-only histogram bucket"), e->tok);
d02548c0 1167 }
1bbeef03 1168 traversing_visitor::visit_arrayindex (e);
67c0a579
GH
1169 }
1170};
1171
1172
d02548c0 1173struct no_var_mutation_during_iteration_check
07c17d67 1174 : public traversing_visitor
67c0a579
GH
1175{
1176 systemtap_session & session;
d02548c0
GH
1177 map<functiondecl *,set<vardecl *> *> & function_mutates_vars;
1178 vector<vardecl *> vars_being_iterated;
57148ee7
FCE
1179
1180 no_var_mutation_during_iteration_check
67c0a579 1181 (systemtap_session & sess,
d02548c0
GH
1182 map<functiondecl *,set<vardecl *> *> & fmv)
1183 : session(sess), function_mutates_vars (fmv)
67c0a579
GH
1184 {}
1185
1186 void visit_arrayindex (arrayindex *e)
1187 {
d7f3e0c5 1188 if (is_active_lvalue(e))
67c0a579 1189 {
d02548c0
GH
1190 vardecl *vd = get_symbol_within_indexable (e->base)->referent;
1191 if (vd)
67c0a579 1192 {
d02548c0 1193 for (unsigned i = 0; i < vars_being_iterated.size(); ++i)
67c0a579 1194 {
d02548c0
GH
1195 vardecl *v = vars_being_iterated[i];
1196 if (v == vd)
1197 {
4af765b2 1198 string err = _F("variable '%s' modified during 'foreach' iteration",
5eb6ecb1 1199 v->unmangled_name.to_string().c_str());
dc09353a 1200 session.print_error (SEMANTIC_ERROR (err, e->tok));
d02548c0 1201 }
67c0a579
GH
1202 }
1203 }
1204 }
1bbeef03 1205 traversing_visitor::visit_arrayindex (e);
67c0a579
GH
1206 }
1207
1208 void visit_functioncall (functioncall* e)
1209 {
7b5b30a8 1210 for (unsigned fd = 0; fd < e->referents.size(); fd++)
67c0a579 1211 {
7b5b30a8
FL
1212 map<functiondecl *,set<vardecl *> *>::const_iterator i
1213 = function_mutates_vars.find (e->referents[fd]);
1214
1215 if (i != function_mutates_vars.end())
1216 {
1217 for (unsigned j = 0; j < vars_being_iterated.size(); ++j)
1218 {
1219 vardecl *m = vars_being_iterated[j];
1220 if (i->second->find (m) != i->second->end())
1221 {
1222 string err = _F("function call modifies var '%s' during 'foreach' iteration",
1223 m->unmangled_name.to_string().c_str());
1224 session.print_error (SEMANTIC_ERROR (err, e->tok));
1225 }
1226 }
1227 }
67c0a579
GH
1228 }
1229
1bbeef03 1230 traversing_visitor::visit_functioncall (e);
67c0a579
GH
1231 }
1232
1233 void visit_foreach_loop(foreach_loop* s)
1234 {
d02548c0
GH
1235 vardecl *vd = get_symbol_within_indexable (s->base)->referent;
1236
1237 if (vd)
1238 vars_being_iterated.push_back (vd);
57148ee7 1239
1bbeef03 1240 traversing_visitor::visit_foreach_loop (s);
d02548c0
GH
1241
1242 if (vd)
1243 vars_being_iterated.pop_back();
67c0a579
GH
1244 }
1245};
20c6c071 1246
2b066ec1 1247
67c0a579
GH
1248// ------------------------------------------------------------------------
1249
07c17d67
GH
1250struct stat_decl_collector
1251 : public traversing_visitor
1252{
1253 systemtap_session & session;
57148ee7 1254
07c17d67
GH
1255 stat_decl_collector(systemtap_session & sess)
1256 : session(sess)
1257 {}
1258
1259 void visit_stat_op (stat_op* e)
1260 {
1261 symbol *sym = get_symbol_within_expression (e->stat);
1262 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1263 session.stat_decls[sym->name] = statistic_decl();
1264 }
1265
1266 void visit_assignment (assignment* e)
1267 {
1268 if (e->op == "<<<")
1269 {
1270 symbol *sym = get_symbol_within_expression (e->left);
1271 if (session.stat_decls.find(sym->name) == session.stat_decls.end())
1272 session.stat_decls[sym->name] = statistic_decl();
1273 }
1274 else
1275 traversing_visitor::visit_assignment(e);
1276 }
1277
1278 void visit_hist_op (hist_op* e)
1279 {
1280 symbol *sym = get_symbol_within_expression (e->stat);
1281 statistic_decl new_stat;
1282
1283 if (e->htype == hist_linear)
1284 {
1285 new_stat.type = statistic_decl::linear;
1286 assert (e->params.size() == 3);
1287 new_stat.linear_low = e->params[0];
1288 new_stat.linear_high = e->params[1];
1289 new_stat.linear_step = e->params[2];
1290 }
1291 else
1292 {
1293 assert (e->htype == hist_log);
1294 new_stat.type = statistic_decl::logarithmic;
e38723d2 1295 assert (e->params.size() == 0);
07c17d67
GH
1296 }
1297
47d349b1 1298 map<interned_string, statistic_decl>::iterator i = session.stat_decls.find(sym->name);
07c17d67
GH
1299 if (i == session.stat_decls.end())
1300 session.stat_decls[sym->name] = new_stat;
1301 else
1302 {
1303 statistic_decl & old_stat = i->second;
1304 if (!(old_stat == new_stat))
1305 {
1306 if (old_stat.type == statistic_decl::none)
1307 i->second = new_stat;
1308 else
1309 {
1310 // FIXME: Support multiple co-declared histogram types
7371cd19
JS
1311 semantic_error se(ERR_SRC, _F("multiple histogram types declared on '%s'",
1312 sym->name.to_string().c_str()), e->tok);
07c17d67
GH
1313 session.print_error (se);
1314 }
1315 }
57148ee7 1316 }
07c17d67
GH
1317 }
1318
1319};
1320
1321static int
1322semantic_pass_stats (systemtap_session & sess)
1323{
1324 stat_decl_collector sdc(sess);
1325
f76427a2
FCE
1326 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
1327 it->second->body->visit (&sdc);
07c17d67 1328
57148ee7 1329 for (unsigned i = 0; i < sess.probes.size(); ++i)
07c17d67
GH
1330 sess.probes[i]->body->visit (&sdc);
1331
1332 for (unsigned i = 0; i < sess.globals.size(); ++i)
1333 {
1334 vardecl *v = sess.globals[i];
1335 if (v->type == pe_stats)
1336 {
57148ee7 1337
07c17d67
GH
1338 if (sess.stat_decls.find(v->name) == sess.stat_decls.end())
1339 {
7371cd19 1340 semantic_error se(ERR_SRC, _F("unable to infer statistic parameters for global '%s'",
5eb6ecb1 1341 v->unmangled_name.to_string().c_str()));
07c17d67
GH
1342 sess.print_error (se);
1343 }
1344 }
1345 }
57148ee7 1346
7e41d3dc 1347 return sess.num_errors();
07c17d67
GH
1348}
1349
5d23847d
FCE
1350// ------------------------------------------------------------------------
1351
1352// Enforce variable-related invariants: no modification of
1353// a foreach()-iterated array.
1354static int
1355semantic_pass_vars (systemtap_session & sess)
1356{
57148ee7 1357
5d23847d
FCE
1358 map<functiondecl *, set<vardecl *> *> fmv;
1359 no_var_mutation_during_iteration_check chk(sess, fmv);
57148ee7 1360
f76427a2 1361 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
5d23847d 1362 {
f76427a2 1363 functiondecl * fn = it->second;
5d23847d
FCE
1364 if (fn->body)
1365 {
1366 set<vardecl *> * m = new set<vardecl *>();
1367 mutated_var_collector mc (m);
1368 fn->body->visit (&mc);
1369 fmv[fn] = m;
1370 }
1371 }
1372
f76427a2 1373 for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++)
5d23847d 1374 {
f76427a2
FCE
1375 functiondecl * fn = it->second;
1376 if (fn->body) fn->body->visit (&chk);
5d23847d
FCE
1377 }
1378
1379 for (unsigned i = 0; i < sess.probes.size(); ++i)
1380 {
1381 if (sess.probes[i]->body)
1382 sess.probes[i]->body->visit (&chk);
57148ee7 1383 }
5d23847d
FCE
1384
1385 return sess.num_errors();
1386}
1387
1388
1389// ------------------------------------------------------------------------
1390
1391// Rewrite probe condition expressions into probe bodies. Tricky and
1392// exciting business, this. This:
1393//
1394// probe foo if (g1 || g2) { ... }
1395// probe bar { ... g1 ++ ... }
1396//
1397// becomes:
1398//
5d23847d 1399// probe foo { if (! (g1 || g2)) next; ... }
57148ee7 1400// probe bar { ... g1 ++ ...;
5d23847d
FCE
1401// if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1402// }
1403//
ecf50eda
JL
1404// In other words, we perform two transformations:
1405// (1) Inline probe condition into its body.
1406// (2) For each probe that modifies a global var in use in any probe's
1407// condition, re-evaluate those probes' condition at the end of that
1408// probe's body.
1409//
1410// Here, we do all of (1), and half of (2): we simply collect the dependency
1411// info between probes, which the translator will use to emit the affected
1412// probes' condition re-evaluation. The translator will also ensure that the
1413// conditions are evaluated using the globals' starting values prior to any
1414// probes starting.
1415
1416// Adds the condition expression to the front of the probe's body
1417static void
1418derived_probe_condition_inline (derived_probe *p)
1419{
1420 expression* e = p->sole_location()->condition;
1421 assert(e);
1422
1423 if_statement *ifs = new if_statement ();
1424 ifs->tok = e->tok;
1425 ifs->thenblock = new next_statement ();
1426 ifs->thenblock->tok = e->tok;
1427 ifs->elseblock = NULL;
1428 unary_expression *notex = new unary_expression ();
1429 notex->op = "!";
1430 notex->tok = e->tok;
1431 notex->operand = e;
1432 ifs->condition = notex;
1433 p->body = new block (ifs, p->body);
1434}
5d23847d
FCE
1435
1436static int
1437semantic_pass_conditions (systemtap_session & sess)
1438{
ecf50eda
JL
1439 map<derived_probe*, set<vardecl*> > vars_read_in_cond;
1440 map<derived_probe*, set<vardecl*> > vars_written_in_body;
1441
1442 // do a first pass through the probes to ensure safety, inline any condition,
1443 // and collect var usage
5d23847d
FCE
1444 for (unsigned i = 0; i < sess.probes.size(); ++i)
1445 {
1446 derived_probe* p = sess.probes[i];
1447 expression* e = p->sole_location()->condition;
ecf50eda 1448
5d23847d
FCE
1449 if (e)
1450 {
ecf50eda
JL
1451 varuse_collecting_visitor vcv_cond(sess);
1452 e->visit (& vcv_cond);
1453
1454 if (!vcv_cond.written.empty())
1455 sess.print_error (SEMANTIC_ERROR (_("probe condition must not "
1456 "modify any variables"),
1457 e->tok));
1458 else if (vcv_cond.embedded_seen)
1459 sess.print_error (SEMANTIC_ERROR (_("probe condition must not "
1460 "include impure embedded-C"),
1461 e->tok));
1462
1463 derived_probe_condition_inline(p);
1464
1465 vars_read_in_cond[p].insert(vcv_cond.read.begin(),
1466 vcv_cond.read.end());
1467 }
5d23847d 1468
ecf50eda
JL
1469 varuse_collecting_visitor vcv_body(sess);
1470 p->body->visit (& vcv_body);
1471
1472 vars_written_in_body[p].insert(vcv_body.written.begin(),
1473 vcv_body.written.end());
1474 }
1475
1476 // do a second pass to collect affected probes
ecf50eda
JL
1477 for (unsigned i = 0; i < sess.probes.size(); ++i)
1478 {
1479 derived_probe *p = sess.probes[i];
1480
1481 // for each variable this probe modifies...
1482 set<vardecl*>::const_iterator var;
1483 for (var = vars_written_in_body[p].begin();
1484 var != vars_written_in_body[p].end(); ++var)
1485 {
1486 // collect probes which could be affected
1487 for (unsigned j = 0; j < sess.probes.size(); ++j)
5d23847d 1488 {
ecf50eda
JL
1489 if (vars_read_in_cond[sess.probes[j]].count(*var))
1490 {
1491 if (!p->probes_with_affected_conditions.count(sess.probes[j]))
1492 {
1493 p->probes_with_affected_conditions.insert(sess.probes[j]);
1494 if (sess.verbose > 2)
1495 clog << "probe " << i << " can affect condition of "
1496 "probe " << j << endl;
1497 }
ecf50eda 1498 }
5d23847d 1499 }
5d23847d 1500 }
57148ee7 1501 }
5d23847d 1502
f161bd74
JL
1503 // PR18115: We create a begin probe which is artificially registered as
1504 // affecting every other probe. This will serve as the initializer so that
1505 // other probe types with false conditions can be skipped (or registered as
1506 // disabled) during module initialization.
1507
1508 set<derived_probe*> targets;
1509 for (unsigned i = 0; i < sess.probes.size(); ++i)
1510 if (!vars_read_in_cond[sess.probes[i]].empty())
1511 targets.insert(sess.probes[i]);
1512
1513 if (!targets.empty())
1514 {
1515 stringstream ss("probe begin {}");
1516
1517 // no good token to choose here... let's just use the condition expression
1518 // of one of the probes as the token
1519 const token *tok = (*targets.begin())->sole_location()->condition->tok;
1520
1521 probe *p = parse_synthetic_probe(sess, ss, tok);
1522 if (!p)
1523 throw SEMANTIC_ERROR (_("can't create cond initializer probe"), tok);
1524
1525 vector<derived_probe*> dps;
1526 derive_probes(sess, p, dps);
1527
1528 // there should only be one
1529 assert(dps.size() == 1);
1530
1531 derived_probe* dp = dps[0];
1532 dp->probes_with_affected_conditions.insert(targets.begin(),
1533 targets.end());
1534 sess.probes.push_back (dp);
1535 dp->join_group (sess);
1536
1537 // no need to manually do symresolution since body is empty
1538 }
1539
5d23847d
FCE
1540 return sess.num_errors();
1541}
1542
ac9ca50a
MW
1543// ------------------------------------------------------------------------
1544
1545
1546// Simple visitor that just goes through all embedded code blocks that
1547// are available at the end all the optimizations to register any
1548// relevant pragmas or other indicators found, so that session flags can
1549// be set that can be inspected at translation time to trigger any
1550// necessary initialization of code needed by the embedded code functions.
1551
1552// This is only for pragmas that don't have any other side-effect than
8af41ec2 1553// needing some initialization at module init time. Currently handles
0af18f5a 1554// /* pragma:vma */ /* pragma:unwind */ /* pragma:symbols */ /* pragma:lines */
ac9ca50a
MW
1555
1556// /* pragma:uprobes */ is handled during the typeresolution_info pass.
2363d2a5
DB
1557// /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */
1558// are handled by the varuse_collecting_visitor.
ac9ca50a
MW
1559
1560struct embeddedcode_info: public functioncall_traversing_visitor
1561{
1562protected:
1563 systemtap_session& session;
1564
1565public:
1566 embeddedcode_info (systemtap_session& s): session(s) { }
1567
1568 void visit_embeddedcode (embeddedcode* c)
1569 {
a057c85c 1570 if (! vma_tracker_enabled(session)
ac9ca50a
MW
1571 && c->code.find("/* pragma:vma */") != string::npos)
1572 {
ac9ca50a 1573 if (session.verbose > 2)
4af765b2 1574 clog << _F("Turning on task_finder vma_tracker, pragma:vma found in %s",
5eb6ecb1 1575 current_function->unmangled_name.to_string().c_str()) << endl;
7f085e3f
JS
1576
1577 // PR15052: stapdyn doesn't have VMA-tracking yet.
1578 if (session.runtime_usermode_p())
dc09353a 1579 throw SEMANTIC_ERROR(_("VMA-tracking is only supported by the kernel runtime (PR15052)"), c->tok);
7f085e3f
JS
1580
1581 enable_vma_tracker(session);
ac9ca50a 1582 }
08badca8
MW
1583
1584 if (! session.need_unwind
1585 && c->code.find("/* pragma:unwind */") != string::npos)
1586 {
1587 if (session.verbose > 2)
1588 clog << _F("Turning on unwind support, pragma:unwind found in %s",
5eb6ecb1 1589 current_function->unmangled_name.to_string().c_str()) << endl;
8af41ec2
MW
1590 session.need_unwind = true;
1591 }
1592
1593 if (! session.need_symbols
1594 && c->code.find("/* pragma:symbols */") != string::npos)
1595 {
1596 if (session.verbose > 2)
1597 clog << _F("Turning on symbol data collecting, pragma:symbols found in %s",
5eb6ecb1
DS
1598 current_function->unmangled_name.to_string().c_str())
1599 << endl;
8af41ec2
MW
1600 session.need_symbols = true;
1601 }
ee533a58
AJ
1602
1603 if (! session.need_lines
1604 && c->code.find("/* pragma:lines */") != string::npos)
1605 {
1606 if (session.verbose > 2)
1607 clog << _F("Turning on debug line data collecting, pragma:lines found in %s",
5eb6ecb1
DS
1608 current_function->unmangled_name.to_string().c_str())
1609 << endl;
dbfc9df8 1610 session.need_lines = true;
ee533a58 1611 }
ac9ca50a
MW
1612 }
1613};
1614
1615void embeddedcode_info_pass (systemtap_session& s)
1616{
1617 embeddedcode_info eci (s);
1618 for (unsigned i=0; i<s.probes.size(); i++)
1619 s.probes[i]->body->visit (& eci);
1620}
5d23847d 1621
07c17d67
GH
1622// ------------------------------------------------------------------------
1623
2b066ec1 1624
d2548fe7
SM
1625// Simple visitor that collects all the regular expressions in the
1626// file and adds them to the session DFA table.
1627
1628struct regex_collecting_visitor: public functioncall_traversing_visitor
1629{
1630protected:
1631 systemtap_session& session;
1632
1633public:
1634 regex_collecting_visitor (systemtap_session& s): session(s) { }
1635
1636 void visit_regex_query (regex_query *q) {
d3bc48f0 1637 functioncall_traversing_visitor::visit_regex_query (q);
d2548fe7 1638
47d349b1 1639 string re = q->right->value;
60cf5fae 1640 regex_to_stapdfa (&session, re, q->right->tok);
d2548fe7
SM
1641 }
1642};
1643
1644// Go through the regex match invocations and generate corresponding DFAs.
e471dfb0 1645int gen_dfa_table (systemtap_session& s)
d2548fe7 1646{
e471dfb0 1647 regex_collecting_visitor rcv(s);
d2548fe7
SM
1648
1649 for (unsigned i=0; i<s.probes.size(); i++)
1650 {
e471dfb0
SM
1651 try
1652 {
1653 s.probes[i]->body->visit (& rcv);
1654
1655 if (s.probes[i]->sole_location()->condition)
1656 s.probes[i]->sole_location()->condition->visit (& rcv);
1657 }
1658 catch (const semantic_error& e)
1659 {
1660 s.print_error (e);
1661 }
d2548fe7 1662 }
e471dfb0
SM
1663
1664 return s.num_errors();
d2548fe7
SM
1665}
1666
1667// ------------------------------------------------------------------------
1668
1669
2b066ec1 1670static int semantic_pass_symbols (systemtap_session&);
c214bd6a
DS
1671static int semantic_pass_optimize1 (systemtap_session&);
1672static int semantic_pass_optimize2 (systemtap_session&);
2b066ec1 1673static int semantic_pass_types (systemtap_session&);
d02548c0 1674static int semantic_pass_vars (systemtap_session&);
07c17d67 1675static int semantic_pass_stats (systemtap_session&);
5d23847d 1676static int semantic_pass_conditions (systemtap_session&);
2b066ec1
FCE
1677
1678
40a393cd
JS
1679struct expression_build_no_more_visitor : public expression_visitor
1680{
1681 // Clear extra details from every expression, like DWARF type info, so that
1682 // builders can safely release them in build_no_more. From here on out,
1683 // we're back to basic types only.
1684 void visit_expression(expression *e)
1685 {
1686 e->type_details.reset();
1687 }
1688};
1689
1690static void
1691build_no_more (systemtap_session& s)
1692{
1693 expression_build_no_more_visitor v;
1694
1695 for (unsigned i=0; i<s.probes.size(); i++)
1696 s.probes[i]->body->visit(&v);
1697
1698 for (map<string,functiondecl*>::iterator it = s.functions.begin();
1699 it != s.functions.end(); it++)
1700 it->second->body->visit(&v);
1701
1702 // Inform all derived_probe builders that we're done with
1703 // all resolution, so it's time to release caches.
1704 s.pattern_root->build_no_more (s);
1705}
1706
1707
1708
2b066ec1
FCE
1709// Link up symbols to their declarations. Set the session's
1710// files/probes/functions/globals vectors from the transitively
1711// reached set of stapfiles in s.library_files, starting from
20c6c071 1712// s.user_file. Perform automatic tapset inclusion and probe
2b066ec1
FCE
1713// alias expansion.
1714static int
1715semantic_pass_symbols (systemtap_session& s)
1716{
1717 symresolution_info sym (s);
1718
eb9ea966
JL
1719 // If we're listing functions, then we need to include all the files. Probe
1720 // aliases won't be visited/derived so all we gain are the functions, global
1721 // variables, and any real probes (e.g. begin probes). NB: type resolution for
1722 // a specific function arg may fail if it could only be determined from a
1723 // function call in one of the skipped aliases.
bba368c5 1724 if (s.dump_mode == systemtap_session::dump_functions)
eb9ea966
JL
1725 {
1726 s.files.insert(s.files.end(), s.library_files.begin(),
1727 s.library_files.end());
1728 }
ba48c27a 1729 else if (!s.user_files.empty())
bba368c5 1730 {
ba48c27a 1731 // Normal run: seed s.files with user_files and let it grow through the
bba368c5
JL
1732 // find_* functions. NB: s.files can grow during this iteration, so
1733 // size() can return gradually increasing numbers.
ba48c27a 1734 s.files.insert (s.files.end(), s.user_files.begin(), s.user_files.end());
bba368c5 1735 }
eb9ea966 1736
2b066ec1
FCE
1737 for (unsigned i = 0; i < s.files.size(); i++)
1738 {
e19ebcf7 1739 assert_no_interrupts();
2b066ec1
FCE
1740 stapfile* dome = s.files[i];
1741
1742 // Pass 1: add globals and functions to systemtap-session master list,
1743 // so the find_* functions find them
e26c2f83
FCE
1744 //
1745 // NB: tapset global/function definitions may duplicate or conflict
1746 // with those already in s.globals/functions. We need to deconflict
1747 // here.
2b066ec1
FCE
1748
1749 for (unsigned i=0; i<dome->globals.size(); i++)
e26c2f83
FCE
1750 {
1751 vardecl* g = dome->globals[i];
1752 for (unsigned j=0; j<s.globals.size(); j++)
1753 {
1754 vardecl* g2 = s.globals[j];
1755 if (g->name == g2->name)
1756 {
dc09353a 1757 s.print_error (SEMANTIC_ERROR (_("conflicting global variables"),
e26c2f83
FCE
1758 g->tok, g2->tok));
1759 }
1760 }
1761 s.globals.push_back (g);
1762 }
2b066ec1
FCE
1763
1764 for (unsigned i=0; i<dome->functions.size(); i++)
e26c2f83
FCE
1765 {
1766 functiondecl* f = dome->functions[i];
1767 functiondecl* f2 = s.functions[f->name];
1768 if (f2 && f != f2)
1769 {
dc09353a 1770 s.print_error (SEMANTIC_ERROR (_("conflicting functions"),
e26c2f83
FCE
1771 f->tok, f2->tok));
1772 }
1773 s.functions[f->name] = f;
1774 }
2b066ec1 1775
e26c2f83 1776 // NB: embeds don't conflict with each other
54dfabe9
FCE
1777 for (unsigned i=0; i<dome->embeds.size(); i++)
1778 s.embeds.push_back (dome->embeds[i]);
1779
f8809d54 1780 // Pass 2: derive probes and resolve any further symbols in the
57148ee7 1781 // derived results.
2b066ec1
FCE
1782
1783 for (unsigned i=0; i<dome->probes.size(); i++)
1784 {
e19ebcf7 1785 assert_no_interrupts();
2b066ec1
FCE
1786 probe* p = dome->probes [i];
1787 vector<derived_probe*> dps;
1788
a971b891
FCE
1789 // much magic happens here: probe alias expansion, wildcard
1790 // matching, low-level derived_probe construction.
b4ceace2 1791 derive_probes (s, p, dps);
2b066ec1
FCE
1792
1793 for (unsigned j=0; j<dps.size(); j++)
1794 {
e19ebcf7 1795 assert_no_interrupts();
2b066ec1 1796 derived_probe* dp = dps[j];
b20febf3
FCE
1797 s.probes.push_back (dp);
1798 dp->join_group (s);
2b066ec1 1799
57148ee7 1800 try
2b066ec1 1801 {
f80d9004 1802 for (unsigned k=0; k<s.code_filters.size(); k++)
8b095b45 1803 s.code_filters[k]->replace (dp->body);
f80d9004 1804
2b066ec1 1805 sym.current_function = 0;
5227f1ea 1806 sym.current_probe = dp;
2b066ec1 1807 dp->body->visit (& sym);
5d23847d
FCE
1808
1809 // Process the probe-point condition expression.
1810 sym.current_function = 0;
1811 sym.current_probe = 0;
1812 if (dp->sole_location()->condition)
1813 dp->sole_location()->condition->visit (& sym);
2b066ec1
FCE
1814 }
1815 catch (const semantic_error& e)
1816 {
1817 s.print_error (e);
1818 }
1819 }
1820 }
f8809d54
JS
1821
1822 // Pass 3: process functions
1823
1824 for (unsigned i=0; i<dome->functions.size(); i++)
1825 {
e19ebcf7 1826 assert_no_interrupts();
f8809d54
JS
1827 functiondecl* fd = dome->functions[i];
1828
1829 try
1830 {
1831 for (unsigned j=0; j<s.code_filters.size(); j++)
1832 s.code_filters[j]->replace (fd->body);
1833
1834 sym.current_function = fd;
1835 sym.current_probe = 0;
1836 fd->body->visit (& sym);
1837 }
1838 catch (const semantic_error& e)
1839 {
1840 s.print_error (e);
1841 }
1842 }
2b066ec1 1843 }
aa30ccd3 1844
a07a2c28
LB
1845 if(s.systemtap_v_check){
1846 for(unsigned i=0;i<s.globals.size();i++){
1847 if(s.globals[i]->systemtap_v_conditional)
4af765b2 1848 s.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s.globals[i]->tok);
a07a2c28
LB
1849 }
1850
1851 for(map<string, functiondecl*>::const_iterator i=s.functions.begin();i != s.functions.end();++i){
1852 if(i->second->systemtap_v_conditional)
4af765b2 1853 s.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i->second->tok);
a07a2c28
LB
1854 }
1855
1856 for(unsigned i=0;i<s.probes.size();i++){
1857 vector<probe*> sysvc;
1858 s.probes[i]->collect_derivation_chain(sysvc);
1859 for(unsigned j=0;j<sysvc.size();j++){
1860 if(sysvc[j]->systemtap_v_conditional)
4af765b2 1861 s.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc[j]->tok);
a07a2c28 1862 if(sysvc[j]->get_alias() && sysvc[j]->get_alias()->systemtap_v_conditional)
4af765b2 1863 s.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc[j]->get_alias()->tok);
a07a2c28
LB
1864 }
1865 }
1866 }
1867
7e41d3dc 1868 return s.num_errors(); // all those print_error calls
2b066ec1
FCE
1869}
1870
1871
0a102c82
SC
1872// Keep unread global variables for probe end value display.
1873void add_global_var_display (systemtap_session& s)
1874{
bba368c5
JL
1875 // Don't generate synthetic end probes when in listing mode; it would clutter
1876 // up the list of probe points with "end ...". In fact, don't bother in any
1877 // dump mode at all, since it'll never be used.
1878 if (s.dump_mode) return;
3438f38f 1879
313db8e6 1880 varuse_collecting_visitor vut(s);
9d8a6ba3 1881
0a102c82
SC
1882 for (unsigned i=0; i<s.probes.size(); i++)
1883 {
1884 s.probes[i]->body->visit (& vut);
1885
1886 if (s.probes[i]->sole_location()->condition)
1887 s.probes[i]->sole_location()->condition->visit (& vut);
1888 }
1889
1890 for (unsigned g=0; g < s.globals.size(); g++)
1891 {
1892 vardecl* l = s.globals[g];
9d8a6ba3
SC
1893 if ((vut.read.find (l) != vut.read.end()
1894 && vut.used.find (l) != vut.used.end())
e491a713 1895 || vut.written.find (l) == vut.written.end())
0a102c82
SC
1896 continue;
1897
b5852334 1898 // Don't generate synthetic end probes for unread globals
5ae31731
FCE
1899 // declared only within tapsets. (RHBZ 468139), but rather
1900 // only within the end-user script.
1901
7584f162
RA
1902 bool tapset_global = false;
1903 for (size_t m=0; m < s.library_files.size(); m++)
1904 {
1905 for (size_t n=0; n < s.library_files[m]->globals.size(); n++)
1906 {
1907 if (l->name == s.library_files[m]->globals[n]->name)
1908 {tapset_global = true; break;}
1909 }
1910 }
1911 if (tapset_global)
1912 continue;
5ae31731 1913
101b0805
JS
1914 stringstream code;
1915 code << "probe end {" << endl;
d5e178c1 1916
9fef07ff 1917 string format = l->unmangled_name;
0a102c82 1918
101b0805 1919 string indexes;
96c3fced 1920 string foreach_value;
101b0805 1921 if (!l->index_types.empty())
0a102c82 1922 {
101b0805
JS
1923 // Add index values to the printf format, and prepare
1924 // a simple list of indexes for passing around elsewhere
1925 format += "[";
1926 for (size_t i = 0; i < l->index_types.size(); ++i)
e071e49b 1927 {
101b0805 1928 if (i > 0)
e071e49b 1929 {
101b0805
JS
1930 indexes += ",";
1931 format += ",";
e071e49b 1932 }
101b0805 1933 indexes += "__idx" + lex_cast(i);
ead25cf5 1934 if (l->index_types[i] == pe_string)
101b0805 1935 format += "\\\"%#s\\\"";
ead25cf5 1936 else
101b0805 1937 format += "%#d";
ead25cf5 1938 }
101b0805 1939 format += "]";
0a102c82 1940
101b0805 1941 // Iterate over all indexes in the array, sorted by decreasing value
96c3fced
JS
1942 code << "foreach (";
1943 if (l->type != pe_stats)
1944 {
1945 foreach_value = "__val";
1946 code << foreach_value << " = ";
1947 }
9fef07ff 1948 code << "[" << indexes << "] in " << l->unmangled_name << "-)" << endl;
101b0805
JS
1949 }
1950 else if (l->type == pe_stats)
1951 {
1952 // PR7053: Check scalar globals for empty aggregate
9fef07ff
DS
1953 code << "if (@count(" << l->unmangled_name << ") == 0)" << endl;
1954 code << "printf(\"" << l->unmangled_name << " @count=0x0\\n\")" << endl;
101b0805
JS
1955 code << "else" << endl;
1956 }
e491a713 1957
101b0805
JS
1958 static const string stats[] = { "@count", "@min", "@max", "@sum", "@avg" };
1959 const string stats_format =
1960 (strverscmp(s.compatible.c_str(), "1.4") >= 0) ? "%#d" : "%#x";
e071e49b 1961
101b0805
JS
1962 // Fill in the printf format for values
1963 if (l->type == pe_stats)
1964 for (size_t i = 0; i < sizeof(stats)/sizeof(stats[0]); ++i)
1965 format += " " + stats[i] + "=" + stats_format;
1966 else if (l->type == pe_string)
1967 format += "=\\\"%#s\\\"";
1968 else
1969 format += "=%#x";
1970 format += "\\n";
1971
1972 // Output the actual printf
1973 code << "printf (\"" << format << "\"";
57148ee7 1974
101b0805 1975 // Feed indexes to the printf, and include them in the value
9fef07ff 1976 string value = !foreach_value.empty() ? foreach_value : string(l->unmangled_name);
101b0805
JS
1977 if (!l->index_types.empty())
1978 {
1979 code << "," << indexes;
96c3fced
JS
1980 if (foreach_value.empty())
1981 value += "[" + indexes + "]";
0a102c82
SC
1982 }
1983
101b0805
JS
1984 // Feed the actual values to the printf
1985 if (l->type == pe_stats)
1986 for (size_t i = 0; i < sizeof(stats)/sizeof(stats[0]); ++i)
1987 code << "," << stats[i] << "(" << value << ")";
1988 else
1989 code << "," << value;
1990 code << ")" << endl;
1991
1992 // End of probe
1993 code << "}" << endl;
1994
1995 probe *p = parse_synthetic_probe (s, code, l->tok);
1996 if (!p)
1997 throw SEMANTIC_ERROR (_("can't create global var display"), l->tok);
1998
1999 vector<derived_probe*> dps;
6d2685fe 2000 derive_probes (s, p, dps);
0a102c82
SC
2001 for (unsigned i = 0; i < dps.size(); i++)
2002 {
2003 derived_probe* dp = dps[i];
2004 s.probes.push_back (dp);
2005 dp->join_group (s);
101b0805
JS
2006
2007 // Repopulate symbol and type info
2008 symresolution_info sym (s);
2009 sym.current_function = 0;
2010 sym.current_probe = dp;
2011 dp->body->visit (& sym);
0a102c82
SC
2012 }
2013
6d2685fe
SC
2014 semantic_pass_types(s);
2015 // Mark that variable is read
0a102c82
SC
2016 vut.read.insert (l);
2017 }
2018}
2b066ec1 2019
6120441d
FL
2020static void monitor_mode_read(systemtap_session& s)
2021{
2022 if (!s.monitor) return;
2023
2024 stringstream code;
2025
3e3756f8
FCE
2026 unsigned long rough_max_json_size = 100 +
2027 s.globals.size() * 100 +
2028 s.probes.size() * 200;
2029
2030 code << "probe procfs(\"monitor_status\").read.maxsize(" << rough_max_json_size << ") {" << endl;
2031 code << "try {"; // absorb .= overflows!
f6429b94
FL
2032 code << "elapsed = (jiffies()-__monitor_module_start)/HZ()" << endl;
2033 code << "hrs = elapsed/3600; mins = elapsed%3600/60; secs = elapsed%3600%60;" << endl;
1f3802d4 2034 code << "$value .= sprintf(\"{\\n\")" << endl;
19a81101 2035 code << "$value .= sprintf(\"\\\"uptime\\\": \\\"%02d:%02d:%02d\\\",\\n\", hrs, mins, secs)" << endl;
1f3802d4
FL
2036 code << "$value .= sprintf(\"\\\"uid\\\": \\\"%d\\\",\\n\", uid())" << endl;
2037 code << "$value .= sprintf(\"\\\"memory\\\": \\\"%s\\\",\\n\", module_size())" << endl;
2038 code << "$value .= sprintf(\"\\\"module_name\\\": \\\"%s\\\",\\n\", module_name())" << endl;
6120441d 2039
d86502b0 2040 code << "$value .= sprintf(\"\\\"globals\\\": {\\n\")" << endl;
6120441d
FL
2041 for (vector<vardecl*>::const_iterator it = s.globals.begin();
2042 it != s.globals.end(); ++it)
2043 {
f6429b94
FL
2044 if ((*it)->synthetic) continue;
2045
1f3802d4
FL
2046 if (it != s.globals.begin())
2047 code << "$value .= sprintf(\",\\n\")" << endl;
2048
38098f65 2049 code << "$value .= sprintf(\"\\\"%s\\\":\", \"" << (*it)->unmangled_name << "\")" << endl;
9e42a050 2050 if ((*it)->arity == 0)
38098f65 2051 code << "$value .= string_quoted(sprint(" << (*it)->name << "))" << endl;
9e42a050 2052 else if ((*it)->arity > 0)
38098f65 2053 code << "$value .= sprintf(\"\\\"[%d]\\\"\", " << (*it)->maxsize << ")" << endl;
6120441d 2054 }
d86502b0 2055 code << "$value .= sprintf(\"\\n},\\n\")" << endl;
6120441d 2056
8fb73e48 2057 code << "$value .= sprintf(\"\\\"probe_list\\\": [\\n\")" << endl;
6120441d
FL
2058 for (vector<derived_probe*>::const_iterator it = s.probes.begin();
2059 it != s.probes.end(); ++it)
2060 {
1f3802d4
FL
2061 if (it != s.probes.begin())
2062 code << "$value .= sprintf(\",\\n\")" << endl;
2063
6120441d
FL
2064 istringstream probe_point((*it)->sole_location()->str());
2065 string name;
2066 probe_point >> name;
aa5bc745
FL
2067 /* Escape quotes once for systemtap parser and once more for json parser */
2068 name = lex_cast_qstring(lex_cast_qstring(name));
6120441d 2069
c0d0d623 2070 code << "$value .= sprintf(\"{%s\", __private___monitor_data_function_probes("
6120441d 2071 << it-s.probes.begin() << "))" << endl;
aa5bc745 2072 code << "$value .= sprintf(\"\\\"name\\\": %s}\", " << name << ")" << endl;
6120441d 2073 }
8fb73e48 2074 code << "$value .= sprintf(\"\\n],\\n\")" << endl;
1f3802d4
FL
2075
2076 code << "$value .= sprintf(\"}\\n\")" << endl;
6120441d 2077
3e3756f8 2078 code << "} catch(ex) { warn(\"JSON construction error: \" . ex) }" << endl;
6120441d 2079 code << "}" << endl;
6120441d
FL
2080 probe* p = parse_synthetic_probe(s, code, 0);
2081 if (!p)
2082 throw SEMANTIC_ERROR (_("can't create procfs probe"), 0);
2083
2084 vector<derived_probe*> dps;
2085 derive_probes (s, p, dps);
2086
2087 derived_probe* dp = dps[0];
2088 s.probes.push_back (dp);
2089 dp->join_group (s);
2090
32bcf988 2091 // Repopulate symbol info
6120441d
FL
2092 symresolution_info sym (s);
2093 sym.current_function = 0;
2094 sym.current_probe = dp;
2095 dp->body->visit (&sym);
6120441d
FL
2096}
2097
2098static void monitor_mode_write(systemtap_session& s)
2099{
2100 if (!s.monitor) return;
2101
2102 for (vector<derived_probe*>::const_iterator it = s.probes.begin();
32bcf988 2103 it != s.probes.end()-1; ++it) // Skip monitor read probe
6120441d
FL
2104 {
2105 vardecl* v = new vardecl;
1d9d91c2 2106 v->unmangled_name = v->name = "__monitor_" + lex_cast(it-s.probes.begin()) + "_enabled";
6120441d
FL
2107 v->tok = (*it)->tok;
2108 v->set_arity(0, (*it)->tok);
2109 v->type = pe_long;
2110 v->init = new literal_number(1);
2111 v->synthetic = true;
2112 s.globals.push_back(v);
2113
2114 symbol* sym = new symbol;
2115 sym->name = v->name;
2116 sym->tok = v->tok;
2117 sym->type = pe_long;
2118 sym->referent = v;
2119
2120 if ((*it)->sole_location()->condition)
2121 {
2122 logical_and_expr *e = new logical_and_expr;
2123 e->tok = v->tok;
2124 e->left = sym;
2125 e->op = "&&";
2126 e->type = pe_long;
2127 e->right = (*it)->sole_location()->condition;
2128 (*it)->sole_location()->condition = e;
2129 }
2130 else
2131 {
2132 (*it)->sole_location()->condition = sym;
2133 }
2134 }
2135
2136 stringstream code;
2137
2138 code << "probe procfs(\"monitor_control\").write {" << endl;
2139
1d9d91c2 2140 code << "if ($value == \"clear\") {";
6120441d
FL
2141 for (vector<vardecl*>::const_iterator it = s.globals.begin();
2142 it != s.globals.end(); ++it)
2143 {
2144 vardecl* v = *it;
f6429b94
FL
2145
2146 if (v->synthetic) continue;
2147
6120441d
FL
2148 if (v->arity == 0 && v->init)
2149 {
2150 if (v->type == pe_long)
2151 {
2152 literal_number* ln = dynamic_cast<literal_number*>(v->init);
2153 code << v->name << " = " << ln->value << endl;
2154 }
2155 else if (v->type == pe_string)
2156 {
2157 literal_string* ln = dynamic_cast<literal_string*>(v->init);
2158 code << v->name << " = " << lex_cast_qstring(ln->value) << endl;
2159 }
2160 }
2161 else
2162 {
2163 // For scalar elements with no initial values, we reset to 0 or empty as
2164 // done with arrays and aggregates.
2165 code << "delete " << v->name << endl;
2166 }
2167 }
6120441d 2168
32bcf988 2169 code << "} else if ($value == \"resume\") {" << endl;
6120441d 2170 for (vector<derived_probe*>::const_iterator it = s.probes.begin();
32bcf988
FL
2171 it != s.probes.end()-1; ++it)
2172 {
2173 code << " __monitor_" << it-s.probes.begin() << "_enabled" << " = 1" << endl;
2174 }
2175
2176 code << "} else if ($value == \"pause\") {" << endl;
2177 for (vector<derived_probe*>::const_iterator it = s.probes.begin();
2178 it != s.probes.end()-1; ++it)
2179 {
2180 code << " __monitor_" << it-s.probes.begin() << "_enabled" << " = 0" << endl;
2181 }
1a442bf4
FCE
2182 code << "} else if ($value == \"quit\") {" << endl;
2183 code << " exit()" << endl;
32bcf988
FL
2184 code << "}";
2185
2186 for (vector<derived_probe*>::const_iterator it = s.probes.begin();
2187 it != s.probes.end()-1; ++it)
6120441d 2188 {
d86502b0 2189 code << " if ($value == \"" << it-s.probes.begin() << "\")"
6120441d
FL
2190 << " __monitor_" << it-s.probes.begin() << "_enabled" << " ^= 1" << endl;
2191 }
2192
2193 code << "}" << endl;
2194
2195 probe* p = parse_synthetic_probe(s, code, 0);
2196 if (!p)
2197 throw SEMANTIC_ERROR (_("can't create procfs probe"), 0);
2198
2199 vector<derived_probe*> dps;
2200 derive_probes (s, p, dps);
2201
2202 derived_probe* dp = dps[0];
2203 s.probes.push_back (dp);
2204 dp->join_group (s);
2205
32bcf988 2206 // Repopulate symbol info
87103d2b 2207 symresolution_info sym (s, /* omniscient-unmangled */ true);
32bcf988
FL
2208 sym.current_function = 0;
2209 sym.current_probe = dp;
2210 dp->body->visit (&sym);
2211}
2212
2213static void create_monitor_function(systemtap_session& s)
2214{
2215 functiondecl* fd = new functiondecl;
2216 fd->synthetic = true;
2217 fd->unmangled_name = fd->name = "__private___monitor_data_function_probes";
2218 fd->type = pe_string;
2219
2220 vardecl* v = new vardecl;
2221 v->type = pe_long;
2222 v->unmangled_name = v->name = "index";
2223 fd->formal_args.push_back(v);
2224
2225 embeddedcode* ec = new embeddedcode;
2226 string code;
2227 code = "/* unprivileged */ /* pure */"
2228 "const struct stap_probe *const p = &stap_probes[STAP_ARG_index];\n"
2229 "if (likely (probe_timing(STAP_ARG_index))) {\n"
2230 "struct stat_data *stats = _stp_stat_get (probe_timing(STAP_ARG_index), 0);\n"
2231 "if (stats->count) {\n"
2232 "int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);\n"
2233 "snprintf(_monitor_buf, STAP_MONITOR_READ,\n"
2234 "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %lld, "
2235 "\\\"min\\\": %lld, \\\"avg\\\": %lld, \\\"max\\\": %lld, \",\n"
2236 "p->index, p->cond_enabled ? \"on\" : \"off\", (long long) stats->count,\n"
2237 "(long long) stats->min, (long long) avg, (long long) stats->max);\n"
2238 "} else {\n"
2239 "snprintf(_monitor_buf, STAP_MONITOR_READ,\n"
2240 "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %d, "
2241 "\\\"min\\\": %d, \\\"avg\\\": %d, \\\"max\\\": %d, \",\n"
2242 "p->index, p->cond_enabled ? \"on\" : \"off\", 0, 0, 0, 0);}}\n"
2243 "STAP_RETURN(_monitor_buf);\n";
2244 ec->code = code;
2245 fd->body = ec;
2246
2247 s.functions[fd->name] = fd;
2248}
2249
2250static void monitor_mode_init(systemtap_session& s)
2251{
2252 if (!s.monitor) return;
2253
2254 vardecl* v = new vardecl;
2255 v->unmangled_name = v->name = "__global___monitor_module_start";
2256 v->set_arity(0, 0);
2257 v->type = pe_long;
2258 v->synthetic = true;
2259 s.globals.push_back(v);
2260
2261 embeddedcode* ec = new embeddedcode;
2262 ec->code = "#define STAP_MONITOR_READ 8192\n"
2263 "static char _monitor_buf[STAP_MONITOR_READ];";
2264 s.embeds.push_back(ec);
2265
2266 create_monitor_function(s);
2267 monitor_mode_read(s);
2268 monitor_mode_write(s);
2269
2270 stringstream code;
2271 code << "probe begin {" << endl;
2272 code << "__monitor_module_start = jiffies()" << endl;
2273 code << "}" << endl;
2274
2275 probe* p = parse_synthetic_probe(s, code, 0);
2276 if (!p)
2277 throw SEMANTIC_ERROR (_("can't create begin probe"), 0);
2278
2279 vector<derived_probe*> dps;
2280 derive_probes (s, p, dps);
2281
2282 derived_probe* dp = dps[0];
2283 s.probes.push_back (dp);
2284 dp->join_group (s);
2285
2286 // Repopulate symbol info
6120441d
FL
2287 symresolution_info sym (s);
2288 sym.current_function = 0;
2289 sym.current_probe = dp;
2290 dp->body->visit (&sym);
6120441d
FL
2291}
2292
2b066ec1
FCE
2293int
2294semantic_pass (systemtap_session& s)
2295{
59bafbe8 2296 int rc = 0;
20c6c071 2297
57148ee7 2298 try
59bafbe8 2299 {
11a046b7
DS
2300 // FIXME: interactive mode, register_library_aliases handles
2301 // both aliases from library files *and* user scripts. It would
2302 // be nice to have them in separate lists and register them
2303 // separately.
59bafbe8
FCE
2304 s.register_library_aliases();
2305 register_standard_tapsets(s);
57148ee7 2306
5d23847d 2307 if (rc == 0) rc = semantic_pass_symbols (s);
2e7f71c9 2308 if (rc == 0) monitor_mode_init (s);
5d23847d 2309 if (rc == 0) rc = semantic_pass_conditions (s);
c0f56268 2310 if (rc == 0) rc = semantic_pass_optimize1 (s);
59bafbe8 2311 if (rc == 0) rc = semantic_pass_types (s);
e471dfb0 2312 if (rc == 0) rc = gen_dfa_table(s);
0a102c82 2313 if (rc == 0) add_global_var_display (s);
c0f56268 2314 if (rc == 0) rc = semantic_pass_optimize2 (s);
d02548c0 2315 if (rc == 0) rc = semantic_pass_vars (s);
07c17d67 2316 if (rc == 0) rc = semantic_pass_stats (s);
7b8548ee 2317 if (rc == 0) embeddedcode_info_pass (s);
59bafbe8
FCE
2318 }
2319 catch (const semantic_error& e)
2320 {
2321 s.print_error (e);
21beacc9 2322 rc ++;
59bafbe8 2323 }
57148ee7 2324
1ee0d3ba
JL
2325 bool no_primary_probes = true;
2326 for (unsigned i = 0; i < s.probes.size(); i++)
2327 if (s.is_primary_probe(s.probes[i]))
2328 no_primary_probes = false;
2329
2330 if (s.num_errors() == 0 && no_primary_probes && !s.dump_mode)
2331 {
2332 s.print_error(SEMANTIC_ERROR(_("no probes found")));
2333 rc ++;
2334 }
2335
66facfa3
JS
2336 build_no_more (s);
2337
f119a57f 2338 // PR11443
f5b1b8bc
JS
2339 // NB: listing mode only cares whether we have any probes,
2340 // so all previous error conditions are disregarded.
bba368c5
JL
2341 if (s.dump_mode == systemtap_session::dump_matched_probes ||
2342 s.dump_mode == systemtap_session::dump_matched_probes_vars)
1ee0d3ba 2343 rc = no_primary_probes;
f119a57f 2344
eb9ea966 2345 // If we're dumping functions, only error out if no functions were found
bba368c5 2346 if (s.dump_mode == systemtap_session::dump_functions)
eb9ea966
JL
2347 rc = s.functions.empty();
2348
2b066ec1
FCE
2349 return rc;
2350}
2351
2352
2b066ec1
FCE
2353// ------------------------------------------------------------------------
2354// semantic processing: symbol resolution
2355
2356
87103d2b
FCE
2357symresolution_info::symresolution_info (systemtap_session& s, bool omniscient_unmangled):
2358 session (s), unmangled_p(omniscient_unmangled), current_function (0), current_probe (0)
2b066ec1
FCE
2359{
2360}
2361
2362
2363void
2364symresolution_info::visit_block (block* e)
2365{
2366 for (unsigned i=0; i<e->statements.size(); i++)
2367 {
57148ee7 2368 try
2b066ec1
FCE
2369 {
2370 e->statements[i]->visit (this);
2371 }
2372 catch (const semantic_error& e)
2373 {
2374 session.print_error (e);
2375 }
2376 }
2377}
2378
2379
69c68955
FCE
2380void
2381symresolution_info::visit_foreach_loop (foreach_loop* e)
2382{
2383 for (unsigned i=0; i<e->indexes.size(); i++)
2384 e->indexes[i]->visit (this);
3040bf3a 2385 for (unsigned i=0; i<e->array_slice.size(); i++)
45af9d1b 2386 if (e->array_slice[i])
3040bf3a 2387 e->array_slice[i]->visit(this);
69c68955 2388
57148ee7 2389 symbol *array = NULL;
d02548c0
GH
2390 hist_op *hist = NULL;
2391 classify_indexable (e->base, array, hist);
69c68955 2392
d02548c0
GH
2393 if (array)
2394 {
2395 if (!array->referent)
57148ee7 2396 {
2e526dab 2397 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
d02548c0 2398 if (d)
38bf68a8 2399 {
d02548c0 2400 array->referent = d;
38bf68a8
MC
2401 array->name = d->name;
2402 }
d02548c0 2403 else
60bebf58
JS
2404 {
2405 stringstream msg;
4af765b2 2406 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
7371cd19 2407 e->indexes.size(), array->name.to_string().c_str());
980f1e82 2408 throw SEMANTIC_ERROR (msg.str(), array->tok);
60bebf58 2409 }
d02548c0 2410 }
69c68955 2411
9972a915 2412 if (!e->array_slice.empty() && e->array_slice.size() != e->indexes.size())
3040bf3a
AJ
2413 {
2414 stringstream msg;
2415 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
7371cd19 2416 e->array_slice.size(), array->name.to_string().c_str());
3040bf3a
AJ
2417 throw SEMANTIC_ERROR (msg.str(), array->tok);
2418 }
d02548c0 2419 }
57148ee7 2420 else
d02548c0
GH
2421 {
2422 assert (hist);
2423 hist->visit (this);
2424 }
69c68955 2425
c261711d
JS
2426 if (e->value)
2427 e->value->visit (this);
2428
27f21e8c
DS
2429 if (e->limit)
2430 e->limit->visit (this);
2431
69c68955
FCE
2432 e->block->visit (this);
2433}
2434
d02548c0 2435
57148ee7 2436struct
d98d459c
GH
2437delete_statement_symresolution_info:
2438 public traversing_visitor
2439{
2440 symresolution_info *parent;
2441
2442 delete_statement_symresolution_info (symresolution_info *p):
2443 parent(p)
2444 {}
2445
2446 void visit_arrayindex (arrayindex* e)
2447 {
9972a915 2448 parent->visit_arrayindex(e, true);
d98d459c 2449 }
a98c930b 2450
d98d459c
GH
2451 void visit_functioncall (functioncall* e)
2452 {
2453 parent->visit_functioncall (e);
2454 }
2455
2456 void visit_symbol (symbol* e)
2457 {
2458 if (e->referent)
2459 return;
57148ee7 2460
2e526dab 2461 vardecl* d = parent->find_var (e->name, -1, e->tok);
d98d459c
GH
2462 if (d)
2463 e->referent = d;
2464 else
dc09353a 2465 throw SEMANTIC_ERROR (_("unresolved array in delete statement"), e->tok);
d98d459c
GH
2466 }
2467};
2468
57148ee7 2469void
d98d459c
GH
2470symresolution_info::visit_delete_statement (delete_statement* s)
2471{
2472 delete_statement_symresolution_info di (this);
2473 s->value->visit (&di);
2474}
2475
69c68955 2476
2b066ec1
FCE
2477void
2478symresolution_info::visit_symbol (symbol* e)
2479{
2480 if (e->referent)
2481 return;
2482
2e526dab 2483 vardecl* d = find_var (e->name, 0, e->tok);
2b066ec1 2484 if (d)
38bf68a8 2485 {
2b066ec1 2486 e->referent = d;
38bf68a8
MC
2487 e->name = d->name;
2488 }
2b066ec1
FCE
2489 else
2490 {
2491 // new local
2492 vardecl* v = new vardecl;
62ac4eaf 2493 v->unmangled_name = v->name = e->name;
2b066ec1 2494 v->tok = e->tok;
58701b78 2495 v->set_arity(0, e->tok);
2b066ec1
FCE
2496 if (current_function)
2497 current_function->locals.push_back (v);
2498 else if (current_probe)
2499 current_probe->locals.push_back (v);
2500 else
5d23847d 2501 // must be probe-condition expression
dc09353a 2502 throw SEMANTIC_ERROR (_("probe condition must not reference undeclared global"), e->tok);
2b066ec1
FCE
2503 e->referent = v;
2504 }
2505}
2506
2507
2508void
2509symresolution_info::visit_arrayindex (arrayindex* e)
9972a915
AJ
2510{
2511 visit_arrayindex(e, false);
2512}
2513
2514void
2515symresolution_info::visit_arrayindex (arrayindex* e, bool wildcard_ok)
2b066ec1
FCE
2516{
2517 for (unsigned i=0; i<e->indexes.size(); i++)
45af9d1b
AJ
2518 {
2519 // assuming that if NULL, it was originally a wildcard (*)
2520 if (e->indexes[i] == NULL)
9972a915
AJ
2521 {
2522 if (!wildcard_ok)
2523 throw SEMANTIC_ERROR(_("wildcard not allowed in array index"), e->tok);
2524 }
45af9d1b
AJ
2525 else
2526 e->indexes[i]->visit (this);
2527 }
2b066ec1 2528
57148ee7 2529 symbol *array = NULL;
d02548c0
GH
2530 hist_op *hist = NULL;
2531 classify_indexable(e->base, array, hist);
2b066ec1 2532
d02548c0 2533 if (array)
313b2f74 2534 {
d02548c0
GH
2535 if (array->referent)
2536 return;
2537
2e526dab 2538 vardecl* d = find_var (array->name, e->indexes.size (), array->tok);
d02548c0 2539 if (d)
38bf68a8 2540 {
d02548c0 2541 array->referent = d;
38bf68a8
MC
2542 array->name = d->name;
2543 }
313b2f74 2544 else
d02548c0 2545 {
60bebf58 2546 stringstream msg;
4af765b2 2547 msg << _F("unresolved arity-%zu global array %s, missing global declaration?",
7371cd19 2548 e->indexes.size(), array->name.to_string().c_str());
dc09353a 2549 throw SEMANTIC_ERROR (msg.str(), e->tok);
57148ee7 2550 }
d02548c0
GH
2551 }
2552 else
2553 {
2554 assert (hist);
2555 hist->visit (this);
313b2f74 2556 }
2b066ec1
FCE
2557}
2558
2559
e225e273
AJ
2560void
2561symresolution_info::visit_array_in (array_in* e)
2562{
9972a915 2563 visit_arrayindex(e->operand, true);
e225e273
AJ
2564}
2565
2b066ec1
FCE
2566
2567void
2568symresolution_info::visit_functioncall (functioncall* e)
2569{
5d23847d
FCE
2570 // XXX: we could relax this, if we're going to examine the
2571 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
2572 if (! (current_function || current_probe))
2573 {
2574 // must be probe-condition expression
dc09353a 2575 throw SEMANTIC_ERROR (_("probe condition must not reference function"), e->tok);
5d23847d
FCE
2576 }
2577
2b066ec1
FCE
2578 for (unsigned i=0; i<e->args.size(); i++)
2579 e->args[i]->visit (this);
2580
7b5b30a8 2581 if (!e->referents.empty())
2b066ec1
FCE
2582 return;
2583
7b5b30a8
FL
2584 vector<functiondecl*> fds = find_functions (e->function, e->args.size (), e->tok);
2585 if (!fds.empty())
2586 {
2587 e->referents = fds;
2588 function_priority_order order;
2589 stable_sort(e->referents.begin(), e->referents.end(), order); // preserve declaration order
2590 e->function = e->referents[0]->name;
2591 }
2b066ec1 2592 else
2a99f48f 2593 {
4e9b3f99
JL
2594 string sugs = levenshtein_suggest(e->function, collect_functions(), 5); // print 5 funcs
2595 throw SEMANTIC_ERROR(_F("unresolved function%s",
2596 sugs.empty() ? "" : (_(" (similar: ") + sugs + ")").c_str()),
2597 e->tok);
2a99f48f 2598 }
6120441d
FL
2599
2600 // In monitor mode, tapset functions used in the synthetic probe are not resolved and added
2601 // to the master list at the same time as the other functions so we must add them here to
2602 // allow the translator to generate the functions in the module.
2603 if (session.monitor && session.functions.find(e->function) == session.functions.end())
7b5b30a8 2604 session.functions[e->function] = fds[0]; // no overload
2b066ec1
FCE
2605}
2606
a07a2c28
LB
2607/*find_var will return an argument other than zero if the name matches the var
2608 * name ie, if the current local name matches the name passed to find_var*/
57148ee7 2609vardecl*
47d349b1 2610symresolution_info::find_var (interned_string name, int arity, const token* tok)
2b066ec1 2611{
5d23847d
FCE
2612 if (current_function || current_probe)
2613 {
2614 // search locals
57148ee7 2615 vector<vardecl*>& locals = (current_function ?
5d23847d
FCE
2616 current_function->locals :
2617 current_probe->locals);
57148ee7
FCE
2618
2619
5d23847d 2620 for (unsigned i=0; i<locals.size(); i++)
60bebf58 2621 if (locals[i]->name == name)
5d23847d 2622 {
58701b78 2623 locals[i]->set_arity (arity, tok);
5d23847d
FCE
2624 return locals[i];
2625 }
2626 }
2b066ec1 2627
313b2f74
GH
2628 // search function formal parameters (for scalars)
2629 if (arity == 0 && current_function)
2b066ec1
FCE
2630 for (unsigned i=0; i<current_function->formal_args.size(); i++)
2631 if (current_function->formal_args[i]->name == name)
8846477c
FCE
2632 {
2633 // NB: no need to check arity here: formal args always scalar
58701b78 2634 current_function->formal_args[i]->set_arity (0, tok);
8846477c
FCE
2635 return current_function->formal_args[i];
2636 }
2b066ec1 2637
313b2f74 2638 // search processed globals
87103d2b
FCE
2639 string gname, pname;
2640 if (unmangled_p)
2641 {
2642 gname = pname = string(name);
2643 }
2644 else
2645 {
2646 gname = "__global_" + string(name);
2647 pname = "__private_" + detox_path(tok->location.file->name) + string(name);
2648 }
2b066ec1 2649 for (unsigned i=0; i<session.globals.size(); i++)
38bf68a8 2650 {
8f54215e 2651 if ((session.globals[i]->name == name && startswith(name, "__global_")) ||
38bf68a8
MC
2652 (session.globals[i]->name == gname) ||
2653 (session.globals[i]->name == pname))
8846477c 2654 {
2e526dab
FCE
2655 if (! session.suppress_warnings)
2656 {
2657 vardecl* v = session.globals[i];
101b0805 2658 stapfile* f = tok->location.file;
2e526dab 2659 // clog << "resolved " << *tok << " to global " << *v->tok << endl;
f6429b94 2660 if (v->tok && v->tok->location.file != f && !f->synthetic)
2e526dab 2661 {
4af765b2
LB
2662 session.print_warning (_F("cross-file global variable reference to %s from",
2663 lex_cast(*v->tok).c_str()), tok);
2e526dab
FCE
2664 }
2665 }
2a7153bf
JS
2666 session.globals[i]->set_arity (arity, tok);
2667 return session.globals[i];
8846477c 2668 }
38bf68a8 2669 }
57148ee7 2670
2b066ec1
FCE
2671 // search library globals
2672 for (unsigned i=0; i<session.library_files.size(); i++)
2673 {
2674 stapfile* f = session.library_files[i];
2675 for (unsigned j=0; j<f->globals.size(); j++)
84e5ea0f
FCE
2676 {
2677 vardecl* g = f->globals[j];
38bf68a8 2678 if (g->name == gname)
84e5ea0f 2679 {
58701b78 2680 g->set_arity (arity, tok);
57148ee7
FCE
2681
2682 // put library into the queue if not already there
2683 if (find (session.files.begin(), session.files.end(), f)
84e5ea0f
FCE
2684 == session.files.end())
2685 session.files.push_back (f);
57148ee7 2686
84e5ea0f
FCE
2687 return g;
2688 }
2689 }
2b066ec1
FCE
2690 }
2691
2b066ec1 2692 return 0;
2b066ec1
FCE
2693}
2694
2695
7b5b30a8
FL
2696vector<functiondecl*>
2697symresolution_info::find_functions (const string& name, unsigned arity, const token *tok)
2b066ec1 2698{
7b5b30a8
FL
2699 vector<functiondecl*> functions;
2700 functiondecl* last = 0; // used for error message
8f54215e 2701
f76427a2 2702 // the common path
8f54215e
MC
2703
2704 // internal global functions bypassing the parser, such as __global_dwarf_tvar_[gs]et
2705 if ((session.functions.find(name) != session.functions.end()) && startswith(name, "__private_"))
2b066ec1 2706 {
f76427a2
FCE
2707 functiondecl* fd = session.functions[name];
2708 assert (fd->name == name);
2709 if (fd->formal_args.size() == arity)
7b5b30a8
FL
2710 functions.push_back(fd);
2711 else
2712 last = fd;
2b066ec1
FCE
2713 }
2714
7b5b30a8
FL
2715 // functions scanned by the parser are overloaded
2716 unsigned alternatives = session.overload_count[name];
2717 for (unsigned alt = 0; alt < alternatives; alt++)
8f54215e 2718 {
7b5b30a8
FL
2719 bool found = false; // multiple inclusion guard
2720 string gname = "__global_" + string(name) + "__overload_" + lex_cast(alt);
2721 string pname = "__private_" + detox_path(tok->location.file->name) + string(name) +
2722 "__overload_" + lex_cast(alt);
8f54215e 2723
7b5b30a8
FL
2724 // tapset or user script global functions coming from the parser
2725 if (!found && session.functions.find(gname) != session.functions.end())
2726 {
2727 functiondecl* fd = session.functions[gname];
2728 assert (fd->name == gname);
2729 if (fd->formal_args.size() == arity)
2730 {
2731 functions.push_back(fd);
2732 found = true;
2733 }
2734 else
2735 last = fd;
2736 }
8f54215e 2737
7b5b30a8
FL
2738 // tapset or user script private functions coming from the parser
2739 if (!found && session.functions.find(pname) != session.functions.end())
2740 {
2741 functiondecl* fd = session.functions[pname];
2742 assert (fd->name == pname);
2743 if (fd->formal_args.size() == arity)
2744 {
2745 functions.push_back(fd);
2746 found = true;
2747 }
2748 else
2749 last = fd;
2750 }
8f54215e 2751
7b5b30a8
FL
2752 // search library functions
2753 for (unsigned i=0; !found && i<session.library_files.size(); i++)
2754 {
2755 stapfile* f = session.library_files[i];
2756 for (unsigned j=0; !found && j<f->functions.size(); j++)
2b066ec1 2757 {
7b5b30a8
FL
2758 if ((f->functions[j]->name == gname) ||
2759 (f->functions[j]->name == pname))
103c95fb 2760 {
7b5b30a8
FL
2761 if (f->functions[j]->formal_args.size() == arity)
2762 {
2763 // put library into the queue if not already there
2764 if (0) // session.verbose_resolution
2765 cerr << _F(" function %s is defined from %s",
2766 name.c_str(), f->name.c_str()) << endl;
2767
2768 if (find (session.files.begin(), session.files.end(), f)
2769 == session.files.end())
2770 session.files.push_back (f);
2771 // else .. print different message?
2772
2773 functions.push_back(f->functions[j]);
2774 found = true;
2775 }
2776 else
2777 last = f->functions[j];
103c95fb 2778 }
2b066ec1 2779 }
7b5b30a8 2780 }
2b066ec1
FCE
2781 }
2782
7b5b30a8
FL
2783 // suggest last found function with matching name
2784 if (last && functions.empty())
2785 {
2786 throw SEMANTIC_ERROR(_F("arity mismatch found (function '%s' takes %zu args)",
2787 name.c_str(), last->formal_args.size()), tok, last->tok);
2788 }
2789
2790 return functions;
2b066ec1
FCE
2791}
2792
4e9b3f99
JL
2793set<string>
2794symresolution_info::collect_functions(void)
2795{
2796 set<string> funcs;
2797
2798 for (map<string,functiondecl*>::const_iterator it = session.functions.begin();
2799 it != session.functions.end(); ++it)
5eb6ecb1 2800 funcs.insert(it->second->unmangled_name);
4e9b3f99
JL
2801
2802 // search library functions
2803 for (unsigned i=0; i<session.library_files.size(); i++)
2804 {
2805 stapfile* f = session.library_files[i];
2806 for (unsigned j=0; j<f->functions.size(); j++)
5eb6ecb1 2807 funcs.insert(f->functions[j]->unmangled_name);
4e9b3f99 2808 }
2b066ec1 2809
4e9b3f99
JL
2810 return funcs;
2811}
cbfbbf69
FCE
2812
2813// ------------------------------------------------------------------------
2814// optimization
2815
2816
2817// Do away with functiondecls that are never (transitively) called
2818// from probes.
2819void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
2820{
2821 functioncall_traversing_visitor ftv;
2822 for (unsigned i=0; i<s.probes.size(); i++)
5d23847d
FCE
2823 {
2824 s.probes[i]->body->visit (& ftv);
2825 if (s.probes[i]->sole_location()->condition)
2826 s.probes[i]->sole_location()->condition->visit (& ftv);
2827 }
f76427a2
FCE
2828 vector<functiondecl*> new_unused_functions;
2829 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
cbfbbf69 2830 {
f76427a2 2831 functiondecl* fd = it->second;
13133f2c 2832 if (ftv.seen.find(fd) == ftv.seen.end())
cbfbbf69 2833 {
ba48c27a 2834 if (! fd->synthetic && s.is_user_file(fd->tok->location.file->name))
7371cd19 2835 s.print_warning (_F("Eliding unused function '%s'",
5eb6ecb1
DS
2836 fd->unmangled_name.to_string().c_str()),
2837 fd->tok);
f76427a2
FCE
2838 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
2839 new_unused_functions.push_back (fd);
cbfbbf69 2840 relaxed_p = false;
cbfbbf69 2841 }
f76427a2
FCE
2842 }
2843 for (unsigned i=0; i<new_unused_functions.size(); i++)
2844 {
2845 map<string,functiondecl*>::iterator where = s.functions.find (new_unused_functions[i]->name);
2846 assert (where != s.functions.end());
2847 s.functions.erase (where);
2848 if (s.tapset_compile_coverage)
2849 s.unused_functions.push_back (new_unused_functions[i]);
cbfbbf69
FCE
2850 }
2851}
2852
2853
2854// ------------------------------------------------------------------------
2855
2856// Do away with local & global variables that are never
2857// written nor read.
cfd621bc 2858void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations)
cbfbbf69 2859{
313db8e6 2860 varuse_collecting_visitor vut(s);
cfd621bc 2861
cbfbbf69 2862 for (unsigned i=0; i<s.probes.size(); i++)
5d23847d
FCE
2863 {
2864 s.probes[i]->body->visit (& vut);
2865
2866 if (s.probes[i]->sole_location()->condition)
2867 s.probes[i]->sole_location()->condition->visit (& vut);
2868 }
2869
cbfbbf69
FCE
2870 // NB: Since varuse_collecting_visitor also traverses down
2871 // actually called functions, we don't need to explicitly
2872 // iterate over them. Uncalled ones should have been pruned
2873 // in _opt1 above.
2874 //
2875 // for (unsigned i=0; i<s.functions.size(); i++)
2876 // s.functions[i]->body->visit (& vut);
57148ee7 2877
cbfbbf69 2878 // Now in vut.read/written, we have a mixture of all locals, globals
57148ee7
FCE
2879
2880 for (unsigned i=0; i<s.probes.size(); i++)
cbfbbf69
FCE
2881 for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */)
2882 {
2883 vardecl* l = s.probes[i]->locals[j];
a9e8f7e0 2884
a45664f4 2885 // skip over "special" locals
69aa668e 2886 if (l->synthetic) { j++; continue; }
a45664f4 2887
cbfbbf69
FCE
2888 if (vut.read.find (l) == vut.read.end() &&
2889 vut.written.find (l) == vut.written.end())
2890 {
ba48c27a 2891 if (s.is_user_file(l->tok->location.file->name))
7371cd19 2892 s.print_warning (_F("Eliding unused variable '%s'",
5eb6ecb1
DS
2893 l->unmangled_name.to_string().c_str()),
2894 l->tok);
c3a3c0c9
WC
2895 if (s.tapset_compile_coverage) {
2896 s.probes[i]->unused_locals.push_back
2897 (s.probes[i]->locals[j]);
2898 }
cbfbbf69
FCE
2899 s.probes[i]->locals.erase(s.probes[i]->locals.begin() + j);
2900 relaxed_p = false;
2901 // don't increment j
2902 }
2903 else
27d24ae2
FCE
2904 {
2905 if (vut.written.find (l) == vut.written.end())
cfd621bc 2906 if (iterations == 0 && ! s.suppress_warnings)
64e0bc5a
JL
2907 {
2908 set<string> vars;
2909 vector<vardecl*>::iterator it;
2910 for (it = s.probes[i]->locals.begin(); it != s.probes[i]->locals.end(); it++)
5eb6ecb1 2911 vars.insert((*it)->unmangled_name);
64e0bc5a 2912 for (it = s.globals.begin(); it != s.globals.end(); it++)
5eb6ecb1 2913 vars.insert((*it)->unmangled_name);
64e0bc5a
JL
2914
2915 vars.erase(l->name);
2916 string sugs = levenshtein_suggest(l->name, vars, 5); // suggest top 5 vars
2917 s.print_warning (_F("never-assigned local variable '%s'%s",
5eb6ecb1
DS
2918 l->unmangled_name.to_string().c_str(),
2919 (sugs.empty() ? "" :
2920 (_(" (similar: ") + sugs + ")")).c_str()), l->tok);
64e0bc5a 2921 }
27d24ae2
FCE
2922 j++;
2923 }
cbfbbf69 2924 }
57148ee7 2925
f76427a2
FCE
2926 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
2927 {
2928 functiondecl *fd = it->second;
2929 for (unsigned j=0; j<fd->locals.size(); /* see below */)
2930 {
2931 vardecl* l = fd->locals[j];
2932 if (vut.read.find (l) == vut.read.end() &&
2933 vut.written.find (l) == vut.written.end())
2934 {
ba48c27a 2935 if (s.is_user_file(l->tok->location.file->name))
7371cd19 2936 s.print_warning (_F("Eliding unused variable '%s'",
5eb6ecb1
DS
2937 l->unmangled_name.to_string().c_str()),
2938 l->tok);
f76427a2
FCE
2939 if (s.tapset_compile_coverage) {
2940 fd->unused_locals.push_back (fd->locals[j]);
2941 }
2942 fd->locals.erase(fd->locals.begin() + j);
2943 relaxed_p = false;
2944 // don't increment j
2945 }
2946 else
2947 {
2948 if (vut.written.find (l) == vut.written.end())
2949 if (iterations == 0 && ! s.suppress_warnings)
2950 {
64e0bc5a 2951 set<string> vars;
f76427a2
FCE
2952 vector<vardecl*>::iterator it;
2953 for (it = fd->formal_args.begin() ;
2954 it != fd->formal_args.end(); it++)
5eb6ecb1 2955 vars.insert((*it)->unmangled_name);
f76427a2 2956 for (it = fd->locals.begin(); it != fd->locals.end(); it++)
5eb6ecb1 2957 vars.insert((*it)->unmangled_name);
f76427a2 2958 for (it = s.globals.begin(); it != s.globals.end(); it++)
5eb6ecb1 2959 vars.insert((*it)->unmangled_name);
f76427a2 2960
64e0bc5a
JL
2961 vars.erase(l->name);
2962 string sugs = levenshtein_suggest(l->name, vars, 5); // suggest top 5 vars
2963 s.print_warning (_F("never-assigned local variable '%s'%s",
5eb6ecb1
DS
2964 l->unmangled_name.to_string().c_str(),
2965 (sugs.empty() ? "" :
2966 (_(" (similar: ") + sugs + ")")).c_str()), l->tok);
f76427a2 2967 }
cfd621bc 2968
f76427a2
FCE
2969 j++;
2970 }
2971 }
2972 }
cbfbbf69
FCE
2973 for (unsigned i=0; i<s.globals.size(); /* see below */)
2974 {
2975 vardecl* l = s.globals[i];
2976 if (vut.read.find (l) == vut.read.end() &&
2977 vut.written.find (l) == vut.written.end())
2978 {
ba48c27a 2979 if (s.is_user_file(l->tok->location.file->name))
7371cd19 2980 s.print_warning (_F("Eliding unused variable '%s'",
5eb6ecb1
DS
2981 l->unmangled_name.to_string().c_str()),
2982 l->tok);
c3a3c0c9 2983 if (s.tapset_compile_coverage) {
0a102c82 2984 s.unused_globals.push_back(s.globals[i]);
c3a3c0c9 2985 }
0a102c82
SC
2986 s.globals.erase(s.globals.begin() + i);
2987 relaxed_p = false;
2988 // don't increment i
cbfbbf69
FCE
2989 }
2990 else
27d24ae2 2991 {
cfd621bc
FCE
2992 if (vut.written.find (l) == vut.written.end() && ! l->init) // no initializer
2993 if (iterations == 0 && ! s.suppress_warnings)
2994 {
64e0bc5a 2995 set<string> vars;
cfd621bc
FCE
2996 vector<vardecl*>::iterator it;
2997 for (it = s.globals.begin(); it != s.globals.end(); it++)
5eb6ecb1
DS
2998 if (l->name != (*it)->unmangled_name)
2999 vars.insert((*it)->unmangled_name);
57148ee7 3000
64e0bc5a
JL
3001 string sugs = levenshtein_suggest(l->name, vars, 5); // suggest top 5 vars
3002 s.print_warning (_F("never-assigned global variable '%s'%s",
5eb6ecb1
DS
3003 l->unmangled_name.to_string().c_str(),
3004 (sugs.empty() ? "" :
3005 (_(" (similar: ") + sugs + ")")).c_str()),
3006 l->tok);
cfd621bc
FCE
3007 }
3008
27d24ae2
FCE
3009 i++;
3010 }
cbfbbf69
FCE
3011 }
3012}
3013
3014
3015// ------------------------------------------------------------------------
3016
8bda6498 3017struct dead_assignment_remover: public update_visitor
cbfbbf69
FCE
3018{
3019 systemtap_session& session;
3020 bool& relaxed_p;
3021 const varuse_collecting_visitor& vut;
cbfbbf69
FCE
3022
3023 dead_assignment_remover(systemtap_session& s, bool& r,
57148ee7 3024 const varuse_collecting_visitor& v):
8bda6498 3025 session(s), relaxed_p(r), vut(v) {}
cbfbbf69
FCE
3026
3027 void visit_assignment (assignment* e);
f4fe2e93 3028 void visit_try_block (try_block *s);
cbfbbf69
FCE
3029};
3030
3031
bd70b999
JS
3032// symbol_fetcher augmented to allow target-symbol types, but NULLed.
3033struct assignment_symbol_fetcher
3034 : public symbol_fetcher
3035{
3036 assignment_symbol_fetcher (symbol *&sym): symbol_fetcher(sym)
3037 {}
3038
dabd71bb 3039 void visit_target_symbol (target_symbol*)
bd70b999
JS
3040 {
3041 sym = NULL;
3042 }
3043
dabd71bb 3044 void visit_atvar_op (atvar_op*)
bd70b999
JS
3045 {
3046 sym = NULL;
3047 }
3048
dabd71bb 3049 void visit_cast_op (cast_op*)
bd70b999
JS
3050 {
3051 sym = NULL;
3052 }
3053
dabd71bb 3054 void visit_autocast_op (autocast_op*)
bd70b999
JS
3055 {
3056 sym = NULL;
3057 }
3058
3059 void throwone (const token* t)
3060 {
3061 if (t->type == tok_operator && t->content == ".")
3062 // guess someone misused . in $foo->bar.baz expression
3063 // XXX why are we only checking this in lvalues?
3064 throw SEMANTIC_ERROR (_("Expecting lvalue expression, try -> instead"), t);
3065 else
3066 throw SEMANTIC_ERROR (_("Expecting lvalue expression"), t);
3067 }
3068};
3069
3070symbol *
3071get_assignment_symbol_within_expression (expression *e)
3072{
3073 symbol *sym = NULL;
3074 assignment_symbol_fetcher fetcher(sym);
3075 e->visit (&fetcher);
3076 return sym; // NB: may be null!
3077}
3078
3079
cbfbbf69
FCE
3080void
3081dead_assignment_remover::visit_assignment (assignment* e)
3082{
8b095b45
JS
3083 replace (e->left);
3084 replace (e->right);
8bda6498 3085
bd70b999
JS
3086 symbol* left = get_assignment_symbol_within_expression (e->left);
3087 if (left) // not unresolved $target, so intended sideeffect may be elided
cbfbbf69 3088 {
bd70b999 3089 vardecl* leftvar = left->referent;
cbfbbf69
FCE
3090 if (vut.read.find(leftvar) == vut.read.end()) // var never read?
3091 {
cf9ff341
FCE
3092 // NB: Not so fast! The left side could be an array whose
3093 // index expressions may have side-effects. This would be
57148ee7 3094 // OK if we could replace the array assignment with a
cf9ff341
FCE
3095 // statement-expression containing all the index expressions
3096 // and the rvalue... but we can't.
0a102c82
SC
3097 // Another possibility is that we have an unread global variable
3098 // which are kept for probe end value display.
3099
3100 bool is_global = false;
3101 vector<vardecl*>::iterator it;
3102 for (it = session.globals.begin(); it != session.globals.end(); it++)
3103 if (leftvar->name == (*it)->name)
3104 {
3105 is_global = true;
3106 break;
3107 }
cf9ff341 3108
313db8e6 3109 varuse_collecting_visitor lvut(session);
8bda6498 3110 e->left->visit (& lvut);
df16cbea 3111 if (lvut.side_effect_free () && !is_global // XXX: use _wrt() once we track focal_vars
69aa668e 3112 && !leftvar->synthetic) // don't elide assignment to synthetic $context variables
cf9ff341 3113 {
a9e8f7e0
FCE
3114 /* PR 1119: NB: This is not necessary here. A write-only
3115 variable will also be elided soon at the next _opt2 iteration.
bad814e8
CM
3116 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
3117 session.print_warning("eliding write-only ", *e->left->tok);
a9e8f7e0
FCE
3118 else
3119 */
ba48c27a 3120 if (session.is_user_file(e->left->tok->location.file->name))
7371cd19 3121 session.print_warning(_F("Eliding assignment to '%s'",
5eb6ecb1 3122 leftvar->unmangled_name.to_string().c_str()), e->tok);
8bda6498 3123 provide (e->right); // goodbye assignment*
cf9ff341 3124 relaxed_p = false;
8bda6498 3125 return;
cf9ff341 3126 }
cbfbbf69
FCE
3127 }
3128 }
8bda6498 3129 provide (e);
e7625481 3130}
cbfbbf69 3131
f4fe2e93
FCE
3132
3133void
3134dead_assignment_remover::visit_try_block (try_block *s)
3135{
3136 replace (s->try_block);
3137 if (s->catch_error_var)
3138 {
3139 vardecl* errvar = s->catch_error_var->referent;
3140 if (vut.read.find(errvar) == vut.read.end()) // never read?
3141 {
3142 if (session.verbose>2)
4af765b2 3143 clog << _F("Eliding unused error string catcher %s at %s",
5eb6ecb1
DS
3144 errvar->unmangled_name.to_string().c_str(),
3145 lex_cast(*s->tok).c_str()) << endl;
f4fe2e93
FCE
3146 s->catch_error_var = 0;
3147 }
3148 }
3149 replace (s->catch_block);
3150 provide (s);
3151}
3152
3153
cbfbbf69
FCE
3154// Let's remove assignments to variables that are never read. We
3155// rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
3156// be optimized away as an unused variable, and expr a candidate to be
3157// removed as a side-effect-free statement expression. Wahoo!
3158void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
3159{
3160 // Recompute the varuse data, which will probably match the opt2
3161 // copy of the computation, except for those totally unused
3162 // variables that opt2 removed.
313db8e6 3163 varuse_collecting_visitor vut(s);
cbfbbf69
FCE
3164 for (unsigned i=0; i<s.probes.size(); i++)
3165 s.probes[i]->body->visit (& vut); // includes reachable functions too
3166
3167 dead_assignment_remover dar (s, relaxed_p, vut);
3168 // This instance may be reused for multiple probe/function body trims.
3169
3170 for (unsigned i=0; i<s.probes.size(); i++)
8b095b45 3171 dar.replace (s.probes[i]->body);
8bda6498
JS
3172 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3173 it != s.functions.end(); it++)
8b095b45 3174 dar.replace (it->second->body);
cbfbbf69 3175 // The rewrite operation is performed within the visitor.
27d24ae2
FCE
3176
3177 // XXX: we could also zap write-only globals here
cbfbbf69
FCE
3178}
3179
3180
3181// ------------------------------------------------------------------------
3182
1cd151d5 3183struct dead_stmtexpr_remover: public update_visitor
cbfbbf69
FCE
3184{
3185 systemtap_session& session;
3186 bool& relaxed_p;
1b07c728 3187 set<vardecl*> focal_vars; // vars considered subject to side-effects
cbfbbf69 3188
57148ee7 3189 dead_stmtexpr_remover(systemtap_session& s, bool& r):
1cd151d5 3190 session(s), relaxed_p(r) {}
cbfbbf69
FCE
3191
3192 void visit_block (block *s);
f4fe2e93 3193 void visit_try_block (try_block *s);
ba6f838d 3194 void visit_null_statement (null_statement *s);
739a3e81
FCE
3195 void visit_if_statement (if_statement* s);
3196 void visit_foreach_loop (foreach_loop *s);
3197 void visit_for_loop (for_loop *s);
cbfbbf69
FCE
3198 // XXX: and other places where stmt_expr's might be nested
3199
3200 void visit_expr_statement (expr_statement *s);
3201};
3202
3203
ba6f838d
FCE
3204void
3205dead_stmtexpr_remover::visit_null_statement (null_statement *s)
3206{
3207 // easy!
3208 if (session.verbose>2)
4af765b2 3209 clog << _("Eliding side-effect-free null statement ") << *s->tok << endl;
1cd151d5
JS
3210 s = 0;
3211 provide (s);
ba6f838d
FCE
3212}
3213
3214
cbfbbf69
FCE
3215void
3216dead_stmtexpr_remover::visit_block (block *s)
3217{
ba6f838d
FCE
3218 vector<statement*> new_stmts;
3219 for (unsigned i=0; i<s->statements.size(); i++ )
cbfbbf69 3220 {
1cd151d5
JS
3221 statement* new_stmt = require (s->statements[i], true);
3222 if (new_stmt != 0)
bea72737
JS
3223 {
3224 // flatten nested blocks into this one
1cd151d5 3225 block *b = dynamic_cast<block *>(new_stmt);
bea72737
JS
3226 if (b)
3227 {
3228 if (session.verbose>2)
4af765b2 3229 clog << _("Flattening nested block ") << *b->tok << endl;
bea72737
JS
3230 new_stmts.insert(new_stmts.end(),
3231 b->statements.begin(), b->statements.end());
3232 relaxed_p = false;
3233 }
3234 else
1cd151d5 3235 new_stmts.push_back (new_stmt);
bea72737 3236 }
cbfbbf69 3237 }
ba6f838d
FCE
3238 if (new_stmts.size() == 0)
3239 {
3240 if (session.verbose>2)
4af765b2 3241 clog << _("Eliding side-effect-free empty block ") << *s->tok << endl;
1cd151d5 3242 s = 0;
ba6f838d
FCE
3243 }
3244 else if (new_stmts.size() == 1)
3245 {
3246 if (session.verbose>2)
4af765b2 3247 clog << _("Eliding side-effect-free singleton block ") << *s->tok << endl;
1cd151d5
JS
3248 provide (new_stmts[0]);
3249 return;
ba6f838d
FCE
3250 }
3251 else
1cd151d5
JS
3252 s->statements = new_stmts;
3253 provide (s);
cbfbbf69
FCE
3254}
3255
f4fe2e93
FCE
3256
3257void
3258dead_stmtexpr_remover::visit_try_block (try_block *s)
3259{
3260 replace (s->try_block, true);
3261 replace (s->catch_block, true); // null catch{} is ok and useful
3262 if (s->try_block == 0)
3263 {
3264 if (session.verbose>2)
4af765b2 3265 clog << _("Eliding empty try {} block ") << *s->tok << endl;
f4fe2e93
FCE
3266 s = 0;
3267 }
3268 provide (s);
3269}
3270
3271
739a3e81
FCE
3272void
3273dead_stmtexpr_remover::visit_if_statement (if_statement *s)
3274{
8b095b45
JS
3275 replace (s->thenblock, true);
3276 replace (s->elseblock, true);
ba6f838d 3277
bea72737 3278 if (s->thenblock == 0)
ba6f838d 3279 {
bea72737
JS
3280 if (s->elseblock == 0)
3281 {
3282 // We may be able to elide this statement, if the condition
3283 // expression is side-effect-free.
313db8e6 3284 varuse_collecting_visitor vct(session);
bea72737
JS
3285 s->condition->visit(& vct);
3286 if (vct.side_effect_free ())
3287 {
3288 if (session.verbose>2)
4af765b2 3289 clog << _("Eliding side-effect-free if statement ")
bea72737 3290 << *s->tok << endl;
1cd151d5 3291 s = 0; // yeah, baby
bea72737
JS
3292 }
3293 else
3294 {
3295 // We can still turn it into a simple expr_statement though...
3296 if (session.verbose>2)
4af765b2 3297 clog << _("Creating simple evaluation from if statement ")
bea72737
JS
3298 << *s->tok << endl;
3299 expr_statement *es = new expr_statement;
3300 es->value = s->condition;
3301 es->tok = es->value->tok;
1cd151d5
JS
3302 provide (es);
3303 return;
bea72737
JS
3304 }
3305 }
3306 else
ba6f838d 3307 {
bea72737
JS
3308 // For an else without a then, we can invert the condition logic to
3309 // avoid having a null statement in the thenblock
ba6f838d 3310 if (session.verbose>2)
4af765b2 3311 clog << _("Inverting the condition of if statement ")
bea72737
JS
3312 << *s->tok << endl;
3313 unary_expression *ue = new unary_expression;
3314 ue->operand = s->condition;
3315 ue->tok = ue->operand->tok;
3316 ue->op = "!";
3317 s->condition = ue;
3318 s->thenblock = s->elseblock;
3319 s->elseblock = 0;
ba6f838d
FCE
3320 }
3321 }
1cd151d5 3322 provide (s);
739a3e81
FCE
3323}
3324
3325void
3326dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
3327{
8b095b45 3328 replace (s->block, true);
ba6f838d
FCE
3329
3330 if (s->block == 0)
3331 {
10328bcf 3332 // XXX what if s->limit has side effects?
c261711d 3333 // XXX what about s->indexes or s->value used outside the loop?
bad814e8 3334 if(session.verbose > 2)
4af765b2 3335 clog << _("Eliding side-effect-free foreach statement ") << *s->tok << endl;
1cd151d5 3336 s = 0; // yeah, baby
ba6f838d 3337 }
1cd151d5 3338 provide (s);
739a3e81
FCE
3339}
3340
3341void
3342dead_stmtexpr_remover::visit_for_loop (for_loop *s)
3343{
8b095b45 3344 replace (s->block, true);
ba6f838d
FCE
3345
3346 if (s->block == 0)
3347 {
3348 // We may be able to elide this statement, if the condition
3349 // expression is side-effect-free.
313db8e6 3350 varuse_collecting_visitor vct(session);
ba6f838d
FCE
3351 if (s->init) s->init->visit(& vct);
3352 s->cond->visit(& vct);
3353 if (s->incr) s->incr->visit(& vct);
3354 if (vct.side_effect_free ())
3355 {
3356 if (session.verbose>2)
4af765b2 3357 clog << _("Eliding side-effect-free for statement ") << *s->tok << endl;
1cd151d5
JS
3358 s = 0; // yeah, baby
3359 }
3360 else
3361 {
3362 // Can't elide this whole statement; put a null in there.
f946b10f 3363 s->block = new null_statement(s->tok);
ba6f838d 3364 }
ba6f838d 3365 }
1cd151d5 3366 provide (s);
739a3e81
FCE
3367}
3368
3369
cbfbbf69
FCE
3370
3371void
3372dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
3373{
3374 // Run a varuse query against the operand expression. If it has no
3375 // side-effects, replace the entire statement expression by a null
1cd151d5 3376 // statement with the provide() call.
cbfbbf69
FCE
3377 //
3378 // Unlike many other visitors, we do *not* traverse this outermost
3379 // one into the expression subtrees. There is no need - no
3380 // expr_statement nodes will be found there. (Function bodies
3381 // need to be visited explicitly by our caller.)
3382 //
3383 // NB. While we don't share nodes in the parse tree, let's not
3384 // deallocate *s anyway, just in case...
3385
313db8e6 3386 varuse_collecting_visitor vut(session);
cbfbbf69 3387 s->value->visit (& vut);
57148ee7 3388
1cd151d5 3389 if (vut.side_effect_free_wrt (focal_vars))
cbfbbf69 3390 {
a9e8f7e0
FCE
3391 /* PR 1119: NB: this message is not a good idea here. It can
3392 name some arbitrary RHS expression of an assignment.
bad814e8
CM
3393 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
3394 session.print_warning("eliding never-assigned ", *s->value->tok);
57148ee7 3395 else
a9e8f7e0 3396 */
ba48c27a 3397 if (session.is_user_file(s->value->tok->location.file->name))
bad814e8 3398 session.print_warning("Eliding side-effect-free expression ", s->tok);
cbfbbf69 3399
ba6f838d
FCE
3400 // NB: this 0 pointer is invalid to leave around for any length of
3401 // time, but the parent parse tree objects above handle it.
1cd151d5 3402 s = 0;
cbfbbf69
FCE
3403 relaxed_p = false;
3404 }
1cd151d5 3405 provide (s);
cbfbbf69
FCE
3406}
3407
3408
3409void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
3410{
3411 // Finally, let's remove some statement-expressions that have no
3412 // side-effect. These should be exactly those whose private varuse
3413 // visitors come back with an empty "written" and "embedded" lists.
57148ee7 3414
cbfbbf69
FCE
3415 dead_stmtexpr_remover duv (s, relaxed_p);
3416 // This instance may be reused for multiple probe/function body trims.
3417
3418 for (unsigned i=0; i<s.probes.size(); i++)
1b07c728 3419 {
e19ebcf7 3420 assert_no_interrupts();
f76427a2 3421
ba6f838d
FCE
3422 derived_probe* p = s.probes[i];
3423
1b07c728
FCE
3424 duv.focal_vars.clear ();
3425 duv.focal_vars.insert (s.globals.begin(),
3426 s.globals.end());
ba6f838d
FCE
3427 duv.focal_vars.insert (p->locals.begin(),
3428 p->locals.end());
3429
8b095b45 3430 duv.replace (p->body, true);
ba6f838d
FCE
3431 if (p->body == 0)
3432 {
f161bd74
JL
3433 if (! s.timing && // PR10070
3434 !(p->base->tok->location.file->synthetic)) // don't warn for synthetic probes
7371cd19 3435 s.print_warning (_F("side-effect-free probe '%s'",
1341a03c 3436 p->name().c_str()), p->tok);
ba6f838d 3437
f946b10f 3438 p->body = new null_statement(p->tok);
27d24ae2
FCE
3439
3440 // XXX: possible duplicate warnings; see below
ba6f838d 3441 }
1b07c728 3442 }
f76427a2 3443 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
1b07c728 3444 {
e19ebcf7 3445 assert_no_interrupts();
f76427a2
FCE
3446
3447 functiondecl* fn = it->second;
1b07c728 3448 duv.focal_vars.clear ();
ba6f838d
FCE
3449 duv.focal_vars.insert (fn->locals.begin(),
3450 fn->locals.end());
3451 duv.focal_vars.insert (fn->formal_args.begin(),
3452 fn->formal_args.end());
1b07c728
FCE
3453 duv.focal_vars.insert (s.globals.begin(),
3454 s.globals.end());
ba6f838d 3455
8b095b45 3456 duv.replace (fn->body, true);
ba6f838d
FCE
3457 if (fn->body == 0)
3458 {
7371cd19 3459 s.print_warning (_F("side-effect-free function '%s'",
5eb6ecb1
DS
3460 fn->unmangled_name.to_string().c_str()),
3461 fn->tok);
ba6f838d 3462
f946b10f 3463 fn->body = new null_statement(fn->tok);
27d24ae2
FCE
3464
3465 // XXX: the next iteration of the outer optimization loop may
3466 // take this new null_statement away again, and thus give us a
3467 // fresh warning. It would be better if this fixup was performed
3468 // only after the relaxation iterations.
3469 // XXX: or else see bug #6469.
ba6f838d 3470 }
1b07c728 3471 }
cbfbbf69
FCE
3472}
3473
bea72737
JS
3474
3475// ------------------------------------------------------------------------
3476
3477// The goal of this visitor is to reduce top-level expressions in void context
3478// into separate statements that evaluate each subcomponent of the expression.
3479// The dead-statement-remover can later remove some parts if they have no side
3480// effects.
9f9873df
JS
3481//
3482// All expressions must be overridden here so we never visit their subexpressions
3483// accidentally. Thus, the only visited expressions should be value of an
3484// expr_statement.
3485//
3486// For an expression to replace its expr_statement with something else, it will
3487// let the new statement provide(), and then provide(0) for itself. The
3488// expr_statement will take this as a sign that it's been replaced.
3489struct void_statement_reducer: public update_visitor
bea72737
JS
3490{
3491 systemtap_session& session;
3492 bool& relaxed_p;
bea72737
JS
3493 set<vardecl*> focal_vars; // vars considered subject to side-effects
3494
3495 void_statement_reducer(systemtap_session& s, bool& r):
9f9873df 3496 session(s), relaxed_p(r) {}
bea72737 3497
133c7b1d 3498 void visit_expr_statement (expr_statement* s);
9f9873df
JS
3499
3500 // expressions in conditional / loop controls are definitely a side effect,
3501 // but still recurse into the child statements
bea72737
JS
3502 void visit_if_statement (if_statement* s);
3503 void visit_for_loop (for_loop* s);
3504 void visit_foreach_loop (foreach_loop* s);
3505
3506 // these expressions get rewritten into their statement equivalents
3507 void visit_logical_or_expr (logical_or_expr* e);
3508 void visit_logical_and_expr (logical_and_expr* e);
3509 void visit_ternary_expression (ternary_expression* e);
3510
93daaca8 3511 // all of these can (usually) be reduced into simpler statements
bea72737
JS
3512 void visit_binary_expression (binary_expression* e);
3513 void visit_unary_expression (unary_expression* e);
ac01386b 3514 void visit_regex_query (regex_query* e); // XXX depends on subexpr extraction
bea72737
JS
3515 void visit_comparison (comparison* e);
3516 void visit_concatenation (concatenation* e);
3517 void visit_functioncall (functioncall* e);
3518 void visit_print_format (print_format* e);
6fda2dff 3519 void visit_target_symbol (target_symbol* e);
bd1fcbad 3520 void visit_atvar_op (atvar_op* e);
9b5af295 3521 void visit_cast_op (cast_op* e);
251707c8 3522 void visit_autocast_op (autocast_op* e);
30263a73 3523 void visit_defined_op (defined_op* e);
bea72737
JS
3524
3525 // these are a bit hairy to grok due to the intricacies of indexables and
3526 // stats, so I'm chickening out and skipping them...
9f9873df
JS
3527 void visit_array_in (array_in* e) { provide (e); }
3528 void visit_arrayindex (arrayindex* e) { provide (e); }
3529 void visit_stat_op (stat_op* e) { provide (e); }
3530 void visit_hist_op (hist_op* e) { provide (e); }
bea72737
JS
3531
3532 // these can't be reduced because they always have an effect
9f9873df
JS
3533 void visit_return_statement (return_statement* s) { provide (s); }
3534 void visit_delete_statement (delete_statement* s) { provide (s); }
3535 void visit_pre_crement (pre_crement* e) { provide (e); }
3536 void visit_post_crement (post_crement* e) { provide (e); }
3537 void visit_assignment (assignment* e) { provide (e); }
251707c8
JS
3538
3539private:
3540 void reduce_target_symbol (target_symbol* e, expression* operand=NULL);
bea72737
JS
3541};
3542
3543
133c7b1d
JS
3544void
3545void_statement_reducer::visit_expr_statement (expr_statement* s)
3546{
8b095b45 3547 replace (s->value, true);
133c7b1d 3548
9f9873df
JS
3549 // if the expression provides 0, that's our signal that a new
3550 // statement has been provided, so we shouldn't provide this one.
3551 if (s->value != 0)
3552 provide(s);
bea72737
JS
3553}
3554
3555void
3556void_statement_reducer::visit_if_statement (if_statement* s)
3557{
9f9873df 3558 // s->condition is never void
8b095b45
JS
3559 replace (s->thenblock);
3560 replace (s->elseblock);
9f9873df 3561 provide (s);
bea72737
JS
3562}
3563
3564void
3565void_statement_reducer::visit_for_loop (for_loop* s)
3566{
9f9873df 3567 // s->init/cond/incr are never void
8b095b45 3568 replace (s->block);
9f9873df 3569 provide (s);
bea72737
JS
3570}
3571
3572void
3573void_statement_reducer::visit_foreach_loop (foreach_loop* s)
3574{
c261711d 3575 // s->indexes/base/value/limit are never void
8b095b45 3576 replace (s->block);
9f9873df 3577 provide (s);
bea72737
JS
3578}
3579
3580void
3581void_statement_reducer::visit_logical_or_expr (logical_or_expr* e)
3582{
3583 // In void context, the evaluation of "a || b" is exactly like
3584 // "if (!a) b", so let's do that instead.
3585
bea72737 3586 if (session.verbose>2)
4af765b2 3587 clog << _("Creating if statement from unused logical-or ")
bea72737
JS
3588 << *e->tok << endl;
3589
3590 if_statement *is = new if_statement;
3591 is->tok = e->tok;
3592 is->elseblock = 0;
bea72737
JS
3593
3594 unary_expression *ue = new unary_expression;
3595 ue->operand = e->left;
3596 ue->tok = e->tok;
3597 ue->op = "!";
3598 is->condition = ue;
3599
133c7b1d 3600 expr_statement *es = new expr_statement;
bea72737
JS
3601 es->value = e->right;
3602 es->tok = es->value->tok;
3603 is->thenblock = es;
3604
3605 is->visit(this);
3606 relaxed_p = false;
9f9873df
JS
3607 e = 0;
3608 provide (e);
bea72737
JS
3609}
3610
3611void
3612void_statement_reducer::visit_logical_and_expr (logical_and_expr* e)
3613{
3614 // In void context, the evaluation of "a && b" is exactly like
3615 // "if (a) b", so let's do that instead.
3616
bea72737 3617 if (session.verbose>2)
4af765b2 3618 clog << _("Creating if statement from unused logical-and ")
bea72737
JS
3619 << *e->tok << endl;
3620
3621 if_statement *is = new if_statement;
3622 is->tok = e->tok;
3623 is->elseblock = 0;
3624 is->condition = e->left;
bea72737 3625
133c7b1d 3626 expr_statement *es = new expr_statement;
bea72737
JS
3627 es->value = e->right;
3628 es->tok = es->value->tok;
3629 is->thenblock = es;
3630
3631 is->visit(this);
3632 relaxed_p = false;
9f9873df
JS
3633 e = 0;
3634 provide (e);
bea72737
JS
3635}
3636
3637void
3638void_statement_reducer::visit_ternary_expression (ternary_expression* e)
3639{
3640 // In void context, the evaluation of "a ? b : c" is exactly like
3641 // "if (a) b else c", so let's do that instead.
3642
bea72737 3643 if (session.verbose>2)
4af765b2 3644 clog << _("Creating if statement from unused ternary expression ")
bea72737
JS
3645 << *e->tok << endl;
3646
3647 if_statement *is = new if_statement;
3648 is->tok = e->tok;
3649 is->condition = e->cond;
bea72737 3650
133c7b1d 3651 expr_statement *es = new expr_statement;
bea72737
JS
3652 es->value = e->truevalue;
3653 es->tok = es->value->tok;
3654 is->thenblock = es;
3655
3656 es = new expr_statement;
3657 es->value = e->falsevalue;
3658 es->tok = es->value->tok;
3659 is->elseblock = es;
3660
3661 is->visit(this);
3662 relaxed_p = false;
9f9873df
JS
3663 e = 0;
3664 provide (e);
bea72737
JS
3665}
3666
3667void
3668void_statement_reducer::visit_binary_expression (binary_expression* e)
3669{
3670 // When the result of a binary operation isn't needed, it's just as good to
3671 // evaluate the operands as sequential statements in a block.
3672
bea72737 3673 if (session.verbose>2)
4af765b2 3674 clog << _("Eliding unused binary ") << *e->tok << endl;
bea72737
JS
3675
3676 block *b = new block;
9f9873df 3677 b->tok = e->tok;
bea72737 3678
133c7b1d 3679 expr_statement *es = new expr_statement;
bea72737
JS
3680 es->value = e->left;
3681 es->tok = es->value->tok;
3682 b->statements.push_back(es);
3683
3684 es = new expr_statement;
3685 es->value = e->right;
3686 es->tok = es->value->tok;
3687 b->statements.push_back(es);
3688
3689 b->visit(this);
3690 relaxed_p = false;
9f9873df
JS
3691 e = 0;
3692 provide (e);
bea72737
JS
3693}
3694
3695void
3696void_statement_reducer::visit_unary_expression (unary_expression* e)
3697{
3698 // When the result of a unary operation isn't needed, it's just as good to
3699 // evaluate the operand directly
3700
bea72737 3701 if (session.verbose>2)
4af765b2 3702 clog << _("Eliding unused unary ") << *e->tok << endl;
bea72737 3703
bea72737 3704 relaxed_p = false;
9f9873df 3705 e->operand->visit(this);
bea72737
JS
3706}
3707
93daaca8
SM
3708void
3709void_statement_reducer::visit_regex_query (regex_query* e)
3710{
ac01386b
SM
3711 // TODOXXX After subexpression extraction is implemented,
3712 // regular expression matches *may* have side-effects in
3713 // terms of producing matched subexpressions, e.g.:
93daaca8 3714 //
ac01386b
SM
3715 // str =~ "pat"; println(matched(0));
3716 //
3717 // It's debatable if we want to actually allow this, though.
93daaca8 3718
ac01386b
SM
3719 // Treat e as a unary expression on the left operand -- since the
3720 // right hand side must be a literal (as verified by the parser),
93daaca8
SM
3721 // evaluating it never has side effects.
3722
3723 if (session.verbose>2)
3724 clog << _("Eliding regex query ") << *e->tok << endl;
3725
3726 relaxed_p = false;
3727 e->left->visit(this);
3728}
3729
bea72737
JS
3730void
3731void_statement_reducer::visit_comparison (comparison* e)
3732{
3733 visit_binary_expression(e);
3734}
3735
3736void
3737void_statement_reducer::visit_concatenation (concatenation* e)
3738{
3739 visit_binary_expression(e);
3740}
3741
3742void
3743void_statement_reducer::visit_functioncall (functioncall* e)
3744{
3745 // If a function call is pure and its result ignored, we can elide the call
c7d47935 3746 // and just evaluate the arguments in sequence
bea72737 3747
7b5b30a8 3748 if (e->args.empty())
9f9873df
JS
3749 {
3750 provide (e);
3751 return;
3752 }
bea72737 3753
7b5b30a8
FL
3754 bool side_effect_free = true;
3755 for (unsigned i = 0; i < e->referents.size(); i++)
3756 {
3757 varuse_collecting_visitor vut(session);
3758 vut.seen.insert (e->referents[i]);
3759 vut.current_function = e->referents[i];
3760 e->referents[i]->body->visit (& vut);
3761 if (!vut.side_effect_free_wrt(focal_vars))
3762 {
3763 side_effect_free = false;
3764 break;
3765 }
3766 }
3767
3768 if (!side_effect_free)
9f9873df
JS
3769 {
3770 provide (e);
3771 return;
3772 }
bea72737
JS
3773
3774 if (session.verbose>2)
4af765b2 3775 clog << _("Eliding side-effect-free function call ") << *e->tok << endl;
bea72737 3776
133c7b1d
JS
3777 block *b = new block;
3778 b->tok = e->tok;
bea72737 3779
133c7b1d 3780 for (unsigned i=0; i<e->args.size(); i++ )
bea72737 3781 {
133c7b1d
JS
3782 expr_statement *es = new expr_statement;
3783 es->value = e->args[i];
3784 es->tok = es->value->tok;
bea72737 3785 b->statements.push_back(es);
bea72737
JS
3786 }
3787
133c7b1d 3788 b->visit(this);
bea72737 3789 relaxed_p = false;
9f9873df
JS
3790 e = 0;
3791 provide (e);
bea72737
JS
3792}
3793
3794void
3795void_statement_reducer::visit_print_format (print_format* e)
3796{
3797 // When an sprint's return value is ignored, we can simply evaluate the
3798 // arguments in sequence
3799
3800 if (e->print_to_stream || !e->args.size())
9f9873df
JS
3801 {
3802 provide (e);
3803 return;
3804 }
bea72737
JS
3805
3806 if (session.verbose>2)
4af765b2 3807 clog << _("Eliding unused print ") << *e->tok << endl;
bea72737 3808
133c7b1d
JS
3809 block *b = new block;
3810 b->tok = e->tok;
bea72737 3811
133c7b1d 3812 for (unsigned i=0; i<e->args.size(); i++ )
bea72737 3813 {
133c7b1d
JS
3814 expr_statement *es = new expr_statement;
3815 es->value = e->args[i];
3816 es->tok = es->value->tok;
bea72737 3817 b->statements.push_back(es);
bea72737
JS
3818 }
3819
133c7b1d 3820 b->visit(this);
bea72737 3821 relaxed_p = false;
9f9873df
JS
3822 e = 0;
3823 provide (e);
bea72737
JS
3824}
3825
bd1fcbad 3826void
251707c8
JS
3827void_statement_reducer::reduce_target_symbol (target_symbol* e,
3828 expression* operand)
bd1fcbad 3829{
251707c8
JS
3830 // When the result of any target_symbol isn't needed, it's just as good to
3831 // evaluate the operand and any array indexes directly
6fda2dff
JS
3832
3833 block *b = new block;
3834 b->tok = e->tok;
3835
251707c8
JS
3836 if (operand)
3837 {
3838 expr_statement *es = new expr_statement;
3839 es->value = operand;
3840 es->tok = es->value->tok;
3841 b->statements.push_back(es);
3842 }
3843
6fda2dff
JS
3844 for (unsigned i=0; i<e->components.size(); i++ )
3845 {
3846 if (e->components[i].type != target_symbol::comp_expression_array_index)
3847 continue;
3848
3849 expr_statement *es = new expr_statement;
3850 es->value = e->components[i].expr_index;
3851 es->tok = es->value->tok;
3852 b->statements.push_back(es);
3853 }
3854
6fda2dff
JS
3855 b->visit(this);
3856 relaxed_p = false;
3857 e = 0;
3858 provide (e);
3859}
3860
9b5af295 3861void
251707c8 3862void_statement_reducer::visit_atvar_op (atvar_op* e)
9b5af295 3863{
251707c8
JS
3864 if (session.verbose>2)
3865 clog << _("Eliding unused target symbol ") << *e->tok << endl;
3866 reduce_target_symbol (e);
3867}
6fda2dff 3868
251707c8
JS
3869void
3870void_statement_reducer::visit_target_symbol (target_symbol* e)
3871{
3872 if (session.verbose>2)
3873 clog << _("Eliding unused target symbol ") << *e->tok << endl;
3874 reduce_target_symbol (e);
3875}
9b5af295 3876
251707c8
JS
3877void
3878void_statement_reducer::visit_cast_op (cast_op* e)
3879{
9b5af295 3880 if (session.verbose>2)
4af765b2 3881 clog << _("Eliding unused typecast ") << *e->tok << endl;
251707c8
JS
3882 reduce_target_symbol (e, e->operand);
3883}
9b5af295 3884
251707c8
JS
3885void
3886void_statement_reducer::visit_autocast_op (autocast_op* e)
3887{
3888 if (session.verbose>2)
3889 clog << _("Eliding unused autocast ") << *e->tok << endl;
3890 reduce_target_symbol (e, e->operand);
9b5af295
JS
3891}
3892
bea72737 3893
30263a73
FCE
3894void
3895void_statement_reducer::visit_defined_op (defined_op* e)
3896{
3897 // When the result of a @defined operation isn't needed, just elide
3898 // it entirely. Its operand $expression must already be
3899 // side-effect-free.
3900
3901 if (session.verbose>2)
4af765b2 3902 clog << _("Eliding unused check ") << *e->tok << endl;
30263a73
FCE
3903
3904 relaxed_p = false;
3905 e = 0;
3906 provide (e);
3907}
3908
3909
3910
bea72737
JS
3911void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
3912{
3913 // Let's simplify statements with unused computed values.
3914
3915 void_statement_reducer vuv (s, relaxed_p);
3916 // This instance may be reused for multiple probe/function body trims.
3917
3918 vuv.focal_vars.insert (s.globals.begin(), s.globals.end());
3919
3920 for (unsigned i=0; i<s.probes.size(); i++)
8b095b45 3921 vuv.replace (s.probes[i]->body);
9f9873df
JS
3922 for (map<string,functiondecl*>::iterator it = s.functions.begin();
3923 it != s.functions.end(); it++)
8b095b45 3924 vuv.replace (it->second->body);
bea72737
JS
3925}
3926
3927
10328bcf
JS
3928struct const_folder: public update_visitor
3929{
3930 systemtap_session& session;
3931 bool& relaxed_p;
3932
3933 const_folder(systemtap_session& s, bool& r):
3934 session(s), relaxed_p(r), last_number(0), last_string(0) {}
3935
3936 literal_number* last_number;
3937 literal_number* get_number(expression*& e);
3938 void visit_literal_number (literal_number* e);
3939
3940 literal_string* last_string;
3941 literal_string* get_string(expression*& e);
3942 void visit_literal_string (literal_string* e);
3943
f4869658
JS
3944 void get_literal(expression*& e, literal_number*& n, literal_string*& s);
3945
10328bcf
JS
3946 void visit_if_statement (if_statement* s);
3947 void visit_for_loop (for_loop* s);
3948 void visit_foreach_loop (foreach_loop* s);
3949 void visit_binary_expression (binary_expression* e);
3950 void visit_unary_expression (unary_expression* e);
3951 void visit_logical_or_expr (logical_or_expr* e);
3952 void visit_logical_and_expr (logical_and_expr* e);
7a6ae283 3953 // void visit_regex_query (regex_query* e); // XXX: would require executing dfa at compile-time
10328bcf
JS
3954 void visit_comparison (comparison* e);
3955 void visit_concatenation (concatenation* e);
3956 void visit_ternary_expression (ternary_expression* e);
b7aedf26 3957 void visit_defined_op (defined_op* e);
9fab2262 3958 void visit_target_symbol (target_symbol* e);
10328bcf
JS
3959};
3960
f4869658
JS
3961void
3962const_folder::get_literal(expression*& e,
3963 literal_number*& n,
3964 literal_string*& s)
3965{
3966 replace (e);
3967 n = (e == last_number) ? last_number : NULL;
3968 s = (e == last_string) ? last_string : NULL;
3969}
3970
10328bcf
JS
3971literal_number*
3972const_folder::get_number(expression*& e)
3973{
3974 replace (e);
3975 return (e == last_number) ? last_number : NULL;
3976}
3977
3978void
3979const_folder::visit_literal_number (literal_number* e)
3980{
3981 last_number = e;
3982 provide (e);
3983}
3984
3985literal_string*
3986const_folder::get_string(expression*& e)
3987{
3988 replace (e);
3989 return (e == last_string) ? last_string : NULL;
3990}
3991
3992void
3993const_folder::visit_literal_string (literal_string* e)
3994{
3995 last_string = e;
3996 provide (e);
3997}
3998
3999void
4000const_folder::visit_if_statement (if_statement* s)
4001{
4002 literal_number* cond = get_number (s->condition);
4003 if (!cond)
4004 {
4005 replace (s->thenblock);
4006 replace (s->elseblock);
4007 provide (s);
4008 }
4009 else
4010 {
4011 if (session.verbose>2)
4af765b2
LB
4012 clog << _F("Collapsing constant-%" PRIi64 " if-statement %s",
4013 cond->value, lex_cast(*s->tok).c_str()) << endl;
10328bcf
JS
4014 relaxed_p = false;
4015
4016 statement* n = cond->value ? s->thenblock : s->elseblock;
4017 if (n)
4018 n->visit (this);
4019 else
4020 provide (new null_statement (s->tok));
4021 }
4022}
4023
4024void
4025const_folder::visit_for_loop (for_loop* s)
4026{
4027 literal_number* cond = get_number (s->cond);
4028 if (!cond || cond->value)
4029 {
4030 replace (s->init);
4031 replace (s->incr);
4032 replace (s->block);
4033 provide (s);
4034 }
4035 else
4036 {
4037 if (session.verbose>2)
4af765b2 4038 clog << _("Collapsing constantly-false for-loop ") << *s->tok << endl;
10328bcf
JS
4039 relaxed_p = false;
4040
4041 if (s->init)
4042 s->init->visit (this);
4043 else
4044 provide (new null_statement (s->tok));
4045 }
4046}
4047
4048void
4049const_folder::visit_foreach_loop (foreach_loop* s)
4050{
4051 literal_number* limit = get_number (s->limit);
4052 if (!limit || limit->value > 0)
4053 {
4054 for (unsigned i = 0; i < s->indexes.size(); ++i)
4055 replace (s->indexes[i]);
4056 replace (s->base);
c261711d 4057 replace (s->value);
10328bcf
JS
4058 replace (s->block);
4059 provide (s);
4060 }
4061 else
4062 {
4063 if (session.verbose>2)
4af765b2 4064 clog << _("Collapsing constantly-limited foreach-loop ") << *s->tok << endl;
10328bcf
JS
4065 relaxed_p = false;
4066
4067 provide (new null_statement (s->tok));
4068 }
4069}
4070
4071void
4072const_folder::visit_binary_expression (binary_expression* e)
4073{
e7227e90
JS
4074 int64_t value;
4075 literal_number* left = get_number (e->left);
4076 literal_number* right = get_number (e->right);
4077
4078 if (right && !right->value && (e->op == "/" || e->op == "%"))
4079 {
4080 // Give divide-by-zero a chance to be optimized out elsewhere,
4081 // and if not it will be a runtime error anyway...
4082 provide (e);
4083 return;
4084 }
4085
4086 if (left && right)
4087 {
4088 if (e->op == "+")
4089 value = left->value + right->value;
4090 else if (e->op == "-")
4091 value = left->value - right->value;
4092 else if (e->op == "*")
4093 value = left->value * right->value;
4094 else if (e->op == "&")
4095 value = left->value & right->value;
4096 else if (e->op == "|")
4097 value = left->value | right->value;
4098 else if (e->op == "^")
4099 value = left->value ^ right->value;
4100 else if (e->op == ">>")
4101 value = left->value >> max(min(right->value, (int64_t)64), (int64_t)0);
4102 else if (e->op == "<<")
4103 value = left->value << max(min(right->value, (int64_t)64), (int64_t)0);
4104 else if (e->op == "/")
4105 value = (left->value == LLONG_MIN && right->value == -1) ? LLONG_MIN :
4106 left->value / right->value;
4107 else if (e->op == "%")
4108 value = (left->value == LLONG_MIN && right->value == -1) ? 0 :
4109 left->value % right->value;
4110 else
47d349b1 4111 throw SEMANTIC_ERROR (_("unsupported binary operator ") + (string)e->op);
e7227e90
JS
4112 }
4113
4114 else if ((left && ((left->value == 0 && (e->op == "*" || e->op == "&" ||
4115 e->op == ">>" || e->op == "<<" )) ||
4116 (left->value ==-1 && (e->op == "|" || e->op == ">>"))))
4117 ||
4118 (right && ((right->value == 0 && (e->op == "*" || e->op == "&")) ||
4119 (right->value == 1 && (e->op == "%")) ||
4120 (right->value ==-1 && (e->op == "%" || e->op == "|")))))
4121 {
4122 expression* other = left ? e->right : e->left;
4123 varuse_collecting_visitor vu(session);
4124 other->visit(&vu);
4125 if (!vu.side_effect_free())
4126 {
4127 provide (e);
4128 return;
4129 }
4130
cde4a9fe
AJ
4131 // we'll pass on type=pe_long inference to the expression
4132 if (other->type == pe_unknown)
4133 other->type = pe_long;
61f79792
AJ
4134 else if (other->type != pe_long)
4135 {
4136 // this mismatch was not caught in the initial type resolution pass,
4137 // generate a mismatch (left doesn't match right) error
4138 typeresolution_info ti(session);
4139 ti.assert_resolvability = true; // need this to get it throw errors
4140 ti.mismatch_complexity = 1; // also needed to throw errors
4141 ti.mismatch(e);
4142 }
1860faba 4143
e7227e90
JS
4144 if (left)
4145 value = left->value;
4146 else if (e->op == "%")
4147 value = 0;
4148 else
4149 value = right->value;
4150 }
4151
4152 else if ((left && ((left->value == 0 && (e->op == "+" || e->op == "|" ||
4153 e->op == "^")) ||
4154 (left->value == 1 && (e->op == "*")) ||
4155 (left->value ==-1 && (e->op == "&"))))
4156 ||
4157 (right && ((right->value == 0 && (e->op == "+" || e->op == "-" ||
4158 e->op == "|" || e->op == "^")) ||
4159 (right->value == 1 && (e->op == "*" || e->op == "/")) ||
4160 (right->value ==-1 && (e->op == "&")) ||
4161 (right->value <= 0 && (e->op == ">>" || e->op == "<<")))))
4162 {
4163 if (session.verbose>2)
4af765b2 4164 clog << _("Collapsing constant-identity binary operator ") << *e->tok << endl;
e7227e90
JS
4165 relaxed_p = false;
4166
cde4a9fe 4167 // we'll pass on type=pe_long inference to the expression
1860faba
AJ
4168 expression* other = left ? e->right : e->left;
4169 if (other->type == pe_unknown)
4170 other->type = pe_long;
61f79792
AJ
4171 else if (other->type != pe_long)
4172 {
4173 // this mismatch was not caught in the initial type resolution pass,
4174 // generate a mismatch (left doesn't match right) error
4175 typeresolution_info ti(session);
4176 ti.assert_resolvability = true; // need this to get it throw errors
4177 ti.mismatch_complexity = 1; // also needed to throw errors
4178 ti.mismatch(e);
4179 }
1860faba
AJ
4180
4181 provide (other);
e7227e90
JS
4182 return;
4183 }
4184
4185 else
4186 {
4187 provide (e);
4188 return;
4189 }
4190
4191 if (session.verbose>2)
4af765b2
LB
4192 clog << _F("Collapsing constant-%" PRIi64 " binary operator %s",
4193 value, lex_cast(*e->tok).c_str()) << endl;
e7227e90
JS
4194 relaxed_p = false;
4195
4196 literal_number* n = new literal_number(value);
4197 n->tok = e->tok;
4198 n->visit (this);
10328bcf
JS
4199}
4200
4201void
4202const_folder::visit_unary_expression (unary_expression* e)
4203{
4204 literal_number* operand = get_number (e->operand);
4205 if (!operand)
4206 provide (e);
4207 else
4208 {
4209 if (session.verbose>2)
4af765b2 4210 clog << _("Collapsing constant unary ") << *e->tok << endl;
10328bcf
JS
4211 relaxed_p = false;
4212
4213 literal_number* n = new literal_number (*operand);
4214 n->tok = e->tok;
4215 if (e->op == "+")
4216 ; // nothing to do
4217 else if (e->op == "-")
4218 n->value = -n->value;
4219 else if (e->op == "!")
4220 n->value = !n->value;
4221 else if (e->op == "~")
4222 n->value = ~n->value;
4223 else
47d349b1 4224 throw SEMANTIC_ERROR (_("unsupported unary operator ") + (string)e->op);
10328bcf
JS
4225 n->visit (this);
4226 }
4227}
4228
4229void
4230const_folder::visit_logical_or_expr (logical_or_expr* e)
4231{
a7e58d4c
JS
4232 int64_t value;
4233 literal_number* left = get_number (e->left);
4234 literal_number* right = get_number (e->right);
4235
4236 if (left && right)
4237 value = left->value || right->value;
4238
4239 else if ((left && left->value) || (right && right->value))
4240 {
4241 // If the const is on the left, we get to short-circuit the right
4242 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
4243 if (right)
4244 {
4245 varuse_collecting_visitor vu(session);
4246 e->left->visit(&vu);
4247 if (!vu.side_effect_free())
4248 {
4249 provide (e);
4250 return;
4251 }
4252 }
4253
4254 value = 1;
4255 }
4256
4257 // We might also get rid of useless "0||x" and "x||0", except it does
4258 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
4259 // that this would gain us much.
4260
4261 else
4262 {
4263 provide (e);
4264 return;
4265 }
4266
4267 if (session.verbose>2)
4af765b2 4268 clog << _("Collapsing constant logical-OR ") << *e->tok << endl;
a7e58d4c
JS
4269 relaxed_p = false;
4270
4271 literal_number* n = new literal_number(value);
4272 n->tok = e->tok;
4273 n->visit (this);
10328bcf
JS
4274}
4275
4276void
4277const_folder::visit_logical_and_expr (logical_and_expr* e)
4278{
a7e58d4c
JS
4279 int64_t value;
4280 literal_number* left = get_number (e->left);
4281 literal_number* right = get_number (e->right);
4282
4283 if (left && right)
4284 value = left->value && right->value;
4285
4286 else if ((left && !left->value) || (right && !right->value))
4287 {
4288 // If the const is on the left, we get to short-circuit the right
4289 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
4290 if (right)
4291 {
4292 varuse_collecting_visitor vu(session);
4293 e->left->visit(&vu);
4294 if (!vu.side_effect_free())
4295 {
4296 provide (e);
4297 return;
4298 }
4299 }
4300
4301 value = 0;
4302 }
4303
4304 // We might also get rid of useless "1&&x" and "x&&1", except it does
4305 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
4306 // that this would gain us much.
4307
4308 else
4309 {
4310 provide (e);
4311 return;
4312 }
4313
4314 if (session.verbose>2)
4af765b2 4315 clog << _("Collapsing constant logical-AND ") << *e->tok << endl;
a7e58d4c
JS
4316 relaxed_p = false;
4317
4318 literal_number* n = new literal_number(value);
4319 n->tok = e->tok;
4320 n->visit (this);
10328bcf
JS
4321}
4322
4323void
4324const_folder::visit_comparison (comparison* e)
4325{
f4869658
JS
4326 int comp;
4327
4328 literal_number *left_num, *right_num;
4329 literal_string *left_str, *right_str;
4330 get_literal(e->left, left_num, left_str);
4331 get_literal(e->right, right_num, right_str);
4332
4333 if (left_str && right_str)
4334 comp = left_str->value.compare(right_str->value);
4335
4336 else if (left_num && right_num)
4337 comp = left_num->value < right_num->value ? -1 :
4338 left_num->value > right_num->value ? 1 : 0;
4339
4340 else if ((left_num && ((left_num->value == LLONG_MIN &&
4341 (e->op == "<=" || e->op == ">")) ||
4342 (left_num->value == LLONG_MAX &&
4343 (e->op == ">=" || e->op == "<"))))
4344 ||
4345 (right_num && ((right_num->value == LLONG_MIN &&
4346 (e->op == ">=" || e->op == "<")) ||
4347 (right_num->value == LLONG_MAX &&
4348 (e->op == "<=" || e->op == ">")))))
4349 {
4350 expression* other = left_num ? e->right : e->left;
4351 varuse_collecting_visitor vu(session);
4352 other->visit(&vu);
4353 if (!vu.side_effect_free())
4354 provide (e);
4355 else
4356 {
4357 if (session.verbose>2)
4af765b2 4358 clog << _("Collapsing constant-boundary comparison ") << *e->tok << endl;
f4869658
JS
4359 relaxed_p = false;
4360
4361 // ops <= and >= are true, < and > are false
4362 literal_number* n = new literal_number( e->op.length() == 2 );
4363 n->tok = e->tok;
4364 n->visit (this);
4365 }
4366 return;
4367 }
4368
4369 else
4370 {
4371 provide (e);
4372 return;
4373 }
4374
4375 if (session.verbose>2)
4af765b2 4376 clog << _("Collapsing constant comparison ") << *e->tok << endl;
f4869658
JS
4377 relaxed_p = false;
4378
4379 int64_t value;
4380 if (e->op == "==")
4381 value = comp == 0;
4382 else if (e->op == "!=")
4383 value = comp != 0;
4384 else if (e->op == "<")
4385 value = comp < 0;
4386 else if (e->op == ">")
4387 value = comp > 0;
4388 else if (e->op == "<=")
4389 value = comp <= 0;
4390 else if (e->op == ">=")
4391 value = comp >= 0;
4392 else
47d349b1 4393 throw SEMANTIC_ERROR (_("unsupported comparison operator ") + (string)e->op);
f4869658
JS
4394
4395 literal_number* n = new literal_number(value);
4396 n->tok = e->tok;
4397 n->visit (this);
10328bcf
JS
4398}
4399
4400void
4401const_folder::visit_concatenation (concatenation* e)
4402{
29b1a9b7
JS
4403 literal_string* left = get_string (e->left);
4404 literal_string* right = get_string (e->right);
4405
4406 if (left && right)
4407 {
4408 if (session.verbose>2)
4af765b2 4409 clog << _("Collapsing constant concatenation ") << *e->tok << endl;
29b1a9b7
JS
4410 relaxed_p = false;
4411
4412 literal_string* n = new literal_string (*left);
4413 n->tok = e->tok;
47d349b1 4414 n->value = (string)n->value + (string)right->value;
29b1a9b7
JS
4415 n->visit (this);
4416 }
4417 else if ((left && left->value.empty()) ||
4418 (right && right->value.empty()))
4419 {
4420 if (session.verbose>2)
4af765b2 4421 clog << _("Collapsing identity concatenation ") << *e->tok << endl;
29b1a9b7
JS
4422 relaxed_p = false;
4423 provide(left ? e->right : e->left);
4424 }
4425 else
4426 provide (e);
10328bcf
JS
4427}
4428
4429void
4430const_folder::visit_ternary_expression (ternary_expression* e)
4431{
4432 literal_number* cond = get_number (e->cond);
4433 if (!cond)
4434 {
4435 replace (e->truevalue);
4436 replace (e->falsevalue);
4437 provide (e);
4438 }
4439 else
4440 {
4441 if (session.verbose>2)
4af765b2
LB
4442 clog << _F("Collapsing constant-%" PRIi64 " ternary %s",
4443 cond->value, lex_cast(*e->tok).c_str()) << endl;
10328bcf
JS
4444 relaxed_p = false;
4445
4446 expression* n = cond->value ? e->truevalue : e->falsevalue;
4447 n->visit (this);
4448 }
4449}
4450
b7aedf26
JS
4451void
4452const_folder::visit_defined_op (defined_op* e)
4453{
4454 // If a @defined makes it this far, then it is, de facto, undefined.
4455
4456 if (session.verbose>2)
4af765b2 4457 clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
b7aedf26
JS
4458 relaxed_p = false;
4459
4460 literal_number* n = new literal_number (0);
4461 n->tok = e->tok;
4462 n->visit (this);
4463}
4464
9fab2262
JS
4465void
4466const_folder::visit_target_symbol (target_symbol* e)
4467{
a45664f4 4468 if (session.skip_badvars)
9fab2262
JS
4469 {
4470 // Upon user request for ignoring context, the symbol is replaced
4471 // with a literal 0 and a warning message displayed
4472 // XXX this ignores possible side-effects, e.g. in array indexes
4473 literal_number* ln_zero = new literal_number (0);
4474 ln_zero->tok = e->tok;
4475 provide (ln_zero);
bad814e8 4476 session.print_warning (_("Bad $context variable being substituted with literal 0"),
9fab2262 4477 e->tok);
9fab2262
JS
4478 relaxed_p = false;
4479 }
4480 else
4481 update_visitor::visit_target_symbol (e);
4482}
4483
4375d018
AJ
4484static int initial_typeres_pass(systemtap_session& s);
4485static int semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p)
10328bcf 4486{
cde4a9fe
AJ
4487 // attempt an initial type resolution pass to see if there are any type
4488 // mismatches before we starting whisking away vars that get switched out
4489 // with a const.
4375d018
AJ
4490
4491 // return if the initial type resolution pass reported errors (type mismatches)
4492 int rc = initial_typeres_pass(s);
4493 if (rc)
4494 {
4495 relaxed_p = true;
4496 return rc;
4497 }
10328bcf 4498
cde4a9fe 4499 // Let's simplify statements with constant values.
10328bcf
JS
4500 const_folder cf (s, relaxed_p);
4501 // This instance may be reused for multiple probe/function body trims.
4502
4503 for (unsigned i=0; i<s.probes.size(); i++)
4504 cf.replace (s.probes[i]->body);
4505 for (map<string,functiondecl*>::iterator it = s.functions.begin();
4506 it != s.functions.end(); it++)
4507 cf.replace (it->second->body);
4375d018 4508 return 0;
10328bcf
JS
4509}
4510
4511
7c3feb93
JS
4512struct dead_control_remover: public traversing_visitor
4513{
4514 systemtap_session& session;
4515 bool& relaxed_p;
4516 statement* control;
4517
4518 dead_control_remover(systemtap_session& s, bool& r):
4519 session(s), relaxed_p(r), control(NULL) {}
4520
4521 void visit_block (block *b);
4522
4523 // When a block contains any of these, the following statements are dead.
4524 void visit_return_statement (return_statement* s) { control = s; }
4525 void visit_next_statement (next_statement* s) { control = s; }
4526 void visit_break_statement (break_statement* s) { control = s; }
4527 void visit_continue_statement (continue_statement* s) { control = s; }
4528};
4529
4530
4531void dead_control_remover::visit_block (block* b)
4532{
4533 vector<statement*>& vs = b->statements;
a1a230af
FCE
4534 if (vs.size() == 0) /* else (size_t) size()-1 => very big */
4535 return;
7c3feb93
JS
4536 for (size_t i = 0; i < vs.size() - 1; ++i)
4537 {
4538 vs[i]->visit (this);
4539 if (vs[i] == control)
4540 {
4541 session.print_warning(_("statement will never be reached"),
4542 vs[i + 1]->tok);
4543 vs.erase(vs.begin() + i + 1, vs.end());
4544 relaxed_p = false;
4545 break;
4546 }
4547 }
4548}
4549
4550
4551static void semantic_pass_dead_control (systemtap_session& s, bool& relaxed_p)
4552{
4553 // Let's remove code that follow unconditional control statements
4554
4555 dead_control_remover dc (s, relaxed_p);
4556
4557 for (unsigned i=0; i<s.probes.size(); i++)
4558 s.probes[i]->body->visit(&dc);
4559
4560 for (map<string,functiondecl*>::iterator it = s.functions.begin();
4561 it != s.functions.end(); it++)
4562 it->second->body->visit(&dc);
4563}
4564
4565
88bbd60d
DS
4566struct duplicate_function_remover: public functioncall_traversing_visitor
4567{
4568 systemtap_session& s;
88bbd60d
DS
4569 map<functiondecl*, functiondecl*>& duplicate_function_map;
4570
c214bd6a 4571 duplicate_function_remover(systemtap_session& sess,
88bbd60d 4572 map<functiondecl*, functiondecl*>&dfm):
c214bd6a 4573 s(sess), duplicate_function_map(dfm) {};
88bbd60d
DS
4574
4575 void visit_functioncall (functioncall* e);
4576};
4577
4578void
4579duplicate_function_remover::visit_functioncall (functioncall *e)
4580{
4581 functioncall_traversing_visitor::visit_functioncall (e);
4582
7b5b30a8 4583 // If any of the current function call references points to a function that
88bbd60d 4584 // is a duplicate, replace it.
7b5b30a8 4585 for (unsigned i = 0; i < e->referents.size(); i++)
88bbd60d 4586 {
7b5b30a8
FL
4587 functiondecl* referent = e->referents[i];
4588 if (duplicate_function_map.count(referent) != 0)
4589 {
4590 if (s.verbose>2)
4591 clog << _F("Changing %s reference to %s reference\n",
4592 referent->unmangled_name.to_string().c_str(),
4593 duplicate_function_map[referent]->unmangled_name.to_string().c_str());
4594 e->tok = duplicate_function_map[referent]->tok;
4595 e->function = duplicate_function_map[referent]->name;
4596 e->referents[i] = duplicate_function_map[referent];
4597 }
88bbd60d
DS
4598 }
4599}
4600
4601static string
4602get_functionsig (functiondecl* f)
4603{
4604 ostringstream s;
4605
4606 // Get the "name:args body" of the function in s. We have to
4607 // include the args since the function 'x1(a, b)' is different than
4608 // the function 'x2(b, a)' even if the bodies of the two functions
4609 // are exactly the same.
4610 f->printsig(s);
4611 f->body->print(s);
4612
4613 // printsig puts f->name + ':' on the front. Remove this
4614 // (otherwise, functions would never compare equal).
7b5b30a8 4615 string str = s.str().erase(0, f->unmangled_name.size() + 1);
88bbd60d
DS
4616
4617 // Return the function signature.
4618 return str;
4619}
4620
bea72737 4621void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p)
88bbd60d
DS
4622{
4623 // Walk through all the functions, looking for duplicates.
4624 map<string, functiondecl*> functionsig_map;
4625 map<functiondecl*, functiondecl*> duplicate_function_map;
f76427a2
FCE
4626
4627
4628 vector<functiondecl*> newly_zapped_functions;
4629 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
88bbd60d 4630 {
f76427a2
FCE
4631 functiondecl *fd = it->second;
4632 string functionsig = get_functionsig(fd);
88bbd60d
DS
4633
4634 if (functionsig_map.count(functionsig) == 0)
c214bd6a
DS
4635 {
4636 // This function is unique. Remember it.
f76427a2 4637 functionsig_map[functionsig] = fd;
c214bd6a 4638 }
88bbd60d 4639 else
c214bd6a
DS
4640 {
4641 // This function is a duplicate.
f76427a2
FCE
4642 duplicate_function_map[fd] = functionsig_map[functionsig];
4643 newly_zapped_functions.push_back (fd);
c214bd6a 4644 relaxed_p = false;
c214bd6a 4645 }
88bbd60d 4646 }
f76427a2
FCE
4647 for (unsigned i=0; i<newly_zapped_functions.size(); i++)
4648 {
4649 map<string,functiondecl*>::iterator where = s.functions.find (newly_zapped_functions[i]->name);
4650 assert (where != s.functions.end());
4651 s.functions.erase (where);
4652 }
4653
88bbd60d
DS
4654
4655 // If we have duplicate functions, traverse down the tree, replacing
4656 // the appropriate function calls.
4657 // duplicate_function_remover::visit_functioncall() handles the
c214bd6a 4658 // details of replacing the function calls.
88bbd60d
DS
4659 if (duplicate_function_map.size() != 0)
4660 {
c214bd6a 4661 duplicate_function_remover dfr (s, duplicate_function_map);
88bbd60d
DS
4662
4663 for (unsigned i=0; i < s.probes.size(); i++)
4664 s.probes[i]->body->visit(&dfr);
4665 }
4666}
4667
cdda9521 4668struct stable_analysis: public embedded_tags_visitor
0e658756
FL
4669{
4670 bool stable;
1aad7ed4 4671 stable_analysis(): embedded_tags_visitor(true), stable(false) {};
cdda9521 4672
1aad7ed4 4673 void visit_embeddedcode (embeddedcode* s);
cdda9521 4674 void visit_functioncall (functioncall* e);
0e658756
FL
4675};
4676
1aad7ed4 4677void stable_analysis::visit_embeddedcode (embeddedcode* s)
0e658756 4678{
1aad7ed4 4679 embedded_tags_visitor::visit_embeddedcode(s);
0e658756
FL
4680 if (tagged_p("/* stable */"))
4681 stable = true;
1aad7ed4
FL
4682 if (stable && !tagged_p("/* pure */"))
4683 throw SEMANTIC_ERROR(_("stable function must also be /* pure */"),
4684 s->tok);
0e658756
FL
4685}
4686
dabd71bb 4687void stable_analysis::visit_functioncall (functioncall*)
cdda9521 4688{
1aad7ed4 4689}
cdda9521 4690
1aad7ed4
FL
4691// Examines entire subtree for any stable functioncalls.
4692struct stable_finder: public traversing_visitor
4693{
4694 bool stable;
4695 set<string>& stable_fcs;
4696 stable_finder(set<string>&s): stable(false), stable_fcs(s) {};
4697 void visit_functioncall (functioncall* e);
4698};
cdda9521 4699
1aad7ed4
FL
4700void stable_finder::visit_functioncall (functioncall* e)
4701{
4702 if (stable_fcs.find(e->function) != stable_fcs.end())
4703 stable = true;
2a4b3a65 4704 traversing_visitor::visit_functioncall(e);
cdda9521
FL
4705}
4706
4707// Examines current level of block for stable functioncalls.
4708// Does not descend into sublevels.
4709struct level_check: public traversing_visitor
4710{
1aad7ed4 4711 bool stable;
cdda9521 4712 set<string>& stable_fcs;
1aad7ed4
FL
4713 level_check(set<string>& s): stable(false), stable_fcs(s) {};
4714
cdda9521
FL
4715 void visit_block (block* s);
4716 void visit_try_block (try_block *s);
4717 void visit_if_statement (if_statement* s);
4718 void visit_for_loop (for_loop* s);
4719 void visit_foreach_loop (foreach_loop* s);
4720 void visit_functioncall (functioncall* s);
4721};
4722
dabd71bb 4723void level_check::visit_block (block*)
cdda9521
FL
4724{
4725}
4726
4727void level_check::visit_try_block (try_block* s)
4728{
1aad7ed4
FL
4729 if (s->catch_error_var)
4730 s->catch_error_var->visit(this);
cdda9521
FL
4731}
4732
4733void level_check::visit_if_statement (if_statement* s)
4734{
1aad7ed4 4735 s->condition->visit(this);
cdda9521
FL
4736}
4737
4738void level_check::visit_for_loop (for_loop* s)
4739{
1aad7ed4
FL
4740 if (s->init) s->init->visit(this);
4741 s->cond->visit(this);
4742 if (s->incr) s->incr->visit(this);
cdda9521
FL
4743}
4744
4745void level_check::visit_foreach_loop (foreach_loop* s)
4746{
1aad7ed4
FL
4747 s->base->visit(this);
4748
cdda9521 4749 for (unsigned i=0; i<s->indexes.size(); i++)
1aad7ed4 4750 s->indexes[i]->visit(this);
cdda9521
FL
4751
4752 if (s->value)
1aad7ed4 4753 s->value->visit(this);
cdda9521
FL
4754
4755 if (s->limit)
1aad7ed4 4756 s->limit->visit(this);
cdda9521
FL
4757}
4758
4759void level_check::visit_functioncall (functioncall* e)
4760{
4761 if (stable_fcs.find(e->function) != stable_fcs.end())
1aad7ed4 4762 stable = true;
2a4b3a65 4763 traversing_visitor::visit_functioncall(e);
cdda9521
FL
4764}
4765
4766struct stable_functioncall_visitor: public update_visitor
0e658756
FL
4767{
4768 systemtap_session& session;
4769 functiondecl* current_function;
4770 derived_probe* current_probe;
cdda9521
FL
4771 set<string>& stable_fcs;
4772 set<string> scope_vars;
4773 map<string,vardecl*> new_vars;
4774 vector<pair<expr_statement*,block*> > new_stmts;
5e41c8bc
FL
4775 unsigned loop_depth;
4776 block* top_scope;
1aad7ed4 4777 block* curr_scope;
cdda9521 4778 stable_functioncall_visitor(systemtap_session& s, set<string>& sfc):
5e41c8bc 4779 session(s), current_function(0), current_probe(0), stable_fcs(sfc),
45a1aa33 4780 loop_depth(0), top_scope(0), curr_scope(0) {};
cdda9521
FL
4781
4782 statement* convert_stmt(statement* s);
4783 void visit_block (block* s);
4784 void visit_try_block (try_block* s);
4785 void visit_if_statement (if_statement* s);
4786 void visit_for_loop (for_loop* s);
4787 void visit_foreach_loop (foreach_loop* s);
0e658756
FL
4788 void visit_functioncall (functioncall* e);
4789};
4790
cdda9521 4791statement* stable_functioncall_visitor::convert_stmt (statement* s)
0e658756 4792{
1aad7ed4
FL
4793 if (top_scope == 0 &&
4794 (dynamic_cast<for_loop*>(s) || dynamic_cast<foreach_loop*>(s)))
5e41c8bc 4795 {
1aad7ed4
FL
4796 stable_finder sf(stable_fcs);
4797 s->visit(&sf);
4798 if (sf.stable)
5e41c8bc
FL
4799 {
4800 block* b = new block;
4801 b->tok = s->tok;
4802 b->statements.push_back(s);
5e41c8bc
FL
4803 return b;
4804 }
4805 }
1aad7ed4 4806 else if (top_scope == 0 && !dynamic_cast<block*>(s))
0e658756 4807 {
1aad7ed4
FL
4808 level_check lc(stable_fcs);
4809 s->visit(&lc);
4810 if (lc.stable)
4811 {
4812 block* b = new block;
4813 b->tok = s->tok;
4814 b->statements.push_back(s);
4815 return b;
4816 }
cdda9521
FL
4817 }
4818
4819 return s;
4820}
0e658756 4821
cdda9521
FL
4822void stable_functioncall_visitor::visit_block (block* s)
4823{
1aad7ed4
FL
4824 block* prev_top_scope = top_scope;
4825 block* prev_scope = curr_scope;
5e41c8bc
FL
4826 if (loop_depth == 0)
4827 top_scope = s;
1aad7ed4 4828 curr_scope = s;
cdda9521 4829 set<string> current_vars = scope_vars;
5e41c8bc 4830
cdda9521 4831 update_visitor::visit_block(s);
5e41c8bc
FL
4832
4833 if (loop_depth == 0)
1aad7ed4
FL
4834 top_scope = prev_top_scope;
4835 curr_scope = prev_scope;
5e41c8bc 4836 scope_vars = current_vars;
cdda9521 4837}
0e658756 4838
cdda9521
FL
4839void stable_functioncall_visitor::visit_try_block (try_block* s)
4840{
4841 if (s->try_block)
4842 s->try_block = convert_stmt(s->try_block);
1aad7ed4
FL
4843 replace(s->try_block);
4844 replace(s->catch_error_var);
cdda9521
FL
4845 if (s->catch_block)
4846 s->catch_block = convert_stmt(s->catch_block);
1aad7ed4
FL
4847 replace(s->catch_block);
4848 provide(s);
cdda9521 4849}
0e658756 4850
cdda9521
FL
4851void stable_functioncall_visitor::visit_if_statement (if_statement* s)
4852{
1aad7ed4
FL
4853 block* prev_top_scope = top_scope;
4854
5e41c8bc
FL
4855 if (loop_depth == 0)
4856 top_scope = 0;
1aad7ed4 4857 replace(s->condition);
cdda9521 4858 s->thenblock = convert_stmt(s->thenblock);
1aad7ed4
FL
4859 replace(s->thenblock);
4860 if (loop_depth == 0)
4861 top_scope = 0;
cdda9521
FL
4862 if (s->elseblock)
4863 s->elseblock = convert_stmt(s->elseblock);
1aad7ed4
FL
4864 replace(s->elseblock);
4865 provide(s);
4866
4867 top_scope = prev_top_scope;
cdda9521
FL
4868}
4869
4870void stable_functioncall_visitor::visit_for_loop (for_loop* s)
4871{
1aad7ed4
FL
4872 replace(s->init);
4873 replace(s->cond);
4874 replace(s->incr);
5e41c8bc 4875 loop_depth++;
cdda9521 4876 s->block = convert_stmt(s->block);
1aad7ed4 4877 replace(s->block);
5e41c8bc 4878 loop_depth--;
1aad7ed4 4879 provide(s);
cdda9521
FL
4880}
4881
4882void stable_functioncall_visitor::visit_foreach_loop (foreach_loop* s)
4883{
1aad7ed4
FL
4884 for (unsigned i = 0; i < s->indexes.size(); ++i)
4885 replace(s->indexes[i]);
4886 replace(s->base);
4887 replace(s->value);
4888 replace(s->limit);
5e41c8bc 4889 loop_depth++;
cdda9521 4890 s->block = convert_stmt(s->block);
1aad7ed4 4891 replace(s->block);
5e41c8bc 4892 loop_depth--;
1aad7ed4 4893 provide(s);
cdda9521
FL
4894}
4895
4896void stable_functioncall_visitor::visit_functioncall (functioncall* e)
4897{
2a4b3a65
FL
4898 for (unsigned i = 0; i < e->args.size(); ++i)
4899 replace (e->args[i]);
4900
cdda9521
FL
4901 if (stable_fcs.find(e->function) != stable_fcs.end())
4902 {
4903 string name("__stable_");
4904 name.append(e->function).append("_value");
0e658756 4905
cdda9521
FL
4906 // Variable potentially not in scope since it is in a sibling block
4907 if (scope_vars.find(e->function) == scope_vars.end())
4908 {
4909 if (new_vars.find(e->function) == new_vars.end())
0e658756
FL
4910 {
4911 // New variable declaration to store result of function call
4912 vardecl* v = new vardecl;
62ac4eaf 4913 v->unmangled_name = v->name = name;
0e658756
FL
4914 v->tok = e->tok;
4915 v->set_arity(0, e->tok);
4916 v->type = e->type;
4917 if (current_function)
4918 current_function->locals.push_back(v);
4919 else
4920 current_probe->locals.push_back(v);
cdda9521 4921 new_vars[e->function] = v;
0e658756 4922 }
cdda9521
FL
4923
4924 symbol* sym = new symbol;
4925 sym->name = name;
4926 sym->tok = e->tok;
4927 sym->referent = new_vars[e->function];
4928 sym->type = e->type;
4929
4930 functioncall* fc = new functioncall;
4931 fc->tok = e->tok;
4932 fc->function = e->function;
7b5b30a8 4933 fc->referents = e->referents;
cdda9521
FL
4934 fc->type = e->type;
4935
4936 assignment* a = new assignment;
4937 a->tok = e->tok;
4938 a->op = "=";
4939 a->left = sym;
4940 a->right = fc;
4941 a->type = e->type;
4942
4943 expr_statement* es = new expr_statement;
4944 es->tok = e->tok;
4945 es->value = a;
4946
5e41c8bc 4947 // Store location of the block to put new declaration.
5e41c8bc
FL
4948 if (loop_depth != 0)
4949 {
1aad7ed4 4950 assert(top_scope);
5e41c8bc
FL
4951 new_stmts.push_back(make_pair(es,top_scope));
4952 }
4953 else
4954 {
1aad7ed4
FL
4955 assert(curr_scope);
4956 new_stmts.push_back(make_pair(es,curr_scope));
5e41c8bc 4957 }
cdda9521
FL
4958
4959 scope_vars.insert(e->function);
4960
4961 provide(sym);
0e658756 4962 }
cdda9521
FL
4963 else
4964 {
4965 symbol* sym = new symbol;
4966 sym->name = name;
4967 sym->tok = e->tok;
4968 sym->referent = new_vars[e->function];
4969 sym->type = e->type;
4970 provide(sym);
4971 }
4972 return;
0e658756
FL
4973 }
4974
4975 provide(e);
4976}
4977
cdda9521
FL
4978// Cache stable embedded-c functioncall results and replace
4979// all calls with same name using that value to reduce duplicate
1aad7ed4
FL
4980// functioncall overhead. Functioncalls are pulled out of any
4981// top-level loops and put into if/try blocks.
cdda9521 4982void semantic_pass_opt7(systemtap_session& s)
0e658756 4983{
1aad7ed4
FL
4984 set<string> stable_fcs;
4985 for (map<string,functiondecl*>::iterator it = s.functions.begin();
4986 it != s.functions.end(); ++it)
4987 {
4988 functiondecl* fn = (*it).second;
4989 stable_analysis sa;
4990 fn->body->visit(&sa);
67d60c9f 4991 if (sa.stable && fn->formal_args.size() == 0)
1aad7ed4
FL
4992 stable_fcs.insert(fn->name);
4993 }
4994
cdda9521 4995 for (vector<derived_probe*>::iterator it = s.probes.begin();
0e658756
FL
4996 it != s.probes.end(); ++it)
4997 {
1aad7ed4 4998 stable_functioncall_visitor t(s, stable_fcs);
0e658756 4999 t.current_probe = *it;
cdda9521 5000 (*it)->body = t.convert_stmt((*it)->body);
0e658756 5001 t.replace((*it)->body);
cdda9521
FL
5002
5003 for (vector<pair<expr_statement*,block*> >::iterator st = t.new_stmts.begin();
5004 st != t.new_stmts.end(); ++st)
5005 st->second->statements.insert(st->second->statements.begin(), st->first);
0e658756 5006 }
cdda9521
FL
5007
5008 for (map<string,functiondecl*>::iterator it = s.functions.begin();
5009 it != s.functions.end(); ++it)
0e658756 5010 {
cdda9521 5011 functiondecl* fn = (*it).second;
1aad7ed4 5012 stable_functioncall_visitor t(s, stable_fcs);
cdda9521
FL
5013 t.current_function = fn;
5014 fn->body = t.convert_stmt(fn->body);
5015 t.replace(fn->body);
5016
5017 for (vector<pair<expr_statement*,block*> >::iterator st = t.new_stmts.begin();
5018 st != t.new_stmts.end(); ++st)
5019 st->second->statements.insert(st->second->statements.begin(), st->first);
0e658756
FL
5020 }
5021}
cbfbbf69
FCE
5022
5023static int
c214bd6a 5024semantic_pass_optimize1 (systemtap_session& s)
cbfbbf69
FCE
5025{
5026 // In this pass, we attempt to rewrite probe/function bodies to
5027 // eliminate some blatantly unnecessary code. This is run before
5028 // type inference, but after symbol resolution and derived_probe
5029 // creation. We run an outer "relaxation" loop that repeats the
5030 // optimizations until none of them find anything to remove.
5031
5032 int rc = 0;
5033
bad814e8
CM
5034 // Save the old value of suppress_warnings, as we will be changing
5035 // it below.
5036 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
5037
cbfbbf69 5038 bool relaxed_p = false;
cfd621bc 5039 unsigned iterations = 0;
cbfbbf69
FCE
5040 while (! relaxed_p)
5041 {
e19ebcf7 5042 assert_no_interrupts();
49abf162 5043
cbfbbf69
FCE
5044 relaxed_p = true; // until proven otherwise
5045
bad814e8
CM
5046 // If the verbosity is high enough, always print warnings (overrides -w),
5047 // or if not, always suppress warnings for every itteration after the first.
5048 if(s.verbose > 2)
5049 s.suppress_warnings = false;
5050 else if (iterations > 0)
5051 s.suppress_warnings = true;
5052
c0f56268
JS
5053 if (!s.unoptimized)
5054 {
5055 semantic_pass_opt1 (s, relaxed_p);
5056 semantic_pass_opt2 (s, relaxed_p, iterations); // produce some warnings only on iteration=0
5057 semantic_pass_opt3 (s, relaxed_p);
5058 semantic_pass_opt4 (s, relaxed_p);
5059 semantic_pass_opt5 (s, relaxed_p);
5060 }
5061
5062 // For listing mode, we need const-folding regardless of optimization so
5063 // that @defined expressions can be properly resolved. PR11360
ad12c592
MW
5064 // We also want it in case variables are used in if/case expressions,
5065 // so enable always. PR11366
4375d018
AJ
5066 // rc is incremented if there is an error that got reported.
5067 rc += semantic_pass_const_fold (s, relaxed_p);
cfd621bc 5068
7c3feb93
JS
5069 if (!s.unoptimized)
5070 semantic_pass_dead_control (s, relaxed_p);
5071
cfd621bc 5072 iterations ++;
c214bd6a
DS
5073 }
5074
c214bd6a
DS
5075 return rc;
5076}
5077
5078
5079static int
5080semantic_pass_optimize2 (systemtap_session& s)
5081{
5082 // This is run after type inference. We run an outer "relaxation"
5083 // loop that repeats the optimizations until none of them find
5084 // anything to remove.
5085
5086 int rc = 0;
5087
bad814e8
CM
5088 // Save the old value of suppress_warnings, as we will be changing
5089 // it below.
5090 save_and_restore<bool> suppress_warnings(& s.suppress_warnings);
5091
c214bd6a 5092 bool relaxed_p = false;
bad814e8 5093 unsigned iterations = 0;
c214bd6a
DS
5094 while (! relaxed_p)
5095 {
e19ebcf7 5096 assert_no_interrupts();
c214bd6a
DS
5097 relaxed_p = true; // until proven otherwise
5098
bad814e8
CM
5099 // If the verbosity is high enough, always print warnings (overrides -w),
5100 // or if not, always suppress warnings for every itteration after the first.
5101 if(s.verbose > 2)
5102 s.suppress_warnings = false;
5103 else if (iterations > 0)
5104 s.suppress_warnings = true;
5105
c0f56268
JS
5106 if (!s.unoptimized)
5107 semantic_pass_opt6 (s, relaxed_p);
bad814e8
CM
5108
5109 iterations++;
cbfbbf69
FCE
5110 }
5111
1aad7ed4
FL
5112 if (!s.unoptimized)
5113 semantic_pass_opt7(s);
5114
cbfbbf69
FCE
5115 return rc;
5116}
5117
5118
5119
2b066ec1
FCE
5120// ------------------------------------------------------------------------
5121// type resolution
5122
66facfa3
JS
5123struct autocast_expanding_visitor: public var_expanding_visitor
5124{
5125 typeresolution_info& ti;
389236d5
JS
5126 autocast_expanding_visitor (typeresolution_info& ti): ti(ti) {}
5127
5128 void resolve_functioncall (functioncall* fc)
5129 {
5130 // This is a very limited version of semantic_pass_symbols, but we're
5131 // late in the game at this point. We won't get a chance to optimize,
5132 // but for now the only functions we expect are kernel/user_string from
5133 // pretty-printing, which don't need optimization.
5134
5135 systemtap_session& s = ti.session;
5136 size_t nfiles = s.files.size();
5137
5138 symresolution_info sym (s);
5139 sym.current_function = ti.current_function;
5140 sym.current_probe = ti.current_probe;
5141 fc->visit (&sym);
5142
5143 // NB: synthetic functions get tacked onto the origin file, so we won't
5144 // see them growing s.files[]. Traverse it directly.
7b5b30a8 5145 for (unsigned i = 0; i < fc->referents.size(); i++)
389236d5 5146 {
7b5b30a8 5147 functiondecl* fd = fc->referents[i];
389236d5
JS
5148 sym.current_function = fd;
5149 sym.current_probe = 0;
5150 fd->body->visit (&sym);
5151 }
5152
5153 while (nfiles < s.files.size())
5154 {
5155 stapfile* dome = s.files[nfiles++];
5156 for (size_t i = 0; i < dome->functions.size(); ++i)
5157 {
5158 functiondecl* fd = dome->functions[i];
5159 sym.current_function = fd;
5160 sym.current_probe = 0;
5161 fd->body->visit (&sym);
5162 // NB: not adding to s.functions just yet...
5163 }
5164 }
5165
5166 // Add only the direct functions we need.
5167 functioncall_traversing_visitor ftv;
5168 fc->visit (&ftv);
7424f15c
JS
5169 for (set<functiondecl*>::iterator it = ftv.seen.begin();
5170 it != ftv.seen.end(); ++it)
389236d5
JS
5171 {
5172 functiondecl* fd = *it;
5173 pair<map<string,functiondecl*>::iterator,bool> inserted =
5174 s.functions.insert (make_pair (fd->name, fd));
5175 if (!inserted.second && inserted.first->second != fd)
5176 throw SEMANTIC_ERROR
5177 (_F("resolved function '%s' conflicts with an existing function",
5eb6ecb1 5178 fd->unmangled_name.to_string().c_str()), fc->tok);
389236d5
JS
5179 }
5180 }
66facfa3
JS
5181
5182 void visit_autocast_op (autocast_op* e)
5183 {
5184 const bool lvalue = is_active_lvalue (e);
5185 const exp_type_ptr& details = e->operand->type_details;
2107aa37 5186 if (details && !e->saved_conversion_error)
66facfa3 5187 {
389236d5
JS
5188 functioncall* fc = details->expand (e, lvalue);
5189 if (fc)
66facfa3
JS
5190 {
5191 ti.num_newly_resolved++;
5192
389236d5
JS
5193 resolve_functioncall (fc);
5194
66facfa3 5195 if (lvalue)
f55efafe 5196 provide_lvalue_call (fc);
66facfa3 5197
389236d5 5198 fc->visit (this);
66facfa3
JS
5199 return;
5200 }
5201 }
5202 var_expanding_visitor::visit_autocast_op (e);
5203 }
5204};
2b066ec1 5205
357612da
AJ
5206
5207struct initial_typeresolution_info : public typeresolution_info
5208{
5209 initial_typeresolution_info (systemtap_session& s): typeresolution_info(s)
5210 {}
5211
5212 // these expressions are not supposed to make its way to the typeresolution
5213 // pass. they probably get substituted/replaced, but since this is an initial pass
5214 // and not all substitutions are done, replace the functions that throw errors.
dabd71bb
MW
5215 void visit_target_symbol (target_symbol*) {}
5216 void visit_atvar_op (atvar_op*) {}
5217 void visit_defined_op (defined_op*) {}
5218 void visit_entry_op (entry_op*) {}
5219 void visit_cast_op (cast_op*) {}
357612da
AJ
5220};
5221
4375d018 5222static int initial_typeres_pass(systemtap_session& s)
cde4a9fe 5223{
d897ba7f
AJ
5224 // minimal type resolution based off of semantic_pass_types(), without
5225 // checking for complete type resolutions or autocast expanding
357612da 5226 initial_typeresolution_info ti(s);
d897ba7f
AJ
5227
5228 // Globals never have detailed types.
5229 // If we null them now, then all remaining vardecls can be detailed.
5230 for (unsigned j=0; j<s.globals.size(); j++)
5231 {
5232 vardecl* gd = s.globals[j];
5233 if (!gd->type_details)
5234 gd->type_details = ti.null_type;
5235 }
5236
357612da 5237 ti.assert_resolvability = false;
cde4a9fe
AJ
5238 while (1)
5239 {
5240 assert_no_interrupts();
5241
5242 ti.num_newly_resolved = 0;
cde4a9fe
AJ
5243 ti.num_still_unresolved = 0;
5244 ti.num_available_autocasts = 0;
5245
5246 for (map<string,functiondecl*>::iterator it = s.functions.begin();
5247 it != s.functions.end(); it++)
5248 {
5249 assert_no_interrupts();
5250
5251 functiondecl* fd = it->second;
5252 ti.current_probe = 0;
5253 ti.current_function = fd;
5254 ti.t = pe_unknown;
5255 fd->body->visit (& ti);
5256 }
5257
5258 for (unsigned j=0; j<s.probes.size(); j++)
5259 {
5260 assert_no_interrupts();
5261
5262 derived_probe* pn = s.probes[j];
5263 ti.current_function = 0;
5264 ti.current_probe = pn;
5265 ti.t = pe_unknown;
5266 pn->body->visit (& ti);
5267
5268 probe_point* pp = pn->sole_location();
5269 if (pp->condition)
5270 {
5271 ti.current_function = 0;
5272 ti.current_probe = 0;
5273 ti.t = pe_long; // NB: expected type
5274 pp->condition->visit (& ti);
5275 }
5276 }
5277 if (ti.num_newly_resolved == 0) // converged
6540f559
AJ
5278 {
5279 // take into account that if there are mismatches, we'd want to know
5280 // about them incase they get whisked away, later in this process
5281 if (!ti.assert_resolvability && ti.mismatch_complexity > 0) // found a mismatch!!
5282 {
5283 ti.assert_resolvability = true; // report errors
5284 if (s.verbose > 0)
5285 ti.mismatch_complexity = 1; // print out mismatched but not unresolved type mismatches
5286 }
5287 else
5288 break;
5289 }
5290 else
5291 ti.mismatch_complexity = 0;
cde4a9fe 5292 }
4375d018
AJ
5293
5294 return s.num_errors();
cde4a9fe
AJ
5295}
5296
2b066ec1
FCE
5297static int
5298semantic_pass_types (systemtap_session& s)
5299{
5300 int rc = 0;
5301
5302 // next pass: type inference
5303 unsigned iterations = 0;
5304 typeresolution_info ti (s);
57148ee7 5305
eb79eb0a
JS
5306 // Globals never have detailed types.
5307 // If we null them now, then all remaining vardecls can be detailed.
5308 for (unsigned j=0; j<s.globals.size(); j++)
5309 {
5310 vardecl* gd = s.globals[j];
5311 if (!gd->type_details)
5312 gd->type_details = ti.null_type;
5313 }
5314
2b066ec1 5315 ti.assert_resolvability = false;
2b066ec1
FCE
5316 while (1)
5317 {
e19ebcf7 5318 assert_no_interrupts();
49abf162 5319
2b066ec1 5320 iterations ++;
2b066ec1
FCE
5321 ti.num_newly_resolved = 0;
5322 ti.num_still_unresolved = 0;
66facfa3 5323 ti.num_available_autocasts = 0;
2b066ec1 5324
9e85f932
JL
5325 for (map<string,functiondecl*>::iterator it = s.functions.begin();
5326 it != s.functions.end(); it++)
96c7f494
FCE
5327 try
5328 {
5329 assert_no_interrupts();
5330
5331 functiondecl* fd = it->second;
5332 ti.current_probe = 0;
5333 ti.current_function = fd;
5334 ti.t = pe_unknown;
5335 fd->body->visit (& ti);
5336 // NB: we don't have to assert a known type for
5337 // functions here, to permit a "void" function.
5338 // The translator phase will omit the "retvalue".
5339 //
5340 // if (fd->type == pe_unknown)
5341 // ti.unresolved (fd->tok);
5342 for (unsigned i=0; i < fd->locals.size(); ++i)
5343 ti.check_local (fd->locals[i]);
5344
5345 // Check and run the autocast expanding visitor.
5346 if (ti.num_available_autocasts > 0)
5347 {
5348 autocast_expanding_visitor aev (ti);
5349 aev.replace (fd->body);
5350 ti.num_available_autocasts = 0;
5351 }
5352 }
5353 catch (const semantic_error& e)
5354 {
5355 throw SEMANTIC_ERROR(_F("while processing function %s",
5eb6ecb1 5356 it->second->unmangled_name.to_string().c_str())).set_chain(e);
96c7f494
FCE
5357 }
5358
2b066ec1 5359 for (unsigned j=0; j<s.probes.size(); j++)
96c7f494
FCE
5360 try
5361 {
5362 assert_no_interrupts();
5363
5364 derived_probe* pn = s.probes[j];
5365 ti.current_function = 0;
5366 ti.current_probe = pn;
5367 ti.t = pe_unknown;
5368 pn->body->visit (& ti);
5369 for (unsigned i=0; i < pn->locals.size(); ++i)
5370 ti.check_local (pn->locals[i]);
5371
5372 // Check and run the autocast expanding visitor.
5373 if (ti.num_available_autocasts > 0)
5374 {
5375 autocast_expanding_visitor aev (ti);
5376 aev.replace (pn->body);
5377 ti.num_available_autocasts = 0;
5378 }
5379
5380 probe_point* pp = pn->sole_location();
5381 if (pp->condition)
5382 {
5383 ti.current_function = 0;
5384 ti.current_probe = 0;
5385 ti.t = pe_long; // NB: expected type
5386 pp->condition->visit (& ti);
5387 }
5388 }
5389 catch (const semantic_error& e)
5390 {
5391 throw SEMANTIC_ERROR(_F("while processing probe %s",
5392 s.probes[j]->derived_locations(false).c_str())).set_chain(e);
5393 }
5394
2b066ec1
FCE
5395 for (unsigned j=0; j<s.globals.size(); j++)
5396 {
5397 vardecl* gd = s.globals[j];
5398 if (gd->type == pe_unknown)
5399 ti.unresolved (gd->tok);
bc889c8d
CM
5400 if(gd->arity == 0 && gd->wrap == true)
5401 {
96c7f494 5402 throw SEMANTIC_ERROR(_("wrapping not supported for scalars"), gd->tok);
bc889c8d 5403 }
2b066ec1 5404 }
57148ee7 5405
2b066ec1 5406 if (ti.num_newly_resolved == 0) // converged
78f6bba6
FCE
5407 {
5408 if (ti.num_still_unresolved == 0)
5409 break; // successfully
5410 else if (! ti.assert_resolvability)
c74ddc54
JL
5411 {
5412 ti.assert_resolvability = true; // last pass, with error msgs
5413 if (s.verbose > 0)
5414 ti.mismatch_complexity = 0; // print every kind of mismatch
5415 }
78f6bba6
FCE
5416 else
5417 { // unsuccessful conclusion
5418 rc ++;
5419 break;
5420 }
5421 }
c74ddc54
JL
5422 else
5423 ti.mismatch_complexity = 0; // reset for next pass
2b066ec1 5424 }
57148ee7 5425
7e41d3dc 5426 return rc + s.num_errors();
2b066ec1
FCE
5427}
5428
5429
eb79eb0a
JS
5430struct exp_type_null : public exp_type_details
5431{
5432 uintptr_t id () const { return 0; }
5433 bool expandable() const { return false; }
5434 functioncall *expand(autocast_op*, bool) { return NULL; }
5435};
bdef2583
FCE
5436
5437typeresolution_info::typeresolution_info (systemtap_session& s):
74fe61bc 5438 session(s), num_newly_resolved(0), num_still_unresolved(0),
c92d3b42 5439 num_available_autocasts(0),
c74ddc54 5440 assert_resolvability(false), mismatch_complexity(0),
eb79eb0a
JS
5441 current_function(0), current_probe(0), t(pe_unknown),
5442 null_type(new exp_type_null())
bdef2583
FCE
5443{
5444}
5445
5446
2b066ec1
FCE
5447void
5448typeresolution_info::visit_literal_number (literal_number* e)
5449{
5450 assert (e->type == pe_long);
5451 if ((t == e->type) || (t == pe_unknown))
5452 return;
5453
18bac841 5454 mismatch (e->tok, t, e->type);
2b066ec1
FCE
5455}
5456
5457
5458void
5459typeresolution_info::visit_literal_string (literal_string* e)
5460{
5461 assert (e->type == pe_string);
5462 if ((t == e->type) || (t == pe_unknown))
5463 return;
5464
18bac841 5465 mismatch (e->tok, t, e->type);
2b066ec1
FCE
5466}
5467
5468
5469void
5470typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
5471{
5472 visit_binary_expression (e);
5473}
5474
5475
5476void
5477typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
5478{
5479 visit_binary_expression (e);
5480}
5481
93daaca8
SM
5482void
5483typeresolution_info::visit_regex_query (regex_query *e)
5484{
5485 // NB: result of regex query is an integer!
5486 if (t == pe_stats || t == pe_string)
5487 invalid (e->tok, t);
5488
5489 t = pe_string;
5490 e->left->visit (this);
5491 t = pe_string;
5492 e->right->visit (this); // parser ensures this is a literal known at compile time
5493
5494 if (e->type == pe_unknown)
5495 {
5496 e->type = pe_long;
5497 resolved (e->tok, e->type);
5498 }
5499}
5500
2b066ec1
FCE
5501
5502void
5503typeresolution_info::visit_comparison (comparison *e)
5504{
d5d7c2cc 5505 // NB: result of any comparison is an integer!
553d27a5
FCE
5506 if (t == pe_stats || t == pe_string)
5507 invalid (e->tok, t);
5508
5509 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
5510 e->left->visit (this);
5511 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
5512 e->right->visit (this);
57148ee7 5513
553d27a5
FCE
5514 if (e->left->type != pe_unknown &&
5515 e->right->type != pe_unknown &&
5516 e->left->type != e->right->type)
18bac841 5517 mismatch (e);
57148ee7 5518
553d27a5
FCE
5519 if (e->type == pe_unknown)
5520 {
5521 e->type = pe_long;
5522 resolved (e->tok, e->type);
5523 }
2b066ec1
FCE
5524}
5525
5526
5527void
5528typeresolution_info::visit_concatenation (concatenation *e)
5529{
553d27a5
FCE
5530 if (t != pe_unknown && t != pe_string)
5531 invalid (e->tok, t);
5532
5533 t = pe_string;
5534 e->left->visit (this);
5535 t = pe_string;
5536 e->right->visit (this);
5537
5538 if (e->type == pe_unknown)
5539 {
5540 e->type = pe_string;
5541 resolved (e->tok, e->type);
5542 }
2b066ec1
FCE
5543}
5544
5545
2b066ec1
FCE
5546void
5547typeresolution_info::visit_assignment (assignment *e)
5548{
553d27a5
FCE
5549 if (t == pe_stats)
5550 invalid (e->tok, t);
2b066ec1 5551
2b066ec1
FCE
5552 if (e->op == "<<<") // stats aggregation
5553 {
553d27a5
FCE
5554 if (t == pe_string)
5555 invalid (e->tok, t);
5556
2b066ec1
FCE
5557 t = pe_stats;
5558 e->left->visit (this);
5559 t = pe_long;
5560 e->right->visit (this);
57b73400
GH
5561 if (e->type == pe_unknown ||
5562 e->type == pe_stats)
2b066ec1
FCE
5563 {
5564 e->type = pe_long;
5565 resolved (e->tok, e->type);
5566 }
5567 }
57b73400
GH
5568
5569 else if (e->left->type == pe_stats)
5570 invalid (e->left->tok, e->left->type);
5571
5572 else if (e->right->type == pe_stats)
5573 invalid (e->right->tok, e->right->type);
5574
553d27a5 5575 else if (e->op == "+=" || // numeric only
d5d7c2cc
FCE
5576 e->op == "-=" ||
5577 e->op == "*=" ||
5578 e->op == "/=" ||
5579 e->op == "%=" ||
5580 e->op == "&=" ||
5581 e->op == "^=" ||
5582 e->op == "|=" ||
5583 e->op == "<<=" ||
5584 e->op == ">>=" ||
553d27a5 5585 false)
2b066ec1 5586 {
553d27a5 5587 visit_binary_expression (e);
2b066ec1 5588 }
d5d7c2cc
FCE
5589 else if (e->op == ".=" || // string only
5590 false)
5591 {
5592 if (t == pe_long || t == pe_stats)
5593 invalid (e->tok, t);
5594
5595 t = pe_string;
5596 e->left->visit (this);
5597 t = pe_string;
5598 e->right->visit (this);
5599 if (e->type == pe_unknown)
5600 {
5601 e->type = pe_string;
5602 resolved (e->tok, e->type);
5603 }
5604 }
5605 else if (e->op == "=") // overloaded = for string & numeric operands
2b066ec1 5606 {
553d27a5 5607 // logic similar to ternary_expression
2b066ec1 5608 exp_type sub_type = t;
553d27a5
FCE
5609
5610 // Infer types across the l/r values
5611 if (sub_type == pe_unknown && e->type != pe_unknown)
2b066ec1 5612 sub_type = e->type;
553d27a5
FCE
5613
5614 t = (sub_type != pe_unknown) ? sub_type :
5615 (e->right->type != pe_unknown) ? e->right->type :
5616 pe_unknown;
2b066ec1 5617 e->left->visit (this);
553d27a5
FCE
5618 t = (sub_type != pe_unknown) ? sub_type :
5619 (e->left->type != pe_unknown) ? e->left->type :
5620 pe_unknown;
2b066ec1 5621 e->right->visit (this);
57148ee7 5622
553d27a5 5623 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2b066ec1
FCE
5624 {
5625 e->type = sub_type;
5626 resolved (e->tok, e->type);
5627 }
553d27a5 5628 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
2b066ec1
FCE
5629 {
5630 e->type = e->left->type;
5631 resolved (e->tok, e->type);
5632 }
553d27a5
FCE
5633
5634 if (e->left->type != pe_unknown &&
5635 e->right->type != pe_unknown &&
5636 e->left->type != e->right->type)
18bac841 5637 mismatch (e);
d02548c0 5638
eb79eb0a
JS
5639 // Propagate type details from the RHS to the assignment
5640 if (e->type == e->right->type &&
5641 e->right->type_details && !e->type_details)
5642 resolved_details(e->right->type_details, e->type_details);
5643
5644 // Propagate type details from the assignment to the LHS
5645 if (e->type == e->left->type && e->type_details)
5646 {
5647 if (e->left->type_details &&
5648 *e->left->type_details != *e->type_details &&
5649 *e->left->type_details != *null_type)
5650 resolved_details(null_type, e->left->type_details);
5651 else if (!e->left->type_details)
5652 resolved_details(e->type_details, e->left->type_details);
5653 }
553d27a5 5654 }
d5d7c2cc 5655 else
47d349b1 5656 throw SEMANTIC_ERROR (_("unsupported assignment operator ") + (string)e->op);
553d27a5
FCE
5657}
5658
5659
7d902887
FCE
5660void
5661typeresolution_info::visit_embedded_expr (embedded_expr *e)
5662{
5663 if (e->type == pe_unknown)
5664 {
5665 if (e->code.find ("/* string */") != string::npos)
5666 e->type = pe_string;
5667 else // if (e->code.find ("/* long */") != string::npos)
5668 e->type = pe_long;
5669
5670 resolved (e->tok, e->type);
5671 }
5672}
5673
5674
553d27a5
FCE
5675void
5676typeresolution_info::visit_binary_expression (binary_expression* e)
5677{
5678 if (t == pe_stats || t == pe_string)
5679 invalid (e->tok, t);
5680
5681 t = pe_long;
5682 e->left->visit (this);
5683 t = pe_long;
5684 e->right->visit (this);
5685
5686 if (e->left->type != pe_unknown &&
5687 e->right->type != pe_unknown &&
5688 e->left->type != e->right->type)
18bac841 5689 mismatch (e);
57148ee7 5690
553d27a5
FCE
5691 if (e->type == pe_unknown)
5692 {
5693 e->type = pe_long;
5694 resolved (e->tok, e->type);
2b066ec1
FCE
5695 }
5696}
5697
5698
5699void
5700typeresolution_info::visit_pre_crement (pre_crement *e)
5701{
5702 visit_unary_expression (e);
5703}
5704
5705
5706void
5707typeresolution_info::visit_post_crement (post_crement *e)
5708{
5709 visit_unary_expression (e);
5710}
5711
5712
5713void
5714typeresolution_info::visit_unary_expression (unary_expression* e)
5715{
553d27a5
FCE
5716 if (t == pe_stats || t == pe_string)
5717 invalid (e->tok, t);
5718
2b066ec1
FCE
5719 t = pe_long;
5720 e->operand->visit (this);
5721
553d27a5 5722 if (e->type == pe_unknown)
2b066ec1
FCE
5723 {
5724 e->type = pe_long;
5725 resolved (e->tok, e->type);
5726 }
5727}
5728
5729
2b066ec1
FCE
5730void
5731typeresolution_info::visit_ternary_expression (ternary_expression* e)
5732{
5733 exp_type sub_type = t;
5734
5735 t = pe_long;
5736 e->cond->visit (this);
5737
553d27a5 5738 // Infer types across the true/false arms of the ternary expression.
2b066ec1
FCE
5739
5740 if (sub_type == pe_unknown && e->type != pe_unknown)
5741 sub_type = e->type;
5742 t = sub_type;
5743 e->truevalue->visit (this);
5744 t = sub_type;
5745 e->falsevalue->visit (this);
5746
5747 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
5748 ; // already resolved
5749 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
5750 {
5751 e->type = sub_type;
5752 resolved (e->tok, e->type);
5753 }
5754 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
5755 {
5756 e->type = e->truevalue->type;
5757 resolved (e->tok, e->type);
5758 }
5759 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
5760 {
5761 e->type = e->falsevalue->type;
5762 resolved (e->tok, e->type);
5763 }
5764 else if (e->type != sub_type)
5765 mismatch (e->tok, sub_type, e->type);
eb79eb0a
JS
5766
5767 // Propagate type details from both true/false branches
5768 if (!e->type_details &&
5769 e->type == e->truevalue->type && e->type == e->falsevalue->type &&
5770 e->truevalue->type_details && e->falsevalue->type_details &&
5771 *e->truevalue->type_details == *e->falsevalue->type_details)
5772 resolved_details(e->truevalue->type_details, e->type_details);
2b066ec1
FCE
5773}
5774
5775
5776template <class Referrer, class Referent>
5777void resolve_2types (Referrer* referrer, Referent* referent,
31966088 5778 typeresolution_info* r, exp_type t, bool accept_unknown = false)
2b066ec1
FCE
5779{
5780 exp_type& re_type = referrer->type;
5781 const token* re_tok = referrer->tok;
5782 exp_type& te_type = referent->type;
2b066ec1
FCE
5783
5784 if (t != pe_unknown && re_type == t && re_type == te_type)
5785 ; // do nothing: all three e->types in agreement
5786 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
5787 ; // do nothing: two known e->types in agreement
5788 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
18bac841 5789 r->mismatch (re_tok, re_type, referent); // referrer-referent
2b066ec1 5790 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
18bac841 5791 r->mismatch (re_tok, t, referent); // referrer-t
2b066ec1 5792 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
18bac841 5793 r->mismatch (re_tok, t, referent); // referent-t
2b066ec1
FCE
5794 else if (re_type == pe_unknown && t != pe_unknown)
5795 {
5796 // propagate from upstream
5797 re_type = t;
5798 r->resolved (re_tok, re_type);
5799 // catch re_type/te_type mismatch later
5800 }
5801 else if (re_type == pe_unknown && te_type != pe_unknown)
5802 {
5803 // propagate from referent
5804 re_type = te_type;
5805 r->resolved (re_tok, re_type);
5806 // catch re_type/t mismatch later
5807 }
5808 else if (re_type != pe_unknown && te_type == pe_unknown)
5809 {
5810 // propagate to referent
5811 te_type = re_type;
18bac841 5812 r->resolved (re_tok, re_type, referent);
2b066ec1
FCE
5813 // catch re_type/t mismatch later
5814 }
31966088 5815 else if (! accept_unknown)
2b066ec1
FCE
5816 r->unresolved (re_tok);
5817}
5818
5819
5820void
5821typeresolution_info::visit_symbol (symbol* e)
5822{
017b0053 5823 if (e->referent == 0)
47d349b1 5824 throw SEMANTIC_ERROR (_F("internal error: unresolved symbol '%s'",
7371cd19 5825 e->name.to_string().c_str()), e->tok);
017b0053 5826
d02548c0 5827 resolve_2types (e, e->referent, this, t);
eb79eb0a
JS
5828
5829 if (e->type == e->referent->type)
5830 {
5831 // If both have type details, then they either must agree;
5832 // otherwise force them both to null.
5833 if (e->type_details && e->referent->type_details &&
5834 *e->type_details != *e->referent->type_details)
5835 {
5836 resolved_details(null_type, e->type_details);
5837 resolved_details(null_type, e->referent->type_details);
5838 }
5839 else if (e->type_details && !e->referent->type_details)
5840 resolved_details(e->type_details, e->referent->type_details);
5841 else if (!e->type_details && e->referent->type_details)
5842 resolved_details(e->referent->type_details, e->type_details);
5843 }
2b066ec1
FCE
5844}
5845
5846
d7f3e0c5
GH
5847void
5848typeresolution_info::visit_target_symbol (target_symbol* e)
5849{
cbfbbf69
FCE
5850 // This occurs only if a target symbol was not resolved over in
5851 // tapset.cxx land, that error was properly suppressed, and the
5852 // later unused-expression-elimination pass didn't get rid of it
5853 // either. So we have a target symbol that is believed to be of
5854 // genuine use, yet unresolved by the provider.
ba6f838d
FCE
5855
5856 if (session.verbose > 2)
5857 {
4af765b2 5858 clog << _("Resolution problem with ");
ba6f838d
FCE
5859 if (current_function)
5860 {
5861 clog << "function " << current_function->name << endl;
5862 current_function->body->print (clog);
5863 clog << endl;
5864 }
5865 else if (current_probe)
5866 {
da2df842 5867 clog << "probe " << *current_probe->sole_location() << endl;
ba6f838d
FCE
5868 current_probe->body->print (clog);
5869 clog << endl;
5870 }
57148ee7 5871 else
4af765b2
LB
5872 //TRANSLATORS: simply saying not an issue with a probe or function
5873 clog << _("other") << endl;
ba6f838d
FCE
5874 }
5875
9b48ce88
FCE
5876 if (e->saved_conversion_error)
5877 throw (* (e->saved_conversion_error));
5878 else
dc09353a 5879 throw SEMANTIC_ERROR(_("unresolved target-symbol expression"), e->tok);
d7f3e0c5
GH
5880}
5881
5882
bd1fcbad
YZ
5883void
5884typeresolution_info::visit_atvar_op (atvar_op* e)
5885{
5886 // This occurs only if an @var() was not resolved over in
5887 // tapset.cxx land, that error was properly suppressed, and the
5888 // later unused-expression-elimination pass didn't get rid of it
5889 // either. So we have an @var() that is believed to be of
5890 // genuine use, yet unresolved by the provider.
5891
5892 if (session.verbose > 2)
5893 {
5894 clog << _("Resolution problem with ");
5895 if (current_function)
5896 {
5897 clog << "function " << current_function->name << endl;
5898 current_function->body->print (clog);
5899 clog << endl;
5900 }
5901 else if (current_probe)
5902 {
5903 clog << "probe " << *current_probe->sole_location() << endl;
5904 current_probe->body->print (clog);
5905 clog << endl;
5906 }
5907 else
5908 //TRANSLATORS: simply saying not an issue with a probe or function
5909 clog << _("other") << endl;
5910 }
5911
5912 if (e->saved_conversion_error)
5913 throw (* (e->saved_conversion_error));
5914 else
dc09353a 5915 throw SEMANTIC_ERROR(_("unresolved @var() expression"), e->tok);
bd1fcbad
YZ
5916}
5917
5918
30263a73
FCE
5919void
5920typeresolution_info::visit_defined_op (defined_op* e)
5921{
dc09353a 5922 throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
30263a73
FCE
5923}
5924
5925
8cc799a5
JS
5926void
5927typeresolution_info::visit_entry_op (entry_op* e)
5928{
dc09353a 5929 throw SEMANTIC_ERROR(_("@entry is only valid in .return probes"), e->tok);
8cc799a5
JS
5930}
5931
5932
9b5af295
JS
5933void
5934typeresolution_info::visit_cast_op (cast_op* e)
5935{
5936 // Like target_symbol, a cast_op shouldn't survive this far
5937 // unless it was not resolved and its value is really needed.
5938 if (e->saved_conversion_error)
5939 throw (* (e->saved_conversion_error));
5940 else
47d349b1 5941 throw SEMANTIC_ERROR(_F("type definition '%s' not found in '%s'",
7371cd19
JS
5942 e->type_name.to_string().c_str(),
5943 e->module.to_string().c_str()), e->tok);
9b5af295
JS
5944}
5945
5946
251707c8
JS
5947void
5948typeresolution_info::visit_autocast_op (autocast_op* e)
5949{
5950 // Like cast_op, a implicit autocast_op shouldn't survive this far
5951 // unless it was not resolved and its value is really needed.
2107aa37 5952 if (assert_resolvability && e->saved_conversion_error)
251707c8 5953 throw (* (e->saved_conversion_error));
66facfa3 5954 else if (assert_resolvability)
251707c8 5955 throw SEMANTIC_ERROR(_("unknown type in dereference"), e->tok);
66facfa3
JS
5956
5957 t = pe_long;
5958 e->operand->visit (this);
5959
5960 num_still_unresolved++;
eb79eb0a
JS
5961 if (e->operand->type_details &&
5962 e->operand->type_details->expandable())
66facfa3 5963 num_available_autocasts++;
251707c8
JS
5964}
5965
5966
3689db05
SC
5967void
5968typeresolution_info::visit_perf_op (perf_op* e)
5969{
5970 // A perf_op should already be resolved
5971 if (t == pe_stats || t == pe_string)
5972 invalid (e->tok, t);
5973
ad583484
FCE
5974 e->type = pe_long;
5975
5976 // (There is no real need to visit our operand - by parser
5977 // construction, it's always a string literal, with its type already
5978 // set.)
5979 t = pe_string;
3689db05
SC
5980 e->operand->visit (this);
5981}
5982
5983
2b066ec1
FCE
5984void
5985typeresolution_info::visit_arrayindex (arrayindex* e)
5986{
2b066ec1 5987
d02548c0
GH
5988 symbol *array = NULL;
5989 hist_op *hist = NULL;
5990 classify_indexable(e->base, array, hist);
57148ee7 5991
d02548c0
GH
5992 // Every hist_op has type [int]:int, that is to say, every hist_op
5993 // is a pseudo-one-dimensional integer array type indexed by
5994 // integers (bucket numbers).
5995
5996 if (hist)
5997 {
5998 if (e->indexes.size() != 1)
5999 unresolved (e->tok);
6000 t = pe_long;
6001 e->indexes[0]->visit (this);
6002 if (e->indexes[0]->type != pe_long)
6003 unresolved (e->tok);
a4636912 6004 hist->visit (this);
1bbeef03
GH
6005 if (e->type != pe_long)
6006 {
6007 e->type = pe_long;
18bac841 6008 resolved (e->tok, e->type);
1bbeef03 6009 }
d02548c0
GH
6010 return;
6011 }
6012
6013 // Now we are left with "normal" map inference and index checking.
6014
6015 assert (array);
6016 assert (array->referent != 0);
6017 resolve_2types (e, array->referent, this, t);
2b066ec1
FCE
6018
6019 // now resolve the array indexes
69c68955
FCE
6020
6021 // if (e->referent->index_types.size() == 0)
6022 // // redesignate referent as array
6023 // e->referent->set_arity (e->indexes.size ());
2b066ec1 6024
d02548c0 6025 if (e->indexes.size() != array->referent->index_types.size())
2b066ec1
FCE
6026 unresolved (e->tok); // symbol resolution should prevent this
6027 else for (unsigned i=0; i<e->indexes.size(); i++)
6028 {
45af9d1b 6029 if (e->indexes[i])
2b066ec1 6030 {
45af9d1b
AJ
6031 expression* ee = e->indexes[i];
6032 exp_type& ft = array->referent->index_types [i];
6033 t = ft;
6034 ee->visit (this);
6035 exp_type at = ee->type;
6036
6037 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
6038 {
6039 // propagate to formal type
6040 ft = at;
6041 resolved (ee->tok, ft, array->referent, i);
6042 }
6043 if (at == pe_stats)
6044 invalid (ee->tok, at);
6045 if (ft == pe_stats)
6046 invalid (ee->tok, ft);
6047 if (at != pe_unknown && ft != pe_unknown && ft != at)
6048 mismatch (ee->tok, ee->type, array->referent, i);
6049 if (at == pe_unknown)
6050 unresolved (ee->tok);
2b066ec1 6051 }
2b066ec1
FCE
6052 }
6053}
6054
6055
6056void
6057typeresolution_info::visit_functioncall (functioncall* e)
6058{
7b5b30a8 6059 if (e->referents.empty())
017b0053 6060 throw SEMANTIC_ERROR (_F("internal error: unresolved function call to '%s'",
7371cd19 6061 e->function.to_string().c_str()), e->tok);
2b066ec1 6062
c0d0d623 6063 exp_type original = t;
7b5b30a8
FL
6064 for (unsigned fd = 0; fd < e->referents.size(); fd++)
6065 {
c0d0d623 6066 t = original; // type may be changed by overloaded functions so restore it
7b5b30a8
FL
6067 functiondecl* referent = e->referents[fd];
6068 resolve_2types (e, referent, this, t, true); // accept unknown type
2b066ec1 6069
7b5b30a8
FL
6070 if (e->type == pe_stats)
6071 invalid (e->tok, e->type);
c3ed664e 6072
7b5b30a8
FL
6073 const exp_type_ptr& func_type = referent->type_details;
6074 if (func_type && referent->type == e->type
6075 && (!e->type_details || *func_type != *e->type_details))
6076 resolved_details(referent->type_details, e->type_details);
57148ee7 6077
7b5b30a8
FL
6078 // now resolve the function parameters
6079 if (e->args.size() != referent->formal_args.size())
6080 unresolved (e->tok); // symbol resolution should prevent this
6081 else for (unsigned i=0; i<e->args.size(); i++)
2b066ec1 6082 {
7b5b30a8
FL
6083 expression* ee = e->args[i];
6084 exp_type& ft = referent->formal_args[i]->type;
6085 const token* fe_tok = referent->formal_args[i]->tok;
6086 t = ft;
6087 ee->visit (this);
6088 exp_type at = ee->type;
6089
6090 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
6091 {
6092 // propagate to formal arg
6093 ft = at;
6094 resolved (ee->tok, ft, referent->formal_args[i], i);
6095 }
6096 if (at == pe_stats)
6097 invalid (ee->tok, at);
6098 if (ft == pe_stats)
6099 invalid (fe_tok, ft);
6100 if (at != pe_unknown && ft != pe_unknown && ft != at)
6101 mismatch (ee->tok, ee->type, referent->formal_args[i], i);
6102 if (at == pe_unknown)
6103 unresolved (ee->tok);
2b066ec1 6104 }
2b066ec1
FCE
6105 }
6106}
6107
6108
6109void
6110typeresolution_info::visit_block (block* e)
6111{
6112 for (unsigned i=0; i<e->statements.size(); i++)
6113 {
1cda9c44
JS
6114 t = pe_unknown;
6115 e->statements[i]->visit (this);
2b066ec1
FCE
6116 }
6117}
6118
6119
f4fe2e93
FCE
6120void
6121typeresolution_info::visit_try_block (try_block* e)
6122{
6123 if (e->try_block)
6124 e->try_block->visit (this);
6125 if (e->catch_error_var)
6126 {
6127 t = pe_string;
6128 e->catch_error_var->visit (this);
6129 }
6130 if (e->catch_block)
6131 e->catch_block->visit (this);
6132}
6133
6134
54dfabe9 6135void
6a80494e 6136typeresolution_info::visit_embeddedcode (embeddedcode* s)
54dfabe9 6137{
6a80494e
FCE
6138 // PR11573. If we have survived thus far with a piece of embedded
6139 // code that requires uprobes, we need to track this.
6140 //
6141 // This is an odd place for this check, as opposed
6142 // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
6143 // over yonder in pass 3. However, we want to do it during pass 2 so
6144 // that cached sessions also get the uprobes treatment.
26c2e4c2
SM
6145 if (! session.need_uprobes
6146 && s->code.find("/* pragma:uprobes */") != string::npos)
6a80494e
FCE
6147 {
6148 if (session.verbose > 2)
4af765b2 6149 clog << _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl;
6a80494e
FCE
6150 session.need_uprobes = true;
6151 }
26c2e4c2
SM
6152
6153 // PR15065. Likewise, we need to detect /* pragma:tagged_dfa */
6154 // before the gen_dfa_table pass. Again, the typechecking part of
6155 // pass 2 is a good place for this.
6156 if (! session.need_tagged_dfa
6157 && s->code.find("/* pragma:tagged_dfa */") != string::npos)
6158 {
112e9e2b
SM
6159 // if (session.verbose > 2)
6160 // clog << _F("Turning on DFA subexpressions, pragma:tagged_dfa found in %s",
6161 // current_function->name.c_str()) << endl;
6162 // session.need_tagged_dfa = true;
dc09353a 6163 throw SEMANTIC_ERROR (_("Tagged DFA support is not yet available"), s->tok);
26c2e4c2 6164 }
54dfabe9
FCE
6165}
6166
6167
2b066ec1
FCE
6168void
6169typeresolution_info::visit_if_statement (if_statement* e)
6170{
6171 t = pe_long;
6172 e->condition->visit (this);
6173
6174 t = pe_unknown;
6175 e->thenblock->visit (this);
6176
6177 if (e->elseblock)
6178 {
6179 t = pe_unknown;
6180 e->elseblock->visit (this);
6181 }
6182}
6183
6184
6185void
6186typeresolution_info::visit_for_loop (for_loop* e)
6187{
6188 t = pe_unknown;
cbfbbf69 6189 if (e->init) e->init->visit (this);
2b066ec1
FCE
6190 t = pe_long;
6191 e->cond->visit (this);
6192 t = pe_unknown;
57148ee7 6193 if (e->incr) e->incr->visit (this);
2b066ec1 6194 t = pe_unknown;
57148ee7 6195 e->block->visit (this);
2b066ec1
FCE
6196}
6197
6198
69c68955
FCE
6199void
6200typeresolution_info::visit_foreach_loop (foreach_loop* e)
6201{
6202 // See also visit_arrayindex.
6203 // This is different in that, being a statement, we can't assign
6204 // a type to the outer array, only propagate to/from the indexes
6205
6206 // if (e->referent->index_types.size() == 0)
6207 // // redesignate referent as array
6208 // e->referent->set_arity (e->indexes.size ());
6209
c261711d 6210 exp_type wanted_value = pe_unknown;
d02548c0
GH
6211 symbol *array = NULL;
6212 hist_op *hist = NULL;
6213 classify_indexable(e->base, array, hist);
69c68955 6214
d02548c0 6215 if (hist)
57148ee7 6216 {
d02548c0
GH
6217 if (e->indexes.size() != 1)
6218 unresolved (e->tok);
6219 t = pe_long;
6220 e->indexes[0]->visit (this);
6221 if (e->indexes[0]->type != pe_long)
6222 unresolved (e->tok);
a4636912 6223 hist->visit (this);
c261711d 6224 wanted_value = pe_long;
d02548c0
GH
6225 }
6226 else
6227 {
57148ee7 6228 assert (array);
d02548c0
GH
6229 if (e->indexes.size() != array->referent->index_types.size())
6230 unresolved (e->tok); // symbol resolution should prevent this
3040bf3a
AJ
6231 else
6232 {
6233 for (unsigned i=0; i<e->indexes.size(); i++)
6234 {
6235 expression* ee = e->indexes[i];
6236 exp_type& ft = array->referent->index_types [i];
6237 t = ft;
6238 ee->visit (this);
6239 exp_type at = ee->type;
57148ee7 6240
3040bf3a
AJ
6241 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
6242 {
6243 // propagate to formal type
6244 ft = at;
6245 resolved (ee->tok, ee->type, array->referent, i);
6246 }
6247 if (at == pe_stats)
6248 invalid (ee->tok, at);
6249 if (ft == pe_stats)
6250 invalid (ee->tok, ft);
6251 if (at != pe_unknown && ft != pe_unknown && ft != at)
6252 mismatch (ee->tok, ee->type, array->referent, i);
6253 if (at == pe_unknown)
6254 unresolved (ee->tok);
6255 }
6256 for (unsigned i=0; i<e->array_slice.size(); i++)
45af9d1b 6257 if (e->array_slice[i])
3040bf3a
AJ
6258 {
6259 expression* ee = e->array_slice[i];
6260 exp_type& ft = array->referent->index_types [i];
6261 t = ft;
6262 ee->visit (this);
6263 exp_type at = ee->type;
6264
6265 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
6266 {
6267 // propagate to formal type
6268 ft = at;
6269 resolved (ee->tok, ee->type, array->referent, i);
6270 }
6271 if (at == pe_stats)
6272 invalid (ee->tok, at);
6273 if (ft == pe_stats)
6274 invalid (ee->tok, ft);
6275 if (at != pe_unknown && ft != pe_unknown && ft != at)
6276 mismatch (ee->tok, ee->type, array->referent, i);
6277 if (at == pe_unknown)
6278 unresolved (ee->tok);
6279 }
6280 }
c261711d
JS
6281 t = pe_unknown;
6282 array->visit (this);
6283 wanted_value = array->type;
6284 }
6285
6286 if (e->value)
6287 {
6288 if (wanted_value == pe_stats)
6289 invalid(e->value->tok, wanted_value);
6290 else if (wanted_value != pe_unknown)
6291 check_arg_type(wanted_value, e->value);
6292 else
6293 {
6294 t = pe_unknown;
6295 e->value->visit (this);
6296 }
69c68955
FCE
6297 }
6298
fd5689dc
FCE
6299 /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */
6300 if (wanted_value != pe_unknown)
6301 if (e->sort_aggr != sc_none && wanted_value != pe_stats)
6302 invalid (array->tok, wanted_value);
6303
27f21e8c
DS
6304 if (e->limit)
6305 {
6306 t = pe_long;
6307 e->limit->visit (this);
6308 }
6309
69c68955 6310 t = pe_unknown;
57148ee7 6311 e->block->visit (this);
69c68955
FCE
6312}
6313
6314
2b066ec1 6315void
78f6bba6 6316typeresolution_info::visit_null_statement (null_statement*)
2b066ec1
FCE
6317{
6318}
6319
6320
6321void
6322typeresolution_info::visit_expr_statement (expr_statement* e)
6323{
6324 t = pe_unknown;
6325 e->value->visit (this);
6326}
6327
6328
57148ee7 6329struct delete_statement_typeresolution_info:
d98d459c
GH
6330 public throwing_visitor
6331{
6332 typeresolution_info *parent;
6333 delete_statement_typeresolution_info (typeresolution_info *p):
4af765b2 6334 throwing_visitor (_("invalid operand of delete expression")),
d98d459c
GH
6335 parent (p)
6336 {}
6337
6338 void visit_arrayindex (arrayindex* e)
6339 {
6340 parent->visit_arrayindex (e);
6341 }
57148ee7 6342
d98d459c
GH
6343 void visit_symbol (symbol* e)
6344 {
6345 exp_type ignored = pe_unknown;
57148ee7 6346 assert (e->referent != 0);
d98d459c
GH
6347 resolve_2types (e, e->referent, parent, ignored);
6348 }
6349};
6350
6351
2b066ec1
FCE
6352void
6353typeresolution_info::visit_delete_statement (delete_statement* e)
6354{
d98d459c
GH
6355 delete_statement_typeresolution_info di (this);
6356 t = pe_unknown;
6357 e->value->visit (&di);
2b066ec1
FCE
6358}
6359
6360
f3c26ea5 6361void
78f6bba6 6362typeresolution_info::visit_next_statement (next_statement*)
f3c26ea5
FCE
6363{
6364}
6365
6366
6367void
78f6bba6 6368typeresolution_info::visit_break_statement (break_statement*)
f3c26ea5
FCE
6369{
6370}
6371
6372
6373void
78f6bba6 6374typeresolution_info::visit_continue_statement (continue_statement*)
f3c26ea5
FCE
6375{
6376}
6377
6378
2b066ec1
FCE
6379void
6380typeresolution_info::visit_array_in (array_in* e)
6381{
ce10591c
FCE
6382 // all unary operators only work on numerics
6383 exp_type t1 = t;
6384 t = pe_unknown; // array value can be anything
6385 e->operand->visit (this);
6386
6387 if (t1 == pe_unknown && e->type != pe_unknown)
6388 ; // already resolved
6389 else if (t1 == pe_string || t1 == pe_stats)
6390 mismatch (e->tok, t1, pe_long);
6391 else if (e->type == pe_unknown)
6392 {
6393 e->type = pe_long;
6394 resolved (e->tok, e->type);
6395 }
2b066ec1
FCE
6396}
6397
6398
6399void
6400typeresolution_info::visit_return_statement (return_statement* e)
6401{
6402 // This is like symbol, where the referent is
6403 // the return value of the function.
6404
57148ee7 6405 // translation pass will print error
2b066ec1 6406 if (current_function == 0)
22f46231 6407 return;
2b066ec1
FCE
6408
6409 exp_type& e_type = current_function->type;
6410 t = current_function->type;
6411 e->value->visit (this);
6412
6413 if (e_type != pe_unknown && e->value->type != pe_unknown
6414 && e_type != e->value->type)
18bac841 6415 mismatch (e->value->tok, e->value->type, current_function);
57148ee7 6416 if (e_type == pe_unknown &&
2b066ec1
FCE
6417 (e->value->type == pe_long || e->value->type == pe_string))
6418 {
6419 // propagate non-statistics from value
6420 e_type = e->value->type;
18bac841 6421 resolved (e->value->tok, e_type, current_function);
2b066ec1
FCE
6422 }
6423 if (e->value->type == pe_stats)
6424 invalid (e->value->tok, e->value->type);
c3ed664e
JS
6425
6426 const exp_type_ptr& value_type = e->value->type_details;
6427 if (value_type && current_function->type == e->value->type)
6428 {
6429 exp_type_ptr& func_type = current_function->type_details;
6430 if (!func_type)
6431 // The function can take on the type details of the return value.
6432 resolved_details(value_type, func_type);
6433 else if (*func_type != *value_type && *func_type != *null_type)
6434 // Conflicting return types? NO TYPE FOR YOU!
6435 resolved_details(null_type, func_type);
6436 }
2b066ec1
FCE
6437}
6438
57148ee7 6439void
d02548c0
GH
6440typeresolution_info::visit_print_format (print_format* e)
6441{
6442 size_t unresolved_args = 0;
6443
1bbeef03
GH
6444 if (e->hist)
6445 {
6446 e->hist->visit(this);
6447 }
6448
6449 else if (e->print_with_format)
d02548c0
GH
6450 {
6451 // If there's a format string, we can do both inference *and*
6452 // checking.
6453
6454 // First we extract the subsequence of formatting components
6455 // which are conversions (not just literal string components)
6456
34201621 6457 unsigned expected_num_args = 0;
d02548c0
GH
6458 std::vector<print_format::format_component> components;
6459 for (size_t i = 0; i < e->components.size(); ++i)
6460 {
6461 if (e->components[i].type == print_format::conv_unspecified)
dc09353a 6462 throw SEMANTIC_ERROR (_("Unspecified conversion in print operator format string"),
d02548c0 6463 e->tok);
b5852334 6464 else if (e->components[i].type == print_format::conv_literal)
d02548c0
GH
6465 continue;
6466 components.push_back(e->components[i]);
34201621
DB
6467 ++expected_num_args;
6468 if (e->components[i].widthtype == print_format::width_dynamic)
6469 ++expected_num_args;
6470 if (e->components[i].prectype == print_format::prec_dynamic)
6471 ++expected_num_args;
d02548c0
GH
6472 }
6473
6474 // Then we check that the number of conversions and the number
6475 // of args agree.
6476
34201621 6477 if (expected_num_args != e->args.size())
dc09353a 6478 throw SEMANTIC_ERROR (_("Wrong number of args to formatted print operator"),
d02548c0
GH
6479 e->tok);
6480
6481 // Then we check that the types of the conversions match the types
6482 // of the args.
34201621 6483 unsigned argno = 0;
d02548c0
GH
6484 for (size_t i = 0; i < components.size(); ++i)
6485 {
34201621
DB
6486 // Check the dynamic width, if specified
6487 if (components[i].widthtype == print_format::width_dynamic)
6488 {
6489 check_arg_type (pe_long, e->args[argno]);
6490 ++argno;
6491 }
6492
6493 // Check the dynamic precision, if specified
6494 if (components[i].prectype == print_format::prec_dynamic)
6495 {
6496 check_arg_type (pe_long, e->args[argno]);
6497 ++argno;
6498 }
6499
d02548c0
GH
6500 exp_type wanted = pe_unknown;
6501
6502 switch (components[i].type)
6503 {
d02548c0
GH
6504 case print_format::conv_unspecified:
6505 case print_format::conv_literal:
6506 assert (false);
6507 break;
6508
929eb962
JS
6509 case print_format::conv_pointer:
6510 case print_format::conv_number:
dc0b623a 6511 case print_format::conv_binary:
fecccf83 6512 case print_format::conv_char:
ec03bd4b 6513 case print_format::conv_memory:
30c94a80 6514 case print_format::conv_memory_hex:
d02548c0
GH
6515 wanted = pe_long;
6516 break;
6517
6518 case print_format::conv_string:
6519 wanted = pe_string;
6520 break;
6521 }
6522
6523 assert (wanted != pe_unknown);
34201621
DB
6524 check_arg_type (wanted, e->args[argno]);
6525 ++argno;
d02548c0
GH
6526 }
6527 }
6528 else
6529 {
6530 // Without a format string, the best we can do is require that
6531 // each argument resolve to a concrete type.
6532 for (size_t i = 0; i < e->args.size(); ++i)
6533 {
6534 t = pe_unknown;
6535 e->args[i]->visit (this);
6536 if (e->args[i]->type == pe_unknown)
6537 {
6538 unresolved (e->args[i]->tok);
6539 ++unresolved_args;
6540 }
6541 }
6542 }
57148ee7 6543
d02548c0
GH
6544 if (unresolved_args == 0)
6545 {
6546 if (e->type == pe_unknown)
6547 {
6548 if (e->print_to_stream)
6549 e->type = pe_long;
6550 else
57148ee7 6551 e->type = pe_string;
d02548c0
GH
6552 resolved (e->tok, e->type);
6553 }
6554 }
6555 else
6556 {
6557 e->type = pe_unknown;
6558 unresolved (e->tok);
6559 }
6560}
6561
6562
57148ee7 6563void
d02548c0
GH
6564typeresolution_info::visit_stat_op (stat_op* e)
6565{
6566 t = pe_stats;
6567 e->stat->visit (this);
6568 if (e->type == pe_unknown)
6569 {
6570 e->type = pe_long;
6571 resolved (e->tok, e->type);
6572 }
07c17d67 6573 else if (e->type != pe_long)
18bac841 6574 mismatch (e->tok, pe_long, e->type);
d02548c0
GH
6575}
6576
57148ee7 6577void
d02548c0
GH
6578typeresolution_info::visit_hist_op (hist_op* e)
6579{
6580 t = pe_stats;
6581 e->stat->visit (this);
6582}
6583
2b066ec1 6584
34201621
DB
6585void
6586typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
6587{
6588 t = wanted;
6589 arg->visit (this);
6590
6591 if (arg->type == pe_unknown)
6592 {
6593 arg->type = wanted;
18bac841 6594 resolved (arg->tok, arg->type);
34201621
DB
6595 }
6596 else if (arg->type != wanted)
6597 {
18bac841 6598 mismatch (arg->tok, wanted, arg->type);
34201621
DB
6599 }
6600}
6601
6602
5abd364d
JS
6603void
6604typeresolution_info::check_local (vardecl* v)
6605{
6606 if (v->arity != 0)
6607 {
6608 num_still_unresolved ++;
6609 if (assert_resolvability)
6610 session.print_error
dc09353a 6611 (SEMANTIC_ERROR (_("array locals not supported, missing global declaration? "), v->tok));
5abd364d
JS
6612 }
6613
6614 if (v->type == pe_unknown)
6615 unresolved (v->tok);
6616 else if (v->type == pe_stats)
6617 {
6618 num_still_unresolved ++;
6619 if (assert_resolvability)
6620 session.print_error
dc09353a 6621 (SEMANTIC_ERROR (_("stat locals not supported, missing global declaration? "), v->tok));
5abd364d
JS
6622 }
6623 else if (!(v->type == pe_long || v->type == pe_string))
6624 invalid (v->tok, v->type);
6625}
6626
6627
2b066ec1
FCE
6628void
6629typeresolution_info::unresolved (const token* tok)
6630{
6631 num_still_unresolved ++;
6632
c74ddc54 6633 if (assert_resolvability && mismatch_complexity <= 0)
2b066ec1 6634 {
6c543717 6635 stringstream msg;
4af765b2 6636 msg << _("unresolved type ");
dc09353a 6637 session.print_error (SEMANTIC_ERROR (msg.str(), tok));
2b066ec1
FCE
6638 }
6639}
6640
6641
6642void
6643typeresolution_info::invalid (const token* tok, exp_type pe)
6644{
6645 num_still_unresolved ++;
6646
6647 if (assert_resolvability)
6648 {
6c543717 6649 stringstream msg;
022b623f 6650 if (tok && tok->type == tok_operator)
4af765b2 6651 msg << _("invalid operator");
2b066ec1 6652 else
4af765b2 6653 msg << _("invalid type ") << pe;
dc09353a 6654 session.print_error (SEMANTIC_ERROR (msg.str(), tok));
2b066ec1
FCE
6655 }
6656}
6657
116562fc
JL
6658void
6659typeresolution_info::mismatch (const binary_expression* e)
6660{
6661 num_still_unresolved ++;
6662
c74ddc54 6663 if (assert_resolvability && mismatch_complexity <= 1)
116562fc
JL
6664 {
6665 stringstream msg;
6666 msg << _F("type mismatch: left and right sides don't agree (%s vs %s)",
6667 lex_cast(e->left->type).c_str(), lex_cast(e->right->type).c_str());
6668 session.print_error (SEMANTIC_ERROR (msg.str(), e->tok));
6669 }
c74ddc54
JL
6670 else if (!assert_resolvability)
6671 mismatch_complexity = max(1, mismatch_complexity);
116562fc 6672}
2b066ec1 6673
9e85f932
JL
6674/* tok token where mismatch occurred
6675 * t1 type we expected (the 'good' type)
6676 * t2 type we received (the 'bad' type)
6677 * */
2b066ec1
FCE
6678void
6679typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
6680{
6681 num_still_unresolved ++;
6682
c74ddc54 6683 if (assert_resolvability && mismatch_complexity <= 2)
2b066ec1 6684 {
6c543717 6685 stringstream msg;
9e85f932
JL
6686 msg << _F("type mismatch: expected %s", lex_cast(t1).c_str());
6687 if (t2 != pe_unknown)
6688 msg << _F(" but found %s", lex_cast(t2).c_str());
6689 session.print_error (SEMANTIC_ERROR (msg.str(), tok));
2b066ec1 6690 }
c74ddc54
JL
6691 else if (!assert_resolvability)
6692 mismatch_complexity = max(2, mismatch_complexity);
2b066ec1
FCE
6693}
6694
116562fc
JL
6695/* tok token where the mismatch happened
6696 * type type we received (the 'bad' type)
6697 * decl declaration of mismatched symbol
6698 * index if index-based (array index or function arg)
6699 * */
6700void
6701typeresolution_info::mismatch (const token *tok, exp_type type,
6702 const symboldecl* decl, int index)
6703{
6704 num_still_unresolved ++;
6705
c74ddc54 6706 if (assert_resolvability && mismatch_complexity <= 3)
116562fc 6707 {
18bac841
JL
6708 assert(decl != NULL);
6709
6710 // If mismatch is against a function parameter from within the function
6711 // itself (rather than a function call), then the index will be -1. We
6712 // check here if the decl corresponds to one of the params and if so,
6713 // adjust the index.
6714 if (current_function != NULL && index == -1)
6715 {
6716 vector<vardecl*>& args = current_function->formal_args;
6717 for (unsigned i = 0; i < args.size() && index < 0; i++)
6718 if (args[i] == decl)
6719 index = i;
6720 }
6721
6722 // get the declaration's original type and token
6723 const resolved_type *original = NULL;
6724 for (vector<resolved_type>::const_iterator it = resolved_types.begin();
6725 it != resolved_types.end() && original == NULL; ++it)
6726 {
6727 if (it->decl == decl && it->index == index)
6728 original = &(*it);
6729 }
6730
6731 // print basic mismatch msg if we couldn't find the decl (this can happen
d2e3c0c7
JL
6732 // for explicitly typed decls e.g. myvar:long or for fabricated (already
6733 // resolved) decls e.g. __perf_read_*)
18bac841
JL
6734 if (original == NULL)
6735 {
6736 session.print_error (SEMANTIC_ERROR (
6737 _F("type mismatch: expected %s but found %s",
6738 lex_cast(type).c_str(),
6739 lex_cast(decl->type).c_str()),
6740 tok));
6741 return;
6742 }
6743
6744 // print where mismatch happened and chain with origin of decl type
6745 // resolution
6746 stringstream msg;
6747
6748 if (index >= 0)
6749 msg << _F("index %d ", index);
6750 msg << _F("type mismatch (%s)", lex_cast(type).c_str());
6751 semantic_error err(ERR_SRC, msg.str(), tok);
6752
6753 stringstream chain_msg;
6754 chain_msg << _("type");
6755 if (index >= 0)
40136471 6756 chain_msg << _F(" of index %d", index);
18bac841
JL
6757 chain_msg << _F(" was first inferred here (%s)",
6758 lex_cast(decl->type).c_str());
c081af73 6759 semantic_error chain(ERR_SRC, chain_msg.str(), original->tok);
18bac841 6760
c081af73 6761 err.set_chain(chain);
18bac841 6762 session.print_error (err);
116562fc 6763 }
c74ddc54
JL
6764 else if (!assert_resolvability)
6765 mismatch_complexity = max(3, mismatch_complexity);
116562fc
JL
6766}
6767
2b066ec1 6768
116562fc
JL
6769/* tok token where resolution occurred
6770 * type type to which we resolved
6771 * decl declaration of resolved symbol
6772 * index if index-based (array index or function arg)
6773 * */
2b066ec1 6774void
dabd71bb 6775typeresolution_info::resolved (const token *tok, exp_type,
116562fc 6776 const symboldecl* decl, int index)
2b066ec1
FCE
6777{
6778 num_newly_resolved ++;
18bac841
JL
6779
6780 // We only use the resolved_types vector to give better mismatch messages
6781 // involving symbols. So don't bother adding it if we're not given a decl
6782 if (decl != NULL)
6783 {
6784 // As a fail-safe, if the decl & index is already in the vector, then
6785 // modify it instead of adding another one to ensure uniqueness. This
6786 // should never happen since we only call resolved once for each decl &
6787 // index, but better safe than sorry. (IE. if it does happen, better have
6788 // the latest resolution info for better mismatch reporting later).
6789 for (unsigned i = 0; i < resolved_types.size(); i++)
6790 {
6791 if (resolved_types[i].decl == decl
6792 && resolved_types[i].index == index)
6793 {
6794 resolved_types[i].tok = tok;
6795 return;
6796 }
6797 }
6798 resolved_type res(tok, decl, index);
6799 resolved_types.push_back(res);
6800 }
2b066ec1
FCE
6801}
6802
eb79eb0a
JS
6803void
6804typeresolution_info::resolved_details (const exp_type_ptr& src,
6805 exp_type_ptr& dest)
6806{
6807 num_newly_resolved ++;
6808 dest = src;
6809}
6810
73267b89 6811/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 1.211499 seconds and 5 git commands to generate.