1 // elaboration functions
2 // Copyright (C) 2005-2008 Red Hat Inc.
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
10 #include "elaborate.h"
17 #include <sys/utsname.h>
34 // ------------------------------------------------------------------------
36 // Used in probe_point condition construction. Either argument may be
37 // NULL; if both, return NULL too. Resulting expression is a deep
38 // copy for symbol resolution purposes.
39 expression
* add_condition (expression
* a
, expression
* b
)
41 if (!a
&& !b
) return 0;
42 if (! a
) return deep_copy_visitor::deep_copy(b
);
43 if (! b
) return deep_copy_visitor::deep_copy(a
);
48 la
.tok
= a
->tok
; // or could be b->tok
49 return deep_copy_visitor::deep_copy(& la
);
52 // ------------------------------------------------------------------------
56 derived_probe::derived_probe (probe
*p
):
60 this->locations
= p
->locations
;
62 this->privileged
= p
->privileged
;
63 this->body
= deep_copy_visitor::deep_copy(p
->body
);
67 derived_probe::derived_probe (probe
*p
, probe_point
*l
):
72 this->privileged
= p
->privileged
;
73 this->body
= deep_copy_visitor::deep_copy(p
->body
);
76 this->locations
.push_back (l
);
81 derived_probe::printsig (ostream
& o
) const
88 derived_probe::printsig_nested (ostream
& o
) const
90 // We'd like to enclose the probe derivation chain in a /* */
91 // comment delimiter. But just printing /* base->printsig() */ is
92 // not enough, since base might itself be a derived_probe. So we,
93 // er, "cleverly" encode our nesting state as a formatting flag for
95 ios::fmtflags f
= o
.flags (ios::internal
);
96 if (f
& ios::internal
)
115 derived_probe::collect_derivation_chain (std::vector
<probe
*> &probes_list
)
117 probes_list
.push_back(this);
118 base
->collect_derivation_chain(probes_list
);
123 derived_probe::sole_location () const
125 if (locations
.size() == 0)
126 throw semantic_error ("derived_probe with no locations", this->tok
);
127 else if (locations
.size() > 1)
128 throw semantic_error ("derived_probe with too many locations", this->tok
);
135 // ------------------------------------------------------------------------
136 // Members of derived_probe_builder
139 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
140 const std::string
& key
,
143 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
144 if (i
== params
.end())
146 literal_string
* ls
= dynamic_cast<literal_string
*>(i
->second
);
155 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
156 const std::string
& key
,
159 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
160 if (i
== params
.end())
162 if (i
->second
== NULL
)
164 literal_number
* ln
= dynamic_cast<literal_number
*>(i
->second
);
173 derived_probe_builder::has_null_param (std::map
<std::string
, literal
*> const & params
,
174 const std::string
& key
)
176 map
<string
, literal
*>::const_iterator i
= params
.find(key
);
177 return (i
!= params
.end() && i
->second
== NULL
);
182 // ------------------------------------------------------------------------
183 // Members of match_key.
185 match_key::match_key(string
const & n
)
187 have_parameter(false),
188 parameter_type(pe_unknown
)
192 match_key::match_key(probe_point::component
const & c
)
194 have_parameter(c
.arg
!= NULL
),
195 parameter_type(c
.arg
? c
.arg
->type
: pe_unknown
)
200 match_key::with_number()
202 have_parameter
= true;
203 parameter_type
= pe_long
;
208 match_key::with_string()
210 have_parameter
= true;
211 parameter_type
= pe_string
;
216 match_key::str() const
219 switch (parameter_type
)
221 case pe_string
: return name
+ "(string)";
222 case pe_long
: return name
+ "(number)";
223 default: return name
+ "(...)";
229 match_key::operator<(match_key
const & other
) const
231 return ((name
< other
.name
)
233 || (name
== other
.name
234 && have_parameter
< other
.have_parameter
)
236 || (name
== other
.name
237 && have_parameter
== other
.have_parameter
238 && parameter_type
< other
.parameter_type
));
242 isglob(string
const & str
)
244 return(str
.find('*') != str
.npos
);
248 match_key::globmatch(match_key
const & other
) const
250 const char *other_str
= other
.name
.c_str();
251 const char *name_str
= name
.c_str();
253 return ((fnmatch(name_str
, other_str
, FNM_NOESCAPE
) == 0)
254 && have_parameter
== other
.have_parameter
255 && parameter_type
== other
.parameter_type
);
258 // ------------------------------------------------------------------------
259 // Members of match_node
260 // ------------------------------------------------------------------------
262 match_node::match_node()
267 match_node::bind(match_key
const & k
)
270 throw semantic_error("invalid use of wildcard probe point component");
272 map
<match_key
, match_node
*>::const_iterator i
= sub
.find(k
);
275 match_node
* n
= new match_node();
276 sub
.insert(make_pair(k
, n
));
281 match_node::bind(derived_probe_builder
* e
)
284 throw semantic_error("duplicate probe point pattern");
289 match_node::bind(string
const & k
)
291 return bind(match_key(k
));
295 match_node::bind_str(string
const & k
)
297 return bind(match_key(k
).with_string());
301 match_node::bind_num(string
const & k
)
303 return bind(match_key(k
).with_number());
308 match_node::find_and_build (systemtap_session
& s
,
309 probe
* p
, probe_point
*loc
, unsigned pos
,
310 vector
<derived_probe
*>& results
)
312 assert (pos
<= loc
->components
.size());
313 if (pos
== loc
->components
.size()) // matched all probe point components so far
315 derived_probe_builder
*b
= end
; // may be 0 if only nested names are bound
320 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
321 alternatives
+= string(" ") + i
->first
.str();
323 throw semantic_error (string("probe point truncated at position ") +
324 lex_cast
<string
> (pos
) +
325 " (follow:" + alternatives
+ ")");
328 map
<string
, literal
*> param_map
;
329 for (unsigned i
=0; i
<pos
; i
++)
330 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
333 b
->build (s
, p
, loc
, param_map
, results
);
335 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
337 match_key
match (* loc
->components
[pos
]);
339 // Call find_and_build for each possible match. Ignore errors -
340 // unless we don't find any match.
341 unsigned int num_results
= results
.size();
342 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
344 const match_key
& subkey
= i
->first
;
345 match_node
* subnode
= i
->second
;
347 if (pending_interrupts
) break;
349 if (match
.globmatch(subkey
))
352 clog
<< "wildcard '" << loc
->components
[pos
]->functor
353 << "' matched '" << subkey
.name
<< "'" << endl
;
355 // When we have a wildcard, we need to create a copy of
356 // the probe point. Then we'll create a copy of the
357 // wildcard component, and substitute the non-wildcard
359 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
360 probe_point::component
*non_wildcard_component
361 = new probe_point::component(*loc
->components
[pos
]);
362 non_wildcard_component
->functor
= subkey
.name
;
363 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
365 // NB: probe conditions are not attached at the wildcard
366 // (component/functor) level, but at the overall
367 // probe_point level.
369 // recurse (with the non-wildcard probe point)
372 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
375 catch (const semantic_error
& e
)
377 // Ignore semantic_errors while expanding wildcards.
378 // If we get done and nothing was expanded, the code
379 // following the loop will complain.
381 // If this wildcard didn't match, cleanup.
382 delete non_wildcard_pp
;
383 delete non_wildcard_component
;
387 if (! loc
->optional
&& num_results
== results
.size())
389 // We didn't find any wildcard matches (since the size of
390 // the result vector didn't change). Throw an error.
392 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
393 alternatives
+= string(" ") + i
->first
.str();
395 throw semantic_error(string("probe point mismatch at position ") +
396 lex_cast
<string
> (pos
) +
397 " (alternatives:" + alternatives
+ ")");
402 match_key
match (* loc
->components
[pos
]);
403 sub_map_iterator_t i
= sub
.find (match
);
404 if (i
== sub
.end()) // no match
407 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
408 alternatives
+= string(" ") + i
->first
.str();
410 throw semantic_error (string("probe point mismatch at position ") +
411 lex_cast
<string
> (pos
) +
412 " (alternatives:" + alternatives
+ ")");
415 match_node
* subnode
= i
->second
;
417 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
423 match_node::build_no_more (systemtap_session
& s
)
425 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
426 i
->second
->build_no_more (s
);
427 if (end
) end
->build_no_more (s
);
431 // ------------------------------------------------------------------------
433 // ------------------------------------------------------------------------
435 struct alias_derived_probe
: public derived_probe
437 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
):
438 derived_probe (base
, l
), alias(a
) {}
440 void upchuck () { throw semantic_error ("inappropriate", this->tok
); }
442 // Alias probes are immediately expanded to other derived_probe
443 // types, and are not themselves emitted or listed in
444 // systemtap_session.probes
446 void join_group (systemtap_session
&) { upchuck (); }
448 virtual const probe_alias
*get_alias () const { return alias
; }
451 const probe_alias
*alias
; // Used to check for recursion
456 alias_expansion_builder
457 : public derived_probe_builder
461 alias_expansion_builder(probe_alias
* a
)
465 virtual void build(systemtap_session
& sess
,
467 probe_point
* location
,
468 std::map
<std::string
, literal
*> const &,
469 vector
<derived_probe
*> & finished_results
)
471 // Don't build the alias expansion if infinite recursion is detected.
472 if (checkForRecursiveExpansion (use
)) {
474 msg
<< "Recursive loop in alias expansion of " << *location
<< " at " << location
->tok
->location
;
475 // semantic_errors thrown here are ignored.
476 sess
.print_error (semantic_error (msg
.str()));
480 // We're going to build a new probe and wrap it up in an
481 // alias_expansion_probe so that the expansion loop recognizes it as
482 // such and re-expands its expansion.
484 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
);
485 n
->body
= new block();
487 // The new probe gets the location list of the alias (with incoming condition joined)
488 n
->locations
= alias
->locations
;
489 for (unsigned i
=0; i
<n
->locations
.size(); i
++)
490 n
->locations
[i
]->condition
= add_condition (n
->locations
[i
]->condition
,
491 location
->condition
);
493 // the token location of the alias,
494 n
->tok
= location
->tok
;
496 // and statements representing the concatenation of the alias'
497 // body with the use's.
499 // NB: locals are *not* copied forward, from either alias or
500 // use. The expansion should have its locals re-inferred since
501 // there's concatenated code here and we only want one vardecl per
502 // resulting variable.
504 if (alias
->epilogue_style
)
505 n
->body
= new block (use
->body
, alias
->body
);
507 n
->body
= new block (alias
->body
, use
->body
);
509 derive_probes (sess
, n
, finished_results
, location
->optional
);
512 bool checkForRecursiveExpansion (probe
*use
)
514 // Collect the derivation chain of this probe.
515 vector
<probe
*>derivations
;
516 use
->collect_derivation_chain (derivations
);
518 // Check all probe points in the alias expansion against the currently-being-expanded probe point
519 // of each of the probes in the derivation chain, looking for a match. This
520 // indicates infinite recursion.
521 // The first element of the derivation chain will be the derived_probe representing 'use', so
522 // start the search with the second element.
523 assert (derivations
.size() > 0);
524 assert (derivations
[0] == use
);
525 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
526 if (use
->get_alias() == derivations
[d
]->get_alias())
527 return true; // recursion detected
534 // ------------------------------------------------------------------------
536 // ------------------------------------------------------------------------
539 // Register all the aliases we've seen in library files, and the user
540 // file, as patterns.
543 systemtap_session::register_library_aliases()
545 vector
<stapfile
*> files(library_files
);
546 files
.push_back(user_file
);
548 for (unsigned f
= 0; f
< files
.size(); ++f
)
550 stapfile
* file
= files
[f
];
551 for (unsigned a
= 0; a
< file
->aliases
.size(); ++a
)
553 probe_alias
* alias
= file
->aliases
[a
];
556 for (unsigned n
= 0; n
< alias
->alias_names
.size(); ++n
)
558 probe_point
* name
= alias
->alias_names
[n
];
559 match_node
* n
= pattern_root
;
560 for (unsigned c
= 0; c
< name
->components
.size(); ++c
)
562 probe_point::component
* comp
= name
->components
[c
];
563 // XXX: alias parameters
565 throw semantic_error("alias component "
567 + " contains illegal parameter");
568 n
= n
->bind(comp
->functor
);
570 n
->bind(new alias_expansion_builder(alias
));
573 catch (const semantic_error
& e
)
575 semantic_error
* er
= new semantic_error (e
); // copy it
578 msg
<< " while registering probe alias ";
579 alias
->printsig(msg
);
580 er
->msg2
= msg
.str();
589 static unsigned max_recursion
= 100;
595 recursion_guard(unsigned & i
) : i(i
)
597 if (i
> max_recursion
)
598 throw semantic_error("recursion limit reached");
607 // The match-and-expand loop.
609 derive_probes (systemtap_session
& s
,
610 probe
*p
, vector
<derived_probe
*>& dps
,
613 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
615 if (pending_interrupts
) break;
617 probe_point
*loc
= p
->locations
[i
];
621 unsigned num_atbegin
= dps
.size();
623 // Pass down optional flag from e.g. alias reference to each
624 // probe_point instance. We do this by temporarily overriding
625 // the probe_point optional flag. We could instead deep-copy
626 // and set a flag on the copy permanently.
627 bool old_loc_opt
= loc
->optional
;
628 loc
->optional
= loc
->optional
|| optional
;
629 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
630 loc
->optional
= old_loc_opt
;
631 unsigned num_atend
= dps
.size();
633 if (! (loc
->optional
||optional
) && // something required, but
634 num_atbegin
== num_atend
) // nothing new derived!
635 throw semantic_error ("no match");
637 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
641 clog
<< "Probe point ";
642 p
->locations
[i
]->print(clog
);
643 clog
<< " sufficient, skipped";
644 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
647 p
->locations
[j
]->print(clog
);
651 break; // we need not try to derive for any other locations
654 catch (const semantic_error
& e
)
656 // XXX: prefer not to print_error at every nest/unroll level
658 semantic_error
* er
= new semantic_error (e
); // copy it
661 msg
<< " while resolving probe point " << *loc
;
662 er
->msg2
= msg
.str();
663 s
.print_error (* er
);
672 // ------------------------------------------------------------------------
674 // Indexable usage checks
677 struct symbol_fetcher
678 : public throwing_visitor
682 symbol_fetcher (symbol
*&sym
): sym(sym
)
685 void visit_symbol (symbol
* e
)
690 void visit_target_symbol (target_symbol
* e
)
695 void visit_arrayindex (arrayindex
* e
)
697 e
->base
->visit_indexable (this);
700 void throwone (const token
* t
)
702 throw semantic_error ("Expecting symbol or array index expression", t
);
707 get_symbol_within_expression (expression
*e
)
710 symbol_fetcher
fetcher(sym
);
712 return sym
; // NB: may be null!
716 get_symbol_within_indexable (indexable
*ix
)
718 symbol
*array
= NULL
;
719 hist_op
*hist
= NULL
;
720 classify_indexable(ix
, array
, hist
);
724 return get_symbol_within_expression (hist
->stat
);
727 struct mutated_var_collector
728 : public traversing_visitor
730 set
<vardecl
*> * mutated_vars
;
732 mutated_var_collector (set
<vardecl
*> * mm
)
736 void visit_assignment(assignment
* e
)
738 if (e
->type
== pe_stats
&& e
->op
== "<<<")
740 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
742 mutated_vars
->insert (vd
);
744 traversing_visitor::visit_assignment(e
);
747 void visit_arrayindex (arrayindex
*e
)
749 if (is_active_lvalue (e
))
752 if (e
->base
->is_symbol (sym
))
753 mutated_vars
->insert (sym
->referent
);
755 throw semantic_error("Assignment to read-only histogram bucket", e
->tok
);
757 traversing_visitor::visit_arrayindex (e
);
762 struct no_var_mutation_during_iteration_check
763 : public traversing_visitor
765 systemtap_session
& session
;
766 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
767 vector
<vardecl
*> vars_being_iterated
;
769 no_var_mutation_during_iteration_check
770 (systemtap_session
& sess
,
771 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
772 : session(sess
), function_mutates_vars (fmv
)
775 void visit_arrayindex (arrayindex
*e
)
777 if (is_active_lvalue(e
))
779 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
782 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
784 vardecl
*v
= vars_being_iterated
[i
];
787 string err
= ("variable '" + v
->name
+
788 "' modified during 'foreach' iteration");
789 session
.print_error (semantic_error (err
, e
->tok
));
794 traversing_visitor::visit_arrayindex (e
);
797 void visit_functioncall (functioncall
* e
)
799 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
800 = function_mutates_vars
.find (e
->referent
);
802 if (i
!= function_mutates_vars
.end())
804 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
806 vardecl
*m
= vars_being_iterated
[j
];
807 if (i
->second
->find (m
) != i
->second
->end())
809 string err
= ("function call modifies var '" + m
->name
+
810 "' during 'foreach' iteration");
811 session
.print_error (semantic_error (err
, e
->tok
));
816 traversing_visitor::visit_functioncall (e
);
819 void visit_foreach_loop(foreach_loop
* s
)
821 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
824 vars_being_iterated
.push_back (vd
);
826 traversing_visitor::visit_foreach_loop (s
);
829 vars_being_iterated
.pop_back();
834 // ------------------------------------------------------------------------
836 struct stat_decl_collector
837 : public traversing_visitor
839 systemtap_session
& session
;
841 stat_decl_collector(systemtap_session
& sess
)
845 void visit_stat_op (stat_op
* e
)
847 symbol
*sym
= get_symbol_within_expression (e
->stat
);
848 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
849 session
.stat_decls
[sym
->name
] = statistic_decl();
852 void visit_assignment (assignment
* e
)
856 symbol
*sym
= get_symbol_within_expression (e
->left
);
857 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
858 session
.stat_decls
[sym
->name
] = statistic_decl();
861 traversing_visitor::visit_assignment(e
);
864 void visit_hist_op (hist_op
* e
)
866 symbol
*sym
= get_symbol_within_expression (e
->stat
);
867 statistic_decl new_stat
;
869 if (e
->htype
== hist_linear
)
871 new_stat
.type
= statistic_decl::linear
;
872 assert (e
->params
.size() == 3);
873 new_stat
.linear_low
= e
->params
[0];
874 new_stat
.linear_high
= e
->params
[1];
875 new_stat
.linear_step
= e
->params
[2];
879 assert (e
->htype
== hist_log
);
880 new_stat
.type
= statistic_decl::logarithmic
;
881 assert (e
->params
.size() == 0);
884 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
885 if (i
== session
.stat_decls
.end())
886 session
.stat_decls
[sym
->name
] = new_stat
;
889 statistic_decl
& old_stat
= i
->second
;
890 if (!(old_stat
== new_stat
))
892 if (old_stat
.type
== statistic_decl::none
)
893 i
->second
= new_stat
;
896 // FIXME: Support multiple co-declared histogram types
897 semantic_error
se("multiple histogram types declared on '" + sym
->name
+ "'",
899 session
.print_error (se
);
908 semantic_pass_stats (systemtap_session
& sess
)
910 stat_decl_collector
sdc(sess
);
912 for (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
913 sess
.functions
[i
]->body
->visit (&sdc
);
915 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
916 sess
.probes
[i
]->body
->visit (&sdc
);
918 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
920 vardecl
*v
= sess
.globals
[i
];
921 if (v
->type
== pe_stats
)
924 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
926 semantic_error
se("unable to infer statistic parameters for global '" + v
->name
+ "'");
927 sess
.print_error (se
);
932 return sess
.num_errors();
935 // ------------------------------------------------------------------------
937 // Enforce variable-related invariants: no modification of
938 // a foreach()-iterated array.
940 semantic_pass_vars (systemtap_session
& sess
)
943 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
944 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
946 for (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
948 functiondecl
* fn
= sess
.functions
[i
];
951 set
<vardecl
*> * m
= new set
<vardecl
*>();
952 mutated_var_collector
mc (m
);
953 fn
->body
->visit (&mc
);
958 for (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
960 if (sess
.functions
[i
]->body
)
961 sess
.functions
[i
]->body
->visit (&chk
);
964 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
966 if (sess
.probes
[i
]->body
)
967 sess
.probes
[i
]->body
->visit (&chk
);
970 return sess
.num_errors();
974 // ------------------------------------------------------------------------
976 // Rewrite probe condition expressions into probe bodies. Tricky and
977 // exciting business, this. This:
979 // probe foo if (g1 || g2) { ... }
980 // probe bar { ... g1 ++ ... }
984 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
985 // probe foo { if (! (g1 || g2)) next; ... }
986 // probe bar { ... g1 ++ ...;
987 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
990 // XXX: As a first cut, do only the "inline probe condition" part of the
994 semantic_pass_conditions (systemtap_session
& sess
)
996 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
998 derived_probe
* p
= sess
.probes
[i
];
999 expression
* e
= p
->sole_location()->condition
;
1002 varuse_collecting_visitor vut
;
1005 if (! vut
.written
.empty())
1007 string err
= ("probe condition must not modify any variables");
1008 sess
.print_error (semantic_error (err
, e
->tok
));
1010 else if (vut
.embedded_seen
)
1012 sess
.print_error (semantic_error ("probe condition must not include impure embedded-C", e
->tok
));
1015 // Add the condition expression to the front of the
1016 // derived_probe body.
1017 if_statement
*ifs
= new if_statement ();
1019 ifs
->thenblock
= new next_statement ();
1020 ifs
->thenblock
->tok
= e
->tok
;
1021 ifs
->elseblock
= NULL
;
1022 unary_expression
*notex
= new unary_expression ();
1024 notex
->tok
= e
->tok
;
1026 ifs
->condition
= notex
;
1027 p
->body
= new block (ifs
, p
->body
);
1031 return sess
.num_errors();
1035 // ------------------------------------------------------------------------
1038 static int semantic_pass_symbols (systemtap_session
&);
1039 static int semantic_pass_optimize1 (systemtap_session
&);
1040 static int semantic_pass_optimize2 (systemtap_session
&);
1041 static int semantic_pass_types (systemtap_session
&);
1042 static int semantic_pass_vars (systemtap_session
&);
1043 static int semantic_pass_stats (systemtap_session
&);
1044 static int semantic_pass_conditions (systemtap_session
&);
1047 // Link up symbols to their declarations. Set the session's
1048 // files/probes/functions/globals vectors from the transitively
1049 // reached set of stapfiles in s.library_files, starting from
1050 // s.user_file. Perform automatic tapset inclusion and probe
1053 semantic_pass_symbols (systemtap_session
& s
)
1055 symresolution_info
sym (s
);
1057 // NB: s.files can grow during this iteration, so size() can
1058 // return gradually increasing numbers.
1059 s
.files
.push_back (s
.user_file
);
1060 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1062 if (pending_interrupts
) break;
1063 stapfile
* dome
= s
.files
[i
];
1065 // Pass 1: add globals and functions to systemtap-session master list,
1066 // so the find_* functions find them
1068 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1069 s
.globals
.push_back (dome
->globals
[i
]);
1071 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1072 s
.functions
.push_back (dome
->functions
[i
]);
1074 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1075 s
.embeds
.push_back (dome
->embeds
[i
]);
1077 // Pass 2: process functions
1079 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1081 if (pending_interrupts
) break;
1082 functiondecl
* fd
= dome
->functions
[i
];
1086 sym
.current_function
= fd
;
1087 sym
.current_probe
= 0;
1088 fd
->body
->visit (& sym
);
1090 catch (const semantic_error
& e
)
1096 // Pass 3: derive probes and resolve any further symbols in the
1099 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1101 if (pending_interrupts
) break;
1102 probe
* p
= dome
->probes
[i
];
1103 vector
<derived_probe
*> dps
;
1105 // much magic happens here: probe alias expansion, wildcard
1106 // matching, low-level derived_probe construction.
1107 derive_probes (s
, p
, dps
);
1109 for (unsigned j
=0; j
<dps
.size(); j
++)
1111 if (pending_interrupts
) break;
1112 derived_probe
* dp
= dps
[j
];
1113 s
.probes
.push_back (dp
);
1118 sym
.current_function
= 0;
1119 sym
.current_probe
= dp
;
1120 dp
->body
->visit (& sym
);
1122 // Process the probe-point condition expression.
1123 sym
.current_function
= 0;
1124 sym
.current_probe
= 0;
1125 if (dp
->sole_location()->condition
)
1126 dp
->sole_location()->condition
->visit (& sym
);
1128 catch (const semantic_error
& e
)
1136 // Inform all derived_probe builders that we're done with
1137 // all resolution, so it's time to release caches.
1138 s
.pattern_root
->build_no_more (s
);
1140 return s
.num_errors(); // all those print_error calls
1146 semantic_pass (systemtap_session
& s
)
1152 s
.register_library_aliases();
1153 register_standard_tapsets(s
);
1155 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1156 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1157 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize1 (s
);
1158 if (rc
== 0) rc
= semantic_pass_types (s
);
1159 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize2 (s
);
1160 if (rc
== 0) rc
= semantic_pass_vars (s
);
1161 if (rc
== 0) rc
= semantic_pass_stats (s
);
1163 if (s
.probes
.size() == 0 && !s
.listing_mode
)
1164 throw semantic_error ("no probes found");
1166 catch (const semantic_error
& e
)
1176 // ------------------------------------------------------------------------
1179 systemtap_session::systemtap_session ():
1180 // NB: pointer members must be manually initialized!
1181 pattern_root(new match_node
),
1183 be_derived_probes(0),
1184 dwarf_derived_probes(0),
1185 uprobe_derived_probes(0),
1186 utrace_derived_probes(0),
1187 task_finder_derived_probes(0),
1188 timer_derived_probes(0),
1189 profile_derived_probes(0),
1190 mark_derived_probes(0),
1191 hrtimer_derived_probes(0),
1192 perfmon_derived_probes(0),
1193 procfs_derived_probes(0),
1195 sym_kprobes_text_start (0),
1196 sym_kprobes_text_end (0),
1203 systemtap_session::print_error (const semantic_error
& e
)
1206 stringstream message
;
1208 // NB: we don't print error messages during listing mode.
1209 if (listing_mode
) return;
1211 message
<< "semantic error: " << e
.what ();
1212 if (e
.tok1
|| e
.tok2
)
1214 if (e
.tok1
) message
<< *e
.tok1
;
1216 if (e
.tok2
) message
<< *e
.tok2
;
1218 message_str
= message
.str();
1220 // Duplicate elimination
1221 if (seen_errors
.find (message_str
) == seen_errors
.end())
1223 seen_errors
.insert (message_str
);
1224 cerr
<< message_str
;
1228 print_error (* e
.chain
);
1232 systemtap_session::print_warning (const string
& message_str
, string optional_str
= "")
1234 // Duplicate elimination
1235 if (seen_warnings
.find (message_str
) == seen_warnings
.end())
1237 seen_warnings
.insert (message_str
);
1238 clog
<< "WARNING: " << message_str
<< optional_str
<< endl
;
1243 // ------------------------------------------------------------------------
1244 // semantic processing: symbol resolution
1247 symresolution_info::symresolution_info (systemtap_session
& s
):
1248 session (s
), current_function (0), current_probe (0)
1254 symresolution_info::visit_block (block
* e
)
1256 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
1260 e
->statements
[i
]->visit (this);
1262 catch (const semantic_error
& e
)
1264 session
.print_error (e
);
1271 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
1273 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1274 e
->indexes
[i
]->visit (this);
1276 symbol
*array
= NULL
;
1277 hist_op
*hist
= NULL
;
1278 classify_indexable (e
->base
, array
, hist
);
1282 if (!array
->referent
)
1284 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1286 array
->referent
= d
;
1290 msg
<< "unresolved arity-" << e
->indexes
.size()
1291 << " global array " << array
->name
;
1292 throw semantic_error (msg
.str(), e
->tok
);
1303 e
->limit
->visit (this);
1305 e
->block
->visit (this);
1310 delete_statement_symresolution_info
:
1311 public traversing_visitor
1313 symresolution_info
*parent
;
1315 delete_statement_symresolution_info (symresolution_info
*p
):
1319 void visit_arrayindex (arrayindex
* e
)
1321 parent
->visit_arrayindex (e
);
1323 void visit_functioncall (functioncall
* e
)
1325 parent
->visit_functioncall (e
);
1328 void visit_symbol (symbol
* e
)
1333 vardecl
* d
= parent
->find_var (e
->name
, -1);
1337 throw semantic_error ("unresolved array in delete statement", e
->tok
);
1342 symresolution_info::visit_delete_statement (delete_statement
* s
)
1344 delete_statement_symresolution_info
di (this);
1345 s
->value
->visit (&di
);
1350 symresolution_info::visit_symbol (symbol
* e
)
1355 vardecl
* d
= find_var (e
->name
, 0);
1361 vardecl
* v
= new vardecl
;
1364 if (current_function
)
1365 current_function
->locals
.push_back (v
);
1366 else if (current_probe
)
1367 current_probe
->locals
.push_back (v
);
1369 // must be probe-condition expression
1370 throw semantic_error ("probe condition must not reference undeclared global", e
->tok
);
1377 symresolution_info::visit_arrayindex (arrayindex
* e
)
1379 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1380 e
->indexes
[i
]->visit (this);
1382 symbol
*array
= NULL
;
1383 hist_op
*hist
= NULL
;
1384 classify_indexable(e
->base
, array
, hist
);
1388 if (array
->referent
)
1391 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1393 array
->referent
= d
;
1397 vardecl
* v
= new vardecl
;
1398 v
->set_arity(e
->indexes
.size());
1399 v
->name
= array
->name
;
1400 v
->tok
= array
->tok
;
1401 if (current_function
)
1402 current_function
->locals
.push_back (v
);
1403 else if (current_probe
)
1404 current_probe
->locals
.push_back (v
);
1407 throw semantic_error ("no current probe/function", e
->tok
);
1408 array
->referent
= v
;
1420 symresolution_info::visit_functioncall (functioncall
* e
)
1422 // XXX: we could relax this, if we're going to examine the
1423 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1424 if (! (current_function
|| current_probe
))
1426 // must be probe-condition expression
1427 throw semantic_error ("probe condition must not reference function", e
->tok
);
1430 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1431 e
->args
[i
]->visit (this);
1436 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
1442 msg
<< "unresolved arity-" << e
->args
.size()
1444 throw semantic_error (msg
.str(), e
->tok
);
1450 symresolution_info::find_var (const string
& name
, int arity
)
1452 if (current_function
|| current_probe
)
1455 vector
<vardecl
*>& locals
= (current_function
?
1456 current_function
->locals
:
1457 current_probe
->locals
);
1460 for (unsigned i
=0; i
<locals
.size(); i
++)
1461 if (locals
[i
]->name
== name
1462 && locals
[i
]->compatible_arity(arity
))
1464 locals
[i
]->set_arity (arity
);
1469 // search function formal parameters (for scalars)
1470 if (arity
== 0 && current_function
)
1471 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
1472 if (current_function
->formal_args
[i
]->name
== name
)
1474 // NB: no need to check arity here: formal args always scalar
1475 current_function
->formal_args
[i
]->set_arity (0);
1476 return current_function
->formal_args
[i
];
1479 // search processed globals
1480 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
1481 if (session
.globals
[i
]->name
== name
1482 && session
.globals
[i
]->compatible_arity(arity
))
1484 session
.globals
[i
]->set_arity (arity
);
1485 return session
.globals
[i
];
1488 // search library globals
1489 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1491 stapfile
* f
= session
.library_files
[i
];
1492 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
1494 vardecl
* g
= f
->globals
[j
];
1495 if (g
->name
== name
&& g
->compatible_arity (arity
))
1497 g
->set_arity (arity
);
1499 // put library into the queue if not already there
1500 if (find (session
.files
.begin(), session
.files
.end(), f
)
1501 == session
.files
.end())
1502 session
.files
.push_back (f
);
1514 symresolution_info::find_function (const string
& name
, unsigned arity
)
1516 for (unsigned j
= 0; j
< session
.functions
.size(); j
++)
1518 functiondecl
* fd
= session
.functions
[j
];
1519 if (fd
->name
== name
&&
1520 fd
->formal_args
.size() == arity
)
1524 // search library globals
1525 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1527 stapfile
* f
= session
.library_files
[i
];
1528 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1529 if (f
->functions
[j
]->name
== name
&&
1530 f
->functions
[j
]->formal_args
.size() == arity
)
1532 // put library into the queue if not already there
1533 if (0) // session.verbose_resolution
1534 cerr
<< " function " << name
<< " "
1535 << "is defined from " << f
->name
<< endl
;
1537 if (find (session
.files
.begin(), session
.files
.end(), f
)
1538 == session
.files
.end())
1539 session
.files
.push_back (f
);
1540 // else .. print different message?
1542 return f
->functions
[j
];
1551 // ------------------------------------------------------------------------
1555 // Do away with functiondecls that are never (transitively) called
1557 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1559 functioncall_traversing_visitor ftv
;
1560 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1562 s
.probes
[i
]->body
->visit (& ftv
);
1563 if (s
.probes
[i
]->sole_location()->condition
)
1564 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1566 for (unsigned i
=0; i
<s
.functions
.size(); /* see below */)
1568 if (ftv
.traversed
.find(s
.functions
[i
]) == ftv
.traversed
.end())
1570 if (s
.functions
[i
]->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1571 ! s
.suppress_warnings
)
1572 s
.print_warning ("eliding unused function " + stringify(*s
.functions
[i
]->tok
));
1573 else if (s
.verbose
>2)
1574 clog
<< "Eliding unused function " << s
.functions
[i
]->name
1576 if (s
.tapset_compile_coverage
) {
1577 s
.unused_functions
.push_back (s
.functions
[i
]);
1579 s
.functions
.erase (s
.functions
.begin() + i
);
1581 // NB: don't increment i
1589 // ------------------------------------------------------------------------
1591 // Do away with local & global variables that are never
1592 // written nor read.
1593 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
)
1595 varuse_collecting_visitor vut
;
1597 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1599 s
.probes
[i
]->body
->visit (& vut
);
1601 if (s
.probes
[i
]->sole_location()->condition
)
1602 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1605 // NB: Since varuse_collecting_visitor also traverses down
1606 // actually called functions, we don't need to explicitly
1607 // iterate over them. Uncalled ones should have been pruned
1610 // for (unsigned i=0; i<s.functions.size(); i++)
1611 // s.functions[i]->body->visit (& vut);
1613 // Now in vut.read/written, we have a mixture of all locals, globals
1615 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1616 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
1618 vardecl
* l
= s
.probes
[i
]->locals
[j
];
1620 if (vut
.read
.find (l
) == vut
.read
.end() &&
1621 vut
.written
.find (l
) == vut
.written
.end())
1623 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1624 ! s
.suppress_warnings
)
1625 s
.print_warning ("eliding unused variable " + stringify(*l
->tok
));
1626 else if (s
.verbose
>2)
1627 clog
<< "Eliding unused local variable "
1628 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
1629 if (s
.tapset_compile_coverage
) {
1630 s
.probes
[i
]->unused_locals
.push_back
1631 (s
.probes
[i
]->locals
[j
]);
1633 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
1635 // don't increment j
1639 if (vut
.written
.find (l
) == vut
.written
.end())
1640 if (! s
.suppress_warnings
)
1643 vector
<vardecl
*>::iterator it
;
1644 for ( it
= s
.probes
[i
]->locals
.begin() ;
1645 it
!= s
.probes
[i
]->locals
.end(); it
++ )
1646 if (l
->name
.compare(((vardecl
*)*it
)->name
) != 0)
1647 o
<< " " << ((vardecl
*)*it
)->name
;
1648 for ( it
= s
.globals
.begin() ;
1649 it
!= s
.globals
.end() ; it
++ )
1650 if (l
->name
.compare(((vardecl
*)*it
)->name
) != 0)
1651 o
<< " " << ((vardecl
*)*it
)->name
;
1653 s
.print_warning ("read-only local variable "
1654 + stringify(*l
->tok
),
1655 " (alternatives: " + o
.str () + ")");
1662 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
1663 for (unsigned j
=0; j
<s
.functions
[i
]->locals
.size(); /* see below */)
1665 vardecl
* l
= s
.functions
[i
]->locals
[j
];
1666 if (vut
.read
.find (l
) == vut
.read
.end() &&
1667 vut
.written
.find (l
) == vut
.written
.end())
1669 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1670 ! s
.suppress_warnings
)
1671 s
.print_warning ("eliding unused variable " + stringify(*l
->tok
));
1672 else if (s
.verbose
>2)
1673 clog
<< "Eliding unused local variable "
1674 << l
->name
<< " in function " << s
.functions
[i
]->name
1676 if (s
.tapset_compile_coverage
) {
1677 s
.functions
[i
]->unused_locals
.push_back
1678 (s
.functions
[i
]->locals
[j
]);
1680 s
.functions
[i
]->locals
.erase(s
.functions
[i
]->locals
.begin() + j
);
1682 // don't increment j
1687 vector
<vardecl
*>::iterator it
;
1688 for ( it
= s
.functions
[i
]->formal_args
.begin() ;
1689 it
!= s
.functions
[i
]->formal_args
.end(); it
++ )
1690 if (l
->name
.compare(((vardecl
*)*it
)->name
) != 0)
1691 o
<< " " << ((vardecl
*)*it
)->name
;
1692 for ( it
= s
.functions
[i
]->locals
.begin() ;
1693 it
!= s
.functions
[i
]->locals
.end(); it
++ )
1694 if (l
->name
.compare(((vardecl
*)*it
)->name
) != 0)
1695 o
<< " " << ((vardecl
*)*it
)->name
;
1696 for ( it
= s
.globals
.begin() ;
1697 it
!= s
.globals
.end() ; it
++ )
1698 if (l
->name
.compare(((vardecl
*)*it
)->name
) != 0)
1699 o
<< " " << ((vardecl
*)*it
)->name
;
1701 if (vut
.written
.find (l
) == vut
.written
.end())
1702 if (! s
.suppress_warnings
)
1703 s
.print_warning ("read-only local variable "
1704 + stringify(*l
->tok
),
1705 " (alternatives:" + o
.str () + ")");
1710 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
1712 vardecl
* l
= s
.globals
[i
];
1713 if (vut
.read
.find (l
) == vut
.read
.end() &&
1714 vut
.written
.find (l
) == vut
.written
.end())
1716 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1717 ! s
.suppress_warnings
)
1718 s
.print_warning ("eliding unused variable " + stringify(*l
->tok
));
1719 else if (s
.verbose
>2)
1720 clog
<< "Eliding unused global variable "
1722 if (s
.tapset_compile_coverage
) {
1723 s
.unused_globals
.push_back(s
.globals
[i
]);
1725 s
.globals
.erase(s
.globals
.begin() + i
);
1727 // don't increment i
1731 if (vut
.written
.find (l
) == vut
.written
.end() &&
1732 ! l
->init
) // no initializer
1733 if (! s
.suppress_warnings
)
1734 s
.print_warning ("read-only global variable " + stringify(*l
->tok
));
1741 // ------------------------------------------------------------------------
1743 struct dead_assignment_remover
: public traversing_visitor
1745 systemtap_session
& session
;
1747 const varuse_collecting_visitor
& vut
;
1748 expression
** current_expr
;
1750 dead_assignment_remover(systemtap_session
& s
, bool& r
,
1751 const varuse_collecting_visitor
& v
):
1752 session(s
), relaxed_p(r
), vut(v
), current_expr(0) {}
1754 void visit_expr_statement (expr_statement
* s
);
1755 // XXX: other places where an assignment may be nested should be
1756 // handled too (e.g., loop/if conditionals, array indexes, function
1757 // parameters). Until then, they result in visit_assignment() being
1758 // called with null current_expr.
1760 void visit_assignment (assignment
* e
);
1761 void visit_binary_expression (binary_expression
* e
);
1762 void visit_arrayindex (arrayindex
* e
);
1763 void visit_functioncall (functioncall
* e
);
1764 void visit_if_statement (if_statement
* e
);
1765 void visit_for_loop (for_loop
* e
);
1770 dead_assignment_remover::visit_expr_statement (expr_statement
* s
)
1772 expression
** last_expr
= current_expr
;
1773 current_expr
= & s
->value
;
1774 s
->value
->visit (this);
1775 s
->tok
= s
->value
->tok
; // in case it was replaced
1776 current_expr
= last_expr
;
1781 dead_assignment_remover::visit_assignment (assignment
* e
)
1783 symbol
* left
= get_symbol_within_expression (e
->left
);
1784 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
1785 if (current_expr
&& // see XXX above: this case represents a missed
1786 // optimization opportunity
1787 *current_expr
== e
&& // we're not nested any deeper than expected
1788 leftvar
) // not unresolved $target; intended sideeffect cannot be elided
1790 expression
** last_expr
= current_expr
;
1791 e
->left
->visit (this);
1792 current_expr
= &e
->right
;
1793 e
->right
->visit (this);
1794 current_expr
= last_expr
;
1795 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
1797 // NB: Not so fast! The left side could be an array whose
1798 // index expressions may have side-effects. This would be
1799 // OK if we could replace the array assignment with a
1800 // statement-expression containing all the index expressions
1801 // and the rvalue... but we can't.
1803 varuse_collecting_visitor vut
;
1804 e
->left
->visit (& vut
);
1805 if (vut
.side_effect_free ()) // XXX: use _wrt() once we track focal_vars
1807 /* PR 1119: NB: This is not necessary here. A write-only
1808 variable will also be elided soon at the next _opt2 iteration.
1809 if (e->left->tok->location.file == session.user_file->name && // !tapset
1810 ! session.suppress_warnings)
1811 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
1814 if (session
.verbose
>2)
1815 clog
<< "Eliding assignment to " << leftvar
->name
1816 << " at " << *e
->tok
<< endl
;
1818 *current_expr
= e
->right
; // goodbye assignment*
1826 dead_assignment_remover::visit_binary_expression (binary_expression
* e
)
1828 expression
** last_expr
= current_expr
;
1829 current_expr
= &e
->left
;
1830 e
->left
->visit (this);
1831 current_expr
= &e
->right
;
1832 e
->right
->visit (this);
1833 current_expr
= last_expr
;
1837 dead_assignment_remover::visit_arrayindex (arrayindex
*e
)
1839 symbol
*array
= NULL
;
1840 hist_op
*hist
= NULL
;
1841 classify_indexable(e
->base
, array
, hist
);
1845 expression
** last_expr
= current_expr
;
1846 for (unsigned i
=0; i
< e
->indexes
.size(); i
++)
1848 current_expr
= & e
->indexes
[i
];
1849 e
->indexes
[i
]->visit (this);
1851 current_expr
= last_expr
;
1856 dead_assignment_remover::visit_functioncall (functioncall
* e
)
1858 expression
** last_expr
= current_expr
;
1859 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1861 current_expr
= & e
->args
[i
];
1862 e
->args
[i
]->visit (this);
1864 current_expr
= last_expr
;
1868 dead_assignment_remover::visit_if_statement (if_statement
* s
)
1870 expression
** last_expr
= current_expr
;
1871 current_expr
= & s
->condition
;
1872 s
->condition
->visit (this);
1873 s
->thenblock
->visit (this);
1875 s
->elseblock
->visit (this);
1876 current_expr
= last_expr
;
1880 dead_assignment_remover::visit_for_loop (for_loop
* s
)
1882 expression
** last_expr
= current_expr
;
1883 if (s
->init
) s
->init
->visit (this);
1884 current_expr
= & s
->cond
;
1885 s
->cond
->visit (this);
1886 if (s
->incr
) s
->incr
->visit (this);
1887 s
->block
->visit (this);
1888 current_expr
= last_expr
;
1891 // Let's remove assignments to variables that are never read. We
1892 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
1893 // be optimized away as an unused variable, and expr a candidate to be
1894 // removed as a side-effect-free statement expression. Wahoo!
1895 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
1897 // Recompute the varuse data, which will probably match the opt2
1898 // copy of the computation, except for those totally unused
1899 // variables that opt2 removed.
1900 varuse_collecting_visitor vut
;
1901 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1902 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
1904 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
1905 // This instance may be reused for multiple probe/function body trims.
1907 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1908 s
.probes
[i
]->body
->visit (& dar
);
1909 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
1910 s
.functions
[i
]->body
->visit (& dar
);
1911 // The rewrite operation is performed within the visitor.
1913 // XXX: we could also zap write-only globals here
1917 // ------------------------------------------------------------------------
1919 struct dead_stmtexpr_remover
: public traversing_visitor
1921 systemtap_session
& session
;
1923 statement
** current_stmt
; // pointer to current stmt* being iterated
1924 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
1926 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
1927 session(s
), relaxed_p(r
), current_stmt(0) {}
1929 void visit_block (block
*s
);
1930 void visit_null_statement (null_statement
*s
);
1931 void visit_if_statement (if_statement
* s
);
1932 void visit_foreach_loop (foreach_loop
*s
);
1933 void visit_for_loop (for_loop
*s
);
1934 // XXX: and other places where stmt_expr's might be nested
1936 void visit_expr_statement (expr_statement
*s
);
1941 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
1944 if (session
.verbose
>2)
1945 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
1951 dead_stmtexpr_remover::visit_block (block
*s
)
1953 vector
<statement
*> new_stmts
;
1954 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
1956 statement
** last_stmt
= current_stmt
;
1957 current_stmt
= & s
->statements
[i
];
1958 s
->statements
[i
]->visit (this);
1959 if (*current_stmt
!= 0)
1960 new_stmts
.push_back (*current_stmt
);
1961 current_stmt
= last_stmt
;
1963 if (new_stmts
.size() == 0)
1965 if (session
.verbose
>2)
1966 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
1969 else if (new_stmts
.size() == 1)
1971 if (session
.verbose
>2)
1972 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
1973 *current_stmt
= new_stmts
[0];
1977 s
->statements
= new_stmts
;
1982 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
1984 statement
** last_stmt
= current_stmt
;
1985 current_stmt
= & s
->thenblock
;
1986 s
->thenblock
->visit (this);
1990 current_stmt
= & s
->elseblock
;
1991 s
->elseblock
->visit (this);
1992 // null *current_stmt is OK here.
1994 current_stmt
= last_stmt
;
1996 if (s
->elseblock
== 0 && s
->thenblock
== 0)
1998 // We may be able to elide this statement, if the condition
1999 // expression is side-effect-free.
2000 varuse_collecting_visitor vct
;
2001 s
->condition
->visit(& vct
);
2002 if (vct
.side_effect_free ())
2004 if (session
.verbose
>2)
2005 clog
<< "Eliding side-effect-free if statement " << *s
->tok
<< endl
;
2006 *current_stmt
= 0; // yeah, baby
2011 if (s
->thenblock
== 0)
2013 // Can't elide this whole if/else statement; put a null in there.
2014 s
->thenblock
= new null_statement();
2015 s
->thenblock
->tok
= s
->tok
;
2020 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2022 statement
** last_stmt
= current_stmt
;
2023 current_stmt
= & s
->block
;
2024 s
->block
->visit (this);
2025 current_stmt
= last_stmt
;
2029 if (session
.verbose
>2)
2030 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2031 *current_stmt
= 0; // yeah, baby
2036 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2038 statement
** last_stmt
= current_stmt
;
2039 current_stmt
= & s
->block
;
2040 s
->block
->visit (this);
2041 current_stmt
= last_stmt
;
2045 // We may be able to elide this statement, if the condition
2046 // expression is side-effect-free.
2047 varuse_collecting_visitor vct
;
2048 if (s
->init
) s
->init
->visit(& vct
);
2049 s
->cond
->visit(& vct
);
2050 if (s
->incr
) s
->incr
->visit(& vct
);
2051 if (vct
.side_effect_free ())
2053 if (session
.verbose
>2)
2054 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2055 *current_stmt
= 0; // yeah, baby
2059 // Can't elide this whole statement; put a null in there.
2060 s
->block
= new null_statement();
2061 s
->block
->tok
= s
->tok
;
2068 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2070 // Run a varuse query against the operand expression. If it has no
2071 // side-effects, replace the entire statement expression by a null
2072 // statement. This replacement is done by overwriting the
2073 // current_stmt pointer.
2075 // Unlike many other visitors, we do *not* traverse this outermost
2076 // one into the expression subtrees. There is no need - no
2077 // expr_statement nodes will be found there. (Function bodies
2078 // need to be visited explicitly by our caller.)
2080 // NB. While we don't share nodes in the parse tree, let's not
2081 // deallocate *s anyway, just in case...
2083 varuse_collecting_visitor vut
;
2084 s
->value
->visit (& vut
);
2085 if (vut
.side_effect_free_wrt (focal_vars
) &&
2086 *current_stmt
== s
) // we're not nested any deeper than expected
2088 /* PR 1119: NB: this message is not a good idea here. It can
2089 name some arbitrary RHS expression of an assignment.
2090 if (s->value->tok->location.file == session.user_file->name && // not tapset
2091 ! session.suppress_warnings)
2092 clog << "WARNING: eliding read-only " << *s->value->tok << endl;
2095 if (session
.verbose
>2)
2096 clog
<< "Eliding side-effect-free expression "
2099 // NB: this 0 pointer is invalid to leave around for any length of
2100 // time, but the parent parse tree objects above handle it.
2108 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2110 // Finally, let's remove some statement-expressions that have no
2111 // side-effect. These should be exactly those whose private varuse
2112 // visitors come back with an empty "written" and "embedded" lists.
2114 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2115 // This instance may be reused for multiple probe/function body trims.
2117 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2119 derived_probe
* p
= s
.probes
[i
];
2121 duv
.focal_vars
.clear ();
2122 duv
.focal_vars
.insert (s
.globals
.begin(),
2124 duv
.focal_vars
.insert (p
->locals
.begin(),
2127 duv
.current_stmt
= & p
->body
;
2128 p
->body
->visit (& duv
);
2131 if (! s
.suppress_warnings
)
2132 s
.print_warning ("side-effect-free probe '" + p
->name
+ "' "
2133 + stringify(*p
->tok
));
2135 p
->body
= new null_statement();
2136 p
->body
->tok
= p
->tok
;
2138 // XXX: possible duplicate warnings; see below
2141 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
2143 functiondecl
* fn
= s
.functions
[i
];
2144 duv
.focal_vars
.clear ();
2145 duv
.focal_vars
.insert (fn
->locals
.begin(),
2147 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2148 fn
->formal_args
.end());
2149 duv
.focal_vars
.insert (s
.globals
.begin(),
2152 duv
.current_stmt
= & fn
->body
;
2153 fn
->body
->visit (& duv
);
2156 if (! s
.suppress_warnings
)
2157 s
.print_warning ("side-effect-free function '" + fn
->name
+ "' "
2158 + stringify(*fn
->tok
));
2160 fn
->body
= new null_statement();
2161 fn
->body
->tok
= fn
->tok
;
2163 // XXX: the next iteration of the outer optimization loop may
2164 // take this new null_statement away again, and thus give us a
2165 // fresh warning. It would be better if this fixup was performed
2166 // only after the relaxation iterations.
2167 // XXX: or else see bug #6469.
2172 struct duplicate_function_remover
: public functioncall_traversing_visitor
2174 systemtap_session
& s
;
2175 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
2177 duplicate_function_remover(systemtap_session
& sess
,
2178 map
<functiondecl
*, functiondecl
*>&dfm
):
2179 s(sess
), duplicate_function_map(dfm
) {};
2181 void visit_functioncall (functioncall
* e
);
2185 duplicate_function_remover::visit_functioncall (functioncall
*e
)
2187 functioncall_traversing_visitor::visit_functioncall (e
);
2189 // If the current function call reference points to a function that
2190 // is a duplicate, replace it.
2191 if (duplicate_function_map
.count(e
->referent
) != 0)
2194 clog
<< "Changing " << e
->referent
->name
2196 << duplicate_function_map
[e
->referent
]->name
2198 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
2199 e
->function
= duplicate_function_map
[e
->referent
]->name
;
2200 e
->referent
= duplicate_function_map
[e
->referent
];
2205 get_functionsig (functiondecl
* f
)
2209 // Get the "name:args body" of the function in s. We have to
2210 // include the args since the function 'x1(a, b)' is different than
2211 // the function 'x2(b, a)' even if the bodies of the two functions
2212 // are exactly the same.
2216 // printsig puts f->name + ':' on the front. Remove this
2217 // (otherwise, functions would never compare equal).
2218 string str
= s
.str().erase(0, f
->name
.size() + 1);
2220 // Return the function signature.
2224 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2226 // Walk through all the functions, looking for duplicates.
2227 map
<string
, functiondecl
*> functionsig_map
;
2228 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
2229 for (unsigned i
=0; i
< s
.functions
.size(); /* see below */)
2231 string functionsig
= get_functionsig(s
.functions
[i
]);
2233 if (functionsig_map
.count(functionsig
) == 0)
2235 // This function is unique. Remember it.
2236 functionsig_map
[functionsig
] = s
.functions
[i
];
2241 // This function is a duplicate.
2242 duplicate_function_map
[s
.functions
[i
]]
2243 = functionsig_map
[functionsig
];
2245 // Remove the duplicate function (since we don't need it
2247 s
.functions
.erase (s
.functions
.begin() + i
);
2250 // NB: don't increment i
2254 // If we have duplicate functions, traverse down the tree, replacing
2255 // the appropriate function calls.
2256 // duplicate_function_remover::visit_functioncall() handles the
2257 // details of replacing the function calls.
2258 if (duplicate_function_map
.size() != 0)
2260 duplicate_function_remover
dfr (s
, duplicate_function_map
);
2262 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
2263 s
.probes
[i
]->body
->visit(&dfr
);
2269 semantic_pass_optimize1 (systemtap_session
& s
)
2271 // In this pass, we attempt to rewrite probe/function bodies to
2272 // eliminate some blatantly unnecessary code. This is run before
2273 // type inference, but after symbol resolution and derived_probe
2274 // creation. We run an outer "relaxation" loop that repeats the
2275 // optimizations until none of them find anything to remove.
2279 bool relaxed_p
= false;
2282 if (pending_interrupts
) break;
2284 relaxed_p
= true; // until proven otherwise
2286 semantic_pass_opt1 (s
, relaxed_p
);
2287 semantic_pass_opt2 (s
, relaxed_p
);
2288 semantic_pass_opt3 (s
, relaxed_p
);
2289 semantic_pass_opt4 (s
, relaxed_p
);
2297 semantic_pass_optimize2 (systemtap_session
& s
)
2299 // This is run after type inference. We run an outer "relaxation"
2300 // loop that repeats the optimizations until none of them find
2301 // anything to remove.
2305 bool relaxed_p
= false;
2308 if (pending_interrupts
) break;
2309 relaxed_p
= true; // until proven otherwise
2311 semantic_pass_opt5 (s
, relaxed_p
);
2319 // ------------------------------------------------------------------------
2324 semantic_pass_types (systemtap_session
& s
)
2328 // next pass: type inference
2329 unsigned iterations
= 0;
2330 typeresolution_info
ti (s
);
2332 ti
.assert_resolvability
= false;
2333 // XXX: maybe convert to exception-based error signalling
2336 if (pending_interrupts
) break;
2339 ti
.num_newly_resolved
= 0;
2340 ti
.num_still_unresolved
= 0;
2342 for (unsigned j
=0; j
<s
.functions
.size(); j
++)
2344 if (pending_interrupts
) break;
2346 functiondecl
* fn
= s
.functions
[j
];
2347 ti
.current_probe
= 0;
2348 ti
.current_function
= fn
;
2350 fn
->body
->visit (& ti
);
2351 // NB: we don't have to assert a known type for
2352 // functions here, to permit a "void" function.
2353 // The translator phase will omit the "retvalue".
2355 // if (fn->type == pe_unknown)
2356 // ti.unresolved (fn->tok);
2359 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
2361 if (pending_interrupts
) break;
2363 derived_probe
* pn
= s
.probes
[j
];
2364 ti
.current_function
= 0;
2365 ti
.current_probe
= pn
;
2367 pn
->body
->visit (& ti
);
2369 probe_point
* pp
= pn
->sole_location();
2372 ti
.current_function
= 0;
2373 ti
.current_probe
= 0;
2374 ti
.t
= pe_long
; // NB: expected type
2375 pp
->condition
->visit (& ti
);
2379 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
2381 vardecl
* gd
= s
.globals
[j
];
2382 if (gd
->type
== pe_unknown
)
2383 ti
.unresolved (gd
->tok
);
2386 if (ti
.num_newly_resolved
== 0) // converged
2388 if (ti
.num_still_unresolved
== 0)
2389 break; // successfully
2390 else if (! ti
.assert_resolvability
)
2391 ti
.assert_resolvability
= true; // last pass, with error msgs
2393 { // unsuccessful conclusion
2400 return rc
+ s
.num_errors();
2405 typeresolution_info::typeresolution_info (systemtap_session
& s
):
2406 session(s
), current_function(0), current_probe(0)
2412 typeresolution_info::visit_literal_number (literal_number
* e
)
2414 assert (e
->type
== pe_long
);
2415 if ((t
== e
->type
) || (t
== pe_unknown
))
2418 mismatch (e
->tok
, e
->type
, t
);
2423 typeresolution_info::visit_literal_string (literal_string
* e
)
2425 assert (e
->type
== pe_string
);
2426 if ((t
== e
->type
) || (t
== pe_unknown
))
2429 mismatch (e
->tok
, e
->type
, t
);
2434 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
2436 visit_binary_expression (e
);
2441 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
2443 visit_binary_expression (e
);
2448 typeresolution_info::visit_comparison (comparison
*e
)
2450 // NB: result of any comparison is an integer!
2451 if (t
== pe_stats
|| t
== pe_string
)
2452 invalid (e
->tok
, t
);
2454 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
2455 e
->left
->visit (this);
2456 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
2457 e
->right
->visit (this);
2459 if (e
->left
->type
!= pe_unknown
&&
2460 e
->right
->type
!= pe_unknown
&&
2461 e
->left
->type
!= e
->right
->type
)
2462 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
2464 if (e
->type
== pe_unknown
)
2467 resolved (e
->tok
, e
->type
);
2473 typeresolution_info::visit_concatenation (concatenation
*e
)
2475 if (t
!= pe_unknown
&& t
!= pe_string
)
2476 invalid (e
->tok
, t
);
2479 e
->left
->visit (this);
2481 e
->right
->visit (this);
2483 if (e
->type
== pe_unknown
)
2485 e
->type
= pe_string
;
2486 resolved (e
->tok
, e
->type
);
2492 typeresolution_info::visit_assignment (assignment
*e
)
2495 invalid (e
->tok
, t
);
2497 if (e
->op
== "<<<") // stats aggregation
2500 invalid (e
->tok
, t
);
2503 e
->left
->visit (this);
2505 e
->right
->visit (this);
2506 if (e
->type
== pe_unknown
||
2507 e
->type
== pe_stats
)
2510 resolved (e
->tok
, e
->type
);
2514 else if (e
->left
->type
== pe_stats
)
2515 invalid (e
->left
->tok
, e
->left
->type
);
2517 else if (e
->right
->type
== pe_stats
)
2518 invalid (e
->right
->tok
, e
->right
->type
);
2520 else if (e
->op
== "+=" || // numeric only
2532 visit_binary_expression (e
);
2534 else if (e
->op
== ".=" || // string only
2537 if (t
== pe_long
|| t
== pe_stats
)
2538 invalid (e
->tok
, t
);
2541 e
->left
->visit (this);
2543 e
->right
->visit (this);
2544 if (e
->type
== pe_unknown
)
2546 e
->type
= pe_string
;
2547 resolved (e
->tok
, e
->type
);
2550 else if (e
->op
== "=") // overloaded = for string & numeric operands
2552 // logic similar to ternary_expression
2553 exp_type sub_type
= t
;
2555 // Infer types across the l/r values
2556 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
2559 t
= (sub_type
!= pe_unknown
) ? sub_type
:
2560 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
2562 e
->left
->visit (this);
2563 t
= (sub_type
!= pe_unknown
) ? sub_type
:
2564 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
2566 e
->right
->visit (this);
2568 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
2571 resolved (e
->tok
, e
->type
);
2573 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
2575 e
->type
= e
->left
->type
;
2576 resolved (e
->tok
, e
->type
);
2579 if (e
->left
->type
!= pe_unknown
&&
2580 e
->right
->type
!= pe_unknown
&&
2581 e
->left
->type
!= e
->right
->type
)
2582 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
2586 throw semantic_error ("unsupported assignment operator " + e
->op
);
2591 typeresolution_info::visit_binary_expression (binary_expression
* e
)
2593 if (t
== pe_stats
|| t
== pe_string
)
2594 invalid (e
->tok
, t
);
2597 e
->left
->visit (this);
2599 e
->right
->visit (this);
2601 if (e
->left
->type
!= pe_unknown
&&
2602 e
->right
->type
!= pe_unknown
&&
2603 e
->left
->type
!= e
->right
->type
)
2604 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
2606 if (e
->type
== pe_unknown
)
2609 resolved (e
->tok
, e
->type
);
2615 typeresolution_info::visit_pre_crement (pre_crement
*e
)
2617 visit_unary_expression (e
);
2622 typeresolution_info::visit_post_crement (post_crement
*e
)
2624 visit_unary_expression (e
);
2629 typeresolution_info::visit_unary_expression (unary_expression
* e
)
2631 if (t
== pe_stats
|| t
== pe_string
)
2632 invalid (e
->tok
, t
);
2635 e
->operand
->visit (this);
2637 if (e
->type
== pe_unknown
)
2640 resolved (e
->tok
, e
->type
);
2646 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
2648 exp_type sub_type
= t
;
2651 e
->cond
->visit (this);
2653 // Infer types across the true/false arms of the ternary expression.
2655 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
2658 e
->truevalue
->visit (this);
2660 e
->falsevalue
->visit (this);
2662 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
2663 ; // already resolved
2664 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
2667 resolved (e
->tok
, e
->type
);
2669 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
2671 e
->type
= e
->truevalue
->type
;
2672 resolved (e
->tok
, e
->type
);
2674 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
2676 e
->type
= e
->falsevalue
->type
;
2677 resolved (e
->tok
, e
->type
);
2679 else if (e
->type
!= sub_type
)
2680 mismatch (e
->tok
, sub_type
, e
->type
);
2684 template <class Referrer
, class Referent
>
2685 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
2686 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
2688 exp_type
& re_type
= referrer
->type
;
2689 const token
* re_tok
= referrer
->tok
;
2690 exp_type
& te_type
= referent
->type
;
2691 const token
* te_tok
= referent
->tok
;
2693 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
2694 ; // do nothing: all three e->types in agreement
2695 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
2696 ; // do nothing: two known e->types in agreement
2697 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
2698 r
->mismatch (re_tok
, re_type
, te_type
);
2699 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
2700 r
->mismatch (re_tok
, re_type
, t
);
2701 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
2702 r
->mismatch (te_tok
, te_type
, t
);
2703 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
2705 // propagate from upstream
2707 r
->resolved (re_tok
, re_type
);
2708 // catch re_type/te_type mismatch later
2710 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
2712 // propagate from referent
2714 r
->resolved (re_tok
, re_type
);
2715 // catch re_type/t mismatch later
2717 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
2719 // propagate to referent
2721 r
->resolved (te_tok
, te_type
);
2722 // catch re_type/t mismatch later
2724 else if (! accept_unknown
)
2725 r
->unresolved (re_tok
);
2730 typeresolution_info::visit_symbol (symbol
* e
)
2732 assert (e
->referent
!= 0);
2733 resolve_2types (e
, e
->referent
, this, t
);
2738 typeresolution_info::visit_target_symbol (target_symbol
* e
)
2740 // This occurs only if a target symbol was not resolved over in
2741 // tapset.cxx land, that error was properly suppressed, and the
2742 // later unused-expression-elimination pass didn't get rid of it
2743 // either. So we have a target symbol that is believed to be of
2744 // genuine use, yet unresolved by the provider.
2746 if (session
.verbose
> 2)
2748 clog
<< "Resolution problem with ";
2749 if (current_function
)
2751 clog
<< "function " << current_function
->name
<< endl
;
2752 current_function
->body
->print (clog
);
2755 else if (current_probe
)
2757 clog
<< "probe " << current_probe
->name
<< endl
;
2758 current_probe
->body
->print (clog
);
2762 clog
<< "other" << endl
;
2765 if (e
->saved_conversion_error
)
2766 throw (* (e
->saved_conversion_error
));
2768 throw semantic_error("unresolved target-symbol expression", e
->tok
);
2773 typeresolution_info::visit_arrayindex (arrayindex
* e
)
2776 symbol
*array
= NULL
;
2777 hist_op
*hist
= NULL
;
2778 classify_indexable(e
->base
, array
, hist
);
2780 // Every hist_op has type [int]:int, that is to say, every hist_op
2781 // is a pseudo-one-dimensional integer array type indexed by
2782 // integers (bucket numbers).
2786 if (e
->indexes
.size() != 1)
2787 unresolved (e
->tok
);
2789 e
->indexes
[0]->visit (this);
2790 if (e
->indexes
[0]->type
!= pe_long
)
2791 unresolved (e
->tok
);
2793 if (e
->type
!= pe_long
)
2796 resolved (e
->tok
, pe_long
);
2801 // Now we are left with "normal" map inference and index checking.
2804 assert (array
->referent
!= 0);
2805 resolve_2types (e
, array
->referent
, this, t
);
2807 // now resolve the array indexes
2809 // if (e->referent->index_types.size() == 0)
2810 // // redesignate referent as array
2811 // e->referent->set_arity (e->indexes.size ());
2813 if (e
->indexes
.size() != array
->referent
->index_types
.size())
2814 unresolved (e
->tok
); // symbol resolution should prevent this
2815 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
2817 expression
* ee
= e
->indexes
[i
];
2818 exp_type
& ft
= array
->referent
->index_types
[i
];
2821 exp_type at
= ee
->type
;
2823 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
2825 // propagate to formal type
2827 resolved (array
->referent
->tok
, ft
);
2828 // uses array decl as there is no token for "formal type"
2831 invalid (ee
->tok
, at
);
2833 invalid (ee
->tok
, ft
);
2834 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
2835 mismatch (e
->tok
, at
, ft
);
2836 if (at
== pe_unknown
)
2837 unresolved (ee
->tok
);
2843 typeresolution_info::visit_functioncall (functioncall
* e
)
2845 assert (e
->referent
!= 0);
2847 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
2849 if (e
->type
== pe_stats
)
2850 invalid (e
->tok
, e
->type
);
2852 // now resolve the function parameters
2853 if (e
->args
.size() != e
->referent
->formal_args
.size())
2854 unresolved (e
->tok
); // symbol resolution should prevent this
2855 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
2857 expression
* ee
= e
->args
[i
];
2858 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
2859 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
2862 exp_type at
= ee
->type
;
2864 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
2866 // propagate to formal arg
2868 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
2871 invalid (e
->tok
, at
);
2873 invalid (fe_tok
, ft
);
2874 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
2875 mismatch (e
->tok
, at
, ft
);
2876 if (at
== pe_unknown
)
2877 unresolved (e
->tok
);
2883 typeresolution_info::visit_block (block
* e
)
2885 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
2890 e
->statements
[i
]->visit (this);
2892 catch (const semantic_error
& e
)
2894 session
.print_error (e
);
2901 typeresolution_info::visit_embeddedcode (embeddedcode
*)
2907 typeresolution_info::visit_if_statement (if_statement
* e
)
2910 e
->condition
->visit (this);
2913 e
->thenblock
->visit (this);
2918 e
->elseblock
->visit (this);
2924 typeresolution_info::visit_for_loop (for_loop
* e
)
2927 if (e
->init
) e
->init
->visit (this);
2929 e
->cond
->visit (this);
2931 if (e
->incr
) e
->incr
->visit (this);
2933 e
->block
->visit (this);
2938 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
2940 // See also visit_arrayindex.
2941 // This is different in that, being a statement, we can't assign
2942 // a type to the outer array, only propagate to/from the indexes
2944 // if (e->referent->index_types.size() == 0)
2945 // // redesignate referent as array
2946 // e->referent->set_arity (e->indexes.size ());
2948 symbol
*array
= NULL
;
2949 hist_op
*hist
= NULL
;
2950 classify_indexable(e
->base
, array
, hist
);
2954 if (e
->indexes
.size() != 1)
2955 unresolved (e
->tok
);
2957 e
->indexes
[0]->visit (this);
2958 if (e
->indexes
[0]->type
!= pe_long
)
2959 unresolved (e
->tok
);
2965 if (e
->indexes
.size() != array
->referent
->index_types
.size())
2966 unresolved (e
->tok
); // symbol resolution should prevent this
2967 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
2969 expression
* ee
= e
->indexes
[i
];
2970 exp_type
& ft
= array
->referent
->index_types
[i
];
2973 exp_type at
= ee
->type
;
2975 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
2977 // propagate to formal type
2979 resolved (array
->referent
->tok
, ft
);
2980 // uses array decl as there is no token for "formal type"
2983 invalid (ee
->tok
, at
);
2985 invalid (ee
->tok
, ft
);
2986 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
2987 mismatch (e
->tok
, at
, ft
);
2988 if (at
== pe_unknown
)
2989 unresolved (ee
->tok
);
2996 e
->limit
->visit (this);
3000 e
->block
->visit (this);
3005 typeresolution_info::visit_null_statement (null_statement
*)
3011 typeresolution_info::visit_expr_statement (expr_statement
* e
)
3014 e
->value
->visit (this);
3018 struct delete_statement_typeresolution_info
:
3019 public throwing_visitor
3021 typeresolution_info
*parent
;
3022 delete_statement_typeresolution_info (typeresolution_info
*p
):
3023 throwing_visitor ("invalid operand of delete expression"),
3027 void visit_arrayindex (arrayindex
* e
)
3029 parent
->visit_arrayindex (e
);
3032 void visit_symbol (symbol
* e
)
3034 exp_type ignored
= pe_unknown
;
3035 assert (e
->referent
!= 0);
3036 resolve_2types (e
, e
->referent
, parent
, ignored
);
3042 typeresolution_info::visit_delete_statement (delete_statement
* e
)
3044 delete_statement_typeresolution_info
di (this);
3046 e
->value
->visit (&di
);
3051 typeresolution_info::visit_next_statement (next_statement
*)
3057 typeresolution_info::visit_break_statement (break_statement
*)
3063 typeresolution_info::visit_continue_statement (continue_statement
*)
3069 typeresolution_info::visit_array_in (array_in
* e
)
3071 // all unary operators only work on numerics
3073 t
= pe_unknown
; // array value can be anything
3074 e
->operand
->visit (this);
3076 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
3077 ; // already resolved
3078 else if (t1
== pe_string
|| t1
== pe_stats
)
3079 mismatch (e
->tok
, t1
, pe_long
);
3080 else if (e
->type
== pe_unknown
)
3083 resolved (e
->tok
, e
->type
);
3089 typeresolution_info::visit_return_statement (return_statement
* e
)
3091 // This is like symbol, where the referent is
3092 // the return value of the function.
3094 // translation pass will print error
3095 if (current_function
== 0)
3098 exp_type
& e_type
= current_function
->type
;
3099 t
= current_function
->type
;
3100 e
->value
->visit (this);
3102 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
3103 && e_type
!= e
->value
->type
)
3104 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
3105 if (e_type
== pe_unknown
&&
3106 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
3108 // propagate non-statistics from value
3109 e_type
= e
->value
->type
;
3110 resolved (current_function
->tok
, e
->value
->type
);
3112 if (e
->value
->type
== pe_stats
)
3113 invalid (e
->value
->tok
, e
->value
->type
);
3117 typeresolution_info::visit_print_format (print_format
* e
)
3119 size_t unresolved_args
= 0;
3123 e
->hist
->visit(this);
3126 else if (e
->print_with_format
)
3128 // If there's a format string, we can do both inference *and*
3131 // First we extract the subsequence of formatting components
3132 // which are conversions (not just literal string components)
3134 unsigned expected_num_args
= 0;
3135 std::vector
<print_format::format_component
> components
;
3136 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
3138 if (e
->components
[i
].type
== print_format::conv_unspecified
)
3139 throw semantic_error ("Unspecified conversion in print operator format string",
3141 else if (e
->components
[i
].type
== print_format::conv_literal
3142 || e
->components
[i
].type
== print_format::conv_size
)
3144 components
.push_back(e
->components
[i
]);
3145 ++expected_num_args
;
3146 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
3147 ++expected_num_args
;
3148 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
3149 ++expected_num_args
;
3152 // Then we check that the number of conversions and the number
3155 if (expected_num_args
!= e
->args
.size())
3156 throw semantic_error ("Wrong number of args to formatted print operator",
3159 // Then we check that the types of the conversions match the types
3162 for (size_t i
= 0; i
< components
.size(); ++i
)
3164 // Check the dynamic width, if specified
3165 if (components
[i
].widthtype
== print_format::width_dynamic
)
3167 check_arg_type (pe_long
, e
->args
[argno
]);
3171 // Check the dynamic precision, if specified
3172 if (components
[i
].prectype
== print_format::prec_dynamic
)
3174 check_arg_type (pe_long
, e
->args
[argno
]);
3178 exp_type wanted
= pe_unknown
;
3180 switch (components
[i
].type
)
3182 case print_format::conv_unspecified
:
3183 case print_format::conv_literal
:
3184 case print_format::conv_size
:
3188 case print_format::conv_signed_decimal
:
3189 case print_format::conv_unsigned_decimal
:
3190 case print_format::conv_unsigned_octal
:
3191 case print_format::conv_unsigned_ptr
:
3192 case print_format::conv_unsigned_uppercase_hex
:
3193 case print_format::conv_unsigned_lowercase_hex
:
3194 case print_format::conv_binary
:
3195 case print_format::conv_memory
:
3199 case print_format::conv_string
:
3204 assert (wanted
!= pe_unknown
);
3205 check_arg_type (wanted
, e
->args
[argno
]);
3211 // Without a format string, the best we can do is require that
3212 // each argument resolve to a concrete type.
3213 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
3216 e
->args
[i
]->visit (this);
3217 if (e
->args
[i
]->type
== pe_unknown
)
3219 unresolved (e
->args
[i
]->tok
);
3225 if (unresolved_args
== 0)
3227 if (e
->type
== pe_unknown
)
3229 if (e
->print_to_stream
)
3232 e
->type
= pe_string
;
3233 resolved (e
->tok
, e
->type
);
3238 e
->type
= pe_unknown
;
3239 unresolved (e
->tok
);
3245 typeresolution_info::visit_stat_op (stat_op
* e
)
3248 e
->stat
->visit (this);
3249 if (e
->type
== pe_unknown
)
3252 resolved (e
->tok
, e
->type
);
3254 else if (e
->type
!= pe_long
)
3255 mismatch (e
->tok
, e
->type
, pe_long
);
3259 typeresolution_info::visit_hist_op (hist_op
* e
)
3262 e
->stat
->visit (this);
3267 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
3272 if (arg
->type
== pe_unknown
)
3275 resolved (arg
->tok
, wanted
);
3277 else if (arg
->type
!= wanted
)
3279 mismatch (arg
->tok
, arg
->type
, wanted
);
3285 typeresolution_info::unresolved (const token
* tok
)
3287 num_still_unresolved
++;
3289 if (assert_resolvability
)
3292 string nm
= (current_function
? current_function
->name
:
3293 current_probe
? current_probe
->name
:
3295 msg
<< nm
+ " with unresolved type";
3296 session
.print_error (semantic_error (msg
.str(), tok
));
3302 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
3304 num_still_unresolved
++;
3306 if (assert_resolvability
)
3309 string nm
= (current_function
? current_function
->name
:
3310 current_probe
? current_probe
->name
:
3312 if (tok
&& tok
->type
== tok_operator
)
3313 msg
<< nm
+ " uses invalid operator";
3315 msg
<< nm
+ " with invalid type " << pe
;
3316 session
.print_error (semantic_error (msg
.str(), tok
));
3322 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
3324 num_still_unresolved
++;
3326 if (assert_resolvability
)
3329 string nm
= (current_function
? current_function
->name
:
3330 current_probe
? current_probe
->name
:
3332 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
3333 session
.print_error (semantic_error (msg
.str(), tok
));
3339 typeresolution_info::resolved (const token
*, exp_type
)
3341 num_newly_resolved
++;