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