1 // elaboration functions
2 // Copyright (C) 2005-2010 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"
20 #include <sys/utsname.h>
38 // ------------------------------------------------------------------------
40 // Used in probe_point condition construction. Either argument may be
41 // NULL; if both, return NULL too. Resulting expression is a deep
42 // copy for symbol resolution purposes.
43 expression
* add_condition (expression
* a
, expression
* b
)
45 if (!a
&& !b
) return 0;
46 if (! a
) return deep_copy_visitor::deep_copy(b
);
47 if (! b
) return deep_copy_visitor::deep_copy(a
);
52 la
.tok
= a
->tok
; // or could be b->tok
53 return deep_copy_visitor::deep_copy(& la
);
56 // ------------------------------------------------------------------------
60 derived_probe::derived_probe (probe
*p
):
61 base (p
), sdt_semaphore_addr(0)
64 this->locations
= p
->locations
;
66 this->privileged
= p
->privileged
;
67 this->body
= deep_copy_visitor::deep_copy(p
->body
);
71 derived_probe::derived_probe (probe
*p
, probe_point
*l
):
72 base (p
), sdt_semaphore_addr(0)
76 this->privileged
= p
->privileged
;
77 this->body
= deep_copy_visitor::deep_copy(p
->body
);
80 this->locations
.push_back (l
);
85 derived_probe::printsig (ostream
& o
) const
92 derived_probe::printsig_nested (ostream
& o
) const
94 // We'd like to enclose the probe derivation chain in a /* */
95 // comment delimiter. But just printing /* base->printsig() */ is
96 // not enough, since base might itself be a derived_probe. So we,
97 // er, "cleverly" encode our nesting state as a formatting flag for
99 ios::fmtflags f
= o
.flags (ios::internal
);
100 if (f
& ios::internal
)
119 derived_probe::collect_derivation_chain (std::vector
<probe
*> &probes_list
)
121 probes_list
.push_back(this);
122 base
->collect_derivation_chain(probes_list
);
127 derived_probe::sole_location () const
129 if (locations
.size() == 0)
130 throw semantic_error ("derived_probe with no locations", this->tok
);
131 else if (locations
.size() > 1)
132 throw semantic_error ("derived_probe with too many locations", this->tok
);
139 derived_probe::script_location () const
141 const probe
* p
= almost_basest();
142 const probe_alias
*a
= p
->get_alias();
143 const vector
<probe_point
*>& locs
= a
? a
->alias_names
: p
->locations
;
144 if (locs
.size() == 0)
145 throw semantic_error ("derived_probe with no locations", this->tok
);
146 else if (locs
.size() > 1)
147 throw semantic_error ("derived_probe with too many locations", this->tok
);
154 derived_probe::emit_unprivileged_assertion (translator_output
* o
)
156 // Emit code which will cause compilation to fail if it is compiled in
157 // unprivileged mode.
158 o
->newline() << "#ifndef STP_PRIVILEGED";
159 o
->newline() << "#error Internal Error: Probe ";
160 probe::printsig (o
->line());
161 o
->line() << " generated in --unprivileged mode";
162 o
->newline() << "#endif";
167 derived_probe::emit_process_owner_assertion (translator_output
* o
)
169 // Emit code which will abort should the current target not belong to the
170 // user in unprivileged mode.
171 o
->newline() << "#ifndef STP_PRIVILEGED";
172 o
->newline(1) << "if (! is_myproc ()) {";
173 o
->newline(1) << "snprintf(c->error_buffer, sizeof(c->error_buffer),";
174 o
->newline() << " \"Internal Error: Process %d does not belong to user %d in probe %s in --unprivileged mode\",";
175 o
->newline() << " current->tgid, _stp_uid, c->probe_point);";
176 o
->newline() << "c->last_error = c->error_buffer;";
177 // NB: since this check occurs before probe locking, its exit should
178 // not be a "goto out", which would attempt unlocking.
179 o
->newline() << "return;";
180 o
->newline(-1) << "}";
181 o
->newline(-1) << "#endif";
185 derived_probe::print_dupe_stamp_unprivileged(ostream
& o
)
187 o
<< "unprivileged users: authorized" << endl
;
191 derived_probe::print_dupe_stamp_unprivileged_process_owner(ostream
& o
)
193 o
<< "unprivileged users: authorized for process owner" << endl
;
196 // ------------------------------------------------------------------------
197 // Members of derived_probe_builder
200 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
201 const std::string
& key
,
204 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
205 if (i
== params
.end())
207 literal_string
* ls
= dynamic_cast<literal_string
*>(i
->second
);
216 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
217 const std::string
& key
,
220 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
221 if (i
== params
.end())
223 if (i
->second
== NULL
)
225 literal_number
* ln
= dynamic_cast<literal_number
*>(i
->second
);
234 derived_probe_builder::has_null_param (std::map
<std::string
, literal
*> const & params
,
235 const std::string
& key
)
237 map
<string
, literal
*>::const_iterator i
= params
.find(key
);
238 return (i
!= params
.end() && i
->second
== NULL
);
243 // ------------------------------------------------------------------------
244 // Members of match_key.
246 match_key::match_key(string
const & n
)
248 have_parameter(false),
249 parameter_type(pe_unknown
)
253 match_key::match_key(probe_point::component
const & c
)
255 have_parameter(c
.arg
!= NULL
),
256 parameter_type(c
.arg
? c
.arg
->type
: pe_unknown
)
261 match_key::with_number()
263 have_parameter
= true;
264 parameter_type
= pe_long
;
269 match_key::with_string()
271 have_parameter
= true;
272 parameter_type
= pe_string
;
277 match_key::str() const
280 switch (parameter_type
)
282 case pe_string
: return name
+ "(string)";
283 case pe_long
: return name
+ "(number)";
284 default: return name
+ "(...)";
290 match_key::operator<(match_key
const & other
) const
292 return ((name
< other
.name
)
294 || (name
== other
.name
295 && have_parameter
< other
.have_parameter
)
297 || (name
== other
.name
298 && have_parameter
== other
.have_parameter
299 && parameter_type
< other
.parameter_type
));
303 isglob(string
const & str
)
305 return(str
.find('*') != str
.npos
);
309 isdoubleglob(string
const & str
)
311 return(str
.find("**") != str
.npos
);
315 match_key::globmatch(match_key
const & other
) const
317 const char *other_str
= other
.name
.c_str();
318 const char *name_str
= name
.c_str();
320 return ((fnmatch(name_str
, other_str
, FNM_NOESCAPE
) == 0)
321 && have_parameter
== other
.have_parameter
322 && parameter_type
== other
.parameter_type
);
325 // ------------------------------------------------------------------------
326 // Members of match_node
327 // ------------------------------------------------------------------------
329 match_node::match_node() :
330 unprivileged_ok(false)
335 match_node::bind(match_key
const & k
)
338 throw semantic_error("invalid use of wildcard probe point component");
340 map
<match_key
, match_node
*>::const_iterator i
= sub
.find(k
);
343 match_node
* n
= new match_node();
344 sub
.insert(make_pair(k
, n
));
349 match_node::bind(derived_probe_builder
* e
)
355 match_node::bind(string
const & k
)
357 return bind(match_key(k
));
361 match_node::bind_str(string
const & k
)
363 return bind(match_key(k
).with_string());
367 match_node::bind_num(string
const & k
)
369 return bind(match_key(k
).with_number());
373 match_node::bind_unprivileged(bool b
)
380 match_node::find_and_build (systemtap_session
& s
,
381 probe
* p
, probe_point
*loc
, unsigned pos
,
382 vector
<derived_probe
*>& results
)
384 assert (pos
<= loc
->components
.size());
385 if (pos
== loc
->components
.size()) // matched all probe point components so far
390 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
391 alternatives
+= string(" ") + i
->first
.str();
393 throw semantic_error (string("probe point truncated at position ") +
395 " (follow:" + alternatives
+ ")", loc
->components
.back()->tok
);
398 if (s
.unprivileged
&& ! unprivileged_ok
)
400 throw semantic_error (string("probe point is not allowed for unprivileged users"),
401 loc
->components
.back()->tok
);
404 map
<string
, literal
*> param_map
;
405 for (unsigned i
=0; i
<pos
; i
++)
406 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
409 // Iterate over all bound builders
410 for (unsigned k
=0; k
<ends
.size(); k
++)
412 derived_probe_builder
*b
= ends
[k
];
413 b
->build (s
, p
, loc
, param_map
, results
);
416 else if (isdoubleglob(loc
->components
[pos
]->functor
)) // ** wildcard?
418 unsigned int num_results
= results
.size();
420 // When faced with "foo**bar", we try "foo*bar" and "foo*.**bar"
422 const probe_point::component
*comp
= loc
->components
[pos
];
423 const string
&functor
= comp
->functor
;
424 size_t glob_start
= functor
.find("**");
425 size_t glob_end
= functor
.find_first_not_of('*', glob_start
);
426 const string prefix
= functor
.substr(0, glob_start
);
427 const string suffix
= ((glob_end
!= string::npos
) ?
428 functor
.substr(glob_end
) : "");
430 // Synthesize "foo*bar"
431 probe_point
*simple_pp
= new probe_point(*loc
);
432 probe_point::component
*simple_comp
= new probe_point::component(*comp
);
433 simple_comp
->functor
= prefix
+ "*" + suffix
;
434 simple_pp
->components
[pos
] = simple_comp
;
437 find_and_build (s
, p
, simple_pp
, pos
, results
);
439 catch (const semantic_error
& e
)
441 // Ignore semantic_errors, but cleanup
446 // Synthesize "foo*.**bar"
447 // NB: any component arg should attach to the latter part only
448 probe_point
*expanded_pp
= new probe_point(*loc
);
449 probe_point::component
*expanded_comp_pre
= new probe_point::component(*comp
);
450 expanded_comp_pre
->functor
= prefix
+ "*";
451 expanded_comp_pre
->arg
= NULL
;
452 probe_point::component
*expanded_comp_post
= new probe_point::component(*comp
);
453 expanded_comp_post
->functor
= "**" + suffix
;
454 expanded_pp
->components
[pos
] = expanded_comp_pre
;
455 expanded_pp
->components
.insert(expanded_pp
->components
.begin() + pos
+ 1,
459 find_and_build (s
, p
, expanded_pp
, pos
, results
);
461 catch (const semantic_error
& e
)
463 // Ignore semantic_errors, but cleanup
465 delete expanded_comp_pre
;
466 delete expanded_comp_post
;
469 if (! loc
->optional
&& num_results
== results
.size())
471 // We didn't find any wildcard matches (since the size of
472 // the result vector didn't change). Throw an error.
474 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
475 alternatives
+= string(" ") + i
->first
.str();
477 throw semantic_error(string("probe point mismatch at position ") +
479 " (alternatives:" + alternatives
+ ")" +
480 " didn't find any wildcard matches",
484 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
486 match_key
match (* loc
->components
[pos
]);
488 // Call find_and_build for each possible match. Ignore errors -
489 // unless we don't find any match.
490 unsigned int num_results
= results
.size();
491 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
493 const match_key
& subkey
= i
->first
;
494 match_node
* subnode
= i
->second
;
496 if (pending_interrupts
) break;
498 if (match
.globmatch(subkey
))
501 clog
<< "wildcard '" << loc
->components
[pos
]->functor
502 << "' matched '" << subkey
.name
<< "'" << endl
;
504 // When we have a wildcard, we need to create a copy of
505 // the probe point. Then we'll create a copy of the
506 // wildcard component, and substitute the non-wildcard
508 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
509 probe_point::component
*non_wildcard_component
510 = new probe_point::component(*loc
->components
[pos
]);
511 non_wildcard_component
->functor
= subkey
.name
;
512 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
514 // NB: probe conditions are not attached at the wildcard
515 // (component/functor) level, but at the overall
516 // probe_point level.
518 // recurse (with the non-wildcard probe point)
521 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
524 catch (const semantic_error
& e
)
526 // Ignore semantic_errors while expanding wildcards.
527 // If we get done and nothing was expanded, the code
528 // following the loop will complain.
530 // If this wildcard didn't match, cleanup.
531 delete non_wildcard_pp
;
532 delete non_wildcard_component
;
536 if (! loc
->optional
&& num_results
== results
.size())
538 // We didn't find any wildcard matches (since the size of
539 // the result vector didn't change). Throw an error.
541 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
542 alternatives
+= string(" ") + i
->first
.str();
544 throw semantic_error(string("probe point mismatch at position ") +
546 (alternatives
== "" ? "" :
547 (" (alternatives:" + alternatives
+ ")")) +
548 " didn't find any wildcard matches",
549 loc
->components
[pos
]->tok
);
554 match_key
match (* loc
->components
[pos
]);
555 sub_map_iterator_t i
= sub
.find (match
);
556 if (i
== sub
.end()) // no match
559 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
560 alternatives
+= string(" ") + i
->first
.str();
562 throw semantic_error(string("probe point mismatch at position ") +
564 (alternatives
== "" ? "" :
565 (" (alternatives:" + alternatives
+ ")")),
566 loc
->components
[pos
]->tok
);
569 match_node
* subnode
= i
->second
;
571 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
577 match_node::build_no_more (systemtap_session
& s
)
579 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
580 i
->second
->build_no_more (s
);
581 for (unsigned k
=0; k
<ends
.size(); k
++)
583 derived_probe_builder
*b
= ends
[k
];
584 b
->build_no_more (s
);
589 // ------------------------------------------------------------------------
591 // ------------------------------------------------------------------------
593 struct alias_derived_probe
: public derived_probe
595 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
):
596 derived_probe (base
, l
), alias(a
) {}
598 void upchuck () { throw semantic_error ("inappropriate", this->tok
); }
600 // Alias probes are immediately expanded to other derived_probe
601 // types, and are not themselves emitted or listed in
602 // systemtap_session.probes
604 void join_group (systemtap_session
&) { upchuck (); }
606 virtual const probe_alias
*get_alias () const { return alias
; }
609 const probe_alias
*alias
; // Used to check for recursion
613 probe::create_alias(probe_point
* l
, probe_point
* a
)
615 vector
<probe_point
*> aliases(1, a
);
616 probe_alias
* p
= new probe_alias(aliases
);
618 p
->locations
.push_back(l
);
620 p
->privileged
= privileged
;
621 p
->epilogue_style
= false;
622 return new alias_derived_probe(this, l
, p
);
627 alias_expansion_builder::build(systemtap_session
& sess
,
629 probe_point
* location
,
630 std::map
<std::string
, literal
*> const &,
631 vector
<derived_probe
*> & finished_results
)
633 // Don't build the alias expansion if infinite recursion is detected.
634 if (checkForRecursiveExpansion (use
)) {
636 msg
<< "Recursive loop in alias expansion of " << *location
<< " at " << location
->components
.front()->tok
->location
;
637 // semantic_errors thrown here are ignored.
638 sess
.print_error (semantic_error (msg
.str()));
642 // We're going to build a new probe and wrap it up in an
643 // alias_expansion_probe so that the expansion loop recognizes it as
644 // such and re-expands its expansion.
646 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
);
647 n
->body
= new block();
649 // The new probe gets a deep copy of the location list of
650 // the alias (with incoming condition joined)
651 n
->locations
.clear();
652 for (unsigned i
=0; i
<alias
->locations
.size(); i
++)
654 probe_point
*pp
= new probe_point(*alias
->locations
[i
]);
655 pp
->condition
= add_condition (pp
->condition
, location
->condition
);
656 n
->locations
.push_back(pp
);
659 // the token location of the alias,
660 n
->tok
= location
->components
.front()->tok
;
662 // and statements representing the concatenation of the alias'
663 // body with the use's.
665 // NB: locals are *not* copied forward, from either alias or
666 // use. The expansion should have its locals re-inferred since
667 // there's concatenated code here and we only want one vardecl per
668 // resulting variable.
670 if (alias
->epilogue_style
)
671 n
->body
= new block (use
->body
, alias
->body
);
673 n
->body
= new block (alias
->body
, use
->body
);
675 unsigned old_num_results
= finished_results
.size();
676 derive_probes (sess
, n
, finished_results
, location
->optional
);
678 // Check whether we resolved something. If so, put the
679 // whole library into the queue if not already there.
680 if (finished_results
.size() > old_num_results
)
682 stapfile
*f
= alias
->tok
->location
.file
;
683 if (find (sess
.files
.begin(), sess
.files
.end(), f
)
685 sess
.files
.push_back (f
);
690 alias_expansion_builder::checkForRecursiveExpansion (probe
*use
)
692 // Collect the derivation chain of this probe.
693 vector
<probe
*>derivations
;
694 use
->collect_derivation_chain (derivations
);
696 // Check all probe points in the alias expansion against the currently-being-expanded probe point
697 // of each of the probes in the derivation chain, looking for a match. This
698 // indicates infinite recursion.
699 // The first element of the derivation chain will be the derived_probe representing 'use', so
700 // start the search with the second element.
701 assert (derivations
.size() > 0);
702 assert (derivations
[0] == use
);
703 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
704 if (use
->get_alias() == derivations
[d
]->get_alias())
705 return true; // recursion detected
711 // ------------------------------------------------------------------------
713 // ------------------------------------------------------------------------
715 static unsigned max_recursion
= 100;
721 recursion_guard(unsigned & i
) : i(i
)
723 if (i
> max_recursion
)
724 throw semantic_error("recursion limit reached");
733 // The match-and-expand loop.
735 derive_probes (systemtap_session
& s
,
736 probe
*p
, vector
<derived_probe
*>& dps
,
739 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
741 if (pending_interrupts
) break;
743 probe_point
*loc
= p
->locations
[i
];
747 unsigned num_atbegin
= dps
.size();
749 // Pass down optional flag from e.g. alias reference to each
750 // probe_point instance. We do this by temporarily overriding
751 // the probe_point optional flag. We could instead deep-copy
752 // and set a flag on the copy permanently.
753 bool old_loc_opt
= loc
->optional
;
754 loc
->optional
= loc
->optional
|| optional
;
757 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
759 catch (const semantic_error
& e
)
762 throw semantic_error(e
);
763 else /* tolerate failure for optional probe */
767 loc
->optional
= old_loc_opt
;
768 unsigned num_atend
= dps
.size();
770 if (! (loc
->optional
||optional
) && // something required, but
771 num_atbegin
== num_atend
) // nothing new derived!
772 throw semantic_error ("no match");
774 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
778 clog
<< "Probe point ";
779 p
->locations
[i
]->print(clog
);
780 clog
<< " sufficient, skipped";
781 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
784 p
->locations
[j
]->print(clog
);
788 break; // we need not try to derive for any other locations
791 catch (const semantic_error
& e
)
793 if (! s
.listing_mode
) // suppress error messages in listing mode
795 // XXX: prefer not to print_error at every nest/unroll level
796 semantic_error
* er
= new semantic_error (e
); // copy it
799 msg
<< " while resolving probe point " << *loc
;
800 er
->msg2
= msg
.str();
801 s
.print_error (* er
);
811 // ------------------------------------------------------------------------
813 // Indexable usage checks
816 struct symbol_fetcher
817 : public throwing_visitor
821 symbol_fetcher (symbol
*&sym
): sym(sym
)
824 void visit_symbol (symbol
* e
)
829 void visit_target_symbol (target_symbol
* e
)
834 void visit_arrayindex (arrayindex
* e
)
836 e
->base
->visit_indexable (this);
839 void visit_cast_op (cast_op
* e
)
844 void throwone (const token
* t
)
846 throw semantic_error ("Expecting symbol or array index expression", t
);
851 get_symbol_within_expression (expression
*e
)
854 symbol_fetcher
fetcher(sym
);
856 return sym
; // NB: may be null!
860 get_symbol_within_indexable (indexable
*ix
)
862 symbol
*array
= NULL
;
863 hist_op
*hist
= NULL
;
864 classify_indexable(ix
, array
, hist
);
868 return get_symbol_within_expression (hist
->stat
);
871 struct mutated_var_collector
872 : public traversing_visitor
874 set
<vardecl
*> * mutated_vars
;
876 mutated_var_collector (set
<vardecl
*> * mm
)
880 void visit_assignment(assignment
* e
)
882 if (e
->type
== pe_stats
&& e
->op
== "<<<")
884 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
886 mutated_vars
->insert (vd
);
888 traversing_visitor::visit_assignment(e
);
891 void visit_arrayindex (arrayindex
*e
)
893 if (is_active_lvalue (e
))
896 if (e
->base
->is_symbol (sym
))
897 mutated_vars
->insert (sym
->referent
);
899 throw semantic_error("Assignment to read-only histogram bucket", e
->tok
);
901 traversing_visitor::visit_arrayindex (e
);
906 struct no_var_mutation_during_iteration_check
907 : public traversing_visitor
909 systemtap_session
& session
;
910 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
911 vector
<vardecl
*> vars_being_iterated
;
913 no_var_mutation_during_iteration_check
914 (systemtap_session
& sess
,
915 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
916 : session(sess
), function_mutates_vars (fmv
)
919 void visit_arrayindex (arrayindex
*e
)
921 if (is_active_lvalue(e
))
923 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
926 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
928 vardecl
*v
= vars_being_iterated
[i
];
931 string err
= ("variable '" + v
->name
+
932 "' modified during 'foreach' iteration");
933 session
.print_error (semantic_error (err
, e
->tok
));
938 traversing_visitor::visit_arrayindex (e
);
941 void visit_functioncall (functioncall
* e
)
943 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
944 = function_mutates_vars
.find (e
->referent
);
946 if (i
!= function_mutates_vars
.end())
948 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
950 vardecl
*m
= vars_being_iterated
[j
];
951 if (i
->second
->find (m
) != i
->second
->end())
953 string err
= ("function call modifies var '" + m
->name
+
954 "' during 'foreach' iteration");
955 session
.print_error (semantic_error (err
, e
->tok
));
960 traversing_visitor::visit_functioncall (e
);
963 void visit_foreach_loop(foreach_loop
* s
)
965 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
968 vars_being_iterated
.push_back (vd
);
970 traversing_visitor::visit_foreach_loop (s
);
973 vars_being_iterated
.pop_back();
978 // ------------------------------------------------------------------------
980 struct stat_decl_collector
981 : public traversing_visitor
983 systemtap_session
& session
;
985 stat_decl_collector(systemtap_session
& sess
)
989 void visit_stat_op (stat_op
* e
)
991 symbol
*sym
= get_symbol_within_expression (e
->stat
);
992 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
993 session
.stat_decls
[sym
->name
] = statistic_decl();
996 void visit_assignment (assignment
* e
)
1000 symbol
*sym
= get_symbol_within_expression (e
->left
);
1001 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
1002 session
.stat_decls
[sym
->name
] = statistic_decl();
1005 traversing_visitor::visit_assignment(e
);
1008 void visit_hist_op (hist_op
* e
)
1010 symbol
*sym
= get_symbol_within_expression (e
->stat
);
1011 statistic_decl new_stat
;
1013 if (e
->htype
== hist_linear
)
1015 new_stat
.type
= statistic_decl::linear
;
1016 assert (e
->params
.size() == 3);
1017 new_stat
.linear_low
= e
->params
[0];
1018 new_stat
.linear_high
= e
->params
[1];
1019 new_stat
.linear_step
= e
->params
[2];
1023 assert (e
->htype
== hist_log
);
1024 new_stat
.type
= statistic_decl::logarithmic
;
1025 assert (e
->params
.size() == 0);
1028 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
1029 if (i
== session
.stat_decls
.end())
1030 session
.stat_decls
[sym
->name
] = new_stat
;
1033 statistic_decl
& old_stat
= i
->second
;
1034 if (!(old_stat
== new_stat
))
1036 if (old_stat
.type
== statistic_decl::none
)
1037 i
->second
= new_stat
;
1040 // FIXME: Support multiple co-declared histogram types
1041 semantic_error
se("multiple histogram types declared on '" + sym
->name
+ "'",
1043 session
.print_error (se
);
1052 semantic_pass_stats (systemtap_session
& sess
)
1054 stat_decl_collector
sdc(sess
);
1056 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1057 it
->second
->body
->visit (&sdc
);
1059 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1060 sess
.probes
[i
]->body
->visit (&sdc
);
1062 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
1064 vardecl
*v
= sess
.globals
[i
];
1065 if (v
->type
== pe_stats
)
1068 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
1070 semantic_error
se("unable to infer statistic parameters for global '" + v
->name
+ "'");
1071 sess
.print_error (se
);
1076 return sess
.num_errors();
1079 // ------------------------------------------------------------------------
1081 // Enforce variable-related invariants: no modification of
1082 // a foreach()-iterated array.
1084 semantic_pass_vars (systemtap_session
& sess
)
1087 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
1088 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
1090 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1092 functiondecl
* fn
= it
->second
;
1095 set
<vardecl
*> * m
= new set
<vardecl
*>();
1096 mutated_var_collector
mc (m
);
1097 fn
->body
->visit (&mc
);
1102 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1104 functiondecl
* fn
= it
->second
;
1105 if (fn
->body
) fn
->body
->visit (&chk
);
1108 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1110 if (sess
.probes
[i
]->body
)
1111 sess
.probes
[i
]->body
->visit (&chk
);
1114 return sess
.num_errors();
1118 // ------------------------------------------------------------------------
1120 // Rewrite probe condition expressions into probe bodies. Tricky and
1121 // exciting business, this. This:
1123 // probe foo if (g1 || g2) { ... }
1124 // probe bar { ... g1 ++ ... }
1128 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1129 // probe foo { if (! (g1 || g2)) next; ... }
1130 // probe bar { ... g1 ++ ...;
1131 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1134 // XXX: As a first cut, do only the "inline probe condition" part of the
1138 semantic_pass_conditions (systemtap_session
& sess
)
1140 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1142 derived_probe
* p
= sess
.probes
[i
];
1143 expression
* e
= p
->sole_location()->condition
;
1146 varuse_collecting_visitor
vut(sess
);
1149 if (! vut
.written
.empty())
1151 string err
= ("probe condition must not modify any variables");
1152 sess
.print_error (semantic_error (err
, e
->tok
));
1154 else if (vut
.embedded_seen
)
1156 sess
.print_error (semantic_error ("probe condition must not include impure embedded-C", e
->tok
));
1159 // Add the condition expression to the front of the
1160 // derived_probe body.
1161 if_statement
*ifs
= new if_statement ();
1163 ifs
->thenblock
= new next_statement ();
1164 ifs
->thenblock
->tok
= e
->tok
;
1165 ifs
->elseblock
= NULL
;
1166 unary_expression
*notex
= new unary_expression ();
1168 notex
->tok
= e
->tok
;
1170 ifs
->condition
= notex
;
1171 p
->body
= new block (ifs
, p
->body
);
1175 return sess
.num_errors();
1178 // ------------------------------------------------------------------------
1181 // Simple visitor that just goes through all embedded code blocks that
1182 // are available at the end all the optimizations to register any
1183 // relevant pragmas or other indicators found, so that session flags can
1184 // be set that can be inspected at translation time to trigger any
1185 // necessary initialization of code needed by the embedded code functions.
1187 // This is only for pragmas that don't have any other side-effect than
1188 // needing some initialization at module init time. Currently only handles
1189 // /* pragma:vma */.
1191 // /* pragma:uprobes */ is handled during the typeresolution_info pass.
1192 // /* pure */, /* unprivileged */ and /* guru */ are handled by the
1193 // varuse_collecting_visitor.
1195 struct embeddedcode_info
: public functioncall_traversing_visitor
1198 systemtap_session
& session
;
1201 embeddedcode_info (systemtap_session
& s
): session(s
) { }
1203 void visit_embeddedcode (embeddedcode
* c
)
1205 if (! vma_tracker_enabled(session
)
1206 && c
->code
.find("/* pragma:vma */") != string::npos
)
1208 enable_vma_tracker(session
);
1209 if (session
.verbose
> 2)
1210 clog
<< "Turning on task_finder vma_tracker, pragma:vma found in "
1211 << current_function
->name
<< endl
;
1216 void embeddedcode_info_pass (systemtap_session
& s
)
1218 embeddedcode_info
eci (s
);
1219 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1220 s
.probes
[i
]->body
->visit (& eci
);
1223 // ------------------------------------------------------------------------
1226 static int semantic_pass_symbols (systemtap_session
&);
1227 static int semantic_pass_optimize1 (systemtap_session
&);
1228 static int semantic_pass_optimize2 (systemtap_session
&);
1229 static int semantic_pass_types (systemtap_session
&);
1230 static int semantic_pass_vars (systemtap_session
&);
1231 static int semantic_pass_stats (systemtap_session
&);
1232 static int semantic_pass_conditions (systemtap_session
&);
1235 // Link up symbols to their declarations. Set the session's
1236 // files/probes/functions/globals vectors from the transitively
1237 // reached set of stapfiles in s.library_files, starting from
1238 // s.user_file. Perform automatic tapset inclusion and probe
1241 semantic_pass_symbols (systemtap_session
& s
)
1243 symresolution_info
sym (s
);
1245 // NB: s.files can grow during this iteration, so size() can
1246 // return gradually increasing numbers.
1247 s
.files
.push_back (s
.user_file
);
1248 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1250 if (pending_interrupts
) break;
1251 stapfile
* dome
= s
.files
[i
];
1253 // Pass 1: add globals and functions to systemtap-session master list,
1254 // so the find_* functions find them
1256 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1257 s
.globals
.push_back (dome
->globals
[i
]);
1259 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1260 s
.functions
[dome
->functions
[i
]->name
] = dome
->functions
[i
];
1262 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1263 s
.embeds
.push_back (dome
->embeds
[i
]);
1265 // Pass 2: derive probes and resolve any further symbols in the
1268 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1270 if (pending_interrupts
) break;
1271 probe
* p
= dome
->probes
[i
];
1272 vector
<derived_probe
*> dps
;
1274 // much magic happens here: probe alias expansion, wildcard
1275 // matching, low-level derived_probe construction.
1276 derive_probes (s
, p
, dps
);
1278 for (unsigned j
=0; j
<dps
.size(); j
++)
1280 if (pending_interrupts
) break;
1281 derived_probe
* dp
= dps
[j
];
1282 s
.probes
.push_back (dp
);
1287 for (unsigned k
=0; k
<s
.code_filters
.size(); k
++)
1288 s
.code_filters
[k
]->replace (dp
->body
);
1290 sym
.current_function
= 0;
1291 sym
.current_probe
= dp
;
1292 dp
->body
->visit (& sym
);
1294 // Process the probe-point condition expression.
1295 sym
.current_function
= 0;
1296 sym
.current_probe
= 0;
1297 if (dp
->sole_location()->condition
)
1298 dp
->sole_location()->condition
->visit (& sym
);
1300 catch (const semantic_error
& e
)
1307 // Pass 3: process functions
1309 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1311 if (pending_interrupts
) break;
1312 functiondecl
* fd
= dome
->functions
[i
];
1316 for (unsigned j
=0; j
<s
.code_filters
.size(); j
++)
1317 s
.code_filters
[j
]->replace (fd
->body
);
1319 sym
.current_function
= fd
;
1320 sym
.current_probe
= 0;
1321 fd
->body
->visit (& sym
);
1323 catch (const semantic_error
& e
)
1330 // Inform all derived_probe builders that we're done with
1331 // all resolution, so it's time to release caches.
1332 s
.pattern_root
->build_no_more (s
);
1334 return s
.num_errors(); // all those print_error calls
1339 // Keep unread global variables for probe end value display.
1340 void add_global_var_display (systemtap_session
& s
)
1342 // Don't generate synthetic end probes when in listings mode;
1343 // it would clutter up the list of probe points with "end ...".
1344 if (s
.listing_mode
) return;
1346 varuse_collecting_visitor
vut(s
);
1347 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1349 s
.probes
[i
]->body
->visit (& vut
);
1351 if (s
.probes
[i
]->sole_location()->condition
)
1352 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1355 for (unsigned g
=0; g
< s
.globals
.size(); g
++)
1357 vardecl
* l
= s
.globals
[g
];
1358 if (vut
.read
.find (l
) != vut
.read
.end()
1359 || vut
.written
.find (l
) == vut
.written
.end())
1362 // Don't generate synthetic end probes for unread globals
1363 // declared only within tapsets. (RHBZ 468139), but rather
1364 // only within the end-user script.
1366 bool tapset_global
= false;
1367 for (size_t m
=0; m
< s
.library_files
.size(); m
++)
1369 for (size_t n
=0; n
< s
.library_files
[m
]->globals
.size(); n
++)
1371 if (l
->name
== s
.library_files
[m
]->globals
[n
]->name
)
1372 {tapset_global
= true; break;}
1378 probe_point::component
* c
= new probe_point::component("end");
1379 probe_point
* pl
= new probe_point
;
1380 pl
->components
.push_back (c
);
1382 vector
<derived_probe
*> dps
;
1383 block
*b
= new block
;
1386 probe
* p
= new probe
;
1388 p
->locations
.push_back (pl
);
1391 symbol
* g_sym
= new symbol
;
1392 g_sym
->name
= l
->name
;
1393 g_sym
->tok
= l
->tok
;
1394 g_sym
->type
= l
->type
;
1395 g_sym
->referent
= l
;
1397 token
* print_tok
= new token(*l
->tok
);
1398 print_tok
->type
= tok_identifier
;
1399 print_tok
->content
= "printf";
1401 print_format
* pf
= print_format::create(print_tok
);
1402 pf
->raw_components
+= l
->name
;
1404 if (l
->index_types
.size() == 0) // Scalar
1406 if (l
->type
== pe_stats
)
1407 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1408 else if (l
->type
== pe_string
)
1409 pf
->raw_components
+= "=\"%#s\"\\n";
1411 pf
->raw_components
+= "=%#x\\n";
1412 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1413 expr_statement
* feb
= new expr_statement
;
1415 feb
->tok
= print_tok
;
1416 if (l
->type
== pe_stats
)
1418 struct stat_op
* so
[5];
1419 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1421 for (unsigned si
= 0;
1422 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1425 so
[si
]= new stat_op
;
1426 so
[si
]->ctype
= stypes
[si
];
1427 so
[si
]->type
= pe_long
;
1428 so
[si
]->stat
= g_sym
;
1429 so
[si
]->tok
= l
->tok
;
1430 pf
->args
.push_back(so
[si
]);
1434 pf
->args
.push_back(g_sym
);
1436 /* PR7053: Checking empty aggregate for global variable */
1437 if (l
->type
== pe_stats
) {
1438 stat_op
*so
= new stat_op
;
1439 so
->ctype
= sc_count
;
1443 comparison
*be
= new comparison
;
1447 be
->right
= new literal_number(0);
1449 /* Create printf @count=0x0 in else block */
1450 print_format
* pf_0
= print_format::create(print_tok
);
1451 pf_0
->raw_components
+= l
->name
;
1452 pf_0
->raw_components
+= " @count=0x0\\n";
1453 pf_0
->components
= print_format::string_to_components(pf_0
->raw_components
);
1454 expr_statement
* feb_else
= new expr_statement
;
1455 feb_else
->value
= pf_0
;
1456 feb_else
->tok
= print_tok
;
1457 if_statement
*ifs
= new if_statement
;
1459 ifs
->condition
= be
;
1460 ifs
->thenblock
= feb
;
1461 ifs
->elseblock
= feb_else
;
1462 b
->statements
.push_back(ifs
);
1464 else /* other non-stat cases */
1465 b
->statements
.push_back(feb
);
1469 int idx_count
= l
->index_types
.size();
1470 symbol
* idx_sym
[idx_count
];
1471 vardecl
* idx_v
[idx_count
];
1472 // Create a foreach loop
1473 foreach_loop
* fe
= new foreach_loop
;
1474 fe
->sort_direction
= -1; // imply decreasing sort on value
1475 fe
->sort_column
= 0; // as in foreach ([a,b,c] in array-) { }
1480 // Create indices for the foreach loop
1481 for (int i
=0; i
< idx_count
; i
++)
1484 if (asprintf (&idx_name
, "idx%d", i
) < 0)
1486 idx_sym
[i
] = new symbol
;
1487 idx_sym
[i
]->name
= idx_name
;
1488 idx_sym
[i
]->tok
= l
->tok
;
1489 idx_v
[i
] = new vardecl
;
1490 idx_v
[i
]->name
= idx_name
;
1491 idx_v
[i
]->type
= l
->index_types
[i
];
1492 idx_v
[i
]->tok
= l
->tok
;
1493 idx_sym
[i
]->referent
= idx_v
[i
];
1494 fe
->indexes
.push_back (idx_sym
[i
]);
1497 // Create a printf for the foreach loop
1498 pf
->raw_components
+= "[";
1499 for (int i
=0; i
< idx_count
; i
++)
1502 pf
->raw_components
+= ",";
1503 if (l
->index_types
[i
] == pe_string
)
1504 pf
->raw_components
+= "\"%#s\"";
1506 pf
->raw_components
+= "%#d";
1508 pf
->raw_components
+= "]";
1509 if (l
->type
== pe_stats
)
1510 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1511 else if (l
->type
== pe_string
)
1512 pf
->raw_components
+= "=\"%#s\"\\n";
1514 pf
->raw_components
+= "=%#x\\n";
1516 // Create an index for the array
1517 struct arrayindex
* ai
= new arrayindex
;
1521 for (int i
=0; i
< idx_count
; i
++)
1523 ai
->indexes
.push_back (idx_sym
[i
]);
1524 pf
->args
.push_back(idx_sym
[i
]);
1526 if (l
->type
== pe_stats
)
1528 struct stat_op
* so
[5];
1529 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1531 ai
->type
= pe_stats
;
1532 for (unsigned si
= 0;
1533 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1536 so
[si
]= new stat_op
;
1537 so
[si
]->ctype
= stypes
[si
];
1538 so
[si
]->type
= pe_long
;
1540 so
[si
]->tok
= l
->tok
;
1541 pf
->args
.push_back(so
[si
]);
1546 // Create value for the foreach loop
1547 fe
->value
= new symbol
;
1548 fe
->value
->name
= "val";
1549 fe
->value
->tok
= l
->tok
;
1550 pf
->args
.push_back(fe
->value
);
1553 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1554 expr_statement
* feb
= new expr_statement
;
1558 fe
->block
= (statement
*)feb
;
1559 b
->statements
.push_back(fe
);
1562 // Add created probe
1564 derive_probes (s
, p
, dps
);
1565 for (unsigned i
= 0; i
< dps
.size(); i
++)
1567 derived_probe
* dp
= dps
[i
];
1568 s
.probes
.push_back (dp
);
1571 // Repopulate symbol and type info
1572 symresolution_info
sym (s
);
1573 sym
.current_function
= 0;
1574 sym
.current_probe
= dps
[0];
1575 dps
[0]->body
->visit (& sym
);
1577 semantic_pass_types(s
);
1578 // Mark that variable is read
1579 vut
.read
.insert (l
);
1584 semantic_pass (systemtap_session
& s
)
1590 s
.register_library_aliases();
1591 register_standard_tapsets(s
);
1593 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1594 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1595 if (rc
== 0) rc
= semantic_pass_optimize1 (s
);
1596 if (rc
== 0) rc
= semantic_pass_types (s
);
1597 if (rc
== 0) add_global_var_display (s
);
1598 if (rc
== 0) rc
= semantic_pass_optimize2 (s
);
1599 if (rc
== 0) rc
= semantic_pass_vars (s
);
1600 if (rc
== 0) rc
= semantic_pass_stats (s
);
1601 if (rc
== 0) embeddedcode_info_pass (s
);
1603 if (s
.num_errors() == 0 && s
.probes
.size() == 0 && !s
.listing_mode
)
1604 throw semantic_error ("no probes found");
1606 catch (const semantic_error
& e
)
1613 if (s
.listing_mode
&& s
.probes
.size() == 0)
1620 // ------------------------------------------------------------------------
1621 // semantic processing: symbol resolution
1624 symresolution_info::symresolution_info (systemtap_session
& s
):
1625 session (s
), current_function (0), current_probe (0)
1631 symresolution_info::visit_block (block
* e
)
1633 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
1637 e
->statements
[i
]->visit (this);
1639 catch (const semantic_error
& e
)
1641 session
.print_error (e
);
1648 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
1650 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1651 e
->indexes
[i
]->visit (this);
1653 symbol
*array
= NULL
;
1654 hist_op
*hist
= NULL
;
1655 classify_indexable (e
->base
, array
, hist
);
1659 if (!array
->referent
)
1661 vardecl
* d
= find_var (array
->name
, e
->indexes
.size (), array
->tok
);
1663 array
->referent
= d
;
1667 msg
<< "unresolved arity-" << e
->indexes
.size()
1668 << " global array " << array
->name
1669 << ", missing global declaration? ";
1670 throw semantic_error (msg
.str(), e
->tok
);
1681 e
->value
->visit (this);
1684 e
->limit
->visit (this);
1686 e
->block
->visit (this);
1691 delete_statement_symresolution_info
:
1692 public traversing_visitor
1694 symresolution_info
*parent
;
1696 delete_statement_symresolution_info (symresolution_info
*p
):
1700 void visit_arrayindex (arrayindex
* e
)
1702 parent
->visit_arrayindex (e
);
1704 void visit_functioncall (functioncall
* e
)
1706 parent
->visit_functioncall (e
);
1709 void visit_symbol (symbol
* e
)
1714 vardecl
* d
= parent
->find_var (e
->name
, -1, e
->tok
);
1718 throw semantic_error ("unresolved array in delete statement", e
->tok
);
1723 symresolution_info::visit_delete_statement (delete_statement
* s
)
1725 delete_statement_symresolution_info
di (this);
1726 s
->value
->visit (&di
);
1731 symresolution_info::visit_symbol (symbol
* e
)
1736 vardecl
* d
= find_var (e
->name
, 0, e
->tok
);
1742 vardecl
* v
= new vardecl
;
1745 v
->set_arity(0, e
->tok
);
1746 if (current_function
)
1747 current_function
->locals
.push_back (v
);
1748 else if (current_probe
)
1749 current_probe
->locals
.push_back (v
);
1751 // must be probe-condition expression
1752 throw semantic_error ("probe condition must not reference undeclared global", e
->tok
);
1759 symresolution_info::visit_arrayindex (arrayindex
* e
)
1761 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1762 e
->indexes
[i
]->visit (this);
1764 symbol
*array
= NULL
;
1765 hist_op
*hist
= NULL
;
1766 classify_indexable(e
->base
, array
, hist
);
1770 if (array
->referent
)
1773 vardecl
* d
= find_var (array
->name
, e
->indexes
.size (), array
->tok
);
1775 array
->referent
= d
;
1779 msg
<< "unresolved arity-" << e
->indexes
.size()
1780 << " global array " << array
->name
1781 << ", missing global declaration? ";
1782 throw semantic_error (msg
.str(), e
->tok
);
1794 symresolution_info::visit_functioncall (functioncall
* e
)
1796 // XXX: we could relax this, if we're going to examine the
1797 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1798 if (! (current_function
|| current_probe
))
1800 // must be probe-condition expression
1801 throw semantic_error ("probe condition must not reference function", e
->tok
);
1804 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1805 e
->args
[i
]->visit (this);
1810 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
1816 msg
<< "unresolved arity-" << e
->args
.size()
1818 throw semantic_error (msg
.str(), e
->tok
);
1824 symresolution_info::find_var (const string
& name
, int arity
, const token
* tok
)
1826 if (current_function
|| current_probe
)
1829 vector
<vardecl
*>& locals
= (current_function
?
1830 current_function
->locals
:
1831 current_probe
->locals
);
1834 for (unsigned i
=0; i
<locals
.size(); i
++)
1835 if (locals
[i
]->name
== name
)
1837 locals
[i
]->set_arity (arity
, tok
);
1842 // search function formal parameters (for scalars)
1843 if (arity
== 0 && current_function
)
1844 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
1845 if (current_function
->formal_args
[i
]->name
== name
)
1847 // NB: no need to check arity here: formal args always scalar
1848 current_function
->formal_args
[i
]->set_arity (0, tok
);
1849 return current_function
->formal_args
[i
];
1852 // search processed globals
1853 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
1854 if (session
.globals
[i
]->name
== name
)
1856 session
.globals
[i
]->set_arity (arity
, tok
);
1857 if (! session
.suppress_warnings
)
1859 vardecl
* v
= session
.globals
[i
];
1860 // clog << "resolved " << *tok << " to global " << *v->tok << endl;
1861 if (v
->tok
->location
.file
!= tok
->location
.file
)
1863 session
.print_warning ("cross-file global variable reference to " + lex_cast (*v
->tok
) + " from",
1867 return session
.globals
[i
];
1870 // search library globals
1871 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1873 stapfile
* f
= session
.library_files
[i
];
1874 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
1876 vardecl
* g
= f
->globals
[j
];
1877 if (g
->name
== name
)
1879 g
->set_arity (arity
, tok
);
1881 // put library into the queue if not already there
1882 if (find (session
.files
.begin(), session
.files
.end(), f
)
1883 == session
.files
.end())
1884 session
.files
.push_back (f
);
1896 symresolution_info::find_function (const string
& name
, unsigned arity
)
1899 if (session
.functions
.find(name
) != session
.functions
.end())
1901 functiondecl
* fd
= session
.functions
[name
];
1902 assert (fd
->name
== name
);
1903 if (fd
->formal_args
.size() == arity
)
1907 // search library globals
1908 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1910 stapfile
* f
= session
.library_files
[i
];
1911 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1912 if (f
->functions
[j
]->name
== name
&&
1913 f
->functions
[j
]->formal_args
.size() == arity
)
1915 // put library into the queue if not already there
1916 if (0) // session.verbose_resolution
1917 cerr
<< " function " << name
<< " "
1918 << "is defined from " << f
->name
<< endl
;
1920 if (find (session
.files
.begin(), session
.files
.end(), f
)
1921 == session
.files
.end())
1922 session
.files
.push_back (f
);
1923 // else .. print different message?
1925 return f
->functions
[j
];
1934 // ------------------------------------------------------------------------
1938 // Do away with functiondecls that are never (transitively) called
1940 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1942 functioncall_traversing_visitor ftv
;
1943 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1945 s
.probes
[i
]->body
->visit (& ftv
);
1946 if (s
.probes
[i
]->sole_location()->condition
)
1947 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1949 vector
<functiondecl
*> new_unused_functions
;
1950 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
1952 functiondecl
* fd
= it
->second
;
1953 if (ftv
.traversed
.find(fd
) == ftv
.traversed
.end())
1955 if (fd
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
1956 ! s
.suppress_warnings
&& ! fd
->synthetic
)
1957 s
.print_warning ("eliding unused function '" + fd
->name
+ "'", fd
->tok
);
1958 else if (s
.verbose
>2)
1959 clog
<< "Eliding unused function " << fd
->name
1961 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
1962 new_unused_functions
.push_back (fd
);
1966 for (unsigned i
=0; i
<new_unused_functions
.size(); i
++)
1968 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (new_unused_functions
[i
]->name
);
1969 assert (where
!= s
.functions
.end());
1970 s
.functions
.erase (where
);
1971 if (s
.tapset_compile_coverage
)
1972 s
.unused_functions
.push_back (new_unused_functions
[i
]);
1977 // ------------------------------------------------------------------------
1979 // Do away with local & global variables that are never
1980 // written nor read.
1981 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
1983 varuse_collecting_visitor
vut(s
);
1985 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1987 s
.probes
[i
]->body
->visit (& vut
);
1989 if (s
.probes
[i
]->sole_location()->condition
)
1990 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1993 // NB: Since varuse_collecting_visitor also traverses down
1994 // actually called functions, we don't need to explicitly
1995 // iterate over them. Uncalled ones should have been pruned
1998 // for (unsigned i=0; i<s.functions.size(); i++)
1999 // s.functions[i]->body->visit (& vut);
2001 // Now in vut.read/written, we have a mixture of all locals, globals
2003 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2004 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
2006 vardecl
* l
= s
.probes
[i
]->locals
[j
];
2008 // skip over "special" locals
2009 if (l
->skip_init
) { j
++; continue; }
2011 if (vut
.read
.find (l
) == vut
.read
.end() &&
2012 vut
.written
.find (l
) == vut
.written
.end())
2014 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2015 ! s
.suppress_warnings
)
2016 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2017 else if (s
.verbose
>2)
2018 clog
<< "Eliding unused local variable "
2019 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
2020 if (s
.tapset_compile_coverage
) {
2021 s
.probes
[i
]->unused_locals
.push_back
2022 (s
.probes
[i
]->locals
[j
]);
2024 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
2026 // don't increment j
2030 if (vut
.written
.find (l
) == vut
.written
.end())
2031 if (iterations
== 0 && ! s
.suppress_warnings
)
2034 vector
<vardecl
*>::iterator it
;
2035 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
2036 if (l
->name
!= (*it
)->name
)
2037 o
<< " " << (*it
)->name
;
2038 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2039 if (l
->name
!= (*it
)->name
)
2040 o
<< " " << (*it
)->name
;
2042 s
.print_warning ("never-assigned local variable '" + l
->name
+ "' " +
2043 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2049 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2051 functiondecl
*fd
= it
->second
;
2052 for (unsigned j
=0; j
<fd
->locals
.size(); /* see below */)
2054 vardecl
* l
= fd
->locals
[j
];
2055 if (vut
.read
.find (l
) == vut
.read
.end() &&
2056 vut
.written
.find (l
) == vut
.written
.end())
2058 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2059 ! s
.suppress_warnings
)
2060 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2061 else if (s
.verbose
>2)
2062 clog
<< "Eliding unused local variable "
2063 << l
->name
<< " in function " << fd
->name
2065 if (s
.tapset_compile_coverage
) {
2066 fd
->unused_locals
.push_back (fd
->locals
[j
]);
2068 fd
->locals
.erase(fd
->locals
.begin() + j
);
2070 // don't increment j
2074 if (vut
.written
.find (l
) == vut
.written
.end())
2075 if (iterations
== 0 && ! s
.suppress_warnings
)
2078 vector
<vardecl
*>::iterator it
;
2079 for (it
= fd
->formal_args
.begin() ;
2080 it
!= fd
->formal_args
.end(); it
++)
2081 if (l
->name
!= (*it
)->name
)
2082 o
<< " " << (*it
)->name
;
2083 for (it
= fd
->locals
.begin(); it
!= fd
->locals
.end(); it
++)
2084 if (l
->name
!= (*it
)->name
)
2085 o
<< " " << (*it
)->name
;
2086 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2087 if (l
->name
!= (*it
)->name
)
2088 o
<< " " << (*it
)->name
;
2090 s
.print_warning ("never-assigned local variable '" + l
->name
+ "' " +
2091 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2098 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
2100 vardecl
* l
= s
.globals
[i
];
2101 if (vut
.read
.find (l
) == vut
.read
.end() &&
2102 vut
.written
.find (l
) == vut
.written
.end())
2104 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2105 ! s
.suppress_warnings
)
2106 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2107 else if (s
.verbose
>2)
2108 clog
<< "Eliding unused global variable "
2110 if (s
.tapset_compile_coverage
) {
2111 s
.unused_globals
.push_back(s
.globals
[i
]);
2113 s
.globals
.erase(s
.globals
.begin() + i
);
2115 // don't increment i
2119 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
2120 if (iterations
== 0 && ! s
.suppress_warnings
)
2123 vector
<vardecl
*>::iterator it
;
2124 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2125 if (l
->name
!= (*it
)->name
)
2126 o
<< " " << (*it
)->name
;
2128 s
.print_warning ("never-assigned global variable '" + l
->name
+ "' " +
2129 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2138 // ------------------------------------------------------------------------
2140 struct dead_assignment_remover
: public update_visitor
2142 systemtap_session
& session
;
2144 const varuse_collecting_visitor
& vut
;
2146 dead_assignment_remover(systemtap_session
& s
, bool& r
,
2147 const varuse_collecting_visitor
& v
):
2148 session(s
), relaxed_p(r
), vut(v
) {}
2150 void visit_assignment (assignment
* e
);
2151 void visit_try_block (try_block
*s
);
2156 dead_assignment_remover::visit_assignment (assignment
* e
)
2161 symbol
* left
= get_symbol_within_expression (e
->left
);
2162 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2163 if (leftvar
) // not unresolved $target, so intended sideeffect may be elided
2165 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2167 // NB: Not so fast! The left side could be an array whose
2168 // index expressions may have side-effects. This would be
2169 // OK if we could replace the array assignment with a
2170 // statement-expression containing all the index expressions
2171 // and the rvalue... but we can't.
2172 // Another possibility is that we have an unread global variable
2173 // which are kept for probe end value display.
2175 bool is_global
= false;
2176 vector
<vardecl
*>::iterator it
;
2177 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2178 if (leftvar
->name
== (*it
)->name
)
2184 varuse_collecting_visitor
lvut(session
);
2185 e
->left
->visit (& lvut
);
2186 if (lvut
.side_effect_free () && !is_global
) // XXX: use _wrt() once we track focal_vars
2188 /* PR 1119: NB: This is not necessary here. A write-only
2189 variable will also be elided soon at the next _opt2 iteration.
2190 if (e->left->tok->location.file == session.user_file->name && // !tapset
2191 ! session.suppress_warnings)
2192 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
2195 if (session
.verbose
>2)
2196 clog
<< "Eliding assignment to " << leftvar
->name
2197 << " at " << *e
->tok
<< endl
;
2199 provide (e
->right
); // goodbye assignment*
2210 dead_assignment_remover::visit_try_block (try_block
*s
)
2212 replace (s
->try_block
);
2213 if (s
->catch_error_var
)
2215 vardecl
* errvar
= s
->catch_error_var
->referent
;
2216 if (vut
.read
.find(errvar
) == vut
.read
.end()) // never read?
2218 if (session
.verbose
>2)
2219 clog
<< "Eliding unused error string catcher " << errvar
->name
2220 << " at " << *s
->tok
<< endl
;
2221 s
->catch_error_var
= 0;
2224 replace (s
->catch_block
);
2229 // Let's remove assignments to variables that are never read. We
2230 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2231 // be optimized away as an unused variable, and expr a candidate to be
2232 // removed as a side-effect-free statement expression. Wahoo!
2233 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2235 // Recompute the varuse data, which will probably match the opt2
2236 // copy of the computation, except for those totally unused
2237 // variables that opt2 removed.
2238 varuse_collecting_visitor
vut(s
);
2239 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2240 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2242 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2243 // This instance may be reused for multiple probe/function body trims.
2245 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2246 dar
.replace (s
.probes
[i
]->body
);
2247 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2248 it
!= s
.functions
.end(); it
++)
2249 dar
.replace (it
->second
->body
);
2250 // The rewrite operation is performed within the visitor.
2252 // XXX: we could also zap write-only globals here
2256 // ------------------------------------------------------------------------
2258 struct dead_stmtexpr_remover
: public update_visitor
2260 systemtap_session
& session
;
2262 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2264 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2265 session(s
), relaxed_p(r
) {}
2267 void visit_block (block
*s
);
2268 void visit_try_block (try_block
*s
);
2269 void visit_null_statement (null_statement
*s
);
2270 void visit_if_statement (if_statement
* s
);
2271 void visit_foreach_loop (foreach_loop
*s
);
2272 void visit_for_loop (for_loop
*s
);
2273 // XXX: and other places where stmt_expr's might be nested
2275 void visit_expr_statement (expr_statement
*s
);
2280 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2283 if (session
.verbose
>2)
2284 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
2291 dead_stmtexpr_remover::visit_block (block
*s
)
2293 vector
<statement
*> new_stmts
;
2294 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2296 statement
* new_stmt
= require (s
->statements
[i
], true);
2299 // flatten nested blocks into this one
2300 block
*b
= dynamic_cast<block
*>(new_stmt
);
2303 if (session
.verbose
>2)
2304 clog
<< "Flattening nested block " << *b
->tok
<< endl
;
2305 new_stmts
.insert(new_stmts
.end(),
2306 b
->statements
.begin(), b
->statements
.end());
2310 new_stmts
.push_back (new_stmt
);
2313 if (new_stmts
.size() == 0)
2315 if (session
.verbose
>2)
2316 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
2319 else if (new_stmts
.size() == 1)
2321 if (session
.verbose
>2)
2322 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
2323 provide (new_stmts
[0]);
2327 s
->statements
= new_stmts
;
2333 dead_stmtexpr_remover::visit_try_block (try_block
*s
)
2335 replace (s
->try_block
, true);
2336 replace (s
->catch_block
, true); // null catch{} is ok and useful
2337 if (s
->try_block
== 0)
2339 if (session
.verbose
>2)
2340 clog
<< "Eliding empty try {} block " << *s
->tok
<< endl
;
2348 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2350 replace (s
->thenblock
, true);
2351 replace (s
->elseblock
, true);
2353 if (s
->thenblock
== 0)
2355 if (s
->elseblock
== 0)
2357 // We may be able to elide this statement, if the condition
2358 // expression is side-effect-free.
2359 varuse_collecting_visitor
vct(session
);
2360 s
->condition
->visit(& vct
);
2361 if (vct
.side_effect_free ())
2363 if (session
.verbose
>2)
2364 clog
<< "Eliding side-effect-free if statement "
2366 s
= 0; // yeah, baby
2370 // We can still turn it into a simple expr_statement though...
2371 if (session
.verbose
>2)
2372 clog
<< "Creating simple evaluation from if statement "
2374 expr_statement
*es
= new expr_statement
;
2375 es
->value
= s
->condition
;
2376 es
->tok
= es
->value
->tok
;
2383 // For an else without a then, we can invert the condition logic to
2384 // avoid having a null statement in the thenblock
2385 if (session
.verbose
>2)
2386 clog
<< "Inverting the condition of if statement "
2388 unary_expression
*ue
= new unary_expression
;
2389 ue
->operand
= s
->condition
;
2390 ue
->tok
= ue
->operand
->tok
;
2393 s
->thenblock
= s
->elseblock
;
2401 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2403 replace (s
->block
, true);
2407 // XXX what if s->limit has side effects?
2408 // XXX what about s->indexes or s->value used outside the loop?
2409 if (session
.verbose
>2)
2410 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2411 s
= 0; // yeah, baby
2417 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2419 replace (s
->block
, true);
2423 // We may be able to elide this statement, if the condition
2424 // expression is side-effect-free.
2425 varuse_collecting_visitor
vct(session
);
2426 if (s
->init
) s
->init
->visit(& vct
);
2427 s
->cond
->visit(& vct
);
2428 if (s
->incr
) s
->incr
->visit(& vct
);
2429 if (vct
.side_effect_free ())
2431 if (session
.verbose
>2)
2432 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2433 s
= 0; // yeah, baby
2437 // Can't elide this whole statement; put a null in there.
2438 s
->block
= new null_statement(s
->tok
);
2447 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2449 // Run a varuse query against the operand expression. If it has no
2450 // side-effects, replace the entire statement expression by a null
2451 // statement with the provide() call.
2453 // Unlike many other visitors, we do *not* traverse this outermost
2454 // one into the expression subtrees. There is no need - no
2455 // expr_statement nodes will be found there. (Function bodies
2456 // need to be visited explicitly by our caller.)
2458 // NB. While we don't share nodes in the parse tree, let's not
2459 // deallocate *s anyway, just in case...
2461 varuse_collecting_visitor
vut(session
);
2462 s
->value
->visit (& vut
);
2464 if (vut
.side_effect_free_wrt (focal_vars
))
2466 /* PR 1119: NB: this message is not a good idea here. It can
2467 name some arbitrary RHS expression of an assignment.
2468 if (s->value->tok->location.file == session.user_file->name && // not tapset
2469 ! session.suppress_warnings)
2470 clog << "WARNING: eliding never-assigned " << *s->value->tok << endl;
2473 if (session
.verbose
>2)
2474 clog
<< "Eliding side-effect-free expression "
2477 // NB: this 0 pointer is invalid to leave around for any length of
2478 // time, but the parent parse tree objects above handle it.
2486 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2488 // Finally, let's remove some statement-expressions that have no
2489 // side-effect. These should be exactly those whose private varuse
2490 // visitors come back with an empty "written" and "embedded" lists.
2492 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2493 // This instance may be reused for multiple probe/function body trims.
2495 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2497 if (pending_interrupts
) break;
2499 derived_probe
* p
= s
.probes
[i
];
2501 duv
.focal_vars
.clear ();
2502 duv
.focal_vars
.insert (s
.globals
.begin(),
2504 duv
.focal_vars
.insert (p
->locals
.begin(),
2507 duv
.replace (p
->body
, true);
2510 if (! s
.suppress_warnings
2511 && ! s
.timing
) // PR10070
2512 s
.print_warning ("side-effect-free probe '" + p
->name
+ "'", p
->tok
);
2514 p
->body
= new null_statement(p
->tok
);
2516 // XXX: possible duplicate warnings; see below
2519 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2521 if (pending_interrupts
) break;
2523 functiondecl
* fn
= it
->second
;
2524 duv
.focal_vars
.clear ();
2525 duv
.focal_vars
.insert (fn
->locals
.begin(),
2527 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2528 fn
->formal_args
.end());
2529 duv
.focal_vars
.insert (s
.globals
.begin(),
2532 duv
.replace (fn
->body
, true);
2535 if (! s
.suppress_warnings
)
2536 s
.print_warning ("side-effect-free function '" + fn
->name
+ "'", fn
->tok
);
2538 fn
->body
= new null_statement(fn
->tok
);
2540 // XXX: the next iteration of the outer optimization loop may
2541 // take this new null_statement away again, and thus give us a
2542 // fresh warning. It would be better if this fixup was performed
2543 // only after the relaxation iterations.
2544 // XXX: or else see bug #6469.
2550 // ------------------------------------------------------------------------
2552 // The goal of this visitor is to reduce top-level expressions in void context
2553 // into separate statements that evaluate each subcomponent of the expression.
2554 // The dead-statement-remover can later remove some parts if they have no side
2557 // All expressions must be overridden here so we never visit their subexpressions
2558 // accidentally. Thus, the only visited expressions should be value of an
2561 // For an expression to replace its expr_statement with something else, it will
2562 // let the new statement provide(), and then provide(0) for itself. The
2563 // expr_statement will take this as a sign that it's been replaced.
2564 struct void_statement_reducer
: public update_visitor
2566 systemtap_session
& session
;
2568 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2570 void_statement_reducer(systemtap_session
& s
, bool& r
):
2571 session(s
), relaxed_p(r
) {}
2573 void visit_expr_statement (expr_statement
* s
);
2575 // expressions in conditional / loop controls are definitely a side effect,
2576 // but still recurse into the child statements
2577 void visit_if_statement (if_statement
* s
);
2578 void visit_for_loop (for_loop
* s
);
2579 void visit_foreach_loop (foreach_loop
* s
);
2581 // these expressions get rewritten into their statement equivalents
2582 void visit_logical_or_expr (logical_or_expr
* e
);
2583 void visit_logical_and_expr (logical_and_expr
* e
);
2584 void visit_ternary_expression (ternary_expression
* e
);
2586 // all of these can be reduced into simpler statements
2587 void visit_binary_expression (binary_expression
* e
);
2588 void visit_unary_expression (unary_expression
* e
);
2589 void visit_comparison (comparison
* e
);
2590 void visit_concatenation (concatenation
* e
);
2591 void visit_functioncall (functioncall
* e
);
2592 void visit_print_format (print_format
* e
);
2593 void visit_target_symbol (target_symbol
* e
);
2594 void visit_cast_op (cast_op
* e
);
2595 void visit_defined_op (defined_op
* e
);
2597 // these are a bit hairy to grok due to the intricacies of indexables and
2598 // stats, so I'm chickening out and skipping them...
2599 void visit_array_in (array_in
* e
) { provide (e
); }
2600 void visit_arrayindex (arrayindex
* e
) { provide (e
); }
2601 void visit_stat_op (stat_op
* e
) { provide (e
); }
2602 void visit_hist_op (hist_op
* e
) { provide (e
); }
2604 // these can't be reduced because they always have an effect
2605 void visit_return_statement (return_statement
* s
) { provide (s
); }
2606 void visit_delete_statement (delete_statement
* s
) { provide (s
); }
2607 void visit_pre_crement (pre_crement
* e
) { provide (e
); }
2608 void visit_post_crement (post_crement
* e
) { provide (e
); }
2609 void visit_assignment (assignment
* e
) { provide (e
); }
2614 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2616 replace (s
->value
, true);
2618 // if the expression provides 0, that's our signal that a new
2619 // statement has been provided, so we shouldn't provide this one.
2625 void_statement_reducer::visit_if_statement (if_statement
* s
)
2627 // s->condition is never void
2628 replace (s
->thenblock
);
2629 replace (s
->elseblock
);
2634 void_statement_reducer::visit_for_loop (for_loop
* s
)
2636 // s->init/cond/incr are never void
2642 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
2644 // s->indexes/base/value/limit are never void
2650 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
2652 // In void context, the evaluation of "a || b" is exactly like
2653 // "if (!a) b", so let's do that instead.
2655 if (session
.verbose
>2)
2656 clog
<< "Creating if statement from unused logical-or "
2659 if_statement
*is
= new if_statement
;
2663 unary_expression
*ue
= new unary_expression
;
2664 ue
->operand
= e
->left
;
2669 expr_statement
*es
= new expr_statement
;
2670 es
->value
= e
->right
;
2671 es
->tok
= es
->value
->tok
;
2681 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
2683 // In void context, the evaluation of "a && b" is exactly like
2684 // "if (a) b", so let's do that instead.
2686 if (session
.verbose
>2)
2687 clog
<< "Creating if statement from unused logical-and "
2690 if_statement
*is
= new if_statement
;
2693 is
->condition
= e
->left
;
2695 expr_statement
*es
= new expr_statement
;
2696 es
->value
= e
->right
;
2697 es
->tok
= es
->value
->tok
;
2707 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
2709 // In void context, the evaluation of "a ? b : c" is exactly like
2710 // "if (a) b else c", so let's do that instead.
2712 if (session
.verbose
>2)
2713 clog
<< "Creating if statement from unused ternary expression "
2716 if_statement
*is
= new if_statement
;
2718 is
->condition
= e
->cond
;
2720 expr_statement
*es
= new expr_statement
;
2721 es
->value
= e
->truevalue
;
2722 es
->tok
= es
->value
->tok
;
2725 es
= new expr_statement
;
2726 es
->value
= e
->falsevalue
;
2727 es
->tok
= es
->value
->tok
;
2737 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
2739 // When the result of a binary operation isn't needed, it's just as good to
2740 // evaluate the operands as sequential statements in a block.
2742 if (session
.verbose
>2)
2743 clog
<< "Eliding unused binary " << *e
->tok
<< endl
;
2745 block
*b
= new block
;
2748 expr_statement
*es
= new expr_statement
;
2749 es
->value
= e
->left
;
2750 es
->tok
= es
->value
->tok
;
2751 b
->statements
.push_back(es
);
2753 es
= new expr_statement
;
2754 es
->value
= e
->right
;
2755 es
->tok
= es
->value
->tok
;
2756 b
->statements
.push_back(es
);
2765 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
2767 // When the result of a unary operation isn't needed, it's just as good to
2768 // evaluate the operand directly
2770 if (session
.verbose
>2)
2771 clog
<< "Eliding unused unary " << *e
->tok
<< endl
;
2774 e
->operand
->visit(this);
2778 void_statement_reducer::visit_comparison (comparison
* e
)
2780 visit_binary_expression(e
);
2784 void_statement_reducer::visit_concatenation (concatenation
* e
)
2786 visit_binary_expression(e
);
2790 void_statement_reducer::visit_functioncall (functioncall
* e
)
2792 // If a function call is pure and its result ignored, we can elide the call
2793 // and just evaluate the arguments in sequence
2795 if (!e
->args
.size())
2801 varuse_collecting_visitor
vut(session
);
2802 vut
.traversed
.insert (e
->referent
);
2803 vut
.current_function
= e
->referent
;
2804 e
->referent
->body
->visit (& vut
);
2805 if (!vut
.side_effect_free_wrt (focal_vars
))
2811 if (session
.verbose
>2)
2812 clog
<< "Eliding side-effect-free function call " << *e
->tok
<< endl
;
2814 block
*b
= new block
;
2817 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2819 expr_statement
*es
= new expr_statement
;
2820 es
->value
= e
->args
[i
];
2821 es
->tok
= es
->value
->tok
;
2822 b
->statements
.push_back(es
);
2832 void_statement_reducer::visit_print_format (print_format
* e
)
2834 // When an sprint's return value is ignored, we can simply evaluate the
2835 // arguments in sequence
2837 if (e
->print_to_stream
|| !e
->args
.size())
2843 if (session
.verbose
>2)
2844 clog
<< "Eliding unused print " << *e
->tok
<< endl
;
2846 block
*b
= new block
;
2849 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2851 expr_statement
*es
= new expr_statement
;
2852 es
->value
= e
->args
[i
];
2853 es
->tok
= es
->value
->tok
;
2854 b
->statements
.push_back(es
);
2864 void_statement_reducer::visit_target_symbol (target_symbol
* e
)
2866 // When target_symbol isn't needed, it's just as good to
2867 // evaluate any array indexes directly
2869 block
*b
= new block
;
2872 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2874 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2877 expr_statement
*es
= new expr_statement
;
2878 es
->value
= e
->components
[i
].expr_index
;
2879 es
->tok
= es
->value
->tok
;
2880 b
->statements
.push_back(es
);
2883 if (b
->statements
.empty())
2890 if (session
.verbose
>2)
2891 clog
<< "Eliding unused target symbol " << *e
->tok
<< endl
;
2900 void_statement_reducer::visit_cast_op (cast_op
* e
)
2902 // When the result of a cast operation isn't needed, it's just as good to
2903 // evaluate the operand and any array indexes directly
2905 block
*b
= new block
;
2908 expr_statement
*es
= new expr_statement
;
2909 es
->value
= e
->operand
;
2910 es
->tok
= es
->value
->tok
;
2911 b
->statements
.push_back(es
);
2913 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2915 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2918 es
= new expr_statement
;
2919 es
->value
= e
->components
[i
].expr_index
;
2920 es
->tok
= es
->value
->tok
;
2921 b
->statements
.push_back(es
);
2924 if (session
.verbose
>2)
2925 clog
<< "Eliding unused typecast " << *e
->tok
<< endl
;
2935 void_statement_reducer::visit_defined_op (defined_op
* e
)
2937 // When the result of a @defined operation isn't needed, just elide
2938 // it entirely. Its operand $expression must already be
2939 // side-effect-free.
2941 if (session
.verbose
>2)
2942 clog
<< "Eliding unused check " << *e
->tok
<< endl
;
2951 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2953 // Let's simplify statements with unused computed values.
2955 void_statement_reducer
vuv (s
, relaxed_p
);
2956 // This instance may be reused for multiple probe/function body trims.
2958 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
2960 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2961 vuv
.replace (s
.probes
[i
]->body
);
2962 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2963 it
!= s
.functions
.end(); it
++)
2964 vuv
.replace (it
->second
->body
);
2968 struct const_folder
: public update_visitor
2970 systemtap_session
& session
;
2973 const_folder(systemtap_session
& s
, bool& r
):
2974 session(s
), relaxed_p(r
), last_number(0), last_string(0) {}
2976 literal_number
* last_number
;
2977 literal_number
* get_number(expression
*& e
);
2978 void visit_literal_number (literal_number
* e
);
2980 literal_string
* last_string
;
2981 literal_string
* get_string(expression
*& e
);
2982 void visit_literal_string (literal_string
* e
);
2984 void get_literal(expression
*& e
, literal_number
*& n
, literal_string
*& s
);
2986 void visit_if_statement (if_statement
* s
);
2987 void visit_for_loop (for_loop
* s
);
2988 void visit_foreach_loop (foreach_loop
* s
);
2989 void visit_binary_expression (binary_expression
* e
);
2990 void visit_unary_expression (unary_expression
* e
);
2991 void visit_logical_or_expr (logical_or_expr
* e
);
2992 void visit_logical_and_expr (logical_and_expr
* e
);
2993 void visit_comparison (comparison
* e
);
2994 void visit_concatenation (concatenation
* e
);
2995 void visit_ternary_expression (ternary_expression
* e
);
2996 void visit_defined_op (defined_op
* e
);
2997 void visit_target_symbol (target_symbol
* e
);
3001 const_folder::get_literal(expression
*& e
,
3006 n
= (e
== last_number
) ? last_number
: NULL
;
3007 s
= (e
== last_string
) ? last_string
: NULL
;
3011 const_folder::get_number(expression
*& e
)
3014 return (e
== last_number
) ? last_number
: NULL
;
3018 const_folder::visit_literal_number (literal_number
* e
)
3025 const_folder::get_string(expression
*& e
)
3028 return (e
== last_string
) ? last_string
: NULL
;
3032 const_folder::visit_literal_string (literal_string
* e
)
3039 const_folder::visit_if_statement (if_statement
* s
)
3041 literal_number
* cond
= get_number (s
->condition
);
3044 replace (s
->thenblock
);
3045 replace (s
->elseblock
);
3050 if (session
.verbose
>2)
3051 clog
<< "Collapsing constant-" << cond
->value
<< " if-statement " << *s
->tok
<< endl
;
3054 statement
* n
= cond
->value
? s
->thenblock
: s
->elseblock
;
3058 provide (new null_statement (s
->tok
));
3063 const_folder::visit_for_loop (for_loop
* s
)
3065 literal_number
* cond
= get_number (s
->cond
);
3066 if (!cond
|| cond
->value
)
3075 if (session
.verbose
>2)
3076 clog
<< "Collapsing constantly-false for-loop " << *s
->tok
<< endl
;
3080 s
->init
->visit (this);
3082 provide (new null_statement (s
->tok
));
3087 const_folder::visit_foreach_loop (foreach_loop
* s
)
3089 literal_number
* limit
= get_number (s
->limit
);
3090 if (!limit
|| limit
->value
> 0)
3092 for (unsigned i
= 0; i
< s
->indexes
.size(); ++i
)
3093 replace (s
->indexes
[i
]);
3101 if (session
.verbose
>2)
3102 clog
<< "Collapsing constantly-limited foreach-loop " << *s
->tok
<< endl
;
3105 provide (new null_statement (s
->tok
));
3110 const_folder::visit_binary_expression (binary_expression
* e
)
3113 literal_number
* left
= get_number (e
->left
);
3114 literal_number
* right
= get_number (e
->right
);
3116 if (right
&& !right
->value
&& (e
->op
== "/" || e
->op
== "%"))
3118 // Give divide-by-zero a chance to be optimized out elsewhere,
3119 // and if not it will be a runtime error anyway...
3127 value
= left
->value
+ right
->value
;
3128 else if (e
->op
== "-")
3129 value
= left
->value
- right
->value
;
3130 else if (e
->op
== "*")
3131 value
= left
->value
* right
->value
;
3132 else if (e
->op
== "&")
3133 value
= left
->value
& right
->value
;
3134 else if (e
->op
== "|")
3135 value
= left
->value
| right
->value
;
3136 else if (e
->op
== "^")
3137 value
= left
->value
^ right
->value
;
3138 else if (e
->op
== ">>")
3139 value
= left
->value
>> max(min(right
->value
, (int64_t)64), (int64_t)0);
3140 else if (e
->op
== "<<")
3141 value
= left
->value
<< max(min(right
->value
, (int64_t)64), (int64_t)0);
3142 else if (e
->op
== "/")
3143 value
= (left
->value
== LLONG_MIN
&& right
->value
== -1) ? LLONG_MIN
:
3144 left
->value
/ right
->value
;
3145 else if (e
->op
== "%")
3146 value
= (left
->value
== LLONG_MIN
&& right
->value
== -1) ? 0 :
3147 left
->value
% right
->value
;
3149 throw semantic_error ("unsupported binary operator " + e
->op
);
3152 else if ((left
&& ((left
->value
== 0 && (e
->op
== "*" || e
->op
== "&" ||
3153 e
->op
== ">>" || e
->op
== "<<" )) ||
3154 (left
->value
==-1 && (e
->op
== "|" || e
->op
== ">>"))))
3156 (right
&& ((right
->value
== 0 && (e
->op
== "*" || e
->op
== "&")) ||
3157 (right
->value
== 1 && (e
->op
== "%")) ||
3158 (right
->value
==-1 && (e
->op
== "%" || e
->op
== "|")))))
3160 expression
* other
= left
? e
->right
: e
->left
;
3161 varuse_collecting_visitor
vu(session
);
3163 if (!vu
.side_effect_free())
3170 value
= left
->value
;
3171 else if (e
->op
== "%")
3174 value
= right
->value
;
3177 else if ((left
&& ((left
->value
== 0 && (e
->op
== "+" || e
->op
== "|" ||
3179 (left
->value
== 1 && (e
->op
== "*")) ||
3180 (left
->value
==-1 && (e
->op
== "&"))))
3182 (right
&& ((right
->value
== 0 && (e
->op
== "+" || e
->op
== "-" ||
3183 e
->op
== "|" || e
->op
== "^")) ||
3184 (right
->value
== 1 && (e
->op
== "*" || e
->op
== "/")) ||
3185 (right
->value
==-1 && (e
->op
== "&")) ||
3186 (right
->value
<= 0 && (e
->op
== ">>" || e
->op
== "<<")))))
3188 if (session
.verbose
>2)
3189 clog
<< "Collapsing constant-identity binary operator " << *e
->tok
<< endl
;
3192 provide (left
? e
->right
: e
->left
);
3202 if (session
.verbose
>2)
3203 clog
<< "Collapsing constant-" << value
<< " binary operator " << *e
->tok
<< endl
;
3206 literal_number
* n
= new literal_number(value
);
3212 const_folder::visit_unary_expression (unary_expression
* e
)
3214 literal_number
* operand
= get_number (e
->operand
);
3219 if (session
.verbose
>2)
3220 clog
<< "Collapsing constant unary " << *e
->tok
<< endl
;
3223 literal_number
* n
= new literal_number (*operand
);
3227 else if (e
->op
== "-")
3228 n
->value
= -n
->value
;
3229 else if (e
->op
== "!")
3230 n
->value
= !n
->value
;
3231 else if (e
->op
== "~")
3232 n
->value
= ~n
->value
;
3234 throw semantic_error ("unsupported unary operator " + e
->op
);
3240 const_folder::visit_logical_or_expr (logical_or_expr
* e
)
3243 literal_number
* left
= get_number (e
->left
);
3244 literal_number
* right
= get_number (e
->right
);
3247 value
= left
->value
|| right
->value
;
3249 else if ((left
&& left
->value
) || (right
&& right
->value
))
3251 // If the const is on the left, we get to short-circuit the right
3252 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3255 varuse_collecting_visitor
vu(session
);
3256 e
->left
->visit(&vu
);
3257 if (!vu
.side_effect_free())
3267 // We might also get rid of useless "0||x" and "x||0", except it does
3268 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3269 // that this would gain us much.
3277 if (session
.verbose
>2)
3278 clog
<< "Collapsing constant logical-OR " << *e
->tok
<< endl
;
3281 literal_number
* n
= new literal_number(value
);
3287 const_folder::visit_logical_and_expr (logical_and_expr
* e
)
3290 literal_number
* left
= get_number (e
->left
);
3291 literal_number
* right
= get_number (e
->right
);
3294 value
= left
->value
&& right
->value
;
3296 else if ((left
&& !left
->value
) || (right
&& !right
->value
))
3298 // If the const is on the left, we get to short-circuit the right
3299 // immediately. Otherwise, we can only eliminate the LHS if it's pure.
3302 varuse_collecting_visitor
vu(session
);
3303 e
->left
->visit(&vu
);
3304 if (!vu
.side_effect_free())
3314 // We might also get rid of useless "1&&x" and "x&&1", except it does
3315 // normalize x to 0 or 1. We could change it to "!!x", but it's not clear
3316 // that this would gain us much.
3324 if (session
.verbose
>2)
3325 clog
<< "Collapsing constant logical-AND " << *e
->tok
<< endl
;
3328 literal_number
* n
= new literal_number(value
);
3334 const_folder::visit_comparison (comparison
* e
)
3338 literal_number
*left_num
, *right_num
;
3339 literal_string
*left_str
, *right_str
;
3340 get_literal(e
->left
, left_num
, left_str
);
3341 get_literal(e
->right
, right_num
, right_str
);
3343 if (left_str
&& right_str
)
3344 comp
= left_str
->value
.compare(right_str
->value
);
3346 else if (left_num
&& right_num
)
3347 comp
= left_num
->value
< right_num
->value
? -1 :
3348 left_num
->value
> right_num
->value
? 1 : 0;
3350 else if ((left_num
&& ((left_num
->value
== LLONG_MIN
&&
3351 (e
->op
== "<=" || e
->op
== ">")) ||
3352 (left_num
->value
== LLONG_MAX
&&
3353 (e
->op
== ">=" || e
->op
== "<"))))
3355 (right_num
&& ((right_num
->value
== LLONG_MIN
&&
3356 (e
->op
== ">=" || e
->op
== "<")) ||
3357 (right_num
->value
== LLONG_MAX
&&
3358 (e
->op
== "<=" || e
->op
== ">")))))
3360 expression
* other
= left_num
? e
->right
: e
->left
;
3361 varuse_collecting_visitor
vu(session
);
3363 if (!vu
.side_effect_free())
3367 if (session
.verbose
>2)
3368 clog
<< "Collapsing constant-boundary comparison " << *e
->tok
<< endl
;
3371 // ops <= and >= are true, < and > are false
3372 literal_number
* n
= new literal_number( e
->op
.length() == 2 );
3385 if (session
.verbose
>2)
3386 clog
<< "Collapsing constant comparison " << *e
->tok
<< endl
;
3392 else if (e
->op
== "!=")
3394 else if (e
->op
== "<")
3396 else if (e
->op
== ">")
3398 else if (e
->op
== "<=")
3400 else if (e
->op
== ">=")
3403 throw semantic_error ("unsupported comparison operator " + e
->op
);
3405 literal_number
* n
= new literal_number(value
);
3411 const_folder::visit_concatenation (concatenation
* e
)
3413 literal_string
* left
= get_string (e
->left
);
3414 literal_string
* right
= get_string (e
->right
);
3418 if (session
.verbose
>2)
3419 clog
<< "Collapsing constant concatenation " << *e
->tok
<< endl
;
3422 literal_string
* n
= new literal_string (*left
);
3424 n
->value
.append(right
->value
);
3427 else if ((left
&& left
->value
.empty()) ||
3428 (right
&& right
->value
.empty()))
3430 if (session
.verbose
>2)
3431 clog
<< "Collapsing identity concatenation " << *e
->tok
<< endl
;
3433 provide(left
? e
->right
: e
->left
);
3440 const_folder::visit_ternary_expression (ternary_expression
* e
)
3442 literal_number
* cond
= get_number (e
->cond
);
3445 replace (e
->truevalue
);
3446 replace (e
->falsevalue
);
3451 if (session
.verbose
>2)
3452 clog
<< "Collapsing constant-" << cond
->value
<< " ternary " << *e
->tok
<< endl
;
3455 expression
* n
= cond
->value
? e
->truevalue
: e
->falsevalue
;
3461 const_folder::visit_defined_op (defined_op
* e
)
3463 // If a @defined makes it this far, then it is, de facto, undefined.
3465 if (session
.verbose
>2)
3466 clog
<< "Collapsing untouched @defined check " << *e
->tok
<< endl
;
3469 literal_number
* n
= new literal_number (0);
3475 const_folder::visit_target_symbol (target_symbol
* e
)
3477 if (session
.skip_badvars
)
3479 // Upon user request for ignoring context, the symbol is replaced
3480 // with a literal 0 and a warning message displayed
3481 // XXX this ignores possible side-effects, e.g. in array indexes
3482 literal_number
* ln_zero
= new literal_number (0);
3483 ln_zero
->tok
= e
->tok
;
3485 if (!session
.suppress_warnings
)
3486 session
.print_warning ("Bad $context variable being substituted with literal 0",
3488 else if (session
.verbose
> 2)
3489 clog
<< "Bad $context variable being substituted with literal 0, "
3494 update_visitor::visit_target_symbol (e
);
3497 static void semantic_pass_const_fold (systemtap_session
& s
, bool& relaxed_p
)
3499 // Let's simplify statements with constant values.
3501 const_folder
cf (s
, relaxed_p
);
3502 // This instance may be reused for multiple probe/function body trims.
3504 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
3505 cf
.replace (s
.probes
[i
]->body
);
3506 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
3507 it
!= s
.functions
.end(); it
++)
3508 cf
.replace (it
->second
->body
);
3512 struct duplicate_function_remover
: public functioncall_traversing_visitor
3514 systemtap_session
& s
;
3515 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
3517 duplicate_function_remover(systemtap_session
& sess
,
3518 map
<functiondecl
*, functiondecl
*>&dfm
):
3519 s(sess
), duplicate_function_map(dfm
) {};
3521 void visit_functioncall (functioncall
* e
);
3525 duplicate_function_remover::visit_functioncall (functioncall
*e
)
3527 functioncall_traversing_visitor::visit_functioncall (e
);
3529 // If the current function call reference points to a function that
3530 // is a duplicate, replace it.
3531 if (duplicate_function_map
.count(e
->referent
) != 0)
3534 clog
<< "Changing " << e
->referent
->name
3536 << duplicate_function_map
[e
->referent
]->name
3538 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
3539 e
->function
= duplicate_function_map
[e
->referent
]->name
;
3540 e
->referent
= duplicate_function_map
[e
->referent
];
3545 get_functionsig (functiondecl
* f
)
3549 // Get the "name:args body" of the function in s. We have to
3550 // include the args since the function 'x1(a, b)' is different than
3551 // the function 'x2(b, a)' even if the bodies of the two functions
3552 // are exactly the same.
3556 // printsig puts f->name + ':' on the front. Remove this
3557 // (otherwise, functions would never compare equal).
3558 string str
= s
.str().erase(0, f
->name
.size() + 1);
3560 // Return the function signature.
3564 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
3566 // Walk through all the functions, looking for duplicates.
3567 map
<string
, functiondecl
*> functionsig_map
;
3568 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
3571 vector
<functiondecl
*> newly_zapped_functions
;
3572 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
3574 functiondecl
*fd
= it
->second
;
3575 string functionsig
= get_functionsig(fd
);
3577 if (functionsig_map
.count(functionsig
) == 0)
3579 // This function is unique. Remember it.
3580 functionsig_map
[functionsig
] = fd
;
3584 // This function is a duplicate.
3585 duplicate_function_map
[fd
] = functionsig_map
[functionsig
];
3586 newly_zapped_functions
.push_back (fd
);
3590 for (unsigned i
=0; i
<newly_zapped_functions
.size(); i
++)
3592 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (newly_zapped_functions
[i
]->name
);
3593 assert (where
!= s
.functions
.end());
3594 s
.functions
.erase (where
);
3598 // If we have duplicate functions, traverse down the tree, replacing
3599 // the appropriate function calls.
3600 // duplicate_function_remover::visit_functioncall() handles the
3601 // details of replacing the function calls.
3602 if (duplicate_function_map
.size() != 0)
3604 duplicate_function_remover
dfr (s
, duplicate_function_map
);
3606 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
3607 s
.probes
[i
]->body
->visit(&dfr
);
3613 semantic_pass_optimize1 (systemtap_session
& s
)
3615 // In this pass, we attempt to rewrite probe/function bodies to
3616 // eliminate some blatantly unnecessary code. This is run before
3617 // type inference, but after symbol resolution and derived_probe
3618 // creation. We run an outer "relaxation" loop that repeats the
3619 // optimizations until none of them find anything to remove.
3623 bool relaxed_p
= false;
3624 unsigned iterations
= 0;
3627 if (pending_interrupts
) break;
3629 relaxed_p
= true; // until proven otherwise
3633 semantic_pass_opt1 (s
, relaxed_p
);
3634 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
3635 semantic_pass_opt3 (s
, relaxed_p
);
3636 semantic_pass_opt4 (s
, relaxed_p
);
3637 semantic_pass_opt5 (s
, relaxed_p
);
3640 // For listing mode, we need const-folding regardless of optimization so
3641 // that @defined expressions can be properly resolved. PR11360
3642 // We also want it in case variables are used in if/case expressions,
3643 // so enable always. PR11366
3644 semantic_pass_const_fold (s
, relaxed_p
);
3654 semantic_pass_optimize2 (systemtap_session
& s
)
3656 // This is run after type inference. We run an outer "relaxation"
3657 // loop that repeats the optimizations until none of them find
3658 // anything to remove.
3662 bool relaxed_p
= false;
3665 if (pending_interrupts
) break;
3666 relaxed_p
= true; // until proven otherwise
3669 semantic_pass_opt6 (s
, relaxed_p
);
3677 // ------------------------------------------------------------------------
3682 semantic_pass_types (systemtap_session
& s
)
3686 // next pass: type inference
3687 unsigned iterations
= 0;
3688 typeresolution_info
ti (s
);
3690 ti
.assert_resolvability
= false;
3691 // XXX: maybe convert to exception-based error signalling
3694 if (pending_interrupts
) break;
3697 ti
.num_newly_resolved
= 0;
3698 ti
.num_still_unresolved
= 0;
3700 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
3702 if (pending_interrupts
) break;
3704 functiondecl
* fd
= it
->second
;
3705 ti
.current_probe
= 0;
3706 ti
.current_function
= fd
;
3708 fd
->body
->visit (& ti
);
3709 // NB: we don't have to assert a known type for
3710 // functions here, to permit a "void" function.
3711 // The translator phase will omit the "retvalue".
3713 // if (fd->type == pe_unknown)
3714 // ti.unresolved (fd->tok);
3715 for (unsigned i
=0; i
< fd
->locals
.size(); ++i
)
3716 ti
.check_local (fd
->locals
[i
]);
3719 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
3721 if (pending_interrupts
) break;
3723 derived_probe
* pn
= s
.probes
[j
];
3724 ti
.current_function
= 0;
3725 ti
.current_probe
= pn
;
3727 pn
->body
->visit (& ti
);
3728 for (unsigned i
=0; i
< pn
->locals
.size(); ++i
)
3729 ti
.check_local (pn
->locals
[i
]);
3731 probe_point
* pp
= pn
->sole_location();
3734 ti
.current_function
= 0;
3735 ti
.current_probe
= 0;
3736 ti
.t
= pe_long
; // NB: expected type
3737 pp
->condition
->visit (& ti
);
3741 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
3743 vardecl
* gd
= s
.globals
[j
];
3744 if (gd
->type
== pe_unknown
)
3745 ti
.unresolved (gd
->tok
);
3748 if (ti
.num_newly_resolved
== 0) // converged
3750 if (ti
.num_still_unresolved
== 0)
3751 break; // successfully
3752 else if (! ti
.assert_resolvability
)
3753 ti
.assert_resolvability
= true; // last pass, with error msgs
3755 { // unsuccessful conclusion
3762 return rc
+ s
.num_errors();
3767 typeresolution_info::typeresolution_info (systemtap_session
& s
):
3768 session(s
), current_function(0), current_probe(0)
3774 typeresolution_info::visit_literal_number (literal_number
* e
)
3776 assert (e
->type
== pe_long
);
3777 if ((t
== e
->type
) || (t
== pe_unknown
))
3780 mismatch (e
->tok
, e
->type
, t
);
3785 typeresolution_info::visit_literal_string (literal_string
* e
)
3787 assert (e
->type
== pe_string
);
3788 if ((t
== e
->type
) || (t
== pe_unknown
))
3791 mismatch (e
->tok
, e
->type
, t
);
3796 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
3798 visit_binary_expression (e
);
3803 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
3805 visit_binary_expression (e
);
3810 typeresolution_info::visit_comparison (comparison
*e
)
3812 // NB: result of any comparison is an integer!
3813 if (t
== pe_stats
|| t
== pe_string
)
3814 invalid (e
->tok
, t
);
3816 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
3817 e
->left
->visit (this);
3818 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
3819 e
->right
->visit (this);
3821 if (e
->left
->type
!= pe_unknown
&&
3822 e
->right
->type
!= pe_unknown
&&
3823 e
->left
->type
!= e
->right
->type
)
3824 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3826 if (e
->type
== pe_unknown
)
3829 resolved (e
->tok
, e
->type
);
3835 typeresolution_info::visit_concatenation (concatenation
*e
)
3837 if (t
!= pe_unknown
&& t
!= pe_string
)
3838 invalid (e
->tok
, t
);
3841 e
->left
->visit (this);
3843 e
->right
->visit (this);
3845 if (e
->type
== pe_unknown
)
3847 e
->type
= pe_string
;
3848 resolved (e
->tok
, e
->type
);
3854 typeresolution_info::visit_assignment (assignment
*e
)
3857 invalid (e
->tok
, t
);
3859 if (e
->op
== "<<<") // stats aggregation
3862 invalid (e
->tok
, t
);
3865 e
->left
->visit (this);
3867 e
->right
->visit (this);
3868 if (e
->type
== pe_unknown
||
3869 e
->type
== pe_stats
)
3872 resolved (e
->tok
, e
->type
);
3876 else if (e
->left
->type
== pe_stats
)
3877 invalid (e
->left
->tok
, e
->left
->type
);
3879 else if (e
->right
->type
== pe_stats
)
3880 invalid (e
->right
->tok
, e
->right
->type
);
3882 else if (e
->op
== "+=" || // numeric only
3894 visit_binary_expression (e
);
3896 else if (e
->op
== ".=" || // string only
3899 if (t
== pe_long
|| t
== pe_stats
)
3900 invalid (e
->tok
, t
);
3903 e
->left
->visit (this);
3905 e
->right
->visit (this);
3906 if (e
->type
== pe_unknown
)
3908 e
->type
= pe_string
;
3909 resolved (e
->tok
, e
->type
);
3912 else if (e
->op
== "=") // overloaded = for string & numeric operands
3914 // logic similar to ternary_expression
3915 exp_type sub_type
= t
;
3917 // Infer types across the l/r values
3918 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3921 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3922 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
3924 e
->left
->visit (this);
3925 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3926 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
3928 e
->right
->visit (this);
3930 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3933 resolved (e
->tok
, e
->type
);
3935 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
3937 e
->type
= e
->left
->type
;
3938 resolved (e
->tok
, e
->type
);
3941 if (e
->left
->type
!= pe_unknown
&&
3942 e
->right
->type
!= pe_unknown
&&
3943 e
->left
->type
!= e
->right
->type
)
3944 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3948 throw semantic_error ("unsupported assignment operator " + e
->op
);
3953 typeresolution_info::visit_embedded_expr (embedded_expr
*e
)
3955 if (e
->type
== pe_unknown
)
3957 if (e
->code
.find ("/* string */") != string::npos
)
3958 e
->type
= pe_string
;
3959 else // if (e->code.find ("/* long */") != string::npos)
3962 resolved (e
->tok
, e
->type
);
3968 typeresolution_info::visit_binary_expression (binary_expression
* e
)
3970 if (t
== pe_stats
|| t
== pe_string
)
3971 invalid (e
->tok
, t
);
3974 e
->left
->visit (this);
3976 e
->right
->visit (this);
3978 if (e
->left
->type
!= pe_unknown
&&
3979 e
->right
->type
!= pe_unknown
&&
3980 e
->left
->type
!= e
->right
->type
)
3981 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3983 if (e
->type
== pe_unknown
)
3986 resolved (e
->tok
, e
->type
);
3992 typeresolution_info::visit_pre_crement (pre_crement
*e
)
3994 visit_unary_expression (e
);
3999 typeresolution_info::visit_post_crement (post_crement
*e
)
4001 visit_unary_expression (e
);
4006 typeresolution_info::visit_unary_expression (unary_expression
* e
)
4008 if (t
== pe_stats
|| t
== pe_string
)
4009 invalid (e
->tok
, t
);
4012 e
->operand
->visit (this);
4014 if (e
->type
== pe_unknown
)
4017 resolved (e
->tok
, e
->type
);
4023 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
4025 exp_type sub_type
= t
;
4028 e
->cond
->visit (this);
4030 // Infer types across the true/false arms of the ternary expression.
4032 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
4035 e
->truevalue
->visit (this);
4037 e
->falsevalue
->visit (this);
4039 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
4040 ; // already resolved
4041 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
4044 resolved (e
->tok
, e
->type
);
4046 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
4048 e
->type
= e
->truevalue
->type
;
4049 resolved (e
->tok
, e
->type
);
4051 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
4053 e
->type
= e
->falsevalue
->type
;
4054 resolved (e
->tok
, e
->type
);
4056 else if (e
->type
!= sub_type
)
4057 mismatch (e
->tok
, sub_type
, e
->type
);
4061 template <class Referrer
, class Referent
>
4062 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
4063 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
4065 exp_type
& re_type
= referrer
->type
;
4066 const token
* re_tok
= referrer
->tok
;
4067 exp_type
& te_type
= referent
->type
;
4068 const token
* te_tok
= referent
->tok
;
4070 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
4071 ; // do nothing: all three e->types in agreement
4072 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
4073 ; // do nothing: two known e->types in agreement
4074 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
4075 r
->mismatch (re_tok
, re_type
, te_type
);
4076 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
4077 r
->mismatch (re_tok
, re_type
, t
);
4078 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
4079 r
->mismatch (te_tok
, te_type
, t
);
4080 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
4082 // propagate from upstream
4084 r
->resolved (re_tok
, re_type
);
4085 // catch re_type/te_type mismatch later
4087 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
4089 // propagate from referent
4091 r
->resolved (re_tok
, re_type
);
4092 // catch re_type/t mismatch later
4094 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
4096 // propagate to referent
4098 r
->resolved (te_tok
, te_type
);
4099 // catch re_type/t mismatch later
4101 else if (! accept_unknown
)
4102 r
->unresolved (re_tok
);
4107 typeresolution_info::visit_symbol (symbol
* e
)
4109 assert (e
->referent
!= 0);
4110 resolve_2types (e
, e
->referent
, this, t
);
4115 typeresolution_info::visit_target_symbol (target_symbol
* e
)
4117 // This occurs only if a target symbol was not resolved over in
4118 // tapset.cxx land, that error was properly suppressed, and the
4119 // later unused-expression-elimination pass didn't get rid of it
4120 // either. So we have a target symbol that is believed to be of
4121 // genuine use, yet unresolved by the provider.
4123 if (session
.verbose
> 2)
4125 clog
<< "Resolution problem with ";
4126 if (current_function
)
4128 clog
<< "function " << current_function
->name
<< endl
;
4129 current_function
->body
->print (clog
);
4132 else if (current_probe
)
4134 clog
<< "probe " << *current_probe
->sole_location() << endl
;
4135 current_probe
->body
->print (clog
);
4139 clog
<< "other" << endl
;
4142 if (e
->saved_conversion_error
)
4143 throw (* (e
->saved_conversion_error
));
4145 throw semantic_error("unresolved target-symbol expression", e
->tok
);
4150 typeresolution_info::visit_defined_op (defined_op
* e
)
4152 throw semantic_error("unexpected @defined", e
->tok
);
4157 typeresolution_info::visit_cast_op (cast_op
* e
)
4159 // Like target_symbol, a cast_op shouldn't survive this far
4160 // unless it was not resolved and its value is really needed.
4161 if (e
->saved_conversion_error
)
4162 throw (* (e
->saved_conversion_error
));
4164 throw semantic_error("type definition '" + e
->type_name
+ "' not found", e
->tok
);
4169 typeresolution_info::visit_arrayindex (arrayindex
* e
)
4172 symbol
*array
= NULL
;
4173 hist_op
*hist
= NULL
;
4174 classify_indexable(e
->base
, array
, hist
);
4176 // Every hist_op has type [int]:int, that is to say, every hist_op
4177 // is a pseudo-one-dimensional integer array type indexed by
4178 // integers (bucket numbers).
4182 if (e
->indexes
.size() != 1)
4183 unresolved (e
->tok
);
4185 e
->indexes
[0]->visit (this);
4186 if (e
->indexes
[0]->type
!= pe_long
)
4187 unresolved (e
->tok
);
4189 if (e
->type
!= pe_long
)
4192 resolved (e
->tok
, pe_long
);
4197 // Now we are left with "normal" map inference and index checking.
4200 assert (array
->referent
!= 0);
4201 resolve_2types (e
, array
->referent
, this, t
);
4203 // now resolve the array indexes
4205 // if (e->referent->index_types.size() == 0)
4206 // // redesignate referent as array
4207 // e->referent->set_arity (e->indexes.size ());
4209 if (e
->indexes
.size() != array
->referent
->index_types
.size())
4210 unresolved (e
->tok
); // symbol resolution should prevent this
4211 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
4213 expression
* ee
= e
->indexes
[i
];
4214 exp_type
& ft
= array
->referent
->index_types
[i
];
4217 exp_type at
= ee
->type
;
4219 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
4221 // propagate to formal type
4223 resolved (array
->referent
->tok
, ft
);
4224 // uses array decl as there is no token for "formal type"
4227 invalid (ee
->tok
, at
);
4229 invalid (ee
->tok
, ft
);
4230 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4231 mismatch (e
->tok
, at
, ft
);
4232 if (at
== pe_unknown
)
4233 unresolved (ee
->tok
);
4239 typeresolution_info::visit_functioncall (functioncall
* e
)
4241 assert (e
->referent
!= 0);
4243 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
4245 if (e
->type
== pe_stats
)
4246 invalid (e
->tok
, e
->type
);
4248 // now resolve the function parameters
4249 if (e
->args
.size() != e
->referent
->formal_args
.size())
4250 unresolved (e
->tok
); // symbol resolution should prevent this
4251 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
4253 expression
* ee
= e
->args
[i
];
4254 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
4255 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
4258 exp_type at
= ee
->type
;
4260 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
4262 // propagate to formal arg
4264 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
4267 invalid (e
->tok
, at
);
4269 invalid (fe_tok
, ft
);
4270 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4271 mismatch (e
->tok
, at
, ft
);
4272 if (at
== pe_unknown
)
4273 unresolved (e
->tok
);
4279 typeresolution_info::visit_block (block
* e
)
4281 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
4286 e
->statements
[i
]->visit (this);
4288 catch (const semantic_error
& e
)
4290 session
.print_error (e
);
4297 typeresolution_info::visit_try_block (try_block
* e
)
4300 e
->try_block
->visit (this);
4301 if (e
->catch_error_var
)
4304 e
->catch_error_var
->visit (this);
4307 e
->catch_block
->visit (this);
4312 typeresolution_info::visit_embeddedcode (embeddedcode
* s
)
4314 // PR11573. If we have survived thus far with a piece of embedded
4315 // code that requires uprobes, we need to track this.
4317 // This is an odd place for this check, as opposed
4318 // to a separate 'optimization' pass, or c_unparser::visit_embeddedcode
4319 // over yonder in pass 3. However, we want to do it during pass 2 so
4320 // that cached sessions also get the uprobes treatment.
4321 if (!session
.need_uprobes
&& s
->code
.find("/* pragma:uprobes */") != string::npos
)
4323 if (session
.verbose
> 2)
4324 clog
<< "Activating uprobes support because /* pragma:uprobes */ seen." << endl
;
4325 session
.need_uprobes
= true;
4331 typeresolution_info::visit_if_statement (if_statement
* e
)
4334 e
->condition
->visit (this);
4337 e
->thenblock
->visit (this);
4342 e
->elseblock
->visit (this);
4348 typeresolution_info::visit_for_loop (for_loop
* e
)
4351 if (e
->init
) e
->init
->visit (this);
4353 e
->cond
->visit (this);
4355 if (e
->incr
) e
->incr
->visit (this);
4357 e
->block
->visit (this);
4362 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
4364 // See also visit_arrayindex.
4365 // This is different in that, being a statement, we can't assign
4366 // a type to the outer array, only propagate to/from the indexes
4368 // if (e->referent->index_types.size() == 0)
4369 // // redesignate referent as array
4370 // e->referent->set_arity (e->indexes.size ());
4372 exp_type wanted_value
= pe_unknown
;
4373 symbol
*array
= NULL
;
4374 hist_op
*hist
= NULL
;
4375 classify_indexable(e
->base
, array
, hist
);
4379 if (e
->indexes
.size() != 1)
4380 unresolved (e
->tok
);
4382 e
->indexes
[0]->visit (this);
4383 if (e
->indexes
[0]->type
!= pe_long
)
4384 unresolved (e
->tok
);
4386 wanted_value
= pe_long
;
4391 if (e
->indexes
.size() != array
->referent
->index_types
.size())
4392 unresolved (e
->tok
); // symbol resolution should prevent this
4393 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
4395 expression
* ee
= e
->indexes
[i
];
4396 exp_type
& ft
= array
->referent
->index_types
[i
];
4399 exp_type at
= ee
->type
;
4401 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
4403 // propagate to formal type
4405 resolved (array
->referent
->tok
, ft
);
4406 // uses array decl as there is no token for "formal type"
4409 invalid (ee
->tok
, at
);
4411 invalid (ee
->tok
, ft
);
4412 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
4413 mismatch (e
->tok
, at
, ft
);
4414 if (at
== pe_unknown
)
4415 unresolved (ee
->tok
);
4418 array
->visit (this);
4419 wanted_value
= array
->type
;
4424 if (wanted_value
== pe_stats
)
4425 invalid(e
->value
->tok
, wanted_value
);
4426 else if (wanted_value
!= pe_unknown
)
4427 check_arg_type(wanted_value
, e
->value
);
4431 e
->value
->visit (this);
4438 e
->limit
->visit (this);
4442 e
->block
->visit (this);
4447 typeresolution_info::visit_null_statement (null_statement
*)
4453 typeresolution_info::visit_expr_statement (expr_statement
* e
)
4456 e
->value
->visit (this);
4460 struct delete_statement_typeresolution_info
:
4461 public throwing_visitor
4463 typeresolution_info
*parent
;
4464 delete_statement_typeresolution_info (typeresolution_info
*p
):
4465 throwing_visitor ("invalid operand of delete expression"),
4469 void visit_arrayindex (arrayindex
* e
)
4471 parent
->visit_arrayindex (e
);
4474 void visit_symbol (symbol
* e
)
4476 exp_type ignored
= pe_unknown
;
4477 assert (e
->referent
!= 0);
4478 resolve_2types (e
, e
->referent
, parent
, ignored
);
4484 typeresolution_info::visit_delete_statement (delete_statement
* e
)
4486 delete_statement_typeresolution_info
di (this);
4488 e
->value
->visit (&di
);
4493 typeresolution_info::visit_next_statement (next_statement
*)
4499 typeresolution_info::visit_break_statement (break_statement
*)
4505 typeresolution_info::visit_continue_statement (continue_statement
*)
4511 typeresolution_info::visit_array_in (array_in
* e
)
4513 // all unary operators only work on numerics
4515 t
= pe_unknown
; // array value can be anything
4516 e
->operand
->visit (this);
4518 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
4519 ; // already resolved
4520 else if (t1
== pe_string
|| t1
== pe_stats
)
4521 mismatch (e
->tok
, t1
, pe_long
);
4522 else if (e
->type
== pe_unknown
)
4525 resolved (e
->tok
, e
->type
);
4531 typeresolution_info::visit_return_statement (return_statement
* e
)
4533 // This is like symbol, where the referent is
4534 // the return value of the function.
4536 // translation pass will print error
4537 if (current_function
== 0)
4540 exp_type
& e_type
= current_function
->type
;
4541 t
= current_function
->type
;
4542 e
->value
->visit (this);
4544 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
4545 && e_type
!= e
->value
->type
)
4546 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
4547 if (e_type
== pe_unknown
&&
4548 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
4550 // propagate non-statistics from value
4551 e_type
= e
->value
->type
;
4552 resolved (current_function
->tok
, e
->value
->type
);
4554 if (e
->value
->type
== pe_stats
)
4555 invalid (e
->value
->tok
, e
->value
->type
);
4559 typeresolution_info::visit_print_format (print_format
* e
)
4561 size_t unresolved_args
= 0;
4565 e
->hist
->visit(this);
4568 else if (e
->print_with_format
)
4570 // If there's a format string, we can do both inference *and*
4573 // First we extract the subsequence of formatting components
4574 // which are conversions (not just literal string components)
4576 unsigned expected_num_args
= 0;
4577 std::vector
<print_format::format_component
> components
;
4578 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
4580 if (e
->components
[i
].type
== print_format::conv_unspecified
)
4581 throw semantic_error ("Unspecified conversion in print operator format string",
4583 else if (e
->components
[i
].type
== print_format::conv_literal
)
4585 components
.push_back(e
->components
[i
]);
4586 ++expected_num_args
;
4587 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
4588 ++expected_num_args
;
4589 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
4590 ++expected_num_args
;
4593 // Then we check that the number of conversions and the number
4596 if (expected_num_args
!= e
->args
.size())
4597 throw semantic_error ("Wrong number of args to formatted print operator",
4600 // Then we check that the types of the conversions match the types
4603 for (size_t i
= 0; i
< components
.size(); ++i
)
4605 // Check the dynamic width, if specified
4606 if (components
[i
].widthtype
== print_format::width_dynamic
)
4608 check_arg_type (pe_long
, e
->args
[argno
]);
4612 // Check the dynamic precision, if specified
4613 if (components
[i
].prectype
== print_format::prec_dynamic
)
4615 check_arg_type (pe_long
, e
->args
[argno
]);
4619 exp_type wanted
= pe_unknown
;
4621 switch (components
[i
].type
)
4623 case print_format::conv_unspecified
:
4624 case print_format::conv_literal
:
4628 case print_format::conv_signed_decimal
:
4629 case print_format::conv_unsigned_decimal
:
4630 case print_format::conv_unsigned_octal
:
4631 case print_format::conv_unsigned_ptr
:
4632 case print_format::conv_unsigned_uppercase_hex
:
4633 case print_format::conv_unsigned_lowercase_hex
:
4634 case print_format::conv_binary
:
4635 case print_format::conv_char
:
4636 case print_format::conv_memory
:
4637 case print_format::conv_memory_hex
:
4641 case print_format::conv_string
:
4646 assert (wanted
!= pe_unknown
);
4647 check_arg_type (wanted
, e
->args
[argno
]);
4653 // Without a format string, the best we can do is require that
4654 // each argument resolve to a concrete type.
4655 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
4658 e
->args
[i
]->visit (this);
4659 if (e
->args
[i
]->type
== pe_unknown
)
4661 unresolved (e
->args
[i
]->tok
);
4667 if (unresolved_args
== 0)
4669 if (e
->type
== pe_unknown
)
4671 if (e
->print_to_stream
)
4674 e
->type
= pe_string
;
4675 resolved (e
->tok
, e
->type
);
4680 e
->type
= pe_unknown
;
4681 unresolved (e
->tok
);
4687 typeresolution_info::visit_stat_op (stat_op
* e
)
4690 e
->stat
->visit (this);
4691 if (e
->type
== pe_unknown
)
4694 resolved (e
->tok
, e
->type
);
4696 else if (e
->type
!= pe_long
)
4697 mismatch (e
->tok
, e
->type
, pe_long
);
4701 typeresolution_info::visit_hist_op (hist_op
* e
)
4704 e
->stat
->visit (this);
4709 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
4714 if (arg
->type
== pe_unknown
)
4717 resolved (arg
->tok
, wanted
);
4719 else if (arg
->type
!= wanted
)
4721 mismatch (arg
->tok
, arg
->type
, wanted
);
4727 typeresolution_info::check_local (vardecl
* v
)
4731 num_still_unresolved
++;
4732 if (assert_resolvability
)
4734 (semantic_error ("array locals not supported, missing global declaration? ", v
->tok
));
4737 if (v
->type
== pe_unknown
)
4738 unresolved (v
->tok
);
4739 else if (v
->type
== pe_stats
)
4741 num_still_unresolved
++;
4742 if (assert_resolvability
)
4744 (semantic_error ("stat locals not supported, missing global declaration? ", v
->tok
));
4746 else if (!(v
->type
== pe_long
|| v
->type
== pe_string
))
4747 invalid (v
->tok
, v
->type
);
4752 typeresolution_info::unresolved (const token
* tok
)
4754 num_still_unresolved
++;
4756 if (assert_resolvability
)
4759 msg
<< "unresolved type ";
4760 session
.print_error (semantic_error (msg
.str(), tok
));
4766 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
4768 num_still_unresolved
++;
4770 if (assert_resolvability
)
4773 if (tok
&& tok
->type
== tok_operator
)
4774 msg
<< "invalid operator";
4776 msg
<< "invalid type " << pe
;
4777 session
.print_error (semantic_error (msg
.str(), tok
));
4783 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
4785 bool tok_resolved
= false;
4787 semantic_error
* err1
= 0;
4788 num_still_unresolved
++;
4790 //BZ 9719: for improving type mismatch messages, a semantic error is
4791 //generated with the token where type was first resolved. All such
4792 //resolved tokens, stored in a vector, are matched against their
4793 //content. If an error for the matching token hasn't been printed out
4794 //already, it is and the token pushed in another printed_toks vector
4796 if (assert_resolvability
)
4799 for (i
=0; i
<resolved_toks
.size(); i
++)
4801 if (resolved_toks
[i
]->content
== tok
->content
)
4803 tok_resolved
= true;
4809 msg
<< "type mismatch (" << t1
<< " vs. " << t2
<< ")";
4813 bool tok_printed
= false;
4814 for (size_t j
=0; j
<printed_toks
.size(); j
++)
4816 if (printed_toks
[j
] == resolved_toks
[i
])
4822 msg
<< "type mismatch (" << t1
<< " vs. " << t2
<< ")";
4825 //error for possible mismatch in the earlier resolved token
4826 printed_toks
.push_back (resolved_toks
[i
]);
4827 stringstream type_msg
;
4828 type_msg
<< "type was first inferred here (" << t2
<< ")";
4829 err1
= new semantic_error (type_msg
.str(), resolved_toks
[i
]);
4832 semantic_error
err (msg
.str(), tok
);
4834 session
.print_error (err
);
4840 typeresolution_info::resolved (const token
* tok
, exp_type
)
4842 resolved_toks
.push_back (tok
);
4843 num_newly_resolved
++;
4846 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */