1 // elaboration functions
2 // Copyright (C) 2005-2013 Red Hat Inc.
3 // Copyright (C) 2008 Intel Corporation
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
11 #include "elaborate.h"
12 #include "translate.h"
17 #include "task_finder.h"
18 #include "stapregex.h"
21 #include <sys/utsname.h>
23 #define __STDC_FORMAT_MACROS
41 // ------------------------------------------------------------------------
43 // Used in probe_point condition construction. Either argument may be
44 // NULL; if both, return NULL too. Resulting expression is a deep
45 // copy for symbol resolution purposes.
46 expression
* add_condition (expression
* a
, expression
* b
)
48 if (!a
&& !b
) return 0;
49 if (! a
) return deep_copy_visitor::deep_copy(b
);
50 if (! b
) return deep_copy_visitor::deep_copy(a
);
55 la
.tok
= a
->tok
; // or could be b->tok
56 return deep_copy_visitor::deep_copy(& la
);
59 // ------------------------------------------------------------------------
63 derived_probe::derived_probe (probe
*p
, probe_point
*l
, bool rewrite_loc
):
64 base (p
), base_pp(l
), sdt_semaphore_addr(0), session_index((unsigned)-1)
68 this->privileged
= p
->privileged
;
69 this->body
= deep_copy_visitor::deep_copy(p
->body
);
72 // make a copy for subclasses which want to rewrite the location
74 l
= new probe_point(*l
);
75 this->locations
.push_back (l
);
80 derived_probe::printsig (ostream
& o
) const
87 derived_probe::printsig_nested (ostream
& o
) const
89 // We'd like to enclose the probe derivation chain in a /* */
90 // comment delimiter. But just printing /* base->printsig() */ is
91 // not enough, since base might itself be a derived_probe. So we,
92 // er, "cleverly" encode our nesting state as a formatting flag for
94 ios::fmtflags f
= o
.flags (ios::internal
);
95 if (f
& ios::internal
)
114 derived_probe::collect_derivation_chain (std::vector
<probe
*> &probes_list
) const
116 probes_list
.push_back(const_cast<derived_probe
*>(this));
117 base
->collect_derivation_chain(probes_list
);
122 derived_probe::collect_derivation_pp_chain (std::vector
<probe_point
*> &pp_list
) const
124 pp_list
.push_back(const_cast<probe_point
*>(this->sole_location()));
125 base
->collect_derivation_pp_chain(pp_list
);
130 derived_probe::derived_locations ()
133 vector
<probe_point
*> reference_point
;
134 collect_derivation_pp_chain(reference_point
);
135 if (reference_point
.size() > 0)
136 for(unsigned i
=1; i
<reference_point
.size(); ++i
)
137 o
<< " from: " << reference_point
[i
]->str(false); // no ?,!,etc
143 derived_probe::sole_location () const
145 if (locations
.size() == 0 || locations
.size() > 1)
146 throw semantic_error (_N("derived_probe with no locations",
147 "derived_probe with too many locations",
148 locations
.size()), this->tok
);
155 derived_probe::script_location () const
157 // This feeds function::pn() in the tapset, which is documented as the
158 // script-level probe point expression, *after wildcard expansion*. If
159 // it were not for wildcard stuff, we'd just return the last item in the
160 // derivation chain. But alas ... we need to search for the last one
161 // that doesn't have a * in the textual representation. Heuristics, eww.
162 vector
<probe_point
*> chain
;
163 collect_derivation_pp_chain (chain
);
165 // NB: we actually start looking from the second-to-last item, so the user's
166 // direct input is not considered. Input like 'kernel.function("init_once")'
167 // will thus be listed with the resolved @file:line too, disambiguating the
168 // distinct functions by this name, and matching our historical behavior.
169 for (int i
=chain
.size()-2; i
>=0; i
--)
171 probe_point
pp_copy (* chain
[i
]);
172 // drop any ?/! denotations that would confuse a glob-char search
173 pp_copy
.optional
= false;
174 pp_copy
.sufficient
= false;
175 string pp_printed
= lex_cast(pp_copy
);
176 if (! contains_glob_chars(pp_printed
))
180 // If that didn't work, just fallback to -something-.
181 return sole_location();
186 derived_probe::emit_privilege_assertion (translator_output
* o
)
188 // Emit code which will cause compilation to fail if it is compiled in
189 // unprivileged mode.
190 o
->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
191 o
->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
192 o
->newline() << "#error Internal Error: Probe ";
193 probe::printsig (o
->line());
194 o
->line() << " generated in --unprivileged mode";
195 o
->newline() << "#endif";
200 derived_probe::emit_process_owner_assertion (translator_output
* o
)
202 // Emit code which will abort should the current target not belong to the
203 // user in unprivileged mode.
204 o
->newline() << "#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \\";
205 o
->newline() << " ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)";
206 o
->newline(1) << "if (! is_myproc ()) {";
207 o
->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
208 o
->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
209 o
->newline() << " current->tgid, _stp_uid, c->probe_point);";
210 o
->newline() << "c->last_error = c->error_buffer;";
211 // NB: since this check occurs before probe locking, its exit should
212 // not be a "goto out", which would attempt unlocking.
213 o
->newline() << "return;";
214 o
->newline(-1) << "}";
215 o
->newline(-1) << "#endif";
219 derived_probe::print_dupe_stamp_unprivileged(ostream
& o
)
221 o
<< _("unprivileged users: authorized") << endl
;
225 derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream
& o
)
227 o
<< _("unprivileged users: authorized for process owner") << endl
;
230 // ------------------------------------------------------------------------
231 // Members of derived_probe_builder
234 derived_probe_builder::build_with_suffix(systemtap_session
& sess
,
236 probe_point
* location
,
237 std::map
<std::string
, literal
*>
239 std::vector
<derived_probe
*>
241 std::vector
<probe_point::component
*>
243 // XXX perhaps build the probe if suffix is empty?
244 // if (suffix.empty()) {
245 // build (sess, use, location, parameters, finished_results);
248 throw semantic_error (_("invalid suffix for probe"));
252 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
253 const std::string
& key
,
256 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
257 if (i
== params
.end())
259 literal_string
* ls
= dynamic_cast<literal_string
*>(i
->second
);
268 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
269 const std::string
& key
,
272 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
273 if (i
== params
.end())
275 if (i
->second
== NULL
)
277 literal_number
* ln
= dynamic_cast<literal_number
*>(i
->second
);
286 derived_probe_builder::has_null_param (std::map
<std::string
, literal
*> const & params
,
287 const std::string
& key
)
289 map
<string
, literal
*>::const_iterator i
= params
.find(key
);
290 return (i
!= params
.end() && i
->second
== NULL
);
295 // ------------------------------------------------------------------------
296 // Members of match_key.
298 match_key::match_key(string
const & n
)
300 have_parameter(false),
301 parameter_type(pe_unknown
)
305 match_key::match_key(probe_point::component
const & c
)
307 have_parameter(c
.arg
!= NULL
),
308 parameter_type(c
.arg
? c
.arg
->type
: pe_unknown
)
313 match_key::with_number()
315 have_parameter
= true;
316 parameter_type
= pe_long
;
321 match_key::with_string()
323 have_parameter
= true;
324 parameter_type
= pe_string
;
329 match_key::str() const
332 switch (parameter_type
)
334 case pe_string
: return name
+ "(string)";
335 case pe_long
: return name
+ "(number)";
336 default: return name
+ "(...)";
342 match_key::operator<(match_key
const & other
) const
344 return ((name
< other
.name
)
346 || (name
== other
.name
347 && have_parameter
< other
.have_parameter
)
349 || (name
== other
.name
350 && have_parameter
== other
.have_parameter
351 && parameter_type
< other
.parameter_type
));
355 // NB: these are only used in the probe point name components, where
356 // only "*" is permitted.
358 // Within module("bar"), function("foo"), process("baz") strings, real
359 // wildcards are permitted too. See also util.h:contains_glob_chars
362 isglob(string
const & str
)
364 return(str
.find('*') != str
.npos
);
368 isdoubleglob(string
const & str
)
370 return(str
.find("**") != str
.npos
);
374 match_key::globmatch(match_key
const & other
) const
376 const char *other_str
= other
.name
.c_str();
377 const char *name_str
= name
.c_str();
379 return ((fnmatch(name_str
, other_str
, FNM_NOESCAPE
) == 0)
380 && have_parameter
== other
.have_parameter
381 && parameter_type
== other
.parameter_type
);
384 // ------------------------------------------------------------------------
385 // Members of match_node
386 // ------------------------------------------------------------------------
388 match_node::match_node() :
389 privilege(privilege_t (pr_stapdev
| pr_stapsys
))
394 match_node::bind(match_key
const & k
)
397 throw semantic_error(_("invalid use of wildcard probe point component"));
399 map
<match_key
, match_node
*>::const_iterator i
= sub
.find(k
);
402 match_node
* n
= new match_node();
403 sub
.insert(make_pair(k
, n
));
408 match_node::bind(derived_probe_builder
* e
)
414 match_node::bind(string
const & k
)
416 return bind(match_key(k
));
420 match_node::bind_str(string
const & k
)
422 return bind(match_key(k
).with_string());
426 match_node::bind_num(string
const & k
)
428 return bind(match_key(k
).with_number());
432 match_node::bind_privilege(privilege_t p
)
439 match_node::find_and_build (systemtap_session
& s
,
440 probe
* p
, probe_point
*loc
, unsigned pos
,
441 vector
<derived_probe
*>& results
)
443 assert (pos
<= loc
->components
.size());
444 if (pos
== loc
->components
.size()) // matched all probe point components so far
449 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
450 alternatives
+= string(" ") + i
->first
.str();
452 throw semantic_error (_F("probe point truncated (follow: %s)",
453 alternatives
.c_str()),
454 loc
->components
.back()->tok
);
457 if (! pr_contains (privilege
, s
.privilege
))
459 throw semantic_error (_F("probe point is not allowed for --privilege=%s",
460 pr_name (s
.privilege
)),
461 loc
->components
.back()->tok
);
464 map
<string
, literal
*> param_map
;
465 for (unsigned i
=0; i
<pos
; i
++)
466 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
469 // Iterate over all bound builders
470 for (unsigned k
=0; k
<ends
.size(); k
++)
472 derived_probe_builder
*b
= ends
[k
];
473 b
->build (s
, p
, loc
, param_map
, results
);
476 else if (isdoubleglob(loc
->components
[pos
]->functor
)) // ** wildcard?
478 unsigned int num_results
= results
.size();
480 // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
482 const probe_point::component
*comp
= loc
->components
[pos
];
483 const string
&functor
= comp
->functor
;
484 size_t glob_start
= functor
.find("**");
485 size_t glob_end
= functor
.find_first_not_of('*', glob_start
);
486 const string prefix
= functor
.substr(0, glob_start
);
487 const string suffix
= ((glob_end
!= string::npos
) ?
488 functor
.substr(glob_end
) : "");
490 // Synthesize "foo*bar"
491 probe_point
*simple_pp
= new probe_point(*loc
);
492 probe_point::component
*simple_comp
= new probe_point::component(*comp
);
493 simple_comp
->functor
= prefix
+ "*" + suffix
;
494 simple_pp
->components
[pos
] = simple_comp
;
497 find_and_build (s
, p
, simple_pp
, pos
, results
);
499 catch (const semantic_error
& e
)
501 // Ignore semantic_errors, but cleanup
506 // Synthesize "foo*.**bar"
507 // NB: any component arg should attach to the latter part only
508 probe_point
*expanded_pp
= new probe_point(*loc
);
509 probe_point::component
*expanded_comp_pre
= new probe_point::component(*comp
);
510 expanded_comp_pre
->functor
= prefix
+ "*";
511 expanded_comp_pre
->arg
= NULL
;
512 probe_point::component
*expanded_comp_post
= new probe_point::component(*comp
);
513 expanded_comp_post
->functor
= "**" + suffix
;
514 expanded_pp
->components
[pos
] = expanded_comp_pre
;
515 expanded_pp
->components
.insert(expanded_pp
->components
.begin() + pos
+ 1,
519 find_and_build (s
, p
, expanded_pp
, pos
, results
);
521 catch (const semantic_error
& e
)
523 // Ignore semantic_errors, but cleanup
525 delete expanded_comp_pre
;
526 delete expanded_comp_post
;
529 // Try suffix expansion only if no matches found:
530 if (num_results
== results
.size())
533 this->try_suffix_expansion (s
, p
, loc
, pos
, results
);
535 catch (const recursive_expansion_error
&e
)
537 s
.print_error(e
); return; // Suppress probe mismatch msg.
540 if (! loc
->optional
&& num_results
== results
.size())
542 // We didn't find any wildcard matches (since the size of
543 // the result vector didn't change). Throw an error.
545 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
546 alternatives
+= string(" ") + i
->first
.str();
548 throw semantic_error(_F("probe point mismatch (alternatives: %s)",
549 alternatives
.c_str()), comp
->tok
);
552 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
554 match_key
match (* loc
->components
[pos
]);
556 // Call find_and_build for each possible match. Ignore errors -
557 // unless we don't find any match.
558 unsigned int num_results
= results
.size();
559 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
561 const match_key
& subkey
= i
->first
;
562 match_node
* subnode
= i
->second
;
564 assert_no_interrupts();
566 if (match
.globmatch(subkey
))
569 clog
<< _F("wildcard '%s' matched '%s'",
570 loc
->components
[pos
]->functor
.c_str(),
571 subkey
.name
.c_str()) << endl
;
573 // When we have a wildcard, we need to create a copy of
574 // the probe point. Then we'll create a copy of the
575 // wildcard component, and substitute the non-wildcard
577 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
578 probe_point::component
*non_wildcard_component
579 = new probe_point::component(*loc
->components
[pos
]);
580 non_wildcard_component
->functor
= subkey
.name
;
581 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
583 // NB: probe conditions are not attached at the wildcard
584 // (component/functor) level, but at the overall
585 // probe_point level.
587 // recurse (with the non-wildcard probe point)
590 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
593 catch (const semantic_error
& e
)
595 // Ignore semantic_errors while expanding wildcards.
596 // If we get done and nothing was expanded, the code
597 // following the loop will complain.
599 // If this wildcard didn't match, cleanup.
600 delete non_wildcard_pp
;
601 delete non_wildcard_component
;
606 // Try suffix expansion only if no matches found:
607 if (num_results
== results
.size())
610 this->try_suffix_expansion (s
, p
, loc
, pos
, results
);
612 catch (const recursive_expansion_error
&e
)
614 s
.print_error(e
); return; // Suppress probe mismatch msg.
617 if (! loc
->optional
&& num_results
== results
.size())
619 // We didn't find any wildcard matches (since the size of
620 // the result vector didn't change). Throw an error.
622 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
623 alternatives
+= string(" ") + i
->first
.str();
625 throw semantic_error(_F("probe point mismatch %s didn't find any wildcard matches",
626 (alternatives
== "" ? "" : _(" (alternatives: ") +
627 alternatives
+ ")").c_str()), loc
->components
[pos
]->tok
);
632 match_key
match (* loc
->components
[pos
]);
633 sub_map_iterator_t i
= sub
.find (match
);
635 if (i
!= sub
.end()) // match found
637 match_node
* subnode
= i
->second
;
639 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
643 unsigned int num_results
= results
.size();
647 this->try_suffix_expansion (s
, p
, loc
, pos
, results
);
649 catch (const recursive_expansion_error
&e
)
651 s
.print_error(e
); return; // Suppress probe mismatch msg.
654 // XXX: how to correctly report alternatives + position numbers
655 // for alias suffixes? file a separate PR to address the issue
656 if (! loc
->optional
&& num_results
== results
.size())
658 // We didn't find any alias suffixes (since the size of the
659 // result vector didn't change). Throw an error.
661 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
662 alternatives
+= string(" ") + i
->first
.str();
664 throw semantic_error(_F("probe point mismatch %s",
665 (alternatives
== "" ? "" : (_(" (alternatives:") + alternatives
+
667 loc
->components
[pos
]->tok
);
674 match_node::try_suffix_expansion (systemtap_session
& s
,
675 probe
*p
, probe_point
*loc
, unsigned pos
,
676 vector
<derived_probe
*>& results
)
678 // PR12210: match alias suffixes. If the components thus far
679 // have been matched, but there is an additional unknown
680 // suffix, we have a potential alias suffix on our hands. We
681 // need to expand the preceding components as probe aliases,
682 // reattach the suffix, and re-run derive_probes() on the
683 // resulting expansion. This is done by the routine
684 // build_with_suffix().
686 if (strverscmp(s
.compatible
.c_str(), "2.0") >= 0)
688 // XXX: technically, param_map isn't used here. So don't
689 // bother actually assembling it unless some
690 // derived_probe_builder appears that actually takes
691 // suffixes *and* consults parameters (currently no such
693 map
<string
, literal
*> param_map
;
694 // for (unsigned i=0; i<pos; i++)
695 // param_map[loc->components[i]->functor] = loc->components[i]->arg;
698 vector
<probe_point::component
*> suffix (loc
->components
.begin()+pos
,
699 loc
->components
.end());
701 // Multiple derived_probe_builders may be bound at a
702 // match_node due to the possibility of multiply defined
704 for (unsigned k
=0; k
< ends
.size(); k
++)
706 derived_probe_builder
*b
= ends
[k
];
709 b
->build_with_suffix (s
, p
, loc
, param_map
, results
, suffix
);
711 catch (const recursive_expansion_error
&e
)
714 throw semantic_error(e
);
716 catch (const semantic_error
&e
)
718 // Adjust source coordinate and re-throw:
720 throw semantic_error(e
.what(), loc
->components
[pos
]->tok
);
728 match_node::build_no_more (systemtap_session
& s
)
730 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
731 i
->second
->build_no_more (s
);
732 for (unsigned k
=0; k
<ends
.size(); k
++)
734 derived_probe_builder
*b
= ends
[k
];
735 b
->build_no_more (s
);
740 match_node::dump (systemtap_session
&s
, const string
&name
)
742 // Dump this node, if it is complete.
743 for (unsigned k
=0; k
<ends
.size(); k
++)
745 // Don't print aliases at all (for now) until we can figure out how to determine whether
746 // the probes they resolve to are ok in unprivileged mode.
747 if (ends
[k
]->is_alias ())
750 // In unprivileged mode, don't show the probes which are not allowed for unprivileged
752 if (pr_contains (privilege
, s
.privilege
))
754 cout
<< name
<< endl
;
755 break; // we need only print one instance.
759 // Recursively dump the children of this node
763 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
765 i
->second
->dump (s
, name
+ dot
+ i
->first
.str());
770 // ------------------------------------------------------------------------
772 // ------------------------------------------------------------------------
774 struct alias_derived_probe
: public derived_probe
776 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
,
777 const vector
<probe_point::component
*> *suffix
= 0);
778 ~alias_derived_probe();
780 void upchuck () { throw semantic_error (_("inappropriate"), this->tok
); }
782 // Alias probes are immediately expanded to other derived_probe
783 // types, and are not themselves emitted or listed in
784 // systemtap_session.probes
786 void join_group (systemtap_session
&) { upchuck (); }
788 virtual const probe_alias
*get_alias () const { return alias
; }
789 virtual probe_point
*get_alias_loc () const { return alias_loc
; }
790 virtual probe_point
*sole_location () const;
793 const probe_alias
*alias
; // Used to check for recursion
794 probe_point
*alias_loc
; // Hack to recover full probe name
798 alias_derived_probe::alias_derived_probe(probe
*base
, probe_point
*l
,
799 const probe_alias
*a
,
800 const vector
<probe_point::component
*>
802 derived_probe (base
, l
), alias(a
)
804 // XXX pretty nasty -- this was cribbed from printscript() in main.cxx
805 assert (alias
->alias_names
.size() >= 1);
806 alias_loc
= new probe_point(*alias
->alias_names
[0]); // XXX: [0] is arbitrary; it would make just as much sense to collect all of the names
808 alias_loc
->components
.insert(alias_loc
->components
.end(),
809 suffix
->begin(), suffix
->end());
813 alias_derived_probe::~alias_derived_probe ()
820 alias_derived_probe::sole_location () const
822 return const_cast<probe_point
*>(alias_loc
);
827 probe::create_alias(probe_point
* l
, probe_point
* a
)
829 vector
<probe_point
*> aliases(1, a
);
830 probe_alias
* p
= new probe_alias(aliases
);
832 p
->locations
.push_back(l
);
835 p
->privileged
= privileged
;
836 p
->epilogue_style
= false;
837 return new alias_derived_probe(this, l
, p
);
842 alias_expansion_builder::build(systemtap_session
& sess
,
844 probe_point
* location
,
845 std::map
<std::string
, literal
*>
847 vector
<derived_probe
*> & finished_results
)
849 vector
<probe_point::component
*> empty_suffix
;
850 build_with_suffix (sess
, use
, location
, parameters
,
851 finished_results
, empty_suffix
);
855 alias_expansion_builder::build_with_suffix(systemtap_session
& sess
,
857 probe_point
* location
,
858 std::map
<std::string
, literal
*>
860 vector
<derived_probe
*>
862 vector
<probe_point::component
*>
865 // Don't build the alias expansion if infinite recursion is detected.
866 if (checkForRecursiveExpansion (use
)) {
868 msg
<< _F("Recursive loop in alias expansion of %s at %s",
869 lex_cast(*location
).c_str(), lex_cast(location
->components
.front()->tok
->location
).c_str());
870 // semantic_errors thrown here might be ignored, so we need a special class:
871 throw recursive_expansion_error (msg
.str());
872 // XXX The point of throwing this custom error is to suppress a
873 // cascade of "probe mismatch" messages that appear in addition to
874 // the error. The current approach suppresses most of the error
875 // cascade, but leaves one spurious error; in any case, the way
876 // this particular error is reported could be improved.
879 // We're going to build a new probe and wrap it up in an
880 // alias_expansion_probe so that the expansion loop recognizes it as
881 // such and re-expands its expansion.
883 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
, &suffix
);
884 n
->body
= new block();
886 // The new probe gets a deep copy of the location list of the alias
887 // (with incoming condition joined) plus the suffix (if any),
888 n
->locations
.clear();
889 for (unsigned i
=0; i
<alias
->locations
.size(); i
++)
891 probe_point
*pp
= new probe_point(*alias
->locations
[i
]);
892 pp
->components
.insert(pp
->components
.end(), suffix
.begin(), suffix
.end());
893 pp
->condition
= add_condition (pp
->condition
, location
->condition
);
894 n
->locations
.push_back(pp
);
897 // the token location of the alias,
898 n
->tok
= location
->components
.front()->tok
;
900 // and statements representing the concatenation of the alias'
901 // body with the use's.
903 // NB: locals are *not* copied forward, from either alias or
904 // use. The expansion should have its locals re-inferred since
905 // there's concatenated code here and we only want one vardecl per
906 // resulting variable.
908 if (alias
->epilogue_style
)
909 n
->body
= new block (use
->body
, alias
->body
);
911 n
->body
= new block (alias
->body
, use
->body
);
913 unsigned old_num_results
= finished_results
.size();
914 // If expanding for an alias suffix, be sure to pass on any errors
915 // to the caller instead of printing them in derive_probes():
916 derive_probes (sess
, n
, finished_results
, location
->optional
, !suffix
.empty());
918 // Check whether we resolved something. If so, put the
919 // whole library into the queue if not already there.
920 if (finished_results
.size() > old_num_results
)
922 stapfile
*f
= alias
->tok
->location
.file
;
923 if (find (sess
.files
.begin(), sess
.files
.end(), f
)
925 sess
.files
.push_back (f
);
930 alias_expansion_builder::checkForRecursiveExpansion (probe
*use
)
932 // Collect the derivation chain of this probe.
933 vector
<probe
*>derivations
;
934 use
->collect_derivation_chain (derivations
);
936 // Check all probe points in the alias expansion against the currently-being-expanded probe point
937 // of each of the probes in the derivation chain, looking for a match. This
938 // indicates infinite recursion.
939 // The first element of the derivation chain will be the derived_probe representing 'use', so
940 // start the search with the second element.
941 assert (derivations
.size() > 0);
942 assert (derivations
[0] == use
);
943 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
944 if (use
->get_alias() == derivations
[d
]->get_alias())
945 return true; // recursion detected
951 // ------------------------------------------------------------------------
953 // ------------------------------------------------------------------------
955 static unsigned max_recursion
= 100;
961 recursion_guard(unsigned & i
) : i(i
)
963 if (i
> max_recursion
)
964 throw semantic_error(_("recursion limit reached"));
973 // The match-and-expand loop.
975 derive_probes (systemtap_session
& s
,
976 probe
*p
, vector
<derived_probe
*>& dps
,
980 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
982 assert_no_interrupts();
984 probe_point
*loc
= p
->locations
[i
];
987 clog
<< "derive-probes " << *loc
<< endl
;
991 unsigned num_atbegin
= dps
.size();
993 // Pass down optional flag from e.g. alias reference to each
994 // probe_point instance. We do this by temporarily overriding
995 // the probe_point optional flag. We could instead deep-copy
996 // and set a flag on the copy permanently.
997 bool old_loc_opt
= loc
->optional
;
998 loc
->optional
= loc
->optional
|| optional
;
1001 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
1003 catch (const semantic_error
& e
)
1006 throw semantic_error(e
);
1007 else /* tolerate failure for optional probe */
1011 loc
->optional
= old_loc_opt
;
1012 unsigned num_atend
= dps
.size();
1014 if (! (loc
->optional
||optional
) && // something required, but
1015 num_atbegin
== num_atend
) // nothing new derived!
1016 throw semantic_error (_("no match"));
1018 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
1022 clog
<< "Probe point ";
1023 p
->locations
[i
]->print(clog
);
1024 clog
<< " sufficient, skipped";
1025 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
1028 p
->locations
[j
]->print(clog
);
1032 break; // we need not try to derive for any other locations
1035 catch (const semantic_error
& e
)
1037 // The rethrow_errors parameter lets the caller decide an
1038 // alternative to printing the error. This is necessary when
1039 // calling derive_probes() recursively during expansion of
1040 // an alias with suffix -- any message printed here would
1041 // point to the alias declaration and not the invalid suffix
1042 // usage, so the caller needs to catch the error themselves
1043 // and print a more appropriate message.
1046 throw semantic_error(e
);
1048 // Only output in listing if -vv is supplied:
1049 else if (!s
.listing_mode
|| (s
.listing_mode
&& s
.verbose
> 1))
1051 // XXX: prefer not to print_error at every nest/unroll level
1052 semantic_error
* er
= new semantic_error (_("while resolving probe point"),
1053 loc
->components
[0]->tok
);
1055 s
.print_error (* er
);
1065 // ------------------------------------------------------------------------
1067 // Indexable usage checks
1070 struct symbol_fetcher
1071 : public throwing_visitor
1075 symbol_fetcher (symbol
*&sym
): sym(sym
)
1078 void visit_symbol (symbol
* e
)
1083 void visit_target_symbol (target_symbol
* e
)
1088 void visit_arrayindex (arrayindex
* e
)
1090 e
->base
->visit (this);
1093 void visit_atvar_op (atvar_op
*e
)
1098 void visit_cast_op (cast_op
* e
)
1103 void throwone (const token
* t
)
1105 if (t
->type
== tok_operator
&& t
->content
== ".") // guess someone misused . in $foo->bar.baz expression
1106 throw semantic_error (_("Expecting symbol or array index expression, try -> instead"), t
);
1108 throw semantic_error (_("Expecting symbol or array index expression"), t
);
1113 get_symbol_within_expression (expression
*e
)
1116 symbol_fetcher
fetcher(sym
);
1117 e
->visit (&fetcher
);
1118 return sym
; // NB: may be null!
1122 get_symbol_within_indexable (indexable
*ix
)
1124 symbol
*array
= NULL
;
1125 hist_op
*hist
= NULL
;
1126 classify_indexable(ix
, array
, hist
);
1130 return get_symbol_within_expression (hist
->stat
);
1133 struct mutated_var_collector
1134 : public traversing_visitor
1136 set
<vardecl
*> * mutated_vars
;
1138 mutated_var_collector (set
<vardecl
*> * mm
)
1142 void visit_assignment(assignment
* e
)
1144 if (e
->type
== pe_stats
&& e
->op
== "<<<")
1146 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
1148 mutated_vars
->insert (vd
);
1150 traversing_visitor::visit_assignment(e
);
1153 void visit_arrayindex (arrayindex
*e
)
1155 if (is_active_lvalue (e
))
1158 if (e
->base
->is_symbol (sym
))
1159 mutated_vars
->insert (sym
->referent
);
1161 throw semantic_error(_("Assignment to read-only histogram bucket"), e
->tok
);
1163 traversing_visitor::visit_arrayindex (e
);
1168 struct no_var_mutation_during_iteration_check
1169 : public traversing_visitor
1171 systemtap_session
& session
;
1172 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
1173 vector
<vardecl
*> vars_being_iterated
;
1175 no_var_mutation_during_iteration_check
1176 (systemtap_session
& sess
,
1177 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
1178 : session(sess
), function_mutates_vars (fmv
)
1181 void visit_arrayindex (arrayindex
*e
)
1183 if (is_active_lvalue(e
))
1185 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
1188 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
1190 vardecl
*v
= vars_being_iterated
[i
];
1193 string err
= _F("variable '%s' modified during 'foreach' iteration",
1195 session
.print_error (semantic_error (err
, e
->tok
));
1200 traversing_visitor::visit_arrayindex (e
);
1203 void visit_functioncall (functioncall
* e
)
1205 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
1206 = function_mutates_vars
.find (e
->referent
);
1208 if (i
!= function_mutates_vars
.end())
1210 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
1212 vardecl
*m
= vars_being_iterated
[j
];
1213 if (i
->second
->find (m
) != i
->second
->end())
1215 string err
= _F("function call modifies var '%s' during 'foreach' iteration",
1217 session
.print_error (semantic_error (err
, e
->tok
));
1222 traversing_visitor::visit_functioncall (e
);
1225 void visit_foreach_loop(foreach_loop
* s
)
1227 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
1230 vars_being_iterated
.push_back (vd
);
1232 traversing_visitor::visit_foreach_loop (s
);
1235 vars_being_iterated
.pop_back();
1240 // ------------------------------------------------------------------------
1242 struct stat_decl_collector
1243 : public traversing_visitor
1245 systemtap_session
& session
;
1247 stat_decl_collector(systemtap_session
& sess
)
1251 void visit_stat_op (stat_op
* e
)
1253 symbol
*sym
= get_symbol_within_expression (e
->stat
);
1254 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
1255 session
.stat_decls
[sym
->name
] = statistic_decl();
1258 void visit_assignment (assignment
* e
)
1262 symbol
*sym
= get_symbol_within_expression (e
->left
);
1263 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
1264 session
.stat_decls
[sym
->name
] = statistic_decl();
1267 traversing_visitor::visit_assignment(e
);
1270 void visit_hist_op (hist_op
* e
)
1272 symbol
*sym
= get_symbol_within_expression (e
->stat
);
1273 statistic_decl new_stat
;
1275 if (e
->htype
== hist_linear
)
1277 new_stat
.type
= statistic_decl::linear
;
1278 assert (e
->params
.size() == 3);
1279 new_stat
.linear_low
= e
->params
[0];
1280 new_stat
.linear_high
= e
->params
[1];
1281 new_stat
.linear_step
= e
->params
[2];
1285 assert (e
->htype
== hist_log
);
1286 new_stat
.type
= statistic_decl::logarithmic
;
1287 assert (e
->params
.size() == 0);
1290 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
1291 if (i
== session
.stat_decls
.end())
1292 session
.stat_decls
[sym
->name
] = new_stat
;
1295 statistic_decl
& old_stat
= i
->second
;
1296 if (!(old_stat
== new_stat
))
1298 if (old_stat
.type
== statistic_decl::none
)
1299 i
->second
= new_stat
;
1302 // FIXME: Support multiple co-declared histogram types
1303 semantic_error
se(_F("multiple histogram types declared on '%s'", sym
->name
.c_str()), e
->tok
);
1304 session
.print_error (se
);
1313 semantic_pass_stats (systemtap_session
& sess
)
1315 stat_decl_collector
sdc(sess
);
1317 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1318 it
->second
->body
->visit (&sdc
);
1320 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1321 sess
.probes
[i
]->body
->visit (&sdc
);
1323 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
1325 vardecl
*v
= sess
.globals
[i
];
1326 if (v
->type
== pe_stats
)
1329 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
1331 semantic_error
se(_F("unable to infer statistic parameters for global '%s'", v
->name
.c_str()));
1332 sess
.print_error (se
);
1337 return sess
.num_errors();
1340 // ------------------------------------------------------------------------
1342 // Enforce variable-related invariants: no modification of
1343 // a foreach()-iterated array.
1345 semantic_pass_vars (systemtap_session
& sess
)
1348 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
1349 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
1351 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1353 functiondecl
* fn
= it
->second
;
1356 set
<vardecl
*> * m
= new set
<vardecl
*>();
1357 mutated_var_collector
mc (m
);
1358 fn
->body
->visit (&mc
);
1363 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1365 functiondecl
* fn
= it
->second
;
1366 if (fn
->body
) fn
->body
->visit (&chk
);
1369 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1371 if (sess
.probes
[i
]->body
)
1372 sess
.probes
[i
]->body
->visit (&chk
);
1375 return sess
.num_errors();
1379 // ------------------------------------------------------------------------
1381 // Rewrite probe condition expressions into probe bodies. Tricky and
1382 // exciting business, this. This:
1384 // probe foo if (g1 || g2) { ... }
1385 // probe bar { ... g1 ++ ... }
1389 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1390 // probe foo { if (! (g1 || g2)) next; ... }
1391 // probe bar { ... g1 ++ ...;
1392 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1395 // XXX: As a first cut, do only the "inline probe condition" part of the
1399 semantic_pass_conditions (systemtap_session
& sess
)
1401 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1403 derived_probe
* p
= sess
.probes
[i
];
1404 expression
* e
= p
->sole_location()->condition
;
1407 varuse_collecting_visitor
vut(sess
);
1410 if (! vut
.written
.empty())
1412 string err
= (_("probe condition must not modify any variables"));
1413 sess
.print_error (semantic_error (err
, e
->tok
));
1415 else if (vut
.embedded_seen
)
1417 sess
.print_error (semantic_error (_("probe condition must not include impure embedded-C"), e
->tok
));
1420 // Add the condition expression to the front of the
1421 // derived_probe body.
1422 if_statement
*ifs
= new if_statement ();
1424 ifs
->thenblock
= new next_statement ();
1425 ifs
->thenblock
->tok
= e
->tok
;
1426 ifs
->elseblock
= NULL
;
1427 unary_expression
*notex
= new unary_expression ();
1429 notex
->tok
= e
->tok
;
1431 ifs
->condition
= notex
;
1432 p
->body
= new block (ifs
, p
->body
);
1436 return sess
.num_errors();
1439 // ------------------------------------------------------------------------
1442 // Simple visitor that just goes through all embedded code blocks that
1443 // are available at the end all the optimizations to register any
1444 // relevant pragmas or other indicators found, so that session flags can
1445 // be set that can be inspected at translation time to trigger any
1446 // necessary initialization of code needed by the embedded code functions.
1448 // This is only for pragmas that don't have any other side-effect than
1449 // needing some initialization at module init time. Currently handles
1450 // /* pragma:vma */ /* pragma:unwind */ /* pragma:symbol */
1452 // /* pragma:uprobes */ is handled during the typeresolution_info pass.
1453 // /* pure */, /* unprivileged */. /* myproc-unprivileged */ and /* guru */
1454 // are handled by the varuse_collecting_visitor.
1456 struct embeddedcode_info
: public functioncall_traversing_visitor
1459 systemtap_session
& session
;
1462 embeddedcode_info (systemtap_session
& s
): session(s
) { }
1464 void visit_embeddedcode (embeddedcode
* c
)
1466 if (! vma_tracker_enabled(session
)
1467 && c
->code
.find("/* pragma:vma */") != string::npos
)
1469 if (session
.verbose
> 2)
1470 clog
<< _F("Turning on task_finder vma_tracker, pragma:vma found in %s",
1471 current_function
->name
.c_str()) << endl
;
1473 // PR15052: stapdyn doesn't have VMA-tracking yet.
1474 if (session
.runtime_usermode_p())
1475 throw semantic_error(_("VMA-tracking is only supported by the kernel runtime (PR15052)"), c
->tok
);
1477 enable_vma_tracker(session
);
1480 if (! session
.need_unwind
1481 && c
->code
.find("/* pragma:unwind */") != string::npos
)
1483 if (session
.verbose
> 2)
1484 clog
<< _F("Turning on unwind support, pragma:unwind found in %s",
1485 current_function
->name
.c_str()) << endl
;
1486 session
.need_unwind
= true;
1489 if (! session
.need_symbols
1490 && c
->code
.find("/* pragma:symbols */") != string::npos
)
1492 if (session
.verbose
> 2)
1493 clog
<< _F("Turning on symbol data collecting, pragma:symbols found in %s",
1494 current_function
->name
.c_str()) << endl
;
1495 session
.need_symbols
= true;
1500 void embeddedcode_info_pass (systemtap_session
& s
)
1502 embeddedcode_info
eci (s
);
1503 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1504 s
.probes
[i
]->body
->visit (& eci
);
1507 // ------------------------------------------------------------------------
1510 // Simple visitor that collects all the regular expressions in the
1511 // file and adds them to the session DFA table.
1513 struct regex_collecting_visitor
: public functioncall_traversing_visitor
1516 systemtap_session
& session
;
1519 regex_collecting_visitor (systemtap_session
& s
): session(s
) { }
1521 void visit_regex_query (regex_query
*q
) {
1522 functioncall_traversing_visitor::visit_regex_query (q
);
1524 string re
= q
->right
->value
;
1525 regex_to_stapdfa (&session
, re
, q
->right
->tok
);
1529 // Go through the regex match invocations and generate corresponding DFAs.
1530 int gen_dfa_table (systemtap_session
& s
)
1532 regex_collecting_visitor
rcv(s
);
1534 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1538 s
.probes
[i
]->body
->visit (& rcv
);
1540 if (s
.probes
[i
]->sole_location()->condition
)
1541 s
.probes
[i
]->sole_location()->condition
->visit (& rcv
);
1543 catch (const semantic_error
& e
)
1549 return s
.num_errors();
1552 // ------------------------------------------------------------------------
1555 static int semantic_pass_symbols (systemtap_session
&);
1556 static int semantic_pass_optimize1 (systemtap_session
&);
1557 static int semantic_pass_optimize2 (systemtap_session
&);
1558 static int semantic_pass_types (systemtap_session
&);
1559 static int semantic_pass_vars (systemtap_session
&);
1560 static int semantic_pass_stats (systemtap_session
&);
1561 static int semantic_pass_conditions (systemtap_session
&);
1564 // Link up symbols to their declarations. Set the session's
1565 // files/probes/functions/globals vectors from the transitively
1566 // reached set of stapfiles in s.library_files, starting from
1567 // s.user_file. Perform automatic tapset inclusion and probe
1570 semantic_pass_symbols (systemtap_session
& s
)
1572 symresolution_info
sym (s
);
1574 // NB: s.files can grow during this iteration, so size() can
1575 // return gradually increasing numbers.
1576 s
.files
.push_back (s
.user_file
);
1577 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1579 assert_no_interrupts();
1580 stapfile
* dome
= s
.files
[i
];
1582 // Pass 1: add globals and functions to systemtap-session master list,
1583 // so the find_* functions find them
1585 // NB: tapset global/function definitions may duplicate or conflict
1586 // with those already in s.globals/functions. We need to deconflict
1589 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1591 vardecl
* g
= dome
->globals
[i
];
1592 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
1594 vardecl
* g2
= s
.globals
[j
];
1595 if (g
->name
== g2
->name
)
1597 s
.print_error (semantic_error (_("conflicting global variables"),
1601 s
.globals
.push_back (g
);
1604 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1606 functiondecl
* f
= dome
->functions
[i
];
1607 functiondecl
* f2
= s
.functions
[f
->name
];
1610 s
.print_error (semantic_error (_("conflicting functions"),
1613 s
.functions
[f
->name
] = f
;
1616 // NB: embeds don't conflict with each other
1617 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1618 s
.embeds
.push_back (dome
->embeds
[i
]);
1620 // Pass 2: derive probes and resolve any further symbols in the
1623 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1625 assert_no_interrupts();
1626 probe
* p
= dome
->probes
[i
];
1627 vector
<derived_probe
*> dps
;
1629 // much magic happens here: probe alias expansion, wildcard
1630 // matching, low-level derived_probe construction.
1631 derive_probes (s
, p
, dps
);
1633 for (unsigned j
=0; j
<dps
.size(); j
++)
1635 assert_no_interrupts();
1636 derived_probe
* dp
= dps
[j
];
1637 s
.probes
.push_back (dp
);
1642 for (unsigned k
=0; k
<s
.code_filters
.size(); k
++)
1643 s
.code_filters
[k
]->replace (dp
->body
);
1645 sym
.current_function
= 0;
1646 sym
.current_probe
= dp
;
1647 dp
->body
->visit (& sym
);
1649 // Process the probe-point condition expression.
1650 sym
.current_function
= 0;
1651 sym
.current_probe
= 0;
1652 if (dp
->sole_location()->condition
)
1653 dp
->sole_location()->condition
->visit (& sym
);
1655 catch (const semantic_error
& e
)
1662 // Pass 3: process functions
1664 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1666 assert_no_interrupts();
1667 functiondecl
* fd
= dome
->functions
[i
];
1671 for (unsigned j
=0; j
<s
.code_filters
.size(); j
++)
1672 s
.code_filters
[j
]->replace (fd
->body
);
1674 sym
.current_function
= fd
;
1675 sym
.current_probe
= 0;
1676 fd
->body
->visit (& sym
);
1678 catch (const semantic_error
& e
)
1685 // Inform all derived_probe builders that we're done with
1686 // all resolution, so it's time to release caches.
1687 s
.pattern_root
->build_no_more (s
);
1689 if(s
.systemtap_v_check
){
1690 for(unsigned i
=0;i
<s
.globals
.size();i
++){
1691 if(s
.globals
[i
]->systemtap_v_conditional
)
1692 s
.print_warning(_("This global uses tapset constructs that are dependent on systemtap version"), s
.globals
[i
]->tok
);
1695 for(map
<string
, functiondecl
*>::const_iterator i
=s
.functions
.begin();i
!= s
.functions
.end();++i
){
1696 if(i
->second
->systemtap_v_conditional
)
1697 s
.print_warning(_("This function uses tapset constructs that are dependent on systemtap version"), i
->second
->tok
);
1700 for(unsigned i
=0;i
<s
.probes
.size();i
++){
1701 vector
<probe
*> sysvc
;
1702 s
.probes
[i
]->collect_derivation_chain(sysvc
);
1703 for(unsigned j
=0;j
<sysvc
.size();j
++){
1704 if(sysvc
[j
]->systemtap_v_conditional
)
1705 s
.print_warning(_("This probe uses tapset constructs that are dependent on systemtap version"), sysvc
[j
]->tok
);
1706 if(sysvc
[j
]->get_alias() && sysvc
[j
]->get_alias()->systemtap_v_conditional
)
1707 s
.print_warning(_("This alias uses tapset constructs that are dependent on systemtap version"), sysvc
[j
]->get_alias()->tok
);
1712 return s
.num_errors(); // all those print_error calls
1716 // Keep unread global variables for probe end value display.
1717 void add_global_var_display (systemtap_session
& s
)
1719 // Don't generate synthetic end probes when in listings mode;
1720 // it would clutter up the list of probe points with "end ...".
1721 if (s
.listing_mode
) return;
1723 varuse_collecting_visitor
vut(s
);
1725 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1727 s
.probes
[i
]->body
->visit (& vut
);
1729 if (s
.probes
[i
]->sole_location()->condition
)
1730 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1733 for (unsigned g
=0; g
< s
.globals
.size(); g
++)
1735 vardecl
* l
= s
.globals
[g
];
1736 if ((vut
.read
.find (l
) != vut
.read
.end()
1737 && vut
.used
.find (l
) != vut
.used
.end())
1738 || vut
.written
.find (l
) == vut
.written
.end())
1741 // Don't generate synthetic end probes for unread globals
1742 // declared only within tapsets. (RHBZ 468139), but rather
1743 // only within the end-user script.
1745 bool tapset_global
= false;
1746 for (size_t m
=0; m
< s
.library_files
.size(); m
++)
1748 for (size_t n
=0; n
< s
.library_files
[m
]->globals
.size(); n
++)
1750 if (l
->name
== s
.library_files
[m
]->globals
[n
]->name
)
1751 {tapset_global
= true; break;}
1757 probe_point::component
* c
= new probe_point::component("end");
1758 probe_point
* pl
= new probe_point
;
1759 pl
->components
.push_back (c
);
1761 vector
<derived_probe
*> dps
;
1762 block
*b
= new block
;
1765 probe
* p
= new probe
;
1767 p
->locations
.push_back (pl
);
1770 symbol
* g_sym
= new symbol
;
1771 g_sym
->name
= l
->name
;
1772 g_sym
->tok
= l
->tok
;
1773 g_sym
->type
= l
->type
;
1774 g_sym
->referent
= l
;
1776 token
* print_tok
= new token(*l
->tok
);
1777 print_tok
->type
= tok_identifier
;
1778 print_tok
->content
= "printf";
1780 print_format
* pf
= print_format::create(print_tok
);
1781 pf
->raw_components
+= l
->name
;
1783 if (l
->index_types
.size() == 0) // Scalar
1785 if (l
->type
== pe_stats
)
1786 if (strverscmp(s
.compatible
.c_str(), "1.4") >= 0)
1787 pf
->raw_components
+= " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1789 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1790 else if (l
->type
== pe_string
)
1791 pf
->raw_components
+= "=\"%#s\"\\n";
1793 pf
->raw_components
+= "=%#x\\n";
1794 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1795 expr_statement
* feb
= new expr_statement
;
1797 feb
->tok
= print_tok
;
1798 if (l
->type
== pe_stats
)
1800 struct stat_op
* so
[5];
1801 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1803 for (unsigned si
= 0;
1804 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1807 so
[si
]= new stat_op
;
1808 so
[si
]->ctype
= stypes
[si
];
1809 so
[si
]->type
= pe_long
;
1810 so
[si
]->stat
= g_sym
;
1811 so
[si
]->tok
= l
->tok
;
1812 pf
->args
.push_back(so
[si
]);
1816 pf
->args
.push_back(g_sym
);
1818 /* PR7053: Checking empty aggregate for global variable */
1819 if (l
->type
== pe_stats
) {
1820 stat_op
*so
= new stat_op
;
1821 so
->ctype
= sc_count
;
1825 comparison
*be
= new comparison
;
1829 be
->right
= new literal_number(0);
1831 /* Create printf @count=0x0 in else block */
1832 print_format
* pf_0
= print_format::create(print_tok
);
1833 pf_0
->raw_components
+= l
->name
;
1834 pf_0
->raw_components
+= " @count=0x0\\n";
1835 pf_0
->components
= print_format::string_to_components(pf_0
->raw_components
);
1836 expr_statement
* feb_else
= new expr_statement
;
1837 feb_else
->value
= pf_0
;
1838 feb_else
->tok
= print_tok
;
1839 if_statement
*ifs
= new if_statement
;
1841 ifs
->condition
= be
;
1842 ifs
->thenblock
= feb
;
1843 ifs
->elseblock
= feb_else
;
1844 b
->statements
.push_back(ifs
);
1846 else /* other non-stat cases */
1847 b
->statements
.push_back(feb
);
1851 int idx_count
= l
->index_types
.size();
1852 symbol
* idx_sym
[idx_count
];
1853 vardecl
* idx_v
[idx_count
];
1854 // Create a foreach loop
1855 foreach_loop
* fe
= new foreach_loop
;
1856 fe
->sort_direction
= -1; // imply decreasing sort on value
1857 fe
->sort_column
= 0; // as in foreach ([a,b,c] in array-) { }
1858 fe
->sort_aggr
= sc_none
; // as in default @count
1863 // Create indices for the foreach loop
1864 for (int i
=0; i
< idx_count
; i
++)
1867 if (asprintf (&idx_name
, "idx%d", i
) < 0) {
1875 idx_sym
[i
] = new symbol
;
1876 idx_sym
[i
]->name
= idx_name
;
1877 idx_sym
[i
]->tok
= l
->tok
;
1878 idx_v
[i
] = new vardecl
;
1879 idx_v
[i
]->name
= idx_name
;
1880 idx_v
[i
]->type
= l
->index_types
[i
];
1881 idx_v
[i
]->tok
= l
->tok
;
1882 idx_sym
[i
]->referent
= idx_v
[i
];
1883 fe
->indexes
.push_back (idx_sym
[i
]);
1886 // Create a printf for the foreach loop
1887 pf
->raw_components
+= "[";
1888 for (int i
=0; i
< idx_count
; i
++)
1891 pf
->raw_components
+= ",";
1892 if (l
->index_types
[i
] == pe_string
)
1893 pf
->raw_components
+= "\"%#s\"";
1895 pf
->raw_components
+= "%#d";
1897 pf
->raw_components
+= "]";
1898 if (l
->type
== pe_stats
)
1899 if (strverscmp(s
.compatible
.c_str(), "1.4") >= 0)
1900 pf
->raw_components
+= " @count=%#d @min=%#d @max=%#d @sum=%#d @avg=%#d\\n";
1902 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1903 else if (l
->type
== pe_string
)
1904 pf
->raw_components
+= "=\"%#s\"\\n";
1906 pf
->raw_components
+= "=%#x\\n";
1908 // Create an index for the array
1909 struct arrayindex
* ai
= new arrayindex
;
1913 for (int i
=0; i
< idx_count
; i
++)
1915 ai
->indexes
.push_back (idx_sym
[i
]);
1916 pf
->args
.push_back(idx_sym
[i
]);
1918 if (l
->type
== pe_stats
)
1920 struct stat_op
* so
[5];
1921 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1923 ai
->type
= pe_stats
;
1924 for (unsigned si
= 0;
1925 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1928 so
[si
]= new stat_op
;
1929 so
[si
]->ctype
= stypes
[si
];
1930 so
[si
]->type
= pe_long
;
1932 so
[si
]->tok
= l
->tok
;
1933 pf
->args
.push_back(so
[si
]);
1938 // Create value for the foreach loop
1939 fe
->value
= new symbol
;
1940 fe
->value
->name
= "val";
1941 fe
->value
->tok
= l
->tok
;
1942 pf
->args
.push_back(fe
->value
);
1945 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1946 expr_statement
* feb
= new expr_statement
;
1950 fe
->block
= (statement
*)feb
;
1951 b
->statements
.push_back(fe
);
1954 // Add created probe
1956 derive_probes (s
, p
, dps
);
1957 for (unsigned i
= 0; i
< dps
.size(); i
++)
1959 derived_probe
* dp
= dps
[i
];
1960 s
.probes
.push_back (dp
);
1963 // Repopulate symbol and type info
1964 symresolution_info
sym (s
);
1965 sym
.current_function
= 0;
1966 sym
.current_probe
= dps
[0];
1967 dps
[0]->body
->visit (& sym
);
1969 semantic_pass_types(s
);
1970 // Mark that variable is read
1971 vut
.read
.insert (l
);
1976 semantic_pass (systemtap_session
& s
)
1982 s
.register_library_aliases();
1983 register_standard_tapsets(s
);
1985 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1986 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1987 if (rc
== 0) rc
= semantic_pass_optimize1 (s
);
1988 if (rc
== 0) rc
= semantic_pass_types (s
);
1989 if (rc
== 0) rc
= gen_dfa_table(s
);
1990 if (rc
== 0) add_global_var_display (s
);
1991 if (rc
== 0) rc
= semantic_pass_optimize2 (s
);
1992 if (rc
== 0) rc
= semantic_pass_vars (s
);
1993 if (rc
== 0) rc
= semantic_pass_stats (s
);
1994 if (rc
== 0) embeddedcode_info_pass (s
);
1996 if (s
.num_errors() == 0 && s
.probes
.size() == 0 && !s
.listing_mode
)
1997 throw semantic_error (_("no probes found"));
1999 catch (const semantic_error
& e
)
2006 // NB: listing mode only cares whether we have any probes,
2007 // so all previous error conditions are disregarded.
2009 rc
= s
.probes
.empty();
2015 // ------------------------------------------------------------------------
2016 // semantic processing: symbol resolution
2019 symresolution_info::symresolution_info (systemtap_session
& s
):
2020 session (s
), current_function (0), current_probe (0)
2026 symresolution_info::visit_block (block
* e
)
2028 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
2032 e
->statements
[i
]->visit (this);
2034 catch (const semantic_error
& e
)
2036 session
.print_error (e
);
2043 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
2045 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
2046 e
->indexes
[i
]->visit (this);
2048 symbol
*array
= NULL
;
2049 hist_op
*hist
= NULL
;
2050 classify_indexable (e
->base
, array
, hist
);
2054 if (!array
->referent
)
2056 vardecl
* d
= find_var (array
->name
, e
->indexes
.size (), array
->tok
);
2058 array
->referent
= d
;
2062 msg
<< _F("unresolved arity-%zu global array %s, missing global declaration?",
2063 e
->indexes
.size(), array
->name
.c_str());
2064 throw semantic_error (msg
.str(), e
->tok
);
2075 e
->value
->visit (this);
2078 e
->limit
->visit (this);
2080 e
->block
->visit (this);
2085 delete_statement_symresolution_info
:
2086 public traversing_visitor
2088 symresolution_info
*parent
;
2090 delete_statement_symresolution_info (symresolution_info
*p
):
2094 void visit_arrayindex (arrayindex
* e
)
2096 parent
->visit_arrayindex (e
);
2098 void visit_functioncall (functioncall
* e
)
2100 parent
->visit_functioncall (e
);
2103 void visit_symbol (symbol
* e
)
2108 vardecl
* d
= parent
->find_var (e
->name
, -1, e
->tok
);
2112 throw semantic_error (_("unresolved array in delete statement"), e
->tok
);
2117 symresolution_info::visit_delete_statement (delete_statement
* s
)
2119 delete_statement_symresolution_info
di (this);
2120 s
->value
->visit (&di
);
2125 symresolution_info::visit_symbol (symbol
* e
)
2130 vardecl
* d
= find_var (e
->name
, 0, e
->tok
);
2136 vardecl
* v
= new vardecl
;
2139 v
->set_arity(0, e
->tok
);
2140 if (current_function
)
2141 current_function
->locals
.push_back (v
);
2142 else if (current_probe
)
2143 current_probe
->locals
.push_back (v
);
2145 // must be probe-condition expression
2146 throw semantic_error (_("probe condition must not reference undeclared global"), e
->tok
);
2153 symresolution_info::visit_arrayindex (arrayindex
* e
)
2155 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
2156 e
->indexes
[i
]->visit (this);
2158 symbol
*array
= NULL
;
2159 hist_op
*hist
= NULL
;
2160 classify_indexable(e
->base
, array
, hist
);
2164 if (array
->referent
)
2167 vardecl
* d
= find_var (array
->name
, e
->indexes
.size (), array
->tok
);
2169 array
->referent
= d
;
2173 msg
<< _F("unresolved arity-%zu global array %s, missing global declaration?",
2174 e
->indexes
.size(), array
->name
.c_str());
2175 throw semantic_error (msg
.str(), e
->tok
);
2187 symresolution_info::visit_functioncall (functioncall
* e
)
2189 // XXX: we could relax this, if we're going to examine the
2190 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
2191 if (! (current_function
|| current_probe
))
2193 // must be probe-condition expression
2194 throw semantic_error (_("probe condition must not reference function"), e
->tok
);
2197 for (unsigned i
=0; i
<e
->args
.size(); i
++)
2198 e
->args
[i
]->visit (this);
2203 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
2209 msg
<< _F("unresolved arity-%zu function", e
->args
.size());
2210 throw semantic_error (msg
.str(), e
->tok
);
2214 /*find_var will return an argument other than zero if the name matches the var
2215 * name ie, if the current local name matches the name passed to find_var*/
2217 symresolution_info::find_var (const string
& name
, int arity
, const token
* tok
)
2219 if (current_function
|| current_probe
)
2222 vector
<vardecl
*>& locals
= (current_function
?
2223 current_function
->locals
:
2224 current_probe
->locals
);
2227 for (unsigned i
=0; i
<locals
.size(); i
++)
2228 if (locals
[i
]->name
== name
)
2230 locals
[i
]->set_arity (arity
, tok
);
2235 // search function formal parameters (for scalars)
2236 if (arity
== 0 && current_function
)
2237 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
2238 if (current_function
->formal_args
[i
]->name
== name
)
2240 // NB: no need to check arity here: formal args always scalar
2241 current_function
->formal_args
[i
]->set_arity (0, tok
);
2242 return current_function
->formal_args
[i
];
2245 // search processed globals
2246 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
2247 if (session
.globals
[i
]->name
== name
)
2249 if (! session
.suppress_warnings
)
2251 vardecl
* v
= session
.globals
[i
];
2252 // clog << "resolved " << *tok << " to global " << *v->tok << endl;
2253 if (v
->tok
->location
.file
!= tok
->location
.file
)
2255 session
.print_warning (_F("cross-file global variable reference to %s from",
2256 lex_cast(*v
->tok
).c_str()), tok
);
2259 session
.globals
[i
]->set_arity (arity
, tok
);
2260 return session
.globals
[i
];
2263 // search library globals
2264 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
2266 stapfile
* f
= session
.library_files
[i
];
2267 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
2269 vardecl
* g
= f
->globals
[j
];
2270 if (g
->name
== name
)
2272 g
->set_arity (arity
, tok
);
2274 // put library into the queue if not already there
2275 if (find (session
.files
.begin(), session
.files
.end(), f
)
2276 == session
.files
.end())
2277 session
.files
.push_back (f
);
2289 symresolution_info::find_function (const string
& name
, unsigned arity
)
2292 if (session
.functions
.find(name
) != session
.functions
.end())
2294 functiondecl
* fd
= session
.functions
[name
];
2295 assert (fd
->name
== name
);
2296 if (fd
->formal_args
.size() == arity
)
2299 session
.print_warning (_F("mismatched arity-%zu function found", fd
->formal_args
.size()),
2301 // and some semantic_error will shortly follow
2304 // search library functions
2305 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
2307 stapfile
* f
= session
.library_files
[i
];
2308 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
2309 if (f
->functions
[j
]->name
== name
&&
2310 f
->functions
[j
]->formal_args
.size() == arity
)
2312 // put library into the queue if not already there
2313 if (0) // session.verbose_resolution
2314 cerr
<< _F(" function %s is defined from %s",
2315 name
.c_str(), f
->name
.c_str()) << endl
;
2317 if (find (session
.files
.begin(), session
.files
.end(), f
)
2318 == session
.files
.end())
2319 session
.files
.push_back (f
);
2320 // else .. print different message?
2322 return f
->functions
[j
];
2331 // ------------------------------------------------------------------------
2335 // Do away with functiondecls that are never (transitively) called
2337 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
2339 functioncall_traversing_visitor ftv
;
2340 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2342 s
.probes
[i
]->body
->visit (& ftv
);
2343 if (s
.probes
[i
]->sole_location()->condition
)
2344 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
2346 vector
<functiondecl
*> new_unused_functions
;
2347 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2349 functiondecl
* fd
= it
->second
;
2350 if (ftv
.traversed
.find(fd
) == ftv
.traversed
.end())
2352 if (fd
->tok
->location
.file
->name
== s
.user_file
->name
&& ! fd
->synthetic
)// !tapset
2353 s
.print_warning (_F("Eliding unused function '%s'", fd
->name
.c_str()), fd
->tok
);
2354 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
2355 new_unused_functions
.push_back (fd
);
2359 for (unsigned i
=0; i
<new_unused_functions
.size(); i
++)
2361 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (new_unused_functions
[i
]->name
);
2362 assert (where
!= s
.functions
.end());
2363 s
.functions
.erase (where
);
2364 if (s
.tapset_compile_coverage
)
2365 s
.unused_functions
.push_back (new_unused_functions
[i
]);
2370 // ------------------------------------------------------------------------
2372 // Do away with local & global variables that are never
2373 // written nor read.
2374 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
2376 varuse_collecting_visitor
vut(s
);
2378 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2380 s
.probes
[i
]->body
->visit (& vut
);
2382 if (s
.probes
[i
]->sole_location()->condition
)
2383 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
2386 // NB: Since varuse_collecting_visitor also traverses down
2387 // actually called functions, we don't need to explicitly
2388 // iterate over them. Uncalled ones should have been pruned
2391 // for (unsigned i=0; i<s.functions.size(); i++)
2392 // s.functions[i]->body->visit (& vut);
2394 // Now in vut.read/written, we have a mixture of all locals, globals
2396 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2397 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
2399 vardecl
* l
= s
.probes
[i
]->locals
[j
];
2401 // skip over "special" locals
2402 if (l
->synthetic
) { j
++; continue; }
2404 if (vut
.read
.find (l
) == vut
.read
.end() &&
2405 vut
.written
.find (l
) == vut
.written
.end())
2407 if (l
->tok
->location
.file
->name
== s
.user_file
->name
) // !tapset
2408 s
.print_warning (_F("Eliding unused variable '%s'", l
->name
.c_str()), l
->tok
);
2409 if (s
.tapset_compile_coverage
) {
2410 s
.probes
[i
]->unused_locals
.push_back
2411 (s
.probes
[i
]->locals
[j
]);
2413 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
2415 // don't increment j
2419 if (vut
.written
.find (l
) == vut
.written
.end())
2420 if (iterations
== 0 && ! s
.suppress_warnings
)
2423 vector
<vardecl
*>::iterator it
;
2424 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
2425 if (l
->name
!= (*it
)->name
)
2426 o
<< " " << (*it
)->name
;
2427 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2428 if (l
->name
!= (*it
)->name
)
2429 o
<< " " << (*it
)->name
;
2431 s
.print_warning (_F("never-assigned local variable '%s' %s",
2432 l
->name
.c_str(), (o
.str() == "" ? "" :
2433 (_("(alternatives:") + o
.str() + ")")).c_str()), l
->tok
);
2439 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2441 functiondecl
*fd
= it
->second
;
2442 for (unsigned j
=0; j
<fd
->locals
.size(); /* see below */)
2444 vardecl
* l
= fd
->locals
[j
];
2445 if (vut
.read
.find (l
) == vut
.read
.end() &&
2446 vut
.written
.find (l
) == vut
.written
.end())
2448 if (l
->tok
->location
.file
->name
== s
.user_file
->name
) // !tapset
2449 s
.print_warning (_F("Eliding unused variable '%s'", l
->name
.c_str()), l
->tok
);
2450 if (s
.tapset_compile_coverage
) {
2451 fd
->unused_locals
.push_back (fd
->locals
[j
]);
2453 fd
->locals
.erase(fd
->locals
.begin() + j
);
2455 // don't increment j
2459 if (vut
.written
.find (l
) == vut
.written
.end())
2460 if (iterations
== 0 && ! s
.suppress_warnings
)
2463 vector
<vardecl
*>::iterator it
;
2464 for (it
= fd
->formal_args
.begin() ;
2465 it
!= fd
->formal_args
.end(); it
++)
2466 if (l
->name
!= (*it
)->name
)
2467 o
<< " " << (*it
)->name
;
2468 for (it
= fd
->locals
.begin(); it
!= fd
->locals
.end(); it
++)
2469 if (l
->name
!= (*it
)->name
)
2470 o
<< " " << (*it
)->name
;
2471 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2472 if (l
->name
!= (*it
)->name
)
2473 o
<< " " << (*it
)->name
;
2475 s
.print_warning (_F("never-assigned local variable '%s' %s",
2476 l
->name
.c_str(), (o
.str() == "" ? "" :
2477 (_("(alternatives:") + o
.str() + ")")).c_str()), l
->tok
);
2484 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
2486 vardecl
* l
= s
.globals
[i
];
2487 if (vut
.read
.find (l
) == vut
.read
.end() &&
2488 vut
.written
.find (l
) == vut
.written
.end())
2490 if (l
->tok
->location
.file
->name
== s
.user_file
->name
) // !tapset
2491 s
.print_warning (_F("Eliding unused variable '%s'", l
->name
.c_str()), l
->tok
);
2492 if (s
.tapset_compile_coverage
) {
2493 s
.unused_globals
.push_back(s
.globals
[i
]);
2495 s
.globals
.erase(s
.globals
.begin() + i
);
2497 // don't increment i
2501 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
2502 if (iterations
== 0 && ! s
.suppress_warnings
)
2505 vector
<vardecl
*>::iterator it
;
2506 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2507 if (l
->name
!= (*it
)->name
)
2508 o
<< " " << (*it
)->name
;
2510 s
.print_warning (_F("never assigned global variable '%s' %s", l
->name
.c_str(),
2511 (o
.str() == "" ? "" : (_("(alternatives:") + o
.str() + ")")).c_str()), l
->tok
);
2520 // ------------------------------------------------------------------------
2522 struct dead_assignment_remover
: public update_visitor
2524 systemtap_session
& session
;
2526 const varuse_collecting_visitor
& vut
;
2528 dead_assignment_remover(systemtap_session
& s
, bool& r
,
2529 const varuse_collecting_visitor
& v
):
2530 session(s
), relaxed_p(r
), vut(v
) {}
2532 void visit_assignment (assignment
* e
);
2533 void visit_try_block (try_block
*s
);
2538 dead_assignment_remover::visit_assignment (assignment
* e
)
2543 symbol
* left
= get_symbol_within_expression (e
->left
);
2544 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2545 if (leftvar
) // not unresolved $target, so intended sideeffect may be elided
2547 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2549 // NB: Not so fast! The left side could be an array whose
2550 // index expressions may have side-effects. This would be
2551 // OK if we could replace the array assignment with a
2552 // statement-expression containing all the index expressions
2553 // and the rvalue... but we can't.
2554 // Another possibility is that we have an unread global variable
2555 // which are kept for probe end value display.
2557 bool is_global
= false;
2558 vector
<vardecl
*>::iterator it
;
2559 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2560 if (leftvar
->name
== (*it
)->name
)
2566 varuse_collecting_visitor
lvut(session
);
2567 e
->left
->visit (& lvut
);
2568 if (lvut
.side_effect_free () && !is_global
// XXX: use _wrt() once we track focal_vars
2569 && !leftvar
->synthetic
) // don't elide assignment to synthetic $context variables
2571 /* PR 1119: NB: This is not necessary here. A write-only
2572 variable will also be elided soon at the next _opt2 iteration.
2573 if (e->left->tok->location.file->name == session.user_file->name) // !tapset
2574 session.print_warning("eliding write-only ", *e->left->tok);
2577 if (e
->left
->tok
->location
.file
->name
== session
.user_file
->name
) // !tapset
2578 session
.print_warning(_F("Eliding assignment to '%s'", leftvar
->name
.c_str()), e
->tok
);
2579 provide (e
->right
); // goodbye assignment*
2590 dead_assignment_remover::visit_try_block (try_block
*s
)
2592 replace (s
->try_block
);
2593 if (s
->catch_error_var
)
2595 vardecl
* errvar
= s
->catch_error_var
->referent
;
2596 if (vut
.read
.find(errvar
) == vut
.read
.end()) // never read?
2598 if (session
.verbose
>2)
2599 clog
<< _F("Eliding unused error string catcher %s at %s",
2600 errvar
->name
.c_str(), lex_cast(*s
->tok
).c_str()) << endl
;
2601 s
->catch_error_var
= 0;
2604 replace (s
->catch_block
);
2609 // Let's remove assignments to variables that are never read. We
2610 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2611 // be optimized away as an unused variable, and expr a candidate to be
2612 // removed as a side-effect-free statement expression. Wahoo!
2613 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2615 // Recompute the varuse data, which will probably match the opt2
2616 // copy of the computation, except for those totally unused
2617 // variables that opt2 removed.
2618 varuse_collecting_visitor
vut(s
);
2619 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2620 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2622 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2623 // This instance may be reused for multiple probe/function body trims.
2625 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2626 dar
.replace (s
.probes
[i
]->body
);
2627 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2628 it
!= s
.functions
.end(); it
++)
2629 dar
.replace (it
->second
->body
);
2630 // The rewrite operation is performed within the visitor.
2632 // XXX: we could also zap write-only globals here
2636 // ------------------------------------------------------------------------
2638 struct dead_stmtexpr_remover
: public update_visitor
2640 systemtap_session
& session
;
2642 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2644 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2645 session(s
), relaxed_p(r
) {}
2647 void visit_block (block
*s
);
2648 void visit_try_block (try_block
*s
);
2649 void visit_null_statement (null_statement
*s
);
2650 void visit_if_statement (if_statement
* s
);
2651 void visit_foreach_loop (foreach_loop
*s
);
2652 void visit_for_loop (for_loop
*s
);
2653 // XXX: and other places where stmt_expr's might be nested
2655 void visit_expr_statement (expr_statement
*s
);
2660 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2663 if (session
.verbose
>2)
2664 clog
<< _("Eliding side-effect-free null statement ") << *s
->tok
<< endl
;
2671 dead_stmtexpr_remover::visit_block (block
*s
)
2673 vector
<statement
*> new_stmts
;
2674 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2676 statement
* new_stmt
= require (s
->statements
[i
], true);
2679 // flatten nested blocks into this one
2680 block
*b
= dynamic_cast<block
*>(new_stmt
);
2683 if (session
.verbose
>2)
2684 clog
<< _("Flattening nested block ") << *b
->tok
<< endl
;
2685 new_stmts
.insert(new_stmts
.end(),
2686 b
->statements
.begin(), b
->statements
.end());
2690 new_stmts
.push_back (new_stmt
);
2693 if (new_stmts
.size() == 0)
2695 if (session
.verbose
>2)
2696 clog
<< _("Eliding side-effect-free empty block ") << *s
->tok
<< endl
;
2699 else if (new_stmts
.size() == 1)
2701 if (session
.verbose
>2)
2702 clog
<< _("Eliding side-effect-free singleton block ") << *s
->tok
<< endl
;
2703 provide (new_stmts
[0]);
2707 s
->statements
= new_stmts
;
2713 dead_stmtexpr_remover::visit_try_block (try_block
*s
)
2715 replace (s
->try_block
, true);
2716 replace (s
->catch_block
, true); // null catch{} is ok and useful
2717 if (s
->try_block
== 0)
2719 if (session
.verbose
>2)
2720 clog
<< _("Eliding empty try {} block ") << *s
->tok
<< endl
;
2728 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2730 replace (s
->thenblock
, true);
2731 replace (s
->elseblock
, true);
2733 if (s
->thenblock
== 0)
2735 if (s
->elseblock
== 0)
2737 // We may be able to elide this statement, if the condition
2738 // expression is side-effect-free.
2739 varuse_collecting_visitor
vct(session
);
2740 s
->condition
->visit(& vct
);
2741 if (vct
.side_effect_free ())
2743 if (session
.verbose
>2)
2744 clog
<< _("Eliding side-effect-free if statement ")
2746 s
= 0; // yeah, baby
2750 // We can still turn it into a simple expr_statement though...
2751 if (session
.verbose
>2)
2752 clog
<< _("Creating simple evaluation from if statement ")
2754 expr_statement
*es
= new expr_statement
;
2755 es
->value
= s
->condition
;
2756 es
->tok
= es
->value
->tok
;
2763 // For an else without a then, we can invert the condition logic to
2764 // avoid having a null statement in the thenblock
2765 if (session
.verbose
>2)
2766 clog
<< _("Inverting the condition of if statement ")
2768 unary_expression
*ue
= new unary_expression
;
2769 ue
->operand
= s
->condition
;
2770 ue
->tok
= ue
->operand
->tok
;
2773 s
->thenblock
= s
->elseblock
;
2781 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2783 replace (s
->block
, true);
2787 // XXX what if s->limit has side effects?
2788 // XXX what about s->indexes or s->value used outside the loop?
2789 if(session
.verbose
> 2)
2790 clog
<< _("Eliding side-effect-free foreach statement ") << *s
->tok
<< endl
;
2791 s
= 0; // yeah, baby
2797 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2799 replace (s
->block
, true);
2803 // We may be able to elide this statement, if the condition
2804 // expression is side-effect-free.
2805 varuse_collecting_visitor
vct(session
);
2806 if (s
->init
) s
->init
->visit(& vct
);
2807 s
->cond
->visit(& vct
);
2808 if (s
->incr
) s
->incr
->visit(& vct
);
2809 if (vct
.side_effect_free ())
2811 if (session
.verbose
>2)
2812 clog
<< _("Eliding side-effect-free for statement ") << *s
->tok
<< endl
;
2813 s
= 0; // yeah, baby
2817 // Can't elide this whole statement; put a null in there.
2818 s
->block
= new null_statement(s
->tok
);
2827 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2829 // Run a varuse query against the operand expression. If it has no
2830 // side-effects, replace the entire statement expression by a null
2831 // statement with the provide() call.
2833 // Unlike many other visitors, we do *not* traverse this outermost
2834 // one into the expression subtrees. There is no need - no
2835 // expr_statement nodes will be found there. (Function bodies
2836 // need to be visited explicitly by our caller.)
2838 // NB. While we don't share nodes in the parse tree, let's not
2839 // deallocate *s anyway, just in case...
2841 varuse_collecting_visitor
vut(session
);
2842 s
->value
->visit (& vut
);
2844 if (vut
.side_effect_free_wrt (focal_vars
))
2846 /* PR 1119: NB: this message is not a good idea here. It can
2847 name some arbitrary RHS expression of an assignment.
2848 if (s->value->tok->location.file->name == session.user_file->name) // not tapset
2849 session.print_warning("eliding never-assigned ", *s->value->tok);
2852 if (s
->value
->tok
->location
.file
->name
== session
.user_file
->name
) // not tapset
2853 session
.print_warning("Eliding side-effect-free expression ", s
->tok
);
2855 // NB: this 0 pointer is invalid to leave around for any length of
2856 // time, but the parent parse tree objects above handle it.
2864 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2866 // Finally, let's remove some statement-expressions that have no
2867 // side-effect. These should be exactly those whose private varuse
2868 // visitors come back with an empty "written" and "embedded" lists.
2870 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2871 // This instance may be reused for multiple probe/function body trims.
2873 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2875 assert_no_interrupts();
2877 derived_probe
* p
= s
.probes
[i
];
2879 duv
.focal_vars
.clear ();
2880 duv
.focal_vars
.insert (s
.globals
.begin(),
2882 duv
.focal_vars
.insert (p
->locals
.begin(),
2885 duv
.replace (p
->body
, true);
2888 if (! s
.timing
) // PR10070
2889 s
.print_warning (_F("side-effect-free probe '%s'", p
->name
.c_str()), p
->tok
);
2891 p
->body
= new null_statement(p
->tok
);
2893 // XXX: possible duplicate warnings; see below
2896 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2898 assert_no_interrupts();
2900 functiondecl
* fn
= it
->second
;
2901 duv
.focal_vars
.clear ();
2902 duv
.focal_vars
.insert (fn
->locals
.begin(),
2904 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2905 fn
->formal_args
.end());
2906 duv
.focal_vars
.insert (s
.globals
.begin(),
2909 duv
.replace (fn
->body
, true);
2912 s
.print_warning (_F("side-effect-free function '%s'", fn
->name
.c_str()), fn
->tok
);
2914 fn
->body
= new null_statement(fn
->tok
);
2916 // XXX: the next iteration of the outer optimization loop may
2917 // take this new null_statement away again, and thus give us a
2918 // fresh warning. It would be better if this fixup was performed
2919 // only after the relaxation iterations.
2920 // XXX: or else see bug #6469.
2926 // ------------------------------------------------------------------------
2928 // The goal of this visitor is to reduce top-level expressions in void context
2929 // into separate statements that evaluate each subcomponent of the expression.
2930 // The dead-statement-remover can later remove some parts if they have no side
2933 // All expressions must be overridden here so we never visit their subexpressions
2934 // accidentally. Thus, the only visited expressions should be value of an
2937 // For an expression to replace its expr_statement with something else, it will
2938 // let the new statement provide(), and then provide(0) for itself. The
2939 // expr_statement will take this as a sign that it's been replaced.
2940 struct void_statement_reducer
: public update_visitor
2942 systemtap_session
& session
;
2944 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2946 void_statement_reducer(systemtap_session
& s
, bool& r
):
2947 session(s
), relaxed_p(r
) {}
2949 void visit_expr_statement (expr_statement
* s
);
2951 // expressions in conditional / loop controls are definitely a side effect,
2952 // but still recurse into the child statements
2953 void visit_if_statement (if_statement
* s
);
2954 void visit_for_loop (for_loop
* s
);
2955 void visit_foreach_loop (foreach_loop
* s
);
2957 // these expressions get rewritten into their statement equivalents
2958 void visit_logical_or_expr (logical_or_expr
* e
);
2959 void visit_logical_and_expr (logical_and_expr
* e
);
2960 void visit_ternary_expression (ternary_expression
* e
);
2962 // all of these can (usually) be reduced into simpler statements
2963 void visit_binary_expression (binary_expression
* e
);
2964 void visit_unary_expression (unary_expression
* e
);
2965 void visit_regex_query (regex_query
* e
); // XXX depends on subexpr extraction
2966 void visit_comparison (comparison
* e
);
2967 void visit_concatenation (concatenation
* e
);
2968 void visit_functioncall (functioncall
* e
);
2969 void visit_print_format (print_format
* e
);
2970 void visit_target_symbol (target_symbol
* e
);
2971 void visit_atvar_op (atvar_op
* e
);
2972 void visit_cast_op (cast_op
* e
);
2973 void visit_defined_op (defined_op
* e
);
2975 // these are a bit hairy to grok due to the intricacies of indexables and
2976 // stats, so I'm chickening out and skipping them...
2977 void visit_array_in (array_in
* e
) { provide (e
); }
2978 void visit_arrayindex (arrayindex
* e
) { provide (e
); }
2979 void visit_stat_op (stat_op
* e
) { provide (e
); }
2980 void visit_hist_op (hist_op
* e
) { provide (e
); }
2982 // these can't be reduced because they always have an effect
2983 void visit_return_statement (return_statement
* s
) { provide (s
); }
2984 void visit_delete_statement (delete_statement
* s
) { provide (s
); }
2985 void visit_pre_crement (pre_crement
* e
) { provide (e
); }
2986 void visit_post_crement (post_crement
* e
) { provide (e
); }
2987 void visit_assignment (assignment
* e
) { provide (e
); }
2992 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2994 replace (s
->value
, true);
2996 // if the expression provides 0, that's our signal that a new
2997 // statement has been provided, so we shouldn't provide this one.
3003 void_statement_reducer::visit_if_statement (if_statement
* s
)
3005 // s->condition is never void
3006 replace (s
->thenblock
);
3007 replace (s
->elseblock
);
3012 void_statement_reducer::visit_for_loop (for_loop
* s
)
3014 // s->init/cond/incr are never void
3020 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
3022 // s->indexes/base/value/limit are never void
3028 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
3030 // In void context, the evaluation of "a || b" is exactly like
3031 // "if (!a) b", so let's do that instead.
3033 if (session
.verbose
>2)
3034 clog
<< _("Creating if statement from unused logical-or ")
3037 if_statement
*is
= new if_statement
;
3041 unary_expression
*ue
= new unary_expression
;
3042 ue
->operand
= e
->left
;
3047 expr_statement
*es
= new expr_statement
;
3048 es
->value
= e
->right
;
3049 es
->tok
= es
->value
->tok
;
3059 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
3061 // In void context, the evaluation of "a && b" is exactly like
3062 // "if (a) b", so let's do that instead.
3064 if (session
.verbose
>2)
3065 clog
<< _("Creating if statement from unused logical-and ")
3068 if_statement
*is
= new if_statement
;
3071 is
->condition
= e
->left
;
3073 expr_statement
*es
= new expr_statement
;
3074 es
->value
= e
->right
;
3075 es
->tok
= es
->value
->tok
;
3085 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
3087 // In void context, the evaluation of "a ? b : c" is exactly like
3088 // "if (a) b else c", so let's do that instead.
3090 if (session
.verbose
>2)
3091 clog
<< _("Creating if statement from unused ternary expression ")
3094 if_statement
*is
= new if_statement
;
3096 is
->condition
= e
->cond
;
3098 expr_statement
*es
= new expr_statement
;
3099 es
->value
= e
->truevalue
;
3100 es
->tok
= es
->value
->tok
;
3103 es
= new expr_statement
;
3104 es
->value
= e
->falsevalue
;
3105 es
->tok
= es
->value
->tok
;
3115 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
3117 // When the result of a binary operation isn't needed, it's just as good to
3118 // evaluate the operands as sequential statements in a block.
3120 if (session
.verbose
>2)
3121 clog
<< _("Eliding unused binary ") << *e
->tok
<< endl
;
3123 block
*b
= new block
;
3126 expr_statement
*es
= new expr_statement
;
3127 es
->value
= e
->left
;
3128 es
->tok
= es
->value
->tok
;
3129 b
->statements
.push_back(es
);
3131 es
= new expr_statement
;
3132 es
->value
= e
->right
;
3133 es
->tok
= es
->value
->tok
;
3134 b
->statements
.push_back(es
);
3143 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
3145 // When the result of a unary operation isn't needed, it's just as good to
3146 // evaluate the operand directly
3148 if (session
.verbose
>2)
3149 clog
<< _("Eliding unused unary ") << *e
->tok
<< endl
;
3152 e
->operand
->visit(this);
3156 void_statement_reducer::visit_regex_query (regex_query
* e
)
3158 // TODOXXX After subexpression extraction is implemented,
3159 // regular expression matches *may* have side-effects in
3160 // terms of producing matched subexpressions, e.g.:
3162 // str =~ "pat"; println(matched(0));
3164 // It's debatable if we want to actually allow this, though.
3166 // Treat e as a unary expression on the left operand -- since the
3167 // right hand side must be a literal (as verified by the parser),
3168 // evaluating it never has side effects.
3170 if (session
.verbose
>2)
3171 clog
<< _("Eliding regex query ") << *e
->tok
<< endl
;
3174 e
->left
->visit(this);
3178 void_statement_reducer::visit_comparison (comparison
* e
)
3180 visit_binary_expression(e
);
3184 void_statement_reducer::visit_concatenation (concatenation
* e
)
3186 visit_binary_expression(e
);
3190 void_statement_reducer::visit_functioncall (functioncall
* e
)
3192 // If a function call is pure and its result ignored, we can elide the call
3193 // and just evaluate the arguments in sequence
3195 if (!e
->args
.size())
3201 varuse_collecting_visitor
vut(session
);
3202 vut
.traversed
.insert (e
->referent
);
3203 vut
.current_function
= e
->referent
;
3204 e
->referent
->body
->visit (& vut
);
3205 if (!vut
.side_effect_free_wrt (focal_vars
))
3211 if (session
.verbose
>2)
3212 clog
<< _("Eliding side-effect-free function call ") << *e
->tok
<< endl
;
3214 block
*b
= new block
;
3217 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
3219 expr_statement
*es
= new expr_statement
;
3220 es
->value
= e
->args
[i
];
3221 es
->tok
= es
->value
->tok
;
3222 b
->statements
.push_back(es
);
3232 void_statement_reducer::visit_print_format (print_format
* e
)
3234 // When an sprint's return value is ignored, we can simply evaluate the
3235 // arguments in sequence
3237 if (e
->print_to_stream
|| !e
->args
.size())
3243 if (session
.verbose
>2)
3244 clog
<< _("Eliding unused print ") << *e
->tok
<< endl
;
3246 block
*b
= new block
;
3249 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
3251 expr_statement
*es
= new expr_statement
;
3252 es
->value
= e
->args
[i
];
3253 es
->tok
= es
->value
->tok
;
3254 b
->statements
.push_back(es
);
3264 void_statement_reducer::visit_atvar_op (atvar_op
* e
)
3266 visit_target_symbol (e
);
3270 void_statement_reducer::visit_target_symbol (target_symbol
* e
)
3272 // When target_symbol isn't needed, it's just as good to
3273 // evaluate any array indexes directly
3275 block
*b
= new block
;
3278 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
3280 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
3283 expr_statement
*es
= new expr_statement
;
3284 es
->value
= e
->components
[i
].expr_index
;
3285 es
->tok
= es
->value
->tok
;
3286 b
->statements
.push_back(es
);
3289 if (b
->statements
.empty())
3296 if (session
.verbose
>2)
3297 clog
<< _("Eliding unused target symbol ") << *e
->tok
<< endl
;
3306 void_statement_reducer::visit_cast_op (cast_op
* e
)
3308 // When the result of a cast operation isn't needed, it's just as good to
3309 // evaluate the operand and any array indexes directly
3311 block
*b
= new block
;
3314 expr_statement
*es
= new expr_statement
;
3315 es
->value
= e
->operand
;
3316 es
->tok
= es
->value
->tok
;
3317 b
->statements
.push_back(es
);
3319 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
3321 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
3324 es
= new expr_statement
;
3325 es
->value
= e
->components
[i
].expr_index
;
3326 es
->tok
= es
->value
->tok
;
3327 b
->statements
.push_back(es
);
3330 if (session
.verbose
>2)
3331 clog
<< _("Eliding unused typecast ") << *e
->tok
<< endl
;
3341 void_statement_reducer::visit_defined_op (defined_op
* e
)
3343 // When the result of a @defined operation isn't needed, just elide
3344 // it entirely. Its operand $expression must already be
3345 // side-effect-free.
3347 if (session
.verbose
>2)
3348 clog
<< _("Eliding unused check ") << *e
->tok
<< endl
;
3357 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
3359 // Let's simplify statements with unused computed values.
3361 void_statement_reducer
vuv (s
, relaxed_p
);
3362 // This instance may be reused for multiple probe/function body trims.
3364 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
3366 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
3367 vuv
.replace (s
.probes
[i
]->body
);
3368 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
3369 it
!= s
.functions
.end(); it
++)
3370 vuv
.replace (it
->second
->body
);
3374 struct const_folder
: public update_visitor
3376 systemtap_session
& session
;
3379 const_folder(systemtap_session
& s
, bool& r
):
3380 session(s
), relaxed_p(r
), last_number(0), last_string(0) {}
3382 literal_number
* last_number
;
3383 literal_number
* get_number(expression
*& e
);
3384 void visit_literal_number (literal_number
* e
);
3386 literal_string
* last_string
;
3387 literal_string
* get_string(expression
*& e
);
3388 void visit_literal_string (literal_string
* e
);
3390 void get_literal(expression
*& e
, literal_number
*& n
, literal_string
*& s
);
3392 void visit_if_statement (if_statement
* s
);
3393 void visit_for_loop (for_loop
* s
);
3394 void visit_foreach_loop (foreach_loop
* s
);
3395 void visit_binary_expression (binary_expression
* e
);
3396 void visit_unary_expression (unary_expression
* e
);
3397 void visit_logical_or_expr (logical_or_expr
* e
);
3398 void visit_logical_and_expr (logical_and_expr
* e
);
3399 // void visit_regex_query (regex_query* e); // XXX: would require executing dfa at compile-time
3400 void visit_comparison (comparison
* e
);
3401 void visit_concatenation (concatenation
* e
);
3402 void visit_ternary_expression (ternary_expression
* e
);
3403 void visit_defined_op (defined_op
* e
);
3404 void visit_target_symbol (target_symbol
* e
);
3408 const_folder::get_literal(expression
*& e
,
3413 n
= (e
== last_number
) ? last_number
: NULL
;
3414 s
= (e
== last_string
) ? last_string
: NULL
;
3418 const_folder::get_number(expression
*& e
)
3421 return (e
== last_number
) ? last_number
: NULL
;
3425 const_folder::visit_literal_number (literal_number
* e
)
3432 const_folder::get_string(expression
*& e
)
3435 return (e
== last_string
) ? last_string
: NULL
;
3439 const_folder::visit_literal_string (literal_string
* e
)
3446 const_folder::visit_if_statement (if_statement
* s
)
3448 literal_number
* cond
= get_number (s
->condition
);
3451 replace (s
->thenblock
);
3452 replace (s
->elseblock
);
3457 if (session
.verbose
>2)
3458 clog
<< _F("Collapsing constant-%" PRIi64
" if-statement %s",
3459 cond
->value
, lex_cast(*s
->tok
).c_str()) << endl
;
3462 statement
* n
= cond
->value
? s
->thenblock
: s
->elseblock
;
3466 provide (new null_statement (s
->tok
));
3471 const_folder::visit_for_loop (for_loop
* s
)
3473 literal_number
* cond
= get_number (s
->cond
);
3474 if (!cond
|| cond
->value
)
3483 if (session
.verbose
>2)
3484 clog
<< _("Collapsing constantly-false for-loop ") << *s
->tok
<< endl
;
3488 s
->init
->visit (this);
3490 provide (new null_statement (s
->tok
));
3495 const_folder::visit_foreach_loop (foreach_loop
* s
)
3497 literal_number
* limit
= get_number (s
->limit
);
3498 if (!limit
|| limit
->value
> 0)
3500 for (unsigned i
= 0; i
< s
->indexes
.size(); ++i
)
3501 replace (s
->indexes
[i
]);
3509 if (session
.verbose
>2)
3510 clog
<< _("Collapsing constantly-limited foreach-loop ") << *s
->tok
<< endl
;
3513 provide (new null_statement (s
->tok
));
3518 const_folder::visit_binary_expression (binary_expression
* e
)
3521 literal_number
* left
= get_number (e
->left
);
3522 literal_number
* right
= get_number (e
->right
);
3524 if (right
&& !right
->value
&& (e
->op
== "/" || e
->op
== "%"))
3526 // Give divide-by-zero a chance to be optimized out elsewhere,
3527 // and if not it will be a runtime error anyway...
3535 value
= left
->value
+ right
->value
;
3536 else if (e
->op
== "-")
3537 value
= left
->value
- right
->value
;
3538 else if (e
->op
== "*")
3539 value
= left
->value
* right
->value
;
3540 else if (e
->op
== "&")
3541 value
= left
->value
& right
->value
;
3542 else if (e
->op
== "|")
3543 value
= left
->value
| right
->value
;
3544 else if (e
->op
== "^")
3545 value
= left
->value
^ right
->value
;
3546 else if (e
->op
== ">>")
3547 value
= left
->value
>> max(min(right
->value
, (int64_t)64), (int64_t)0);
3548 else if (e
->op
== "<<")
3549 value
= left
->value
<< max(min(right
->value
, (int64_t)64), (int64_t)0);
3550 else if (e
->op
== "/")
3551 value
= (left
->value
== LLONG_MIN
&& right
->value
== -1) ? LLONG_MIN
:
3552 left
->value
/ right
->value
;
3553 else if (e
->op
== "%")
3554 value
= (left
->value
== LLONG_MIN
&& right
->value
== -1) ? 0 :
3555 left
->value
% right
->value
;
3557 throw semantic_error (_("unsupported binary operator ") + e
->op
);
3560 else if ((left
&& ((left
->value
== 0 && (e
->op
== "*" || e
->op
== "&" ||
3561 e
->op
== ">>" || e
->op
== "<<" )) ||
3562 (left
->value
==-1 && (e
->op
== "|" || e
->op
== ">>"))))
3564 (right
&& ((right
->value
== 0 && (e
->op
== "*" || e
->op
== "&")) ||
3565 (right
->value
== 1 && (e
->op
== "%")) ||
3566 (right
->value
==-1 && (e
->op
== "%" || e
->op
== "|")))))
3568 expression
* other
= left
? e
->right
: e
->left
;
3569 varuse_collecting_visitor
vu(session
);
3571 if (!vu
.side_effect_free())
3578 value
= left
->value
;
3579 else if (e
->op
== "%")
3582 value
= right
->value
;
3585 else if ((left
&& ((left
->value
== 0 && (e
->op
== "+" || e
->op
== "|" ||
3587 (left
->value
== 1 && (e
->op
== "*")) ||
3588 (left
->value
==-1 && (e
->op
== "&"))))
3590 (right
&& ((right
->value
== 0 && (e
->op
== "+" || e
->op
== "-" ||
3591 e
->op
== "|" || e
->op
== "^")) ||
3592 (right
->value
== 1 && (e
->op
== "*" || e
->op
== "/")) ||
3593 (right
->value
==-1 && (e
->op
== "&")) ||
3594 (right
->value
<= 0 && (e
->op
== ">>" || e
->op
== "<<")))))
3596 if (session
.verbose
>2)
3597 clog
<< _("Collapsing constant-identity binary operator ") << *e
->tok
<< endl
;
3600 provide (left
? e
->right
: e
->left
);
3610 if (session
.verbose
>2)
3611 clog
<< _F("Collapsing constant-%" PRIi64
" binary operator %s",
3612 value
, lex_cast(*e
->tok
).c_str()) << endl
;
3615 literal_number
* n
= new literal_number(value
);
3621 const_folder::visit_unary_expression (unary_expression
* e
)
3623 literal_number
* operand
= get_number (e
->operand
);
3628 if (session
.verbose
>2)
3629 clog
<< _("Collapsing constant unary ") << *e
->tok
<< endl
;
3632 literal_number
* n
= new literal_number (*operand
);
3636 else if (e
->op
== "-")
3637 n
->value
= -n
->value
;
3638 else if (e
->op
== "!")
3639 n
->value
= !n
->value
;
3640 else if (e
->op
== "~")
3641 n
->value
= ~n
->value
;
3643 throw semantic_error (_("unsupported unary operator ") + e
->op
);
3649 const_folder::visit_logical_or_expr (logical_or_expr
* e
)
3652 literal_number
* left
= get_number (e
->left
);
3653 literal_number
* right
= get_number (e
->right
);
3656 value
= left
->value
|| right
->value
;
3658 else if ((left
&& left
->value
) || (right
&& right
->value
))
3660 // If the const is on the left, we get to short-circuit the right
3661 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3664 varuse_collecting_visitor
vu(session
);
3665 e
->left
->visit(&vu
);
3666 if (!vu
.side_effect_free())
3676 // We might also get rid of useless "0||x" and "x||0", except it does
3677 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3678 // that this would gain us much.
3686 if (session
.verbose
>2)
3687 clog
<< _("Collapsing constant logical-OR ") << *e
->tok
<< endl
;
3690 literal_number
* n
= new literal_number(value
);
3696 const_folder::visit_logical_and_expr (logical_and_expr
* e
)
3699 literal_number
* left
= get_number (e
->left
);
3700 literal_number
* right
= get_number (e
->right
);
3703 value
= left
->value
&& right
->value
;
3705 else if ((left
&& !left
->value
) || (right
&& !right
->value
))
3707 // If the const is on the left, we get to short-circuit the right
3708 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3711 varuse_collecting_visitor
vu(session
);
3712 e
->left
->visit(&vu
);
3713 if (!vu
.side_effect_free())
3723 // We might also get rid of useless "1&&x" and "x&&1", except it does
3724 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3725 // that this would gain us much.
3733 if (session
.verbose
>2)
3734 clog
<< _("Collapsing constant logical-AND ") << *e
->tok
<< endl
;
3737 literal_number
* n
= new literal_number(value
);
3743 const_folder::visit_comparison (comparison
* e
)
3747 literal_number
*left_num
, *right_num
;
3748 literal_string
*left_str
, *right_str
;
3749 get_literal(e
->left
, left_num
, left_str
);
3750 get_literal(e
->right
, right_num
, right_str
);
3752 if (left_str
&& right_str
)
3753 comp
= left_str
->value
.compare(right_str
->value
);
3755 else if (left_num
&& right_num
)
3756 comp
= left_num
->value
< right_num
->value
? -1 :
3757 left_num
->value
> right_num
->value
? 1 : 0;
3759 else if ((left_num
&& ((left_num
->value
== LLONG_MIN
&&
3760 (e
->op
== "<=" || e
->op
== ">")) ||
3761 (left_num
->value
== LLONG_MAX
&&
3762 (e
->op
== ">=" || e
->op
== "<"))))
3764 (right_num
&& ((right_num
->value
== LLONG_MIN
&&
3765 (e
->op
== ">=" || e
->op
== "<")) ||
3766 (right_num
->value
== LLONG_MAX
&&
3767 (e
->op
== "<=" || e
->op
== ">")))))
3769 expression
* other
= left_num
? e
->right
: e
->left
;
3770 varuse_collecting_visitor
vu(session
);
3772 if (!vu
.side_effect_free())
3776 if (session
.verbose
>2)
3777 clog
<< _("Collapsing constant-boundary comparison ") << *e
->tok
<< endl
;
3780 // ops <= and >= are true, < and > are false
3781 literal_number
* n
= new literal_number( e
->op
.length() == 2 );
3794 if (session
.verbose
>2)
3795 clog
<< _("Collapsing constant comparison ") << *e
->tok
<< endl
;
3801 else if (e
->op
== "!=")
3803 else if (e
->op
== "<")
3805 else if (e
->op
== ">")
3807 else if (e
->op
== "<=")
3809 else if (e
->op
== ">=")
3812 throw semantic_error (_("unsupported comparison operator ") + e
->op
);
3814 literal_number
* n
= new literal_number(value
);
3820 const_folder::visit_concatenation (concatenation
* e
)
3822 literal_string
* left
= get_string (e
->left
);
3823 literal_string
* right
= get_string (e
->right
);
3827 if (session
.verbose
>2)
3828 clog
<< _("Collapsing constant concatenation ") << *e
->tok
<< endl
;
3831 literal_string
* n
= new literal_string (*left
);
3833 n
->value
.append(right
->value
);
3836 else if ((left
&& left
->value
.empty()) ||
3837 (right
&& right
->value
.empty()))
3839 if (session
.verbose
>2)
3840 clog
<< _("Collapsing identity concatenation ") << *e
->tok
<< endl
;
3842 provide(left
? e
->right
: e
->left
);
3849 const_folder::visit_ternary_expression (ternary_expression
* e
)
3851 literal_number
* cond
= get_number (e
->cond
);
3854 replace (e
->truevalue
);
3855 replace (e
->falsevalue
);
3860 if (session
.verbose
>2)
3861 clog
<< _F("Collapsing constant-%" PRIi64
" ternary %s",
3862 cond
->value
, lex_cast(*e
->tok
).c_str()) << endl
;
3865 expression
* n
= cond
->value
? e
->truevalue
: e
->falsevalue
;
3871 const_folder::visit_defined_op (defined_op
* e
)
3873 // If a @defined makes it this far, then it is, de facto, undefined.
3875 if (session
.verbose
>2)
3876 clog
<< _("Collapsing untouched @defined check ") << *e
->tok
<< endl
;
3879 literal_number
* n
= new literal_number (0);
3885 const_folder::visit_target_symbol (target_symbol
* e
)
3887 if (session
.skip_badvars
)
3889 // Upon user request for ignoring context, the symbol is replaced
3890 // with a literal 0 and a warning message displayed
3891 // XXX this ignores possible side-effects, e.g. in array indexes
3892 literal_number
* ln_zero
= new literal_number (0);
3893 ln_zero
->tok
= e
->tok
;
3895 session
.print_warning (_("Bad $context variable being substituted with literal 0"),
3900 update_visitor::visit_target_symbol (e
);
3903 static void semantic_pass_const_fold (systemtap_session
& s
, bool& relaxed_p
)
3905 // Let's simplify statements with constant values.
3907 const_folder
cf (s
, relaxed_p
);
3908 // This instance may be reused for multiple probe/function body trims.
3910 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
3911 cf
.replace (s
.probes
[i
]->body
);
3912 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
3913 it
!= s
.functions
.end(); it
++)
3914 cf
.replace (it
->second
->body
);
3918 struct duplicate_function_remover
: public functioncall_traversing_visitor
3920 systemtap_session
& s
;
3921 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
3923 duplicate_function_remover(systemtap_session
& sess
,
3924 map
<functiondecl
*, functiondecl
*>&dfm
):
3925 s(sess
), duplicate_function_map(dfm
) {};
3927 void visit_functioncall (functioncall
* e
);
3931 duplicate_function_remover::visit_functioncall (functioncall
*e
)
3933 functioncall_traversing_visitor::visit_functioncall (e
);
3935 // If the current function call reference points to a function that
3936 // is a duplicate, replace it.
3937 if (duplicate_function_map
.count(e
->referent
) != 0)
3940 clog
<< _F("Changing %s reference to %s reference\n",
3941 e
->referent
->name
.c_str(), duplicate_function_map
[e
->referent
]->name
.c_str());
3942 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
3943 e
->function
= duplicate_function_map
[e
->referent
]->name
;
3944 e
->referent
= duplicate_function_map
[e
->referent
];
3949 get_functionsig (functiondecl
* f
)
3953 // Get the "name:args body" of the function in s. We have to
3954 // include the args since the function 'x1(a, b)' is different than
3955 // the function 'x2(b, a)' even if the bodies of the two functions
3956 // are exactly the same.
3960 // printsig puts f->name + ':' on the front. Remove this
3961 // (otherwise, functions would never compare equal).
3962 string str
= s
.str().erase(0, f
->name
.size() + 1);
3964 // Return the function signature.
3968 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
3970 // Walk through all the functions, looking for duplicates.
3971 map
<string
, functiondecl
*> functionsig_map
;
3972 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
3975 vector
<functiondecl
*> newly_zapped_functions
;
3976 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
3978 functiondecl
*fd
= it
->second
;
3979 string functionsig
= get_functionsig(fd
);
3981 if (functionsig_map
.count(functionsig
) == 0)
3983 // This function is unique. Remember it.
3984 functionsig_map
[functionsig
] = fd
;
3988 // This function is a duplicate.
3989 duplicate_function_map
[fd
] = functionsig_map
[functionsig
];
3990 newly_zapped_functions
.push_back (fd
);
3994 for (unsigned i
=0; i
<newly_zapped_functions
.size(); i
++)
3996 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (newly_zapped_functions
[i
]->name
);
3997 assert (where
!= s
.functions
.end());
3998 s
.functions
.erase (where
);
4002 // If we have duplicate functions, traverse down the tree, replacing
4003 // the appropriate function calls.
4004 // duplicate_function_remover::visit_functioncall() handles the
4005 // details of replacing the function calls.
4006 if (duplicate_function_map
.size() != 0)
4008 duplicate_function_remover
dfr (s
, duplicate_function_map
);
4010 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
4011 s
.probes
[i
]->body
->visit(&dfr
);
4017 semantic_pass_optimize1 (systemtap_session
& s
)
4019 // In this pass, we attempt to rewrite probe/function bodies to
4020 // eliminate some blatantly unnecessary code. This is run before
4021 // type inference, but after symbol resolution and derived_probe
4022 // creation. We run an outer "relaxation" loop that repeats the
4023 // optimizations until none of them find anything to remove.
4027 // Save the old value of suppress_warnings, as we will be changing
4029 save_and_restore
<bool> suppress_warnings(& s
.suppress_warnings
);
4031 bool relaxed_p
= false;
4032 unsigned iterations
= 0;
4035 assert_no_interrupts();
4037 relaxed_p
= true; // until proven otherwise
4039 // If the verbosity is high enough, always print warnings (overrides -w),
4040 // or if not, always suppress warnings for every itteration after the first.
4042 s
.suppress_warnings
= false;
4043 else if (iterations
> 0)
4044 s
.suppress_warnings
= true;
4048 semantic_pass_opt1 (s
, relaxed_p
);
4049 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
4050 semantic_pass_opt3 (s
, relaxed_p
);
4051 semantic_pass_opt4 (s
, relaxed_p
);
4052 semantic_pass_opt5 (s
, relaxed_p
);
4055 // For listing mode, we need const-folding regardless of optimization so
4056 // that @defined expressions can be properly resolved. PR11360
4057 // We also want it in case variables are used in if/case expressions,
4058 // so enable always. PR11366
4059 semantic_pass_const_fold (s
, relaxed_p
);
4069 semantic_pass_optimize2 (systemtap_session
& s
)
4071 // This is run after type inference. We run an outer "relaxation"
4072 // loop that repeats the optimizations until none of them find
4073 // anything to remove.
4077 // Save the old value of suppress_warnings, as we will be changing
4079 save_and_restore
<bool> suppress_warnings(& s
.suppress_warnings
);
4081 bool relaxed_p
= false;
4082 unsigned iterations
= 0;
4085 assert_no_interrupts();
4086 relaxed_p
= true; // until proven otherwise
4088 // If the verbosity is high enough, always print warnings (overrides -w),
4089 // or if not, always suppress warnings for every itteration after the first.
4091 s
.suppress_warnings
= false;
4092 else if (iterations
> 0)
4093 s
.suppress_warnings
= true;
4096 semantic_pass_opt6 (s
, relaxed_p
);
4106 // ------------------------------------------------------------------------
4111 semantic_pass_types (systemtap_session
& s
)
4115 // next pass: type inference
4116 unsigned iterations
= 0;
4117 typeresolution_info
ti (s
);
4119 ti
.assert_resolvability
= false;
4120 // XXX: maybe convert to exception-based error signalling
4123 assert_no_interrupts();
4126 ti
.num_newly_resolved
= 0;
4127 ti
.num_still_unresolved
= 0;
4129 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
4131 assert_no_interrupts();
4133 functiondecl
* fd
= it
->second
;
4134 ti
.current_probe
= 0;
4135 ti
.current_function
= fd
;
4137 fd
->body
->visit (& ti
);
4138 // NB: we don't have to assert a known type for
4139 // functions here, to permit a "void" function.
4140 // The translator phase will omit the "retvalue".
4142 // if (fd->type == pe_unknown)
4143 // ti.unresolved (fd->tok);
4144 for (unsigned i
=0; i
< fd
->locals
.size(); ++i
)
4145 ti
.check_local (fd
->locals
[i
]);
4148 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
4150 assert_no_interrupts();
4152 derived_probe
* pn
= s
.probes
[j
];
4153 ti
.current_function
= 0;
4154 ti
.current_probe
= pn
;
4156 pn
->body
->visit (& ti
);
4157 for (unsigned i
=0; i
< pn
->locals
.size(); ++i
)
4158 ti
.check_local (pn
->locals
[i
]);
4160 probe_point
* pp
= pn
->sole_location();
4163 ti
.current_function
= 0;
4164 ti
.current_probe
= 0;
4165 ti
.t
= pe_long
; // NB: expected type
4166 pp
->condition
->visit (& ti
);
4170 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
4172 vardecl
* gd
= s
.globals
[j
];
4173 if (gd
->type
== pe_unknown
)
4174 ti
.unresolved (gd
->tok
);
4175 if(gd
->arity
== 0 && gd
->wrap
== true)
4177 throw semantic_error (_("wrapping not supported for scalars"), gd
->tok
);
4181 if (ti
.num_newly_resolved
== 0) // converged
4183 if (ti
.num_still_unresolved
== 0)
4184 break; // successfully
4185 else if (! ti
.assert_resolvability
)
4186 ti
.assert_resolvability
= true; // last pass, with error msgs
4188 { // unsuccessful conclusion
4195 return rc
+ s
.num_errors();
4200 typeresolution_info::typeresolution_info (systemtap_session
& s
):
4201 session(s
), num_newly_resolved(0), num_still_unresolved(0),
4202 assert_resolvability(false), current_function(0), current_probe(0),
4209 typeresolution_info::visit_literal_number (literal_number
* e
)
4211 assert (e
->type
== pe_long
);
4212 if ((t
== e
->type
) || (t
== pe_unknown
))
4215 mismatch (e
->tok
, e
->type
, t
);
4220 typeresolution_info::visit_literal_string (literal_string
* e
)
4222 assert (e
->type
== pe_string
);
4223 if ((t
== e
->type
) || (t
== pe_unknown
))
4226 mismatch (e
->tok
, e
->type
, t
);
4231 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
4233 visit_binary_expression (e
);
4238 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
4240 visit_binary_expression (e
);
4244 typeresolution_info::visit_regex_query (regex_query
*e
)
4246 // NB: result of regex query is an integer!
4247 if (t
== pe_stats
|| t
== pe_string
)
4248 invalid (e
->tok
, t
);
4251 e
->left
->visit (this);
4253 e
->right
->visit (this); // parser ensures this is a literal known at compile time
4255 if (e
->type
== pe_unknown
)
4258 resolved (e
->tok
, e
->type
);
4264 typeresolution_info::visit_comparison (comparison
*e
)
4266 // NB: result of any comparison is an integer!
4267 if (t
== pe_stats
|| t
== pe_string
)
4268 invalid (e
->tok
, t
);
4270 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
4271 e
->left
->visit (this);
4272 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
4273 e
->right
->visit (this);
4275 if (e
->left
->type
!= pe_unknown
&&
4276 e
->right
->type
!= pe_unknown
&&
4277 e
->left
->type
!= e
->right
->type
)
4278 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
4280 if (e
->type
== pe_unknown
)
4283 resolved (e
->tok
, e
->type
);
4289 typeresolution_info::visit_concatenation (concatenation
*e
)
4291 if (t
!= pe_unknown
&& t
!= pe_string
)
4292 invalid (e
->tok
, t
);
4295 e
->left
->visit (this);
4297 e
->right
->visit (this);
4299 if (e
->type
== pe_unknown
)
4301 e
->type
= pe_string
;
4302 resolved (e
->tok
, e
->type
);
4308 typeresolution_info::visit_assignment (assignment
*e
)
4311 invalid (e
->tok
, t
);
4313 if (e
->op
== "<<<") // stats aggregation
4316 invalid (e
->tok
, t
);
4319 e
->left
->visit (this);
4321 e
->right
->visit (this);
4322 if (e
->type
== pe_unknown
||
4323 e
->type
== pe_stats
)
4326 resolved (e
->tok
, e
->type
);
4330 else if (e
->left
->type
== pe_stats
)
4331 invalid (e
->left
->tok
, e
->left
->type
);
4333 else if (e
->right
->type
== pe_stats
)
4334 invalid (e
->right
->tok
, e
->right
->type
);
4336 else if (e
->op
== "+=" || // numeric only
4348 visit_binary_expression (e
);
4350 else if (e
->op
== ".=" || // string only
4353 if (t
== pe_long
|| t
== pe_stats
)
4354 invalid (e
->tok
, t
);
4357 e
->left
->visit (this);
4359 e
->right
->visit (this);
4360 if (e
->type
== pe_unknown
)
4362 e
->type
= pe_string
;
4363 resolved (e
->tok
, e
->type
);
4366 else if (e
->op
== "=") // overloaded = for string & numeric operands
4368 // logic similar to ternary_expression
4369 exp_type sub_type
= t
;
4371 // Infer types across the l/r values
4372 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
4375 t
= (sub_type
!= pe_unknown
) ? sub_type
:
4376 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
4378 e
->left
->visit (this);
4379 t
= (sub_type
!= pe_unknown
) ? sub_type
:
4380 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
4382 e
->right
->visit (this);
4384 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
4387 resolved (e
->tok
, e
->type
);
4389 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
4391 e
->type
= e
->left
->type
;
4392 resolved (e
->tok
, e
->type
);
4395 if (e
->left
->type
!= pe_unknown
&&
4396 e
->right
->type
!= pe_unknown
&&
4397 e
->left
->type
!= e
->right
->type
)
4398 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
4402 throw semantic_error (_("unsupported assignment operator ") + e
->op
);
4407 typeresolution_info::visit_embedded_expr (embedded_expr
*e
)
4409 if (e
->type
== pe_unknown
)
4411 if (e
->code
.find ("/* string */") != string::npos
)
4412 e
->type
= pe_string
;
4413 else // if (e->code.find ("/* long */") != string::npos)
4416 resolved (e
->tok
, e
->type
);
4422 typeresolution_info::visit_binary_expression (binary_expression
* e
)
4424 if (t
== pe_stats
|| t
== pe_string
)
4425 invalid (e
->tok
, t
);
4428 e
->left
->visit (this);
4430 e
->right
->visit (this);
4432 if (e
->left
->type
!= pe_unknown
&&
4433 e
->right
->type
!= pe_unknown
&&
4434 e
->left
->type
!= e
->right
->type
)
4435 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
4437 if (e
->type
== pe_unknown
)
4440 resolved (e
->tok
, e
->type
);
4446 typeresolution_info::visit_pre_crement (pre_crement
*e
)
4448 visit_unary_expression (e
);
4453 typeresolution_info::visit_post_crement (post_crement
*e
)
4455 visit_unary_expression (e
);
4460 typeresolution_info::visit_unary_expression (unary_expression
* e
)
4462 if (t
== pe_stats
|| t
== pe_string
)
4463 invalid (e
->tok
, t
);
4466 e
->operand
->visit (this);
4468 if (e
->type
== pe_unknown
)
4471 resolved (e
->tok
, e
->type
);
4477 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
4479 exp_type sub_type
= t
;
4482 e
->cond
->visit (this);
4484 // Infer types across the true/false arms of the ternary expression.
4486 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
4489 e
->truevalue
->visit (this);
4491 e
->falsevalue
->visit (this);
4493 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
4494 ; // already resolved
4495 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
4498 resolved (e
->tok
, e
->type
);
4500 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
4502 e
->type
= e
->truevalue
->type
;
4503 resolved (e
->tok
, e
->type
);
4505 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
4507 e
->type
= e
->falsevalue
->type
;
4508 resolved (e
->tok
, e
->type
);
4510 else if (e
->type
!= sub_type
)
4511 mismatch (e
->tok
, sub_type
, e
->type
);
4515 template <class Referrer
, class Referent
>
4516 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
4517 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
4519 exp_type
& re_type
= referrer
->type
;
4520 const token
* re_tok
= referrer
->tok
;
4521 exp_type
& te_type
= referent
->type
;
4522 const token
* te_tok
= referent
->tok
;
4524 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
4525 ; // do nothing: all three e->types in agreement
4526 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
4527 ; // do nothing: two known e->types in agreement
4528 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
4529 r
->mismatch (re_tok
, re_type
, te_type
);
4530 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
4531 r
->mismatch (re_tok
, re_type
, t
);
4532 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
4533 r
->mismatch (te_tok
, te_type
, t
);
4534 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
4536 // propagate from upstream
4538 r
->resolved (re_tok
, re_type
);
4539 // catch re_type/te_type mismatch later
4541 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
4543 // propagate from referent
4545 r
->resolved (re_tok
, re_type
);
4546 // catch re_type/t mismatch later
4548 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
4550 // propagate to referent
4552 r
->resolved (te_tok
, te_type
);
4553 // catch re_type/t mismatch later
4555 else if (! accept_unknown
)
4556 r
->unresolved (re_tok
);
4561 typeresolution_info::visit_symbol (symbol
* e
)
4563 assert (e
->referent
!= 0);
4564 resolve_2types (e
, e
->referent
, this, t
);
4569 typeresolution_info::visit_target_symbol (target_symbol
* e
)
4571 // This occurs only if a target symbol was not resolved over in
4572 // tapset.cxx land, that error was properly suppressed, and the
4573 // later unused-expression-elimination pass didn't get rid of it
4574 // either. So we have a target symbol that is believed to be of
4575 // genuine use, yet unresolved by the provider.
4577 if (session
.verbose
> 2)
4579 clog
<< _("Resolution problem with ");
4580 if (current_function
)
4582 clog
<< "function " << current_function
->name
<< endl
;
4583 current_function
->body
->print (clog
);
4586 else if (current_probe
)
4588 clog
<< "probe " << *current_probe
->sole_location() << endl
;
4589 current_probe
->body
->print (clog
);
4593 //TRANSLATORS: simply saying not an issue with a probe or function
4594 clog
<< _("other") << endl
;
4597 if (e
->saved_conversion_error
)
4598 throw (* (e
->saved_conversion_error
));
4600 throw semantic_error(_("unresolved target-symbol expression"), e
->tok
);
4605 typeresolution_info::visit_atvar_op (atvar_op
* e
)
4607 // This occurs only if an @var() was not resolved over in
4608 // tapset.cxx land, that error was properly suppressed, and the
4609 // later unused-expression-elimination pass didn't get rid of it
4610 // either. So we have an @var() that is believed to be of
4611 // genuine use, yet unresolved by the provider.
4613 if (session
.verbose
> 2)
4615 clog
<< _("Resolution problem with ");
4616 if (current_function
)
4618 clog
<< "function " << current_function
->name
<< endl
;
4619 current_function
->body
->print (clog
);
4622 else if (current_probe
)
4624 clog
<< "probe " << *current_probe
->sole_location() << endl
;
4625 current_probe
->body
->print (clog
);
4629 //TRANSLATORS: simply saying not an issue with a probe or function
4630 clog
<< _("other") << endl
;
4633 if (e
->saved_conversion_error
)
4634 throw (* (e
->saved_conversion_error
));
4636 throw semantic_error(_("unresolved @var() expression"), e
->tok
);
4641 typeresolution_info::visit_defined_op (defined_op
* e
)
4643 throw semantic_error(_("unexpected @defined"), e
->tok
);
4648 typeresolution_info::visit_entry_op (entry_op
* e
)
4650 throw semantic_error(_("@entry is only valid in .return probes"), e
->tok
);
4655 typeresolution_info::visit_cast_op (cast_op
* e
)
4657 // Like target_symbol, a cast_op shouldn't survive this far
4658 // unless it was not resolved and its value is really needed.
4659 if (e
->saved_conversion_error
)
4660 throw (* (e
->saved_conversion_error
));
4662 throw semantic_error(_F("type definition '%s' not found in '%s'",
4663 e
->type_name
.c_str(), e
->module
.c_str()), e
->tok
);
4668 typeresolution_info::visit_perf_op (perf_op
* e
)
4670 // A perf_op should already be resolved
4671 if (t
== pe_stats
|| t
== pe_string
)
4672 invalid (e
->tok
, t
);
4676 // (There is no real need to visit our operand - by parser
4677 // construction, it's always a string literal, with its type already
4680 e
->operand
->visit (this);
4685 typeresolution_info::visit_arrayindex (arrayindex
* e
)
4688 symbol
*array
= NULL
;
4689 hist_op
*hist
= NULL
;
4690 classify_indexable(e
->base
, array
, hist
);
4692 // Every hist_op has type [int]:int, that is to say, every hist_op
4693 // is a pseudo-one-dimensional integer array type indexed by
4694 // integers (bucket numbers).
4698 if (e
->indexes
.size() != 1)
4699 unresolved (e
->tok
);
4701 e
->indexes
[0]->visit (this);
4702 if (e
->indexes
[0]->type
!= pe_long
)
4703 unresolved (e
->tok
);
4705 if (e
->type
!= pe_long
)
4708 resolved (e
->tok
, pe_long
);
4713 // Now we are left with "normal" map inference and index checking.
4716 assert (array
->referent
!= 0);
4717 resolve_2types (e
, array
->referent
, this, t
);
4719 // now resolve the array indexes
4721 // if (e->referent->index_types.size() == 0)
4722 // // redesignate referent as array
4723 // e->referent->set_arity (e->indexes.size ());
4725 if (e
->indexes
.size() != array
->referent
->index_types
.size())
4726 unresolved (e
->tok
); // symbol resolution should prevent this
4727 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
4729 expression
* ee
= e
->indexes
[i
];
4730 exp_type
& ft
= array
->referent
->index_types
[i
];
4733 exp_type at
= ee
->type
;
4735 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
4737 // propagate to formal type
4739 resolved (array
->referent
->tok
, ft
);
4740 // uses array decl as there is no token for "formal type"
4743 invalid (ee
->tok
, at
);
4745 invalid (ee
->tok
, ft
);
4746 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4747 mismatch (e
->tok
, at
, ft
);
4748 if (at
== pe_unknown
)
4749 unresolved (ee
->tok
);
4755 typeresolution_info::visit_functioncall (functioncall
* e
)
4757 assert (e
->referent
!= 0);
4759 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
4761 if (e
->type
== pe_stats
)
4762 invalid (e
->tok
, e
->type
);
4764 // now resolve the function parameters
4765 if (e
->args
.size() != e
->referent
->formal_args
.size())
4766 unresolved (e
->tok
); // symbol resolution should prevent this
4767 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
4769 expression
* ee
= e
->args
[i
];
4770 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
4771 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
4774 exp_type at
= ee
->type
;
4776 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
4778 // propagate to formal arg
4780 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
4783 invalid (e
->tok
, at
);
4785 invalid (fe_tok
, ft
);
4786 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4787 mismatch (e
->tok
, at
, ft
);
4788 if (at
== pe_unknown
)
4789 unresolved (e
->tok
);
4795 typeresolution_info::visit_block (block
* e
)
4797 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
4802 e
->statements
[i
]->visit (this);
4804 catch (const semantic_error
& e
)
4806 session
.print_error (e
);
4813 typeresolution_info::visit_try_block (try_block
* e
)
4816 e
->try_block
->visit (this);
4817 if (e
->catch_error_var
)
4820 e
->catch_error_var
->visit (this);
4823 e
->catch_block
->visit (this);
4828 typeresolution_info::visit_embeddedcode (embeddedcode
* s
)
4830 // PR11573. If we have survived thus far with a piece of embedded
4831 // code that requires uprobes, we need to track this.
4833 // This is an odd place for this check, as opposed
4834 // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
4835 // over yonder in pass 3. However, we want to do it during pass 2 so
4836 // that cached sessions also get the uprobes treatment.
4837 if (! session
.need_uprobes
4838 && s
->code
.find("/* pragma:uprobes */") != string::npos
)
4840 if (session
.verbose
> 2)
4841 clog
<< _("Activating uprobes support because /* pragma:uprobes */ seen.") << endl
;
4842 session
.need_uprobes
= true;
4845 // PR15065. Likewise, we need to detect /* pragma:tagged_dfa */
4846 // before the gen_dfa_table pass. Again, the typechecking part of
4847 // pass 2 is a good place for this.
4848 if (! session
.need_tagged_dfa
4849 && s
->code
.find("/* pragma:tagged_dfa */") != string::npos
)
4851 // if (session.verbose > 2)
4852 // clog << _F("Turning on DFA subexpressions, pragma:tagged_dfa found in %s",
4853 // current_function->name.c_str()) << endl;
4854 // session.need_tagged_dfa = true;
4855 throw semantic_error (_("Tagged DFA support is not yet available"), s
->tok
);
4861 typeresolution_info::visit_if_statement (if_statement
* e
)
4864 e
->condition
->visit (this);
4867 e
->thenblock
->visit (this);
4872 e
->elseblock
->visit (this);
4878 typeresolution_info::visit_for_loop (for_loop
* e
)
4881 if (e
->init
) e
->init
->visit (this);
4883 e
->cond
->visit (this);
4885 if (e
->incr
) e
->incr
->visit (this);
4887 e
->block
->visit (this);
4892 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
4894 // See also visit_arrayindex.
4895 // This is different in that, being a statement, we can't assign
4896 // a type to the outer array, only propagate to/from the indexes
4898 // if (e->referent->index_types.size() == 0)
4899 // // redesignate referent as array
4900 // e->referent->set_arity (e->indexes.size ());
4902 exp_type wanted_value
= pe_unknown
;
4903 symbol
*array
= NULL
;
4904 hist_op
*hist
= NULL
;
4905 classify_indexable(e
->base
, array
, hist
);
4909 if (e
->indexes
.size() != 1)
4910 unresolved (e
->tok
);
4912 e
->indexes
[0]->visit (this);
4913 if (e
->indexes
[0]->type
!= pe_long
)
4914 unresolved (e
->tok
);
4916 wanted_value
= pe_long
;
4921 if (e
->indexes
.size() != array
->referent
->index_types
.size())
4922 unresolved (e
->tok
); // symbol resolution should prevent this
4923 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
4925 expression
* ee
= e
->indexes
[i
];
4926 exp_type
& ft
= array
->referent
->index_types
[i
];
4929 exp_type at
= ee
->type
;
4931 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
4933 // propagate to formal type
4935 resolved (array
->referent
->tok
, ft
);
4936 // uses array decl as there is no token for "formal type"
4939 invalid (ee
->tok
, at
);
4941 invalid (ee
->tok
, ft
);
4942 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4943 mismatch (e
->tok
, at
, ft
);
4944 if (at
== pe_unknown
)
4945 unresolved (ee
->tok
);
4948 array
->visit (this);
4949 wanted_value
= array
->type
;
4954 if (wanted_value
== pe_stats
)
4955 invalid(e
->value
->tok
, wanted_value
);
4956 else if (wanted_value
!= pe_unknown
)
4957 check_arg_type(wanted_value
, e
->value
);
4961 e
->value
->visit (this);
4965 /* Prevent @sum etc. aggregate sorting on non-statistics arrays. */
4966 if (wanted_value
!= pe_unknown
)
4967 if (e
->sort_aggr
!= sc_none
&& wanted_value
!= pe_stats
)
4968 invalid (array
->tok
, wanted_value
);
4973 e
->limit
->visit (this);
4977 e
->block
->visit (this);
4982 typeresolution_info::visit_null_statement (null_statement
*)
4988 typeresolution_info::visit_expr_statement (expr_statement
* e
)
4991 e
->value
->visit (this);
4995 struct delete_statement_typeresolution_info
:
4996 public throwing_visitor
4998 typeresolution_info
*parent
;
4999 delete_statement_typeresolution_info (typeresolution_info
*p
):
5000 throwing_visitor (_("invalid operand of delete expression")),
5004 void visit_arrayindex (arrayindex
* e
)
5006 parent
->visit_arrayindex (e
);
5009 void visit_symbol (symbol
* e
)
5011 exp_type ignored
= pe_unknown
;
5012 assert (e
->referent
!= 0);
5013 resolve_2types (e
, e
->referent
, parent
, ignored
);
5019 typeresolution_info::visit_delete_statement (delete_statement
* e
)
5021 delete_statement_typeresolution_info
di (this);
5023 e
->value
->visit (&di
);
5028 typeresolution_info::visit_next_statement (next_statement
*)
5034 typeresolution_info::visit_break_statement (break_statement
*)
5040 typeresolution_info::visit_continue_statement (continue_statement
*)
5046 typeresolution_info::visit_array_in (array_in
* e
)
5048 // all unary operators only work on numerics
5050 t
= pe_unknown
; // array value can be anything
5051 e
->operand
->visit (this);
5053 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
5054 ; // already resolved
5055 else if (t1
== pe_string
|| t1
== pe_stats
)
5056 mismatch (e
->tok
, t1
, pe_long
);
5057 else if (e
->type
== pe_unknown
)
5060 resolved (e
->tok
, e
->type
);
5066 typeresolution_info::visit_return_statement (return_statement
* e
)
5068 // This is like symbol, where the referent is
5069 // the return value of the function.
5071 // translation pass will print error
5072 if (current_function
== 0)
5075 exp_type
& e_type
= current_function
->type
;
5076 t
= current_function
->type
;
5077 e
->value
->visit (this);
5079 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
5080 && e_type
!= e
->value
->type
)
5081 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
5082 if (e_type
== pe_unknown
&&
5083 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
5085 // propagate non-statistics from value
5086 e_type
= e
->value
->type
;
5087 resolved (current_function
->tok
, e
->value
->type
);
5089 if (e
->value
->type
== pe_stats
)
5090 invalid (e
->value
->tok
, e
->value
->type
);
5094 typeresolution_info::visit_print_format (print_format
* e
)
5096 size_t unresolved_args
= 0;
5100 e
->hist
->visit(this);
5103 else if (e
->print_with_format
)
5105 // If there's a format string, we can do both inference *and*
5108 // First we extract the subsequence of formatting components
5109 // which are conversions (not just literal string components)
5111 unsigned expected_num_args
= 0;
5112 std::vector
<print_format::format_component
> components
;
5113 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
5115 if (e
->components
[i
].type
== print_format::conv_unspecified
)
5116 throw semantic_error (_("Unspecified conversion in print operator format string"),
5118 else if (e
->components
[i
].type
== print_format::conv_literal
)
5120 components
.push_back(e
->components
[i
]);
5121 ++expected_num_args
;
5122 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
5123 ++expected_num_args
;
5124 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
5125 ++expected_num_args
;
5128 // Then we check that the number of conversions and the number
5131 if (expected_num_args
!= e
->args
.size())
5132 throw semantic_error (_("Wrong number of args to formatted print operator"),
5135 // Then we check that the types of the conversions match the types
5138 for (size_t i
= 0; i
< components
.size(); ++i
)
5140 // Check the dynamic width, if specified
5141 if (components
[i
].widthtype
== print_format::width_dynamic
)
5143 check_arg_type (pe_long
, e
->args
[argno
]);
5147 // Check the dynamic precision, if specified
5148 if (components
[i
].prectype
== print_format::prec_dynamic
)
5150 check_arg_type (pe_long
, e
->args
[argno
]);
5154 exp_type wanted
= pe_unknown
;
5156 switch (components
[i
].type
)
5158 case print_format::conv_unspecified
:
5159 case print_format::conv_literal
:
5163 case print_format::conv_pointer
:
5164 case print_format::conv_number
:
5165 case print_format::conv_binary
:
5166 case print_format::conv_char
:
5167 case print_format::conv_memory
:
5168 case print_format::conv_memory_hex
:
5172 case print_format::conv_string
:
5177 assert (wanted
!= pe_unknown
);
5178 check_arg_type (wanted
, e
->args
[argno
]);
5184 // Without a format string, the best we can do is require that
5185 // each argument resolve to a concrete type.
5186 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
5189 e
->args
[i
]->visit (this);
5190 if (e
->args
[i
]->type
== pe_unknown
)
5192 unresolved (e
->args
[i
]->tok
);
5198 if (unresolved_args
== 0)
5200 if (e
->type
== pe_unknown
)
5202 if (e
->print_to_stream
)
5205 e
->type
= pe_string
;
5206 resolved (e
->tok
, e
->type
);
5211 e
->type
= pe_unknown
;
5212 unresolved (e
->tok
);
5218 typeresolution_info::visit_stat_op (stat_op
* e
)
5221 e
->stat
->visit (this);
5222 if (e
->type
== pe_unknown
)
5225 resolved (e
->tok
, e
->type
);
5227 else if (e
->type
!= pe_long
)
5228 mismatch (e
->tok
, e
->type
, pe_long
);
5232 typeresolution_info::visit_hist_op (hist_op
* e
)
5235 e
->stat
->visit (this);
5240 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
5245 if (arg
->type
== pe_unknown
)
5248 resolved (arg
->tok
, wanted
);
5250 else if (arg
->type
!= wanted
)
5252 mismatch (arg
->tok
, arg
->type
, wanted
);
5258 typeresolution_info::check_local (vardecl
* v
)
5262 num_still_unresolved
++;
5263 if (assert_resolvability
)
5265 (semantic_error (_("array locals not supported, missing global declaration? "), v
->tok
));
5268 if (v
->type
== pe_unknown
)
5269 unresolved (v
->tok
);
5270 else if (v
->type
== pe_stats
)
5272 num_still_unresolved
++;
5273 if (assert_resolvability
)
5275 (semantic_error (_("stat locals not supported, missing global declaration? "), v
->tok
));
5277 else if (!(v
->type
== pe_long
|| v
->type
== pe_string
))
5278 invalid (v
->tok
, v
->type
);
5283 typeresolution_info::unresolved (const token
* tok
)
5285 num_still_unresolved
++;
5287 if (assert_resolvability
)
5290 msg
<< _("unresolved type ");
5291 session
.print_error (semantic_error (msg
.str(), tok
));
5297 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
5299 num_still_unresolved
++;
5301 if (assert_resolvability
)
5304 if (tok
&& tok
->type
== tok_operator
)
5305 msg
<< _("invalid operator");
5307 msg
<< _("invalid type ") << pe
;
5308 session
.print_error (semantic_error (msg
.str(), tok
));
5314 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
5316 bool tok_resolved
= false;
5318 semantic_error
* err1
= 0;
5319 num_still_unresolved
++;
5321 //BZ 9719: for improving type mismatch messages, a semantic error is
5322 //generated with the token where type was first resolved. All such
5323 //resolved tokens, stored in a vector, are matched against their
5324 //content. If an error for the matching token hasn't been printed out
5325 //already, it is and the token pushed in another printed_toks vector
5327 if (assert_resolvability
)
5330 for (i
=0; i
<resolved_toks
.size(); i
++)
5332 if (resolved_toks
[i
]->content
== tok
->content
)
5334 tok_resolved
= true;
5340 msg
<< _F("type mismatch (%s vs. %s)",
5341 lex_cast(t1
).c_str(), lex_cast(t2
).c_str());
5345 bool tok_printed
= false;
5346 for (size_t j
=0; j
<printed_toks
.size(); j
++)
5348 if (printed_toks
[j
] == resolved_toks
[i
])
5354 msg
<< _F("type mismatch (%s vs. %s)",
5355 lex_cast(t1
).c_str(), lex_cast(t2
).c_str());
5358 //error for possible mismatch in the earlier resolved token
5359 printed_toks
.push_back (resolved_toks
[i
]);
5360 stringstream type_msg
;
5361 type_msg
<< _F("type was first inferred here (%s)", lex_cast(t2
).c_str());
5362 err1
= new semantic_error (type_msg
.str(), resolved_toks
[i
]);
5365 semantic_error
err (msg
.str(), tok
);
5367 session
.print_error (err
);
5373 typeresolution_info::resolved (const token
* tok
, exp_type
)
5375 resolved_toks
.push_back (tok
);
5376 num_newly_resolved
++;
5379 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */