1 // elaboration functions
2 // Copyright (C) 2005-2009 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"
18 #include <sys/utsname.h>
35 // ------------------------------------------------------------------------
37 // Used in probe_point condition construction. Either argument may be
38 // NULL; if both, return NULL too. Resulting expression is a deep
39 // copy for symbol resolution purposes.
40 expression
* add_condition (expression
* a
, expression
* b
)
42 if (!a
&& !b
) return 0;
43 if (! a
) return deep_copy_visitor::deep_copy(b
);
44 if (! b
) return deep_copy_visitor::deep_copy(a
);
49 la
.tok
= a
->tok
; // or could be b->tok
50 return deep_copy_visitor::deep_copy(& la
);
53 // ------------------------------------------------------------------------
57 derived_probe::derived_probe (probe
*p
):
58 base (p
), sdt_semaphore_addr(0)
61 this->locations
= p
->locations
;
63 this->privileged
= p
->privileged
;
64 this->body
= deep_copy_visitor::deep_copy(p
->body
);
68 derived_probe::derived_probe (probe
*p
, probe_point
*l
):
69 base (p
), sdt_semaphore_addr(0)
73 this->privileged
= p
->privileged
;
74 this->body
= deep_copy_visitor::deep_copy(p
->body
);
77 this->locations
.push_back (l
);
82 derived_probe::printsig (ostream
& o
) const
89 derived_probe::printsig_nested (ostream
& o
) const
91 // We'd like to enclose the probe derivation chain in a /* */
92 // comment delimiter. But just printing /* base->printsig() */ is
93 // not enough, since base might itself be a derived_probe. So we,
94 // er, "cleverly" encode our nesting state as a formatting flag for
96 ios::fmtflags f
= o
.flags (ios::internal
);
97 if (f
& ios::internal
)
116 derived_probe::collect_derivation_chain (std::vector
<probe
*> &probes_list
)
118 probes_list
.push_back(this);
119 base
->collect_derivation_chain(probes_list
);
124 derived_probe::sole_location () const
126 if (locations
.size() == 0)
127 throw semantic_error ("derived_probe with no locations", this->tok
);
128 else if (locations
.size() > 1)
129 throw semantic_error ("derived_probe with too many locations", this->tok
);
136 // ------------------------------------------------------------------------
137 // Members of derived_probe_builder
140 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
141 const std::string
& key
,
144 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
145 if (i
== params
.end())
147 literal_string
* ls
= dynamic_cast<literal_string
*>(i
->second
);
156 derived_probe_builder::get_param (std::map
<std::string
, literal
*> const & params
,
157 const std::string
& key
,
160 map
<string
, literal
*>::const_iterator i
= params
.find (key
);
161 if (i
== params
.end())
163 if (i
->second
== NULL
)
165 literal_number
* ln
= dynamic_cast<literal_number
*>(i
->second
);
174 derived_probe_builder::has_null_param (std::map
<std::string
, literal
*> const & params
,
175 const std::string
& key
)
177 map
<string
, literal
*>::const_iterator i
= params
.find(key
);
178 return (i
!= params
.end() && i
->second
== NULL
);
183 // ------------------------------------------------------------------------
184 // Members of match_key.
186 match_key::match_key(string
const & n
)
188 have_parameter(false),
189 parameter_type(pe_unknown
)
193 match_key::match_key(probe_point::component
const & c
)
195 have_parameter(c
.arg
!= NULL
),
196 parameter_type(c
.arg
? c
.arg
->type
: pe_unknown
)
201 match_key::with_number()
203 have_parameter
= true;
204 parameter_type
= pe_long
;
209 match_key::with_string()
211 have_parameter
= true;
212 parameter_type
= pe_string
;
217 match_key::str() const
220 switch (parameter_type
)
222 case pe_string
: return name
+ "(string)";
223 case pe_long
: return name
+ "(number)";
224 default: return name
+ "(...)";
230 match_key::operator<(match_key
const & other
) const
232 return ((name
< other
.name
)
234 || (name
== other
.name
235 && have_parameter
< other
.have_parameter
)
237 || (name
== other
.name
238 && have_parameter
== other
.have_parameter
239 && parameter_type
< other
.parameter_type
));
243 isglob(string
const & str
)
245 return(str
.find('*') != str
.npos
);
249 match_key::globmatch(match_key
const & other
) const
251 const char *other_str
= other
.name
.c_str();
252 const char *name_str
= name
.c_str();
254 return ((fnmatch(name_str
, other_str
, FNM_NOESCAPE
) == 0)
255 && have_parameter
== other
.have_parameter
256 && parameter_type
== other
.parameter_type
);
259 // ------------------------------------------------------------------------
260 // Members of match_node
261 // ------------------------------------------------------------------------
263 match_node::match_node()
264 : unprivileged_ok (false)
269 match_node::bind(match_key
const & k
)
272 throw semantic_error("invalid use of wildcard probe point component");
274 map
<match_key
, match_node
*>::const_iterator i
= sub
.find(k
);
277 match_node
* n
= new match_node();
278 sub
.insert(make_pair(k
, n
));
283 match_node::bind(derived_probe_builder
* e
)
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());
307 match_node::allow_unprivileged (bool b
)
314 match_node::unprivileged_allowed () const
316 return unprivileged_ok
;
320 match_node::find_and_build (systemtap_session
& s
,
321 probe
* p
, probe_point
*loc
, unsigned pos
,
322 vector
<derived_probe
*>& results
)
324 assert (pos
<= loc
->components
.size());
325 if (pos
== loc
->components
.size()) // matched all probe point components so far
330 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
331 alternatives
+= string(" ") + i
->first
.str();
333 throw semantic_error (string("probe point truncated at position ") +
335 " (follow:" + alternatives
+ ")", loc
->tok
);
338 map
<string
, literal
*> param_map
;
339 for (unsigned i
=0; i
<pos
; i
++)
340 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
343 // Are we compiling for unprivileged users? */
346 // Is this probe point ok for unprivileged users?
347 if (! unprivileged_allowed ())
348 throw semantic_error (string("probe point is not allowed for unprivileged users"));
351 // Iterate over all bound builders
352 for (unsigned k
=0; k
<ends
.size(); k
++)
354 derived_probe_builder
*b
= ends
[k
];
355 b
->build (s
, p
, loc
, param_map
, results
);
358 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
360 match_key
match (* loc
->components
[pos
]);
362 // Call find_and_build for each possible match. Ignore errors -
363 // unless we don't find any match.
364 unsigned int num_results
= results
.size();
365 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
367 const match_key
& subkey
= i
->first
;
368 match_node
* subnode
= i
->second
;
370 if (pending_interrupts
) break;
372 if (match
.globmatch(subkey
))
375 clog
<< "wildcard '" << loc
->components
[pos
]->functor
376 << "' matched '" << subkey
.name
<< "'" << endl
;
378 // When we have a wildcard, we need to create a copy of
379 // the probe point. Then we'll create a copy of the
380 // wildcard component, and substitute the non-wildcard
382 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
383 probe_point::component
*non_wildcard_component
384 = new probe_point::component(*loc
->components
[pos
]);
385 non_wildcard_component
->functor
= subkey
.name
;
386 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
388 // NB: probe conditions are not attached at the wildcard
389 // (component/functor) level, but at the overall
390 // probe_point level.
392 // recurse (with the non-wildcard probe point)
395 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
398 catch (const semantic_error
& e
)
400 // Ignore semantic_errors while expanding wildcards.
401 // If we get done and nothing was expanded, the code
402 // following the loop will complain.
404 // If this wildcard didn't match, cleanup.
405 delete non_wildcard_pp
;
406 delete non_wildcard_component
;
410 if (! loc
->optional
&& num_results
== results
.size())
412 // We didn't find any wildcard matches (since the size of
413 // the result vector didn't change). Throw an error.
415 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
416 alternatives
+= string(" ") + i
->first
.str();
418 throw semantic_error(string("probe point mismatch at position ") +
420 " (alternatives:" + alternatives
+ ")" +
421 " didn't find any wildcard matches",
427 match_key
match (* loc
->components
[pos
]);
428 sub_map_iterator_t i
= sub
.find (match
);
429 if (i
== sub
.end()) // no match
432 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
433 alternatives
+= string(" ") + i
->first
.str();
435 throw semantic_error (string("probe point mismatch at position ") +
437 " (alternatives:" + alternatives
+ ")",
441 match_node
* subnode
= i
->second
;
443 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
449 match_node::build_no_more (systemtap_session
& s
)
451 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
452 i
->second
->build_no_more (s
);
453 for (unsigned k
=0; k
<ends
.size(); k
++)
455 derived_probe_builder
*b
= ends
[k
];
456 b
->build_no_more (s
);
461 // ------------------------------------------------------------------------
463 // ------------------------------------------------------------------------
465 struct alias_derived_probe
: public derived_probe
467 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
):
468 derived_probe (base
, l
), alias(a
) {}
470 void upchuck () { throw semantic_error ("inappropriate", this->tok
); }
472 // Alias probes are immediately expanded to other derived_probe
473 // types, and are not themselves emitted or listed in
474 // systemtap_session.probes
476 void join_group (systemtap_session
&) { upchuck (); }
478 virtual const probe_alias
*get_alias () const { return alias
; }
481 const probe_alias
*alias
; // Used to check for recursion
486 alias_expansion_builder
487 : public derived_probe_builder
491 alias_expansion_builder(probe_alias
* a
)
495 virtual void build(systemtap_session
& sess
,
497 probe_point
* location
,
498 std::map
<std::string
, literal
*> const &,
499 vector
<derived_probe
*> & finished_results
)
501 // Don't build the alias expansion if infinite recursion is detected.
502 if (checkForRecursiveExpansion (use
)) {
504 msg
<< "Recursive loop in alias expansion of " << *location
<< " at " << location
->tok
->location
;
505 // semantic_errors thrown here are ignored.
506 sess
.print_error (semantic_error (msg
.str()));
510 // We're going to build a new probe and wrap it up in an
511 // alias_expansion_probe so that the expansion loop recognizes it as
512 // such and re-expands its expansion.
514 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
);
515 n
->body
= new block();
517 // The new probe gets a deep copy of the location list of
518 // the alias (with incoming condition joined)
519 n
->locations
.clear();
520 for (unsigned i
=0; i
<alias
->locations
.size(); i
++)
522 probe_point
*pp
= new probe_point(*alias
->locations
[i
]);
523 pp
->condition
= add_condition (pp
->condition
, location
->condition
);
524 n
->locations
.push_back(pp
);
527 // the token location of the alias,
528 n
->tok
= location
->tok
;
530 // and statements representing the concatenation of the alias'
531 // body with the use's.
533 // NB: locals are *not* copied forward, from either alias or
534 // use. The expansion should have its locals re-inferred since
535 // there's concatenated code here and we only want one vardecl per
536 // resulting variable.
538 if (alias
->epilogue_style
)
539 n
->body
= new block (use
->body
, alias
->body
);
541 n
->body
= new block (alias
->body
, use
->body
);
543 unsigned old_num_results
= finished_results
.size();
544 derive_probes (sess
, n
, finished_results
, location
->optional
);
546 // Check whether we resolved something. If so, put the
547 // whole library into the queue if not already there.
548 if (finished_results
.size() > old_num_results
)
550 stapfile
*f
= alias
->tok
->location
.file
;
551 if (find (sess
.files
.begin(), sess
.files
.end(), f
)
553 sess
.files
.push_back (f
);
557 bool checkForRecursiveExpansion (probe
*use
)
559 // Collect the derivation chain of this probe.
560 vector
<probe
*>derivations
;
561 use
->collect_derivation_chain (derivations
);
563 // Check all probe points in the alias expansion against the currently-being-expanded probe point
564 // of each of the probes in the derivation chain, looking for a match. This
565 // indicates infinite recursion.
566 // The first element of the derivation chain will be the derived_probe representing 'use', so
567 // start the search with the second element.
568 assert (derivations
.size() > 0);
569 assert (derivations
[0] == use
);
570 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
571 if (use
->get_alias() == derivations
[d
]->get_alias())
572 return true; // recursion detected
579 // ------------------------------------------------------------------------
581 // ------------------------------------------------------------------------
584 // Register all the aliases we've seen in library files, and the user
585 // file, as patterns.
588 systemtap_session::register_library_aliases()
590 vector
<stapfile
*> files(library_files
);
591 files
.push_back(user_file
);
593 for (unsigned f
= 0; f
< files
.size(); ++f
)
595 stapfile
* file
= files
[f
];
596 for (unsigned a
= 0; a
< file
->aliases
.size(); ++a
)
598 probe_alias
* alias
= file
->aliases
[a
];
601 for (unsigned n
= 0; n
< alias
->alias_names
.size(); ++n
)
603 probe_point
* name
= alias
->alias_names
[n
];
604 match_node
* n
= pattern_root
;
605 for (unsigned c
= 0; c
< name
->components
.size(); ++c
)
607 probe_point::component
* comp
= name
->components
[c
];
608 // XXX: alias parameters
610 throw semantic_error("alias component "
612 + " contains illegal parameter");
613 n
= n
->bind(comp
->functor
);
615 n
->bind(new alias_expansion_builder(alias
));
618 catch (const semantic_error
& e
)
620 semantic_error
* er
= new semantic_error (e
); // copy it
623 msg
<< " while registering probe alias ";
624 alias
->printsig(msg
);
625 er
->msg2
= msg
.str();
634 static unsigned max_recursion
= 100;
640 recursion_guard(unsigned & i
) : i(i
)
642 if (i
> max_recursion
)
643 throw semantic_error("recursion limit reached");
652 // The match-and-expand loop.
654 derive_probes (systemtap_session
& s
,
655 probe
*p
, vector
<derived_probe
*>& dps
,
658 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
660 if (pending_interrupts
) break;
662 probe_point
*loc
= p
->locations
[i
];
666 unsigned num_atbegin
= dps
.size();
668 // Pass down optional flag from e.g. alias reference to each
669 // probe_point instance. We do this by temporarily overriding
670 // the probe_point optional flag. We could instead deep-copy
671 // and set a flag on the copy permanently.
672 bool old_loc_opt
= loc
->optional
;
673 loc
->optional
= loc
->optional
|| optional
;
676 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
678 catch (const semantic_error
& e
)
681 throw semantic_error(e
);
682 else /* tolerate failure for optional probe */
686 loc
->optional
= old_loc_opt
;
687 unsigned num_atend
= dps
.size();
689 if (! (loc
->optional
||optional
) && // something required, but
690 num_atbegin
== num_atend
) // nothing new derived!
691 throw semantic_error ("no match");
693 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
697 clog
<< "Probe point ";
698 p
->locations
[i
]->print(clog
);
699 clog
<< " sufficient, skipped";
700 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
703 p
->locations
[j
]->print(clog
);
707 break; // we need not try to derive for any other locations
710 catch (const semantic_error
& e
)
712 // XXX: prefer not to print_error at every nest/unroll level
714 semantic_error
* er
= new semantic_error (e
); // copy it
717 msg
<< " while resolving probe point " << *loc
;
718 er
->msg2
= msg
.str();
719 s
.print_error (* er
);
728 // ------------------------------------------------------------------------
730 // Indexable usage checks
733 struct symbol_fetcher
734 : public throwing_visitor
738 symbol_fetcher (symbol
*&sym
): sym(sym
)
741 void visit_symbol (symbol
* e
)
746 void visit_target_symbol (target_symbol
* e
)
751 void visit_arrayindex (arrayindex
* e
)
753 e
->base
->visit_indexable (this);
756 void visit_cast_op (cast_op
* e
)
761 void throwone (const token
* t
)
763 throw semantic_error ("Expecting symbol or array index expression", t
);
768 get_symbol_within_expression (expression
*e
)
771 symbol_fetcher
fetcher(sym
);
773 return sym
; // NB: may be null!
777 get_symbol_within_indexable (indexable
*ix
)
779 symbol
*array
= NULL
;
780 hist_op
*hist
= NULL
;
781 classify_indexable(ix
, array
, hist
);
785 return get_symbol_within_expression (hist
->stat
);
788 struct mutated_var_collector
789 : public traversing_visitor
791 set
<vardecl
*> * mutated_vars
;
793 mutated_var_collector (set
<vardecl
*> * mm
)
797 void visit_assignment(assignment
* e
)
799 if (e
->type
== pe_stats
&& e
->op
== "<<<")
801 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
803 mutated_vars
->insert (vd
);
805 traversing_visitor::visit_assignment(e
);
808 void visit_arrayindex (arrayindex
*e
)
810 if (is_active_lvalue (e
))
813 if (e
->base
->is_symbol (sym
))
814 mutated_vars
->insert (sym
->referent
);
816 throw semantic_error("Assignment to read-only histogram bucket", e
->tok
);
818 traversing_visitor::visit_arrayindex (e
);
823 struct no_var_mutation_during_iteration_check
824 : public traversing_visitor
826 systemtap_session
& session
;
827 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
828 vector
<vardecl
*> vars_being_iterated
;
830 no_var_mutation_during_iteration_check
831 (systemtap_session
& sess
,
832 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
833 : session(sess
), function_mutates_vars (fmv
)
836 void visit_arrayindex (arrayindex
*e
)
838 if (is_active_lvalue(e
))
840 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
843 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
845 vardecl
*v
= vars_being_iterated
[i
];
848 string err
= ("variable '" + v
->name
+
849 "' modified during 'foreach' iteration");
850 session
.print_error (semantic_error (err
, e
->tok
));
855 traversing_visitor::visit_arrayindex (e
);
858 void visit_functioncall (functioncall
* e
)
860 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
861 = function_mutates_vars
.find (e
->referent
);
863 if (i
!= function_mutates_vars
.end())
865 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
867 vardecl
*m
= vars_being_iterated
[j
];
868 if (i
->second
->find (m
) != i
->second
->end())
870 string err
= ("function call modifies var '" + m
->name
+
871 "' during 'foreach' iteration");
872 session
.print_error (semantic_error (err
, e
->tok
));
877 traversing_visitor::visit_functioncall (e
);
880 void visit_foreach_loop(foreach_loop
* s
)
882 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
885 vars_being_iterated
.push_back (vd
);
887 traversing_visitor::visit_foreach_loop (s
);
890 vars_being_iterated
.pop_back();
895 // ------------------------------------------------------------------------
897 struct stat_decl_collector
898 : public traversing_visitor
900 systemtap_session
& session
;
902 stat_decl_collector(systemtap_session
& sess
)
906 void visit_stat_op (stat_op
* e
)
908 symbol
*sym
= get_symbol_within_expression (e
->stat
);
909 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
910 session
.stat_decls
[sym
->name
] = statistic_decl();
913 void visit_assignment (assignment
* e
)
917 symbol
*sym
= get_symbol_within_expression (e
->left
);
918 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
919 session
.stat_decls
[sym
->name
] = statistic_decl();
922 traversing_visitor::visit_assignment(e
);
925 void visit_hist_op (hist_op
* e
)
927 symbol
*sym
= get_symbol_within_expression (e
->stat
);
928 statistic_decl new_stat
;
930 if (e
->htype
== hist_linear
)
932 new_stat
.type
= statistic_decl::linear
;
933 assert (e
->params
.size() == 3);
934 new_stat
.linear_low
= e
->params
[0];
935 new_stat
.linear_high
= e
->params
[1];
936 new_stat
.linear_step
= e
->params
[2];
940 assert (e
->htype
== hist_log
);
941 new_stat
.type
= statistic_decl::logarithmic
;
942 assert (e
->params
.size() == 0);
945 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
946 if (i
== session
.stat_decls
.end())
947 session
.stat_decls
[sym
->name
] = new_stat
;
950 statistic_decl
& old_stat
= i
->second
;
951 if (!(old_stat
== new_stat
))
953 if (old_stat
.type
== statistic_decl::none
)
954 i
->second
= new_stat
;
957 // FIXME: Support multiple co-declared histogram types
958 semantic_error
se("multiple histogram types declared on '" + sym
->name
+ "'",
960 session
.print_error (se
);
969 semantic_pass_stats (systemtap_session
& sess
)
971 stat_decl_collector
sdc(sess
);
973 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
974 it
->second
->body
->visit (&sdc
);
976 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
977 sess
.probes
[i
]->body
->visit (&sdc
);
979 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
981 vardecl
*v
= sess
.globals
[i
];
982 if (v
->type
== pe_stats
)
985 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
987 semantic_error
se("unable to infer statistic parameters for global '" + v
->name
+ "'");
988 sess
.print_error (se
);
993 return sess
.num_errors();
996 // ------------------------------------------------------------------------
998 // Enforce variable-related invariants: no modification of
999 // a foreach()-iterated array.
1001 semantic_pass_vars (systemtap_session
& sess
)
1004 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
1005 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
1007 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1009 functiondecl
* fn
= it
->second
;
1012 set
<vardecl
*> * m
= new set
<vardecl
*>();
1013 mutated_var_collector
mc (m
);
1014 fn
->body
->visit (&mc
);
1019 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1021 functiondecl
* fn
= it
->second
;
1022 if (fn
->body
) fn
->body
->visit (&chk
);
1025 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1027 if (sess
.probes
[i
]->body
)
1028 sess
.probes
[i
]->body
->visit (&chk
);
1031 return sess
.num_errors();
1035 // ------------------------------------------------------------------------
1037 // Rewrite probe condition expressions into probe bodies. Tricky and
1038 // exciting business, this. This:
1040 // probe foo if (g1 || g2) { ... }
1041 // probe bar { ... g1 ++ ... }
1045 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1046 // probe foo { if (! (g1 || g2)) next; ... }
1047 // probe bar { ... g1 ++ ...;
1048 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1051 // XXX: As a first cut, do only the "inline probe condition" part of the
1055 semantic_pass_conditions (systemtap_session
& sess
)
1057 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1059 derived_probe
* p
= sess
.probes
[i
];
1060 expression
* e
= p
->sole_location()->condition
;
1063 varuse_collecting_visitor
vut(sess
);
1066 if (! vut
.written
.empty())
1068 string err
= ("probe condition must not modify any variables");
1069 sess
.print_error (semantic_error (err
, e
->tok
));
1071 else if (vut
.embedded_seen
)
1073 sess
.print_error (semantic_error ("probe condition must not include impure embedded-C", e
->tok
));
1076 // Add the condition expression to the front of the
1077 // derived_probe body.
1078 if_statement
*ifs
= new if_statement ();
1080 ifs
->thenblock
= new next_statement ();
1081 ifs
->thenblock
->tok
= e
->tok
;
1082 ifs
->elseblock
= NULL
;
1083 unary_expression
*notex
= new unary_expression ();
1085 notex
->tok
= e
->tok
;
1087 ifs
->condition
= notex
;
1088 p
->body
= new block (ifs
, p
->body
);
1092 return sess
.num_errors();
1096 // ------------------------------------------------------------------------
1099 static int semantic_pass_symbols (systemtap_session
&);
1100 static int semantic_pass_optimize1 (systemtap_session
&);
1101 static int semantic_pass_optimize2 (systemtap_session
&);
1102 static int semantic_pass_types (systemtap_session
&);
1103 static int semantic_pass_vars (systemtap_session
&);
1104 static int semantic_pass_stats (systemtap_session
&);
1105 static int semantic_pass_conditions (systemtap_session
&);
1108 // Link up symbols to their declarations. Set the session's
1109 // files/probes/functions/globals vectors from the transitively
1110 // reached set of stapfiles in s.library_files, starting from
1111 // s.user_file. Perform automatic tapset inclusion and probe
1114 semantic_pass_symbols (systemtap_session
& s
)
1116 symresolution_info
sym (s
);
1118 // NB: s.files can grow during this iteration, so size() can
1119 // return gradually increasing numbers.
1120 s
.files
.push_back (s
.user_file
);
1121 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1123 if (pending_interrupts
) break;
1124 stapfile
* dome
= s
.files
[i
];
1126 // Pass 1: add globals and functions to systemtap-session master list,
1127 // so the find_* functions find them
1129 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1130 s
.globals
.push_back (dome
->globals
[i
]);
1132 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1133 s
.functions
[dome
->functions
[i
]->name
] = dome
->functions
[i
];
1135 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1136 s
.embeds
.push_back (dome
->embeds
[i
]);
1138 // Pass 2: process functions
1140 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1142 if (pending_interrupts
) break;
1143 functiondecl
* fd
= dome
->functions
[i
];
1147 for (unsigned j
=0; j
<s
.code_filters
.size(); j
++)
1148 s
.code_filters
[j
]->replace (fd
->body
);
1150 sym
.current_function
= fd
;
1151 sym
.current_probe
= 0;
1152 fd
->body
->visit (& sym
);
1154 catch (const semantic_error
& e
)
1160 // Pass 3: derive probes and resolve any further symbols in the
1163 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1165 if (pending_interrupts
) break;
1166 probe
* p
= dome
->probes
[i
];
1167 vector
<derived_probe
*> dps
;
1169 // much magic happens here: probe alias expansion, wildcard
1170 // matching, low-level derived_probe construction.
1171 derive_probes (s
, p
, dps
);
1173 for (unsigned j
=0; j
<dps
.size(); j
++)
1175 if (pending_interrupts
) break;
1176 derived_probe
* dp
= dps
[j
];
1177 s
.probes
.push_back (dp
);
1182 for (unsigned k
=0; k
<s
.code_filters
.size(); k
++)
1183 s
.code_filters
[k
]->replace (dp
->body
);
1185 sym
.current_function
= 0;
1186 sym
.current_probe
= dp
;
1187 dp
->body
->visit (& sym
);
1189 // Process the probe-point condition expression.
1190 sym
.current_function
= 0;
1191 sym
.current_probe
= 0;
1192 if (dp
->sole_location()->condition
)
1193 dp
->sole_location()->condition
->visit (& sym
);
1195 catch (const semantic_error
& e
)
1203 // Inform all derived_probe builders that we're done with
1204 // all resolution, so it's time to release caches.
1205 s
.pattern_root
->build_no_more (s
);
1207 return s
.num_errors(); // all those print_error calls
1211 // Keep unread global variables for probe end value display.
1212 void add_global_var_display (systemtap_session
& s
)
1214 // Don't generate synthetic end probes when in listings mode;
1215 // it would clutter up the list of probe points with "end ...".
1216 if (s
.listing_mode
) return;
1218 varuse_collecting_visitor
vut(s
);
1219 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1221 s
.probes
[i
]->body
->visit (& vut
);
1223 if (s
.probes
[i
]->sole_location()->condition
)
1224 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1227 for (unsigned g
=0; g
< s
.globals
.size(); g
++)
1229 vardecl
* l
= s
.globals
[g
];
1230 if (vut
.read
.find (l
) != vut
.read
.end()
1231 || vut
.written
.find (l
) == vut
.written
.end())
1234 // Don't generate synthetic end probes for unread globals
1235 // declared only within tapsets. (RHBZ 468139), but rather
1236 // only within the end-user script.
1238 bool tapset_global
= false;
1239 for (size_t m
=0; m
< s
.library_files
.size(); m
++)
1241 for (size_t n
=0; n
< s
.library_files
[m
]->globals
.size(); n
++)
1243 if (l
->name
== s
.library_files
[m
]->globals
[n
]->name
)
1244 {tapset_global
= true; break;}
1250 print_format
* pf
= new print_format
;
1251 probe
* p
= new probe
;
1252 probe_point
* pl
= new probe_point
;
1253 probe_point::component
* c
= new probe_point::component("end");
1254 token
* print_tok
= new token
;
1255 vector
<derived_probe
*> dps
;
1256 block
*b
= new block
;
1258 pl
->components
.push_back (c
);
1260 p
->locations
.push_back (pl
);
1261 print_tok
->type
= tok_identifier
;
1262 print_tok
->content
= "printf";
1265 symbol
* g_sym
= new symbol
;
1266 g_sym
->name
= l
->name
;
1267 g_sym
->tok
= l
->tok
;
1268 g_sym
->type
= l
->type
;
1269 g_sym
->referent
= l
;
1271 pf
->print_to_stream
= true;
1272 pf
->print_with_format
= true;
1273 pf
->print_with_delim
= false;
1274 pf
->print_with_newline
= false;
1275 pf
->print_char
= false;
1276 pf
->raw_components
+= l
->name
;
1277 pf
->tok
= print_tok
;
1279 if (l
->index_types
.size() == 0) // Scalar
1281 if (l
->type
== pe_stats
)
1282 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1283 else if (l
->type
== pe_string
)
1284 pf
->raw_components
+= "=\"%#s\"\\n";
1286 pf
->raw_components
+= "=%#x\\n";
1287 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1288 expr_statement
* feb
= new expr_statement
;
1290 feb
->tok
= print_tok
;
1291 if (l
->type
== pe_stats
)
1293 struct stat_op
* so
[5];
1294 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1296 for (unsigned si
= 0;
1297 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1300 so
[si
]= new stat_op
;
1301 so
[si
]->ctype
= stypes
[si
];
1302 so
[si
]->type
= pe_long
;
1303 so
[si
]->stat
= g_sym
;
1304 so
[si
]->tok
= l
->tok
;
1305 pf
->args
.push_back(so
[si
]);
1309 pf
->args
.push_back(g_sym
);
1311 /* PR7053: Checking empty aggregate for global variable */
1312 if (l
->type
== pe_stats
) {
1313 stat_op
*so
= new stat_op
;
1314 so
->ctype
= sc_count
;
1318 comparison
*be
= new comparison
;
1322 be
->right
= new literal_number(0);
1324 /* Create printf @count=0x0 in else block */
1325 print_format
* pf_0
= new print_format
;
1326 pf_0
->print_to_stream
= true;
1327 pf_0
->print_with_format
= true;
1328 pf_0
->print_with_delim
= false;
1329 pf_0
->print_with_newline
= false;
1330 pf_0
->print_char
= false;
1331 pf_0
->raw_components
+= l
->name
;
1332 pf_0
->raw_components
+= " @count=0x0\\n";
1333 pf_0
->tok
= print_tok
;
1334 pf_0
->components
= print_format::string_to_components(pf_0
->raw_components
);
1335 expr_statement
* feb_else
= new expr_statement
;
1336 feb_else
->value
= pf_0
;
1337 feb_else
->tok
= print_tok
;
1338 if_statement
*ifs
= new if_statement
;
1340 ifs
->condition
= be
;
1341 ifs
->thenblock
= feb
;
1342 ifs
->elseblock
= feb_else
;
1343 b
->statements
.push_back(ifs
);
1345 else /* other non-stat cases */
1346 b
->statements
.push_back(feb
);
1350 int idx_count
= l
->index_types
.size();
1351 symbol
* idx_sym
[idx_count
];
1352 vardecl
* idx_v
[idx_count
];
1353 // Create a foreach loop
1354 foreach_loop
* fe
= new foreach_loop
;
1355 fe
->sort_direction
= -1; // imply decreasing sort on value
1356 fe
->sort_column
= 0; // as in foreach ([a,b,c] in array-) { }
1359 // Create indices for the foreach loop
1360 for (int i
=0; i
< idx_count
; i
++)
1363 if (asprintf (&idx_name
, "idx%d", i
) < 0)
1365 idx_sym
[i
] = new symbol
;
1366 idx_sym
[i
]->name
= idx_name
;
1367 idx_sym
[i
]->tok
= l
->tok
;
1368 idx_v
[i
] = new vardecl
;
1369 idx_v
[i
]->name
= idx_name
;
1370 idx_v
[i
]->type
= l
->index_types
[i
];
1371 idx_v
[i
]->tok
= l
->tok
;
1372 idx_sym
[i
]->referent
= idx_v
[i
];
1373 fe
->indexes
.push_back (idx_sym
[i
]);
1376 // Create a printf for the foreach loop
1377 pf
->raw_components
+= "[";
1378 for (int i
=0; i
< idx_count
; i
++)
1381 pf
->raw_components
+= ",";
1382 if (l
->index_types
[i
] == pe_string
)
1383 pf
->raw_components
+= "\"%#s\"";
1385 pf
->raw_components
+= "%#d";
1387 pf
->raw_components
+= "]";
1388 if (l
->type
== pe_stats
)
1389 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1390 else if (l
->type
== pe_string
)
1391 pf
->raw_components
+= "=\"%#s\"\\n";
1393 pf
->raw_components
+= "=%#x\\n";
1395 // Create an index for the array
1396 struct arrayindex
* ai
= new arrayindex
;
1400 for (int i
=0; i
< idx_count
; i
++)
1402 ai
->indexes
.push_back (idx_sym
[i
]);
1403 pf
->args
.push_back(idx_sym
[i
]);
1405 if (l
->type
== pe_stats
)
1407 struct stat_op
* so
[5];
1408 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1410 ai
->type
= pe_stats
;
1411 for (unsigned si
= 0;
1412 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1415 so
[si
]= new stat_op
;
1416 so
[si
]->ctype
= stypes
[si
];
1417 so
[si
]->type
= pe_long
;
1419 so
[si
]->tok
= l
->tok
;
1420 pf
->args
.push_back(so
[si
]);
1424 pf
->args
.push_back(ai
);
1426 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1427 expr_statement
* feb
= new expr_statement
;
1430 fe
->block
= (statement
*)feb
;
1431 b
->statements
.push_back(fe
);
1434 // Add created probe
1436 derive_probes (s
, p
, dps
);
1437 for (unsigned i
= 0; i
< dps
.size(); i
++)
1439 derived_probe
* dp
= dps
[i
];
1440 s
.probes
.push_back (dp
);
1443 // Repopulate symbol and type info
1444 symresolution_info
sym (s
);
1445 sym
.current_function
= 0;
1446 sym
.current_probe
= dps
[0];
1447 dps
[0]->body
->visit (& sym
);
1449 semantic_pass_types(s
);
1450 // Mark that variable is read
1451 vut
.read
.insert (l
);
1456 semantic_pass (systemtap_session
& s
)
1462 s
.register_library_aliases();
1463 register_standard_tapsets(s
);
1465 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1466 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1467 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize1 (s
);
1468 if (rc
== 0) rc
= semantic_pass_types (s
);
1469 if (rc
== 0) add_global_var_display (s
);
1470 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize2 (s
);
1471 if (rc
== 0) rc
= semantic_pass_vars (s
);
1472 if (rc
== 0) rc
= semantic_pass_stats (s
);
1474 if (s
.num_errors() == 0 && s
.probes
.size() == 0 && !s
.listing_mode
)
1475 throw semantic_error ("no probes found");
1477 catch (const semantic_error
& e
)
1487 // ------------------------------------------------------------------------
1490 systemtap_session::systemtap_session ():
1491 // NB: pointer members must be manually initialized!
1492 pattern_root(new match_node
),
1494 be_derived_probes(0),
1495 dwarf_derived_probes(0),
1496 kprobe_derived_probes(0),
1497 uprobe_derived_probes(0),
1498 utrace_derived_probes(0),
1499 itrace_derived_probes(0),
1500 task_finder_derived_probes(0),
1501 timer_derived_probes(0),
1502 profile_derived_probes(0),
1503 mark_derived_probes(0),
1504 tracepoint_derived_probes(0),
1505 hrtimer_derived_probes(0),
1506 perfmon_derived_probes(0),
1507 procfs_derived_probes(0),
1509 sym_kprobes_text_start (0),
1510 sym_kprobes_text_end (0),
1518 // Print this given token, but abbreviate it if the last one had the
1521 systemtap_session::print_token (ostream
& o
, const token
* tok
)
1525 if (last_token
&& last_token
->location
.file
== tok
->location
.file
)
1529 string ts
= tmpo
.str();
1530 // search & replace the file name with nothing
1531 size_t idx
= ts
.find (tok
->location
.file
->name
);
1532 if (idx
!= string::npos
)
1533 ts
.replace (idx
, tok
->location
.file
->name
.size(), "");
1546 systemtap_session::print_error (const semantic_error
& e
)
1548 string message_str
[2];
1549 string
align_semantic_error (" ");
1551 // We generate two messages. The second one ([1]) is printed
1552 // without token compression, for purposes of duplicate elimination.
1553 // This way, the same message that may be generated once with a
1554 // compressed and once with an uncompressed token still only gets
1556 for (int i
=0; i
<2; i
++)
1558 stringstream message
;
1560 message
<< "semantic error: " << e
.what ();
1561 if (e
.tok1
|| e
.tok2
)
1565 if (i
== 0) print_token (message
, e
.tok1
);
1566 else message
<< *e
.tok1
;
1571 if (i
== 0) print_token (message
, e
.tok2
);
1572 else message
<< *e
.tok2
;
1575 message_str
[i
] = message
.str();
1578 // Duplicate elimination
1579 if (seen_errors
.find (message_str
[1]) == seen_errors
.end())
1581 seen_errors
.insert (message_str
[1]);
1582 cerr
<< message_str
[0];
1585 print_error_source (cerr
, align_semantic_error
, e
.tok1
);
1588 print_error_source (cerr
, align_semantic_error
, e
.tok2
);
1592 print_error (* e
.chain
);
1596 systemtap_session::print_error_source (std::ostream
& message
,
1597 std::string
& align
, const token
* tok
)
1602 if (!tok
->location
.file
)
1603 //No source to print, silently exit
1606 unsigned line
= tok
->location
.line
;
1607 unsigned col
= tok
->location
.column
;
1608 const string
&file_contents
= tok
->location
.file
->file_contents
;
1610 size_t start_pos
= 0, end_pos
= 0;
1611 //Navigate to the appropriate line
1612 while (i
!= line
&& end_pos
!= std::string::npos
)
1614 start_pos
= end_pos
;
1615 end_pos
= file_contents
.find ('\n', start_pos
) + 1;
1618 message
<< align
<< "source: " << file_contents
.substr (start_pos
, end_pos
-start_pos
-1) << endl
;
1619 message
<< align
<< " ";
1620 //Navigate to the appropriate column
1621 for (i
=start_pos
; i
<start_pos
+col
-1; i
++)
1623 if(isspace(file_contents
[i
]))
1624 message
<< file_contents
[i
];
1628 message
<< "^" << endl
;
1632 systemtap_session::print_warning (const string
& message_str
, const token
* tok
)
1634 // Duplicate elimination
1635 string
align_warning (" ");
1636 if (seen_warnings
.find (message_str
) == seen_warnings
.end())
1638 seen_warnings
.insert (message_str
);
1639 clog
<< "WARNING: " << message_str
;
1640 if (tok
) { clog
<< ": "; print_token (clog
, tok
); }
1642 if (tok
) { print_error_source (clog
, align_warning
, tok
); }
1647 // ------------------------------------------------------------------------
1648 // semantic processing: symbol resolution
1651 symresolution_info::symresolution_info (systemtap_session
& s
):
1652 session (s
), current_function (0), current_probe (0)
1658 symresolution_info::visit_block (block
* e
)
1660 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
1664 e
->statements
[i
]->visit (this);
1666 catch (const semantic_error
& e
)
1668 session
.print_error (e
);
1675 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
1677 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1678 e
->indexes
[i
]->visit (this);
1680 symbol
*array
= NULL
;
1681 hist_op
*hist
= NULL
;
1682 classify_indexable (e
->base
, array
, hist
);
1686 if (!array
->referent
)
1688 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1690 array
->referent
= d
;
1694 msg
<< "unresolved arity-" << e
->indexes
.size()
1695 << " global array " << array
->name
;
1696 throw semantic_error (msg
.str(), e
->tok
);
1707 e
->limit
->visit (this);
1709 e
->block
->visit (this);
1714 delete_statement_symresolution_info
:
1715 public traversing_visitor
1717 symresolution_info
*parent
;
1719 delete_statement_symresolution_info (symresolution_info
*p
):
1723 void visit_arrayindex (arrayindex
* e
)
1725 parent
->visit_arrayindex (e
);
1727 void visit_functioncall (functioncall
* e
)
1729 parent
->visit_functioncall (e
);
1732 void visit_symbol (symbol
* e
)
1737 vardecl
* d
= parent
->find_var (e
->name
, -1);
1741 throw semantic_error ("unresolved array in delete statement", e
->tok
);
1746 symresolution_info::visit_delete_statement (delete_statement
* s
)
1748 delete_statement_symresolution_info
di (this);
1749 s
->value
->visit (&di
);
1754 symresolution_info::visit_symbol (symbol
* e
)
1759 vardecl
* d
= find_var (e
->name
, 0);
1765 vardecl
* v
= new vardecl
;
1768 if (current_function
)
1769 current_function
->locals
.push_back (v
);
1770 else if (current_probe
)
1771 current_probe
->locals
.push_back (v
);
1773 // must be probe-condition expression
1774 throw semantic_error ("probe condition must not reference undeclared global", e
->tok
);
1781 symresolution_info::visit_arrayindex (arrayindex
* e
)
1783 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1784 e
->indexes
[i
]->visit (this);
1786 symbol
*array
= NULL
;
1787 hist_op
*hist
= NULL
;
1788 classify_indexable(e
->base
, array
, hist
);
1792 if (array
->referent
)
1795 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1797 array
->referent
= d
;
1801 vardecl
* v
= new vardecl
;
1802 v
->set_arity(e
->indexes
.size());
1803 v
->name
= array
->name
;
1804 v
->tok
= array
->tok
;
1805 if (current_function
)
1806 current_function
->locals
.push_back (v
);
1807 else if (current_probe
)
1808 current_probe
->locals
.push_back (v
);
1811 throw semantic_error ("no current probe/function", e
->tok
);
1812 array
->referent
= v
;
1824 symresolution_info::visit_functioncall (functioncall
* e
)
1826 // XXX: we could relax this, if we're going to examine the
1827 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1828 if (! (current_function
|| current_probe
))
1830 // must be probe-condition expression
1831 throw semantic_error ("probe condition must not reference function", e
->tok
);
1834 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1835 e
->args
[i
]->visit (this);
1840 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
1846 msg
<< "unresolved arity-" << e
->args
.size()
1848 throw semantic_error (msg
.str(), e
->tok
);
1854 symresolution_info::find_var (const string
& name
, int arity
)
1856 if (current_function
|| current_probe
)
1859 vector
<vardecl
*>& locals
= (current_function
?
1860 current_function
->locals
:
1861 current_probe
->locals
);
1864 for (unsigned i
=0; i
<locals
.size(); i
++)
1865 if (locals
[i
]->name
== name
1866 && locals
[i
]->compatible_arity(arity
))
1868 locals
[i
]->set_arity (arity
);
1873 // search function formal parameters (for scalars)
1874 if (arity
== 0 && current_function
)
1875 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
1876 if (current_function
->formal_args
[i
]->name
== name
)
1878 // NB: no need to check arity here: formal args always scalar
1879 current_function
->formal_args
[i
]->set_arity (0);
1880 return current_function
->formal_args
[i
];
1883 // search processed globals
1884 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
1885 if (session
.globals
[i
]->name
== name
1886 && session
.globals
[i
]->compatible_arity(arity
))
1888 session
.globals
[i
]->set_arity (arity
);
1889 return session
.globals
[i
];
1892 // search library globals
1893 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1895 stapfile
* f
= session
.library_files
[i
];
1896 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
1898 vardecl
* g
= f
->globals
[j
];
1899 if (g
->name
== name
&& g
->compatible_arity (arity
))
1901 g
->set_arity (arity
);
1903 // put library into the queue if not already there
1904 if (find (session
.files
.begin(), session
.files
.end(), f
)
1905 == session
.files
.end())
1906 session
.files
.push_back (f
);
1918 symresolution_info::find_function (const string
& name
, unsigned arity
)
1921 if (session
.functions
.find(name
) != session
.functions
.end())
1923 functiondecl
* fd
= session
.functions
[name
];
1924 assert (fd
->name
== name
);
1925 if (fd
->formal_args
.size() == arity
)
1929 // search library globals
1930 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1932 stapfile
* f
= session
.library_files
[i
];
1933 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1934 if (f
->functions
[j
]->name
== name
&&
1935 f
->functions
[j
]->formal_args
.size() == arity
)
1937 // put library into the queue if not already there
1938 if (0) // session.verbose_resolution
1939 cerr
<< " function " << name
<< " "
1940 << "is defined from " << f
->name
<< endl
;
1942 if (find (session
.files
.begin(), session
.files
.end(), f
)
1943 == session
.files
.end())
1944 session
.files
.push_back (f
);
1945 // else .. print different message?
1947 return f
->functions
[j
];
1956 // ------------------------------------------------------------------------
1960 // Do away with functiondecls that are never (transitively) called
1962 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1964 functioncall_traversing_visitor ftv
;
1965 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1967 s
.probes
[i
]->body
->visit (& ftv
);
1968 if (s
.probes
[i
]->sole_location()->condition
)
1969 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1971 vector
<functiondecl
*> new_unused_functions
;
1972 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
1974 functiondecl
* fd
= it
->second
;
1975 if (ftv
.traversed
.find(fd
) == ftv
.traversed
.end())
1977 if (fd
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
1978 ! s
.suppress_warnings
)
1979 s
.print_warning ("eliding unused function '" + fd
->name
+ "'", fd
->tok
);
1980 else if (s
.verbose
>2)
1981 clog
<< "Eliding unused function " << fd
->name
1983 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
1984 new_unused_functions
.push_back (fd
);
1988 for (unsigned i
=0; i
<new_unused_functions
.size(); i
++)
1990 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (new_unused_functions
[i
]->name
);
1991 assert (where
!= s
.functions
.end());
1992 s
.functions
.erase (where
);
1993 if (s
.tapset_compile_coverage
)
1994 s
.unused_functions
.push_back (new_unused_functions
[i
]);
1999 // ------------------------------------------------------------------------
2001 // Do away with local & global variables that are never
2002 // written nor read.
2003 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
2005 varuse_collecting_visitor
vut(s
);
2007 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2009 s
.probes
[i
]->body
->visit (& vut
);
2011 if (s
.probes
[i
]->sole_location()->condition
)
2012 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
2015 // NB: Since varuse_collecting_visitor also traverses down
2016 // actually called functions, we don't need to explicitly
2017 // iterate over them. Uncalled ones should have been pruned
2020 // for (unsigned i=0; i<s.functions.size(); i++)
2021 // s.functions[i]->body->visit (& vut);
2023 // Now in vut.read/written, we have a mixture of all locals, globals
2025 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2026 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
2028 vardecl
* l
= s
.probes
[i
]->locals
[j
];
2030 if (vut
.read
.find (l
) == vut
.read
.end() &&
2031 vut
.written
.find (l
) == vut
.written
.end())
2033 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2034 ! s
.suppress_warnings
)
2035 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2036 else if (s
.verbose
>2)
2037 clog
<< "Eliding unused local variable "
2038 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
2039 if (s
.tapset_compile_coverage
) {
2040 s
.probes
[i
]->unused_locals
.push_back
2041 (s
.probes
[i
]->locals
[j
]);
2043 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
2045 // don't increment j
2049 if (vut
.written
.find (l
) == vut
.written
.end())
2050 if (iterations
== 0 && ! s
.suppress_warnings
)
2053 vector
<vardecl
*>::iterator it
;
2054 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
2055 if (l
->name
!= (*it
)->name
)
2056 o
<< " " << (*it
)->name
;
2057 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2058 if (l
->name
!= (*it
)->name
)
2059 o
<< " " << (*it
)->name
;
2061 s
.print_warning ("never-assigned local variable '" + l
->name
+ "' " +
2062 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2068 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2070 functiondecl
*fd
= it
->second
;
2071 for (unsigned j
=0; j
<fd
->locals
.size(); /* see below */)
2073 vardecl
* l
= fd
->locals
[j
];
2074 if (vut
.read
.find (l
) == vut
.read
.end() &&
2075 vut
.written
.find (l
) == vut
.written
.end())
2077 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2078 ! s
.suppress_warnings
)
2079 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2080 else if (s
.verbose
>2)
2081 clog
<< "Eliding unused local variable "
2082 << l
->name
<< " in function " << fd
->name
2084 if (s
.tapset_compile_coverage
) {
2085 fd
->unused_locals
.push_back (fd
->locals
[j
]);
2087 fd
->locals
.erase(fd
->locals
.begin() + j
);
2089 // don't increment j
2093 if (vut
.written
.find (l
) == vut
.written
.end())
2094 if (iterations
== 0 && ! s
.suppress_warnings
)
2097 vector
<vardecl
*>::iterator it
;
2098 for (it
= fd
->formal_args
.begin() ;
2099 it
!= fd
->formal_args
.end(); it
++)
2100 if (l
->name
!= (*it
)->name
)
2101 o
<< " " << (*it
)->name
;
2102 for (it
= fd
->locals
.begin(); it
!= fd
->locals
.end(); it
++)
2103 if (l
->name
!= (*it
)->name
)
2104 o
<< " " << (*it
)->name
;
2105 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2106 if (l
->name
!= (*it
)->name
)
2107 o
<< " " << (*it
)->name
;
2109 s
.print_warning ("never-assigned local variable '" + l
->name
+ "' " +
2110 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2117 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
2119 vardecl
* l
= s
.globals
[i
];
2120 if (vut
.read
.find (l
) == vut
.read
.end() &&
2121 vut
.written
.find (l
) == vut
.written
.end())
2123 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2124 ! s
.suppress_warnings
)
2125 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2126 else if (s
.verbose
>2)
2127 clog
<< "Eliding unused global variable "
2129 if (s
.tapset_compile_coverage
) {
2130 s
.unused_globals
.push_back(s
.globals
[i
]);
2132 s
.globals
.erase(s
.globals
.begin() + i
);
2134 // don't increment i
2138 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
2139 if (iterations
== 0 && ! s
.suppress_warnings
)
2142 vector
<vardecl
*>::iterator it
;
2143 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2144 if (l
->name
!= (*it
)->name
)
2145 o
<< " " << (*it
)->name
;
2147 s
.print_warning ("never-assigned global variable '" + l
->name
+ "' " +
2148 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2157 // ------------------------------------------------------------------------
2159 struct dead_assignment_remover
: public update_visitor
2161 systemtap_session
& session
;
2163 const varuse_collecting_visitor
& vut
;
2165 dead_assignment_remover(systemtap_session
& s
, bool& r
,
2166 const varuse_collecting_visitor
& v
):
2167 session(s
), relaxed_p(r
), vut(v
) {}
2169 void visit_assignment (assignment
* e
);
2174 dead_assignment_remover::visit_assignment (assignment
* e
)
2179 symbol
* left
= get_symbol_within_expression (e
->left
);
2180 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2181 if (leftvar
) // not unresolved $target, so intended sideeffect may be elided
2183 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2185 // NB: Not so fast! The left side could be an array whose
2186 // index expressions may have side-effects. This would be
2187 // OK if we could replace the array assignment with a
2188 // statement-expression containing all the index expressions
2189 // and the rvalue... but we can't.
2190 // Another possibility is that we have an unread global variable
2191 // which are kept for probe end value display.
2193 bool is_global
= false;
2194 vector
<vardecl
*>::iterator it
;
2195 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2196 if (leftvar
->name
== (*it
)->name
)
2202 varuse_collecting_visitor
lvut(session
);
2203 e
->left
->visit (& lvut
);
2204 if (lvut
.side_effect_free () && !is_global
) // XXX: use _wrt() once we track focal_vars
2206 /* PR 1119: NB: This is not necessary here. A write-only
2207 variable will also be elided soon at the next _opt2 iteration.
2208 if (e->left->tok->location.file == session.user_file->name && // !tapset
2209 ! session.suppress_warnings)
2210 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
2213 if (session
.verbose
>2)
2214 clog
<< "Eliding assignment to " << leftvar
->name
2215 << " at " << *e
->tok
<< endl
;
2217 provide (e
->right
); // goodbye assignment*
2226 // Let's remove assignments to variables that are never read. We
2227 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2228 // be optimized away as an unused variable, and expr a candidate to be
2229 // removed as a side-effect-free statement expression. Wahoo!
2230 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2232 // Recompute the varuse data, which will probably match the opt2
2233 // copy of the computation, except for those totally unused
2234 // variables that opt2 removed.
2235 varuse_collecting_visitor
vut(s
);
2236 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2237 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2239 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2240 // This instance may be reused for multiple probe/function body trims.
2242 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2243 dar
.replace (s
.probes
[i
]->body
);
2244 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2245 it
!= s
.functions
.end(); it
++)
2246 dar
.replace (it
->second
->body
);
2247 // The rewrite operation is performed within the visitor.
2249 // XXX: we could also zap write-only globals here
2253 // ------------------------------------------------------------------------
2255 struct dead_stmtexpr_remover
: public update_visitor
2257 systemtap_session
& session
;
2259 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2261 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2262 session(s
), relaxed_p(r
) {}
2264 void visit_block (block
*s
);
2265 void visit_null_statement (null_statement
*s
);
2266 void visit_if_statement (if_statement
* s
);
2267 void visit_foreach_loop (foreach_loop
*s
);
2268 void visit_for_loop (for_loop
*s
);
2269 // XXX: and other places where stmt_expr's might be nested
2271 void visit_expr_statement (expr_statement
*s
);
2276 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2279 if (session
.verbose
>2)
2280 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
2287 dead_stmtexpr_remover::visit_block (block
*s
)
2289 vector
<statement
*> new_stmts
;
2290 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2292 statement
* new_stmt
= require (s
->statements
[i
], true);
2295 // flatten nested blocks into this one
2296 block
*b
= dynamic_cast<block
*>(new_stmt
);
2299 if (session
.verbose
>2)
2300 clog
<< "Flattening nested block " << *b
->tok
<< endl
;
2301 new_stmts
.insert(new_stmts
.end(),
2302 b
->statements
.begin(), b
->statements
.end());
2306 new_stmts
.push_back (new_stmt
);
2309 if (new_stmts
.size() == 0)
2311 if (session
.verbose
>2)
2312 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
2315 else if (new_stmts
.size() == 1)
2317 if (session
.verbose
>2)
2318 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
2319 provide (new_stmts
[0]);
2323 s
->statements
= new_stmts
;
2328 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2330 replace (s
->thenblock
, true);
2331 replace (s
->elseblock
, true);
2333 if (s
->thenblock
== 0)
2335 if (s
->elseblock
== 0)
2337 // We may be able to elide this statement, if the condition
2338 // expression is side-effect-free.
2339 varuse_collecting_visitor
vct(session
);
2340 s
->condition
->visit(& vct
);
2341 if (vct
.side_effect_free ())
2343 if (session
.verbose
>2)
2344 clog
<< "Eliding side-effect-free if statement "
2346 s
= 0; // yeah, baby
2350 // We can still turn it into a simple expr_statement though...
2351 if (session
.verbose
>2)
2352 clog
<< "Creating simple evaluation from if statement "
2354 expr_statement
*es
= new expr_statement
;
2355 es
->value
= s
->condition
;
2356 es
->tok
= es
->value
->tok
;
2363 // For an else without a then, we can invert the condition logic to
2364 // avoid having a null statement in the thenblock
2365 if (session
.verbose
>2)
2366 clog
<< "Inverting the condition of if statement "
2368 unary_expression
*ue
= new unary_expression
;
2369 ue
->operand
= s
->condition
;
2370 ue
->tok
= ue
->operand
->tok
;
2373 s
->thenblock
= s
->elseblock
;
2381 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2383 replace (s
->block
, true);
2387 if (session
.verbose
>2)
2388 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2389 s
= 0; // yeah, baby
2395 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2397 replace (s
->block
, true);
2401 // We may be able to elide this statement, if the condition
2402 // expression is side-effect-free.
2403 varuse_collecting_visitor
vct(session
);
2404 if (s
->init
) s
->init
->visit(& vct
);
2405 s
->cond
->visit(& vct
);
2406 if (s
->incr
) s
->incr
->visit(& vct
);
2407 if (vct
.side_effect_free ())
2409 if (session
.verbose
>2)
2410 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2411 s
= 0; // yeah, baby
2415 // Can't elide this whole statement; put a null in there.
2416 s
->block
= new null_statement();
2417 s
->block
->tok
= s
->tok
;
2426 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2428 // Run a varuse query against the operand expression. If it has no
2429 // side-effects, replace the entire statement expression by a null
2430 // statement with the provide() call.
2432 // Unlike many other visitors, we do *not* traverse this outermost
2433 // one into the expression subtrees. There is no need - no
2434 // expr_statement nodes will be found there. (Function bodies
2435 // need to be visited explicitly by our caller.)
2437 // NB. While we don't share nodes in the parse tree, let's not
2438 // deallocate *s anyway, just in case...
2440 varuse_collecting_visitor
vut(session
);
2441 s
->value
->visit (& vut
);
2443 if (vut
.side_effect_free_wrt (focal_vars
))
2445 /* PR 1119: NB: this message is not a good idea here. It can
2446 name some arbitrary RHS expression of an assignment.
2447 if (s->value->tok->location.file == session.user_file->name && // not tapset
2448 ! session.suppress_warnings)
2449 clog << "WARNING: eliding never-assigned " << *s->value->tok << endl;
2452 if (session
.verbose
>2)
2453 clog
<< "Eliding side-effect-free expression "
2456 // NB: this 0 pointer is invalid to leave around for any length of
2457 // time, but the parent parse tree objects above handle it.
2465 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2467 // Finally, let's remove some statement-expressions that have no
2468 // side-effect. These should be exactly those whose private varuse
2469 // visitors come back with an empty "written" and "embedded" lists.
2471 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2472 // This instance may be reused for multiple probe/function body trims.
2474 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2476 if (pending_interrupts
) break;
2478 derived_probe
* p
= s
.probes
[i
];
2480 duv
.focal_vars
.clear ();
2481 duv
.focal_vars
.insert (s
.globals
.begin(),
2483 duv
.focal_vars
.insert (p
->locals
.begin(),
2486 duv
.replace (p
->body
, true);
2489 if (! s
.suppress_warnings
2490 && ! s
.timing
) // PR10070
2491 s
.print_warning ("side-effect-free probe '" + p
->name
+ "'", p
->tok
);
2493 p
->body
= new null_statement();
2494 p
->body
->tok
= p
->tok
;
2496 // XXX: possible duplicate warnings; see below
2499 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2501 if (pending_interrupts
) break;
2503 functiondecl
* fn
= it
->second
;
2504 duv
.focal_vars
.clear ();
2505 duv
.focal_vars
.insert (fn
->locals
.begin(),
2507 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2508 fn
->formal_args
.end());
2509 duv
.focal_vars
.insert (s
.globals
.begin(),
2512 duv
.replace (fn
->body
, true);
2515 if (! s
.suppress_warnings
)
2516 s
.print_warning ("side-effect-free function '" + fn
->name
+ "'", fn
->tok
);
2518 fn
->body
= new null_statement();
2519 fn
->body
->tok
= fn
->tok
;
2521 // XXX: the next iteration of the outer optimization loop may
2522 // take this new null_statement away again, and thus give us a
2523 // fresh warning. It would be better if this fixup was performed
2524 // only after the relaxation iterations.
2525 // XXX: or else see bug #6469.
2531 // ------------------------------------------------------------------------
2533 // The goal of this visitor is to reduce top-level expressions in void context
2534 // into separate statements that evaluate each subcomponent of the expression.
2535 // The dead-statement-remover can later remove some parts if they have no side
2538 // All expressions must be overridden here so we never visit their subexpressions
2539 // accidentally. Thus, the only visited expressions should be value of an
2542 // For an expression to replace its expr_statement with something else, it will
2543 // let the new statement provide(), and then provide(0) for itself. The
2544 // expr_statement will take this as a sign that it's been replaced.
2545 struct void_statement_reducer
: public update_visitor
2547 systemtap_session
& session
;
2549 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2551 void_statement_reducer(systemtap_session
& s
, bool& r
):
2552 session(s
), relaxed_p(r
) {}
2554 void visit_expr_statement (expr_statement
* s
);
2556 // expressions in conditional / loop controls are definitely a side effect,
2557 // but still recurse into the child statements
2558 void visit_if_statement (if_statement
* s
);
2559 void visit_for_loop (for_loop
* s
);
2560 void visit_foreach_loop (foreach_loop
* s
);
2562 // these expressions get rewritten into their statement equivalents
2563 void visit_logical_or_expr (logical_or_expr
* e
);
2564 void visit_logical_and_expr (logical_and_expr
* e
);
2565 void visit_ternary_expression (ternary_expression
* e
);
2567 // all of these can be reduced into simpler statements
2568 void visit_binary_expression (binary_expression
* e
);
2569 void visit_unary_expression (unary_expression
* e
);
2570 void visit_comparison (comparison
* e
);
2571 void visit_concatenation (concatenation
* e
);
2572 void visit_functioncall (functioncall
* e
);
2573 void visit_print_format (print_format
* e
);
2574 void visit_target_symbol (target_symbol
* e
);
2575 void visit_cast_op (cast_op
* e
);
2577 // these are a bit hairy to grok due to the intricacies of indexables and
2578 // stats, so I'm chickening out and skipping them...
2579 void visit_array_in (array_in
* e
) { provide (e
); }
2580 void visit_arrayindex (arrayindex
* e
) { provide (e
); }
2581 void visit_stat_op (stat_op
* e
) { provide (e
); }
2582 void visit_hist_op (hist_op
* e
) { provide (e
); }
2584 // these can't be reduced because they always have an effect
2585 void visit_return_statement (return_statement
* s
) { provide (s
); }
2586 void visit_delete_statement (delete_statement
* s
) { provide (s
); }
2587 void visit_pre_crement (pre_crement
* e
) { provide (e
); }
2588 void visit_post_crement (post_crement
* e
) { provide (e
); }
2589 void visit_assignment (assignment
* e
) { provide (e
); }
2594 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2596 replace (s
->value
, true);
2598 // if the expression provides 0, that's our signal that a new
2599 // statement has been provided, so we shouldn't provide this one.
2605 void_statement_reducer::visit_if_statement (if_statement
* s
)
2607 // s->condition is never void
2608 replace (s
->thenblock
);
2609 replace (s
->elseblock
);
2614 void_statement_reducer::visit_for_loop (for_loop
* s
)
2616 // s->init/cond/incr are never void
2622 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
2624 // s->indexes/base/limit are never void
2630 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
2632 // In void context, the evaluation of "a || b" is exactly like
2633 // "if (!a) b", so let's do that instead.
2635 if (session
.verbose
>2)
2636 clog
<< "Creating if statement from unused logical-or "
2639 if_statement
*is
= new if_statement
;
2643 unary_expression
*ue
= new unary_expression
;
2644 ue
->operand
= e
->left
;
2649 expr_statement
*es
= new expr_statement
;
2650 es
->value
= e
->right
;
2651 es
->tok
= es
->value
->tok
;
2661 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
2663 // In void context, the evaluation of "a && b" is exactly like
2664 // "if (a) b", so let's do that instead.
2666 if (session
.verbose
>2)
2667 clog
<< "Creating if statement from unused logical-and "
2670 if_statement
*is
= new if_statement
;
2673 is
->condition
= e
->left
;
2675 expr_statement
*es
= new expr_statement
;
2676 es
->value
= e
->right
;
2677 es
->tok
= es
->value
->tok
;
2687 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
2689 // In void context, the evaluation of "a ? b : c" is exactly like
2690 // "if (a) b else c", so let's do that instead.
2692 if (session
.verbose
>2)
2693 clog
<< "Creating if statement from unused ternary expression "
2696 if_statement
*is
= new if_statement
;
2698 is
->condition
= e
->cond
;
2700 expr_statement
*es
= new expr_statement
;
2701 es
->value
= e
->truevalue
;
2702 es
->tok
= es
->value
->tok
;
2705 es
= new expr_statement
;
2706 es
->value
= e
->falsevalue
;
2707 es
->tok
= es
->value
->tok
;
2717 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
2719 // When the result of a binary operation isn't needed, it's just as good to
2720 // evaluate the operands as sequential statements in a block.
2722 if (session
.verbose
>2)
2723 clog
<< "Eliding unused binary " << *e
->tok
<< endl
;
2725 block
*b
= new block
;
2728 expr_statement
*es
= new expr_statement
;
2729 es
->value
= e
->left
;
2730 es
->tok
= es
->value
->tok
;
2731 b
->statements
.push_back(es
);
2733 es
= new expr_statement
;
2734 es
->value
= e
->right
;
2735 es
->tok
= es
->value
->tok
;
2736 b
->statements
.push_back(es
);
2745 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
2747 // When the result of a unary operation isn't needed, it's just as good to
2748 // evaluate the operand directly
2750 if (session
.verbose
>2)
2751 clog
<< "Eliding unused unary " << *e
->tok
<< endl
;
2754 e
->operand
->visit(this);
2758 void_statement_reducer::visit_comparison (comparison
* e
)
2760 visit_binary_expression(e
);
2764 void_statement_reducer::visit_concatenation (concatenation
* e
)
2766 visit_binary_expression(e
);
2770 void_statement_reducer::visit_functioncall (functioncall
* e
)
2772 // If a function call is pure and its result ignored, we can elide the call
2773 // and just evaluate the arguments in sequence
2775 if (!e
->args
.size())
2781 varuse_collecting_visitor
vut(session
);
2782 vut
.traversed
.insert (e
->referent
);
2783 vut
.current_function
= e
->referent
;
2784 e
->referent
->body
->visit (& vut
);
2785 if (!vut
.side_effect_free_wrt (focal_vars
))
2791 if (session
.verbose
>2)
2792 clog
<< "Eliding side-effect-free function call " << *e
->tok
<< endl
;
2794 block
*b
= new block
;
2797 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2799 expr_statement
*es
= new expr_statement
;
2800 es
->value
= e
->args
[i
];
2801 es
->tok
= es
->value
->tok
;
2802 b
->statements
.push_back(es
);
2812 void_statement_reducer::visit_print_format (print_format
* e
)
2814 // When an sprint's return value is ignored, we can simply evaluate the
2815 // arguments in sequence
2817 if (e
->print_to_stream
|| !e
->args
.size())
2823 if (session
.verbose
>2)
2824 clog
<< "Eliding unused print " << *e
->tok
<< endl
;
2826 block
*b
= new block
;
2829 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2831 expr_statement
*es
= new expr_statement
;
2832 es
->value
= e
->args
[i
];
2833 es
->tok
= es
->value
->tok
;
2834 b
->statements
.push_back(es
);
2844 void_statement_reducer::visit_target_symbol (target_symbol
* e
)
2846 // When target_symbol isn't needed, it's just as good to
2847 // evaluate any array indexes directly
2849 block
*b
= new block
;
2852 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2854 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2857 expr_statement
*es
= new expr_statement
;
2858 es
->value
= e
->components
[i
].expr_index
;
2859 es
->tok
= es
->value
->tok
;
2860 b
->statements
.push_back(es
);
2863 if (b
->statements
.empty())
2870 if (session
.verbose
>2)
2871 clog
<< "Eliding unused target symbol " << *e
->tok
<< endl
;
2880 void_statement_reducer::visit_cast_op (cast_op
* e
)
2882 // When the result of a cast operation isn't needed, it's just as good to
2883 // evaluate the operand and any array indexes directly
2885 block
*b
= new block
;
2888 expr_statement
*es
= new expr_statement
;
2889 es
->value
= e
->operand
;
2890 es
->tok
= es
->value
->tok
;
2891 b
->statements
.push_back(es
);
2893 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2895 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2898 es
= new expr_statement
;
2899 es
->value
= e
->components
[i
].expr_index
;
2900 es
->tok
= es
->value
->tok
;
2901 b
->statements
.push_back(es
);
2904 if (session
.verbose
>2)
2905 clog
<< "Eliding unused typecast " << *e
->tok
<< endl
;
2914 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2916 // Let's simplify statements with unused computed values.
2918 void_statement_reducer
vuv (s
, relaxed_p
);
2919 // This instance may be reused for multiple probe/function body trims.
2921 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
2923 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2924 vuv
.replace (s
.probes
[i
]->body
);
2925 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2926 it
!= s
.functions
.end(); it
++)
2927 vuv
.replace (it
->second
->body
);
2931 struct duplicate_function_remover
: public functioncall_traversing_visitor
2933 systemtap_session
& s
;
2934 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
2936 duplicate_function_remover(systemtap_session
& sess
,
2937 map
<functiondecl
*, functiondecl
*>&dfm
):
2938 s(sess
), duplicate_function_map(dfm
) {};
2940 void visit_functioncall (functioncall
* e
);
2944 duplicate_function_remover::visit_functioncall (functioncall
*e
)
2946 functioncall_traversing_visitor::visit_functioncall (e
);
2948 // If the current function call reference points to a function that
2949 // is a duplicate, replace it.
2950 if (duplicate_function_map
.count(e
->referent
) != 0)
2953 clog
<< "Changing " << e
->referent
->name
2955 << duplicate_function_map
[e
->referent
]->name
2957 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
2958 e
->function
= duplicate_function_map
[e
->referent
]->name
;
2959 e
->referent
= duplicate_function_map
[e
->referent
];
2964 get_functionsig (functiondecl
* f
)
2968 // Get the "name:args body" of the function in s. We have to
2969 // include the args since the function 'x1(a, b)' is different than
2970 // the function 'x2(b, a)' even if the bodies of the two functions
2971 // are exactly the same.
2975 // printsig puts f->name + ':' on the front. Remove this
2976 // (otherwise, functions would never compare equal).
2977 string str
= s
.str().erase(0, f
->name
.size() + 1);
2979 // Return the function signature.
2983 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
2985 // Walk through all the functions, looking for duplicates.
2986 map
<string
, functiondecl
*> functionsig_map
;
2987 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
2990 vector
<functiondecl
*> newly_zapped_functions
;
2991 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2993 functiondecl
*fd
= it
->second
;
2994 string functionsig
= get_functionsig(fd
);
2996 if (functionsig_map
.count(functionsig
) == 0)
2998 // This function is unique. Remember it.
2999 functionsig_map
[functionsig
] = fd
;
3003 // This function is a duplicate.
3004 duplicate_function_map
[fd
] = functionsig_map
[functionsig
];
3005 newly_zapped_functions
.push_back (fd
);
3009 for (unsigned i
=0; i
<newly_zapped_functions
.size(); i
++)
3011 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (newly_zapped_functions
[i
]->name
);
3012 assert (where
!= s
.functions
.end());
3013 s
.functions
.erase (where
);
3017 // If we have duplicate functions, traverse down the tree, replacing
3018 // the appropriate function calls.
3019 // duplicate_function_remover::visit_functioncall() handles the
3020 // details of replacing the function calls.
3021 if (duplicate_function_map
.size() != 0)
3023 duplicate_function_remover
dfr (s
, duplicate_function_map
);
3025 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
3026 s
.probes
[i
]->body
->visit(&dfr
);
3032 semantic_pass_optimize1 (systemtap_session
& s
)
3034 // In this pass, we attempt to rewrite probe/function bodies to
3035 // eliminate some blatantly unnecessary code. This is run before
3036 // type inference, but after symbol resolution and derived_probe
3037 // creation. We run an outer "relaxation" loop that repeats the
3038 // optimizations until none of them find anything to remove.
3042 bool relaxed_p
= false;
3043 unsigned iterations
= 0;
3046 if (pending_interrupts
) break;
3048 relaxed_p
= true; // until proven otherwise
3050 semantic_pass_opt1 (s
, relaxed_p
);
3051 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
3052 semantic_pass_opt3 (s
, relaxed_p
);
3053 semantic_pass_opt4 (s
, relaxed_p
);
3054 semantic_pass_opt5 (s
, relaxed_p
);
3064 semantic_pass_optimize2 (systemtap_session
& s
)
3066 // This is run after type inference. We run an outer "relaxation"
3067 // loop that repeats the optimizations until none of them find
3068 // anything to remove.
3072 bool relaxed_p
= false;
3075 if (pending_interrupts
) break;
3076 relaxed_p
= true; // until proven otherwise
3078 semantic_pass_opt6 (s
, relaxed_p
);
3086 // ------------------------------------------------------------------------
3091 semantic_pass_types (systemtap_session
& s
)
3095 // next pass: type inference
3096 unsigned iterations
= 0;
3097 typeresolution_info
ti (s
);
3099 ti
.assert_resolvability
= false;
3100 // XXX: maybe convert to exception-based error signalling
3103 if (pending_interrupts
) break;
3106 ti
.num_newly_resolved
= 0;
3107 ti
.num_still_unresolved
= 0;
3109 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
3111 if (pending_interrupts
) break;
3113 functiondecl
* fd
= it
->second
;
3114 ti
.current_probe
= 0;
3115 ti
.current_function
= fd
;
3117 fd
->body
->visit (& ti
);
3118 // NB: we don't have to assert a known type for
3119 // functions here, to permit a "void" function.
3120 // The translator phase will omit the "retvalue".
3122 // if (fd->type == pe_unknown)
3123 // ti.unresolved (fd->tok);
3126 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
3128 if (pending_interrupts
) break;
3130 derived_probe
* pn
= s
.probes
[j
];
3131 ti
.current_function
= 0;
3132 ti
.current_probe
= pn
;
3134 pn
->body
->visit (& ti
);
3136 probe_point
* pp
= pn
->sole_location();
3139 ti
.current_function
= 0;
3140 ti
.current_probe
= 0;
3141 ti
.t
= pe_long
; // NB: expected type
3142 pp
->condition
->visit (& ti
);
3146 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
3148 vardecl
* gd
= s
.globals
[j
];
3149 if (gd
->type
== pe_unknown
)
3150 ti
.unresolved (gd
->tok
);
3153 if (ti
.num_newly_resolved
== 0) // converged
3155 if (ti
.num_still_unresolved
== 0)
3156 break; // successfully
3157 else if (! ti
.assert_resolvability
)
3158 ti
.assert_resolvability
= true; // last pass, with error msgs
3160 { // unsuccessful conclusion
3167 return rc
+ s
.num_errors();
3172 typeresolution_info::typeresolution_info (systemtap_session
& s
):
3173 session(s
), current_function(0), current_probe(0)
3179 typeresolution_info::visit_literal_number (literal_number
* e
)
3181 assert (e
->type
== pe_long
);
3182 if ((t
== e
->type
) || (t
== pe_unknown
))
3185 mismatch (e
->tok
, e
->type
, t
);
3190 typeresolution_info::visit_literal_string (literal_string
* e
)
3192 assert (e
->type
== pe_string
);
3193 if ((t
== e
->type
) || (t
== pe_unknown
))
3196 mismatch (e
->tok
, e
->type
, t
);
3201 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
3203 visit_binary_expression (e
);
3208 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
3210 visit_binary_expression (e
);
3215 typeresolution_info::visit_comparison (comparison
*e
)
3217 // NB: result of any comparison is an integer!
3218 if (t
== pe_stats
|| t
== pe_string
)
3219 invalid (e
->tok
, t
);
3221 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
3222 e
->left
->visit (this);
3223 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
3224 e
->right
->visit (this);
3226 if (e
->left
->type
!= pe_unknown
&&
3227 e
->right
->type
!= pe_unknown
&&
3228 e
->left
->type
!= e
->right
->type
)
3229 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3231 if (e
->type
== pe_unknown
)
3234 resolved (e
->tok
, e
->type
);
3240 typeresolution_info::visit_concatenation (concatenation
*e
)
3242 if (t
!= pe_unknown
&& t
!= pe_string
)
3243 invalid (e
->tok
, t
);
3246 e
->left
->visit (this);
3248 e
->right
->visit (this);
3250 if (e
->type
== pe_unknown
)
3252 e
->type
= pe_string
;
3253 resolved (e
->tok
, e
->type
);
3259 typeresolution_info::visit_assignment (assignment
*e
)
3262 invalid (e
->tok
, t
);
3264 if (e
->op
== "<<<") // stats aggregation
3267 invalid (e
->tok
, t
);
3270 e
->left
->visit (this);
3272 e
->right
->visit (this);
3273 if (e
->type
== pe_unknown
||
3274 e
->type
== pe_stats
)
3277 resolved (e
->tok
, e
->type
);
3281 else if (e
->left
->type
== pe_stats
)
3282 invalid (e
->left
->tok
, e
->left
->type
);
3284 else if (e
->right
->type
== pe_stats
)
3285 invalid (e
->right
->tok
, e
->right
->type
);
3287 else if (e
->op
== "+=" || // numeric only
3299 visit_binary_expression (e
);
3301 else if (e
->op
== ".=" || // string only
3304 if (t
== pe_long
|| t
== pe_stats
)
3305 invalid (e
->tok
, t
);
3308 e
->left
->visit (this);
3310 e
->right
->visit (this);
3311 if (e
->type
== pe_unknown
)
3313 e
->type
= pe_string
;
3314 resolved (e
->tok
, e
->type
);
3317 else if (e
->op
== "=") // overloaded = for string & numeric operands
3319 // logic similar to ternary_expression
3320 exp_type sub_type
= t
;
3322 // Infer types across the l/r values
3323 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3326 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3327 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
3329 e
->left
->visit (this);
3330 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3331 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
3333 e
->right
->visit (this);
3335 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3338 resolved (e
->tok
, e
->type
);
3340 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
3342 e
->type
= e
->left
->type
;
3343 resolved (e
->tok
, e
->type
);
3346 if (e
->left
->type
!= pe_unknown
&&
3347 e
->right
->type
!= pe_unknown
&&
3348 e
->left
->type
!= e
->right
->type
)
3349 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3353 throw semantic_error ("unsupported assignment operator " + e
->op
);
3358 typeresolution_info::visit_binary_expression (binary_expression
* e
)
3360 if (t
== pe_stats
|| t
== pe_string
)
3361 invalid (e
->tok
, t
);
3364 e
->left
->visit (this);
3366 e
->right
->visit (this);
3368 if (e
->left
->type
!= pe_unknown
&&
3369 e
->right
->type
!= pe_unknown
&&
3370 e
->left
->type
!= e
->right
->type
)
3371 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3373 if (e
->type
== pe_unknown
)
3376 resolved (e
->tok
, e
->type
);
3382 typeresolution_info::visit_pre_crement (pre_crement
*e
)
3384 visit_unary_expression (e
);
3389 typeresolution_info::visit_post_crement (post_crement
*e
)
3391 visit_unary_expression (e
);
3396 typeresolution_info::visit_unary_expression (unary_expression
* e
)
3398 if (t
== pe_stats
|| t
== pe_string
)
3399 invalid (e
->tok
, t
);
3402 e
->operand
->visit (this);
3404 if (e
->type
== pe_unknown
)
3407 resolved (e
->tok
, e
->type
);
3413 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
3415 exp_type sub_type
= t
;
3418 e
->cond
->visit (this);
3420 // Infer types across the true/false arms of the ternary expression.
3422 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3425 e
->truevalue
->visit (this);
3427 e
->falsevalue
->visit (this);
3429 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
3430 ; // already resolved
3431 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3434 resolved (e
->tok
, e
->type
);
3436 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
3438 e
->type
= e
->truevalue
->type
;
3439 resolved (e
->tok
, e
->type
);
3441 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
3443 e
->type
= e
->falsevalue
->type
;
3444 resolved (e
->tok
, e
->type
);
3446 else if (e
->type
!= sub_type
)
3447 mismatch (e
->tok
, sub_type
, e
->type
);
3451 template <class Referrer
, class Referent
>
3452 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
3453 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
3455 exp_type
& re_type
= referrer
->type
;
3456 const token
* re_tok
= referrer
->tok
;
3457 exp_type
& te_type
= referent
->type
;
3458 const token
* te_tok
= referent
->tok
;
3460 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
3461 ; // do nothing: all three e->types in agreement
3462 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
3463 ; // do nothing: two known e->types in agreement
3464 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
3465 r
->mismatch (re_tok
, re_type
, te_type
);
3466 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
3467 r
->mismatch (re_tok
, re_type
, t
);
3468 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
3469 r
->mismatch (te_tok
, te_type
, t
);
3470 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
3472 // propagate from upstream
3474 r
->resolved (re_tok
, re_type
);
3475 // catch re_type/te_type mismatch later
3477 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
3479 // propagate from referent
3481 r
->resolved (re_tok
, re_type
);
3482 // catch re_type/t mismatch later
3484 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
3486 // propagate to referent
3488 r
->resolved (te_tok
, te_type
);
3489 // catch re_type/t mismatch later
3491 else if (! accept_unknown
)
3492 r
->unresolved (re_tok
);
3497 typeresolution_info::visit_symbol (symbol
* e
)
3499 assert (e
->referent
!= 0);
3500 resolve_2types (e
, e
->referent
, this, t
);
3505 typeresolution_info::visit_target_symbol (target_symbol
* e
)
3507 if (!e
->probe_context_var
.empty())
3510 // This occurs only if a target symbol was not resolved over in
3511 // tapset.cxx land, that error was properly suppressed, and the
3512 // later unused-expression-elimination pass didn't get rid of it
3513 // either. So we have a target symbol that is believed to be of
3514 // genuine use, yet unresolved by the provider.
3516 if (session
.verbose
> 2)
3518 clog
<< "Resolution problem with ";
3519 if (current_function
)
3521 clog
<< "function " << current_function
->name
<< endl
;
3522 current_function
->body
->print (clog
);
3525 else if (current_probe
)
3527 clog
<< "probe " << current_probe
->name
<< endl
;
3528 current_probe
->body
->print (clog
);
3532 clog
<< "other" << endl
;
3535 if (e
->saved_conversion_error
)
3536 throw (* (e
->saved_conversion_error
));
3538 throw semantic_error("unresolved target-symbol expression", e
->tok
);
3543 typeresolution_info::visit_cast_op (cast_op
* e
)
3545 // Like target_symbol, a cast_op shouldn't survive this far
3546 // unless it was not resolved and its value is really needed.
3547 if (e
->saved_conversion_error
)
3548 throw (* (e
->saved_conversion_error
));
3550 throw semantic_error("type definition '" + e
->type
+ "' not found", e
->tok
);
3555 typeresolution_info::visit_arrayindex (arrayindex
* e
)
3558 symbol
*array
= NULL
;
3559 hist_op
*hist
= NULL
;
3560 classify_indexable(e
->base
, array
, hist
);
3562 // Every hist_op has type [int]:int, that is to say, every hist_op
3563 // is a pseudo-one-dimensional integer array type indexed by
3564 // integers (bucket numbers).
3568 if (e
->indexes
.size() != 1)
3569 unresolved (e
->tok
);
3571 e
->indexes
[0]->visit (this);
3572 if (e
->indexes
[0]->type
!= pe_long
)
3573 unresolved (e
->tok
);
3575 if (e
->type
!= pe_long
)
3578 resolved (e
->tok
, pe_long
);
3583 // Now we are left with "normal" map inference and index checking.
3586 assert (array
->referent
!= 0);
3587 resolve_2types (e
, array
->referent
, this, t
);
3589 // now resolve the array indexes
3591 // if (e->referent->index_types.size() == 0)
3592 // // redesignate referent as array
3593 // e->referent->set_arity (e->indexes.size ());
3595 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3596 unresolved (e
->tok
); // symbol resolution should prevent this
3597 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3599 expression
* ee
= e
->indexes
[i
];
3600 exp_type
& ft
= array
->referent
->index_types
[i
];
3603 exp_type at
= ee
->type
;
3605 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3607 // propagate to formal type
3609 resolved (array
->referent
->tok
, ft
);
3610 // uses array decl as there is no token for "formal type"
3613 invalid (ee
->tok
, at
);
3615 invalid (ee
->tok
, ft
);
3616 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3617 mismatch (e
->tok
, at
, ft
);
3618 if (at
== pe_unknown
)
3619 unresolved (ee
->tok
);
3625 typeresolution_info::visit_functioncall (functioncall
* e
)
3627 assert (e
->referent
!= 0);
3629 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
3631 if (e
->type
== pe_stats
)
3632 invalid (e
->tok
, e
->type
);
3634 // now resolve the function parameters
3635 if (e
->args
.size() != e
->referent
->formal_args
.size())
3636 unresolved (e
->tok
); // symbol resolution should prevent this
3637 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
3639 expression
* ee
= e
->args
[i
];
3640 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
3641 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
3644 exp_type at
= ee
->type
;
3646 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
3648 // propagate to formal arg
3650 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
3653 invalid (e
->tok
, at
);
3655 invalid (fe_tok
, ft
);
3656 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3657 mismatch (e
->tok
, at
, ft
);
3658 if (at
== pe_unknown
)
3659 unresolved (e
->tok
);
3665 typeresolution_info::visit_block (block
* e
)
3667 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
3672 e
->statements
[i
]->visit (this);
3674 catch (const semantic_error
& e
)
3676 session
.print_error (e
);
3683 typeresolution_info::visit_embeddedcode (embeddedcode
*)
3689 typeresolution_info::visit_if_statement (if_statement
* e
)
3692 e
->condition
->visit (this);
3695 e
->thenblock
->visit (this);
3700 e
->elseblock
->visit (this);
3706 typeresolution_info::visit_for_loop (for_loop
* e
)
3709 if (e
->init
) e
->init
->visit (this);
3711 e
->cond
->visit (this);
3713 if (e
->incr
) e
->incr
->visit (this);
3715 e
->block
->visit (this);
3720 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
3722 // See also visit_arrayindex.
3723 // This is different in that, being a statement, we can't assign
3724 // a type to the outer array, only propagate to/from the indexes
3726 // if (e->referent->index_types.size() == 0)
3727 // // redesignate referent as array
3728 // e->referent->set_arity (e->indexes.size ());
3730 symbol
*array
= NULL
;
3731 hist_op
*hist
= NULL
;
3732 classify_indexable(e
->base
, array
, hist
);
3736 if (e
->indexes
.size() != 1)
3737 unresolved (e
->tok
);
3739 e
->indexes
[0]->visit (this);
3740 if (e
->indexes
[0]->type
!= pe_long
)
3741 unresolved (e
->tok
);
3747 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3748 unresolved (e
->tok
); // symbol resolution should prevent this
3749 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3751 expression
* ee
= e
->indexes
[i
];
3752 exp_type
& ft
= array
->referent
->index_types
[i
];
3755 exp_type at
= ee
->type
;
3757 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3759 // propagate to formal type
3761 resolved (array
->referent
->tok
, ft
);
3762 // uses array decl as there is no token for "formal type"
3765 invalid (ee
->tok
, at
);
3767 invalid (ee
->tok
, ft
);
3768 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3769 mismatch (e
->tok
, at
, ft
);
3770 if (at
== pe_unknown
)
3771 unresolved (ee
->tok
);
3778 e
->limit
->visit (this);
3782 e
->block
->visit (this);
3787 typeresolution_info::visit_null_statement (null_statement
*)
3793 typeresolution_info::visit_expr_statement (expr_statement
* e
)
3796 e
->value
->visit (this);
3800 struct delete_statement_typeresolution_info
:
3801 public throwing_visitor
3803 typeresolution_info
*parent
;
3804 delete_statement_typeresolution_info (typeresolution_info
*p
):
3805 throwing_visitor ("invalid operand of delete expression"),
3809 void visit_arrayindex (arrayindex
* e
)
3811 parent
->visit_arrayindex (e
);
3814 void visit_symbol (symbol
* e
)
3816 exp_type ignored
= pe_unknown
;
3817 assert (e
->referent
!= 0);
3818 resolve_2types (e
, e
->referent
, parent
, ignored
);
3824 typeresolution_info::visit_delete_statement (delete_statement
* e
)
3826 delete_statement_typeresolution_info
di (this);
3828 e
->value
->visit (&di
);
3833 typeresolution_info::visit_next_statement (next_statement
*)
3839 typeresolution_info::visit_break_statement (break_statement
*)
3845 typeresolution_info::visit_continue_statement (continue_statement
*)
3851 typeresolution_info::visit_array_in (array_in
* e
)
3853 // all unary operators only work on numerics
3855 t
= pe_unknown
; // array value can be anything
3856 e
->operand
->visit (this);
3858 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
3859 ; // already resolved
3860 else if (t1
== pe_string
|| t1
== pe_stats
)
3861 mismatch (e
->tok
, t1
, pe_long
);
3862 else if (e
->type
== pe_unknown
)
3865 resolved (e
->tok
, e
->type
);
3871 typeresolution_info::visit_return_statement (return_statement
* e
)
3873 // This is like symbol, where the referent is
3874 // the return value of the function.
3876 // translation pass will print error
3877 if (current_function
== 0)
3880 exp_type
& e_type
= current_function
->type
;
3881 t
= current_function
->type
;
3882 e
->value
->visit (this);
3884 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
3885 && e_type
!= e
->value
->type
)
3886 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
3887 if (e_type
== pe_unknown
&&
3888 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
3890 // propagate non-statistics from value
3891 e_type
= e
->value
->type
;
3892 resolved (current_function
->tok
, e
->value
->type
);
3894 if (e
->value
->type
== pe_stats
)
3895 invalid (e
->value
->tok
, e
->value
->type
);
3899 typeresolution_info::visit_print_format (print_format
* e
)
3901 size_t unresolved_args
= 0;
3905 e
->hist
->visit(this);
3908 else if (e
->print_with_format
)
3910 // If there's a format string, we can do both inference *and*
3913 // First we extract the subsequence of formatting components
3914 // which are conversions (not just literal string components)
3916 unsigned expected_num_args
= 0;
3917 std::vector
<print_format::format_component
> components
;
3918 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
3920 if (e
->components
[i
].type
== print_format::conv_unspecified
)
3921 throw semantic_error ("Unspecified conversion in print operator format string",
3923 else if (e
->components
[i
].type
== print_format::conv_literal
)
3925 components
.push_back(e
->components
[i
]);
3926 ++expected_num_args
;
3927 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
3928 ++expected_num_args
;
3929 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
3930 ++expected_num_args
;
3933 // Then we check that the number of conversions and the number
3936 if (expected_num_args
!= e
->args
.size())
3937 throw semantic_error ("Wrong number of args to formatted print operator",
3940 // Then we check that the types of the conversions match the types
3943 for (size_t i
= 0; i
< components
.size(); ++i
)
3945 // Check the dynamic width, if specified
3946 if (components
[i
].widthtype
== print_format::width_dynamic
)
3948 check_arg_type (pe_long
, e
->args
[argno
]);
3952 // Check the dynamic precision, if specified
3953 if (components
[i
].prectype
== print_format::prec_dynamic
)
3955 check_arg_type (pe_long
, e
->args
[argno
]);
3959 exp_type wanted
= pe_unknown
;
3961 switch (components
[i
].type
)
3963 case print_format::conv_unspecified
:
3964 case print_format::conv_literal
:
3968 case print_format::conv_signed_decimal
:
3969 case print_format::conv_unsigned_decimal
:
3970 case print_format::conv_unsigned_octal
:
3971 case print_format::conv_unsigned_ptr
:
3972 case print_format::conv_unsigned_uppercase_hex
:
3973 case print_format::conv_unsigned_lowercase_hex
:
3974 case print_format::conv_binary
:
3975 case print_format::conv_char
:
3976 case print_format::conv_memory
:
3977 case print_format::conv_memory_hex
:
3981 case print_format::conv_string
:
3986 assert (wanted
!= pe_unknown
);
3987 check_arg_type (wanted
, e
->args
[argno
]);
3993 // Without a format string, the best we can do is require that
3994 // each argument resolve to a concrete type.
3995 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
3998 e
->args
[i
]->visit (this);
3999 if (e
->args
[i
]->type
== pe_unknown
)
4001 unresolved (e
->args
[i
]->tok
);
4007 if (unresolved_args
== 0)
4009 if (e
->type
== pe_unknown
)
4011 if (e
->print_to_stream
)
4014 e
->type
= pe_string
;
4015 resolved (e
->tok
, e
->type
);
4020 e
->type
= pe_unknown
;
4021 unresolved (e
->tok
);
4027 typeresolution_info::visit_stat_op (stat_op
* e
)
4030 e
->stat
->visit (this);
4031 if (e
->type
== pe_unknown
)
4034 resolved (e
->tok
, e
->type
);
4036 else if (e
->type
!= pe_long
)
4037 mismatch (e
->tok
, e
->type
, pe_long
);
4041 typeresolution_info::visit_hist_op (hist_op
* e
)
4044 e
->stat
->visit (this);
4049 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
4054 if (arg
->type
== pe_unknown
)
4057 resolved (arg
->tok
, wanted
);
4059 else if (arg
->type
!= wanted
)
4061 mismatch (arg
->tok
, arg
->type
, wanted
);
4067 typeresolution_info::unresolved (const token
* tok
)
4069 num_still_unresolved
++;
4071 if (assert_resolvability
)
4074 string nm
= (current_function
? current_function
->name
:
4075 current_probe
? current_probe
->name
:
4077 msg
<< nm
+ " with unresolved type";
4078 session
.print_error (semantic_error (msg
.str(), tok
));
4084 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
4086 num_still_unresolved
++;
4088 if (assert_resolvability
)
4091 string nm
= (current_function
? current_function
->name
:
4092 current_probe
? current_probe
->name
:
4094 if (tok
&& tok
->type
== tok_operator
)
4095 msg
<< nm
+ " uses invalid operator";
4097 msg
<< nm
+ " with invalid type " << pe
;
4098 session
.print_error (semantic_error (msg
.str(), tok
));
4104 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
4106 bool tok_resolved
= false;
4108 semantic_error
* err1
= 0;
4109 num_still_unresolved
++;
4111 //BZ 9719: for improving type mismatch messages, a semantic error is
4112 //generated with the token where type was first resolved. All such
4113 //resolved tokens, stored in a vector, are matched against their
4114 //content. If an error for the matching token hasn't been printed out
4115 //already, it is and the token pushed in another printed_toks vector
4117 if (assert_resolvability
)
4120 for (i
=0; i
<resolved_toks
.size(); i
++)
4122 if (resolved_toks
[i
]->content
== tok
->content
)
4124 tok_resolved
= true;
4130 string nm
= (current_function
? current_function
->name
:
4131 current_probe
? current_probe
->name
:
4133 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
4137 bool tok_printed
= false;
4138 for (size_t j
=0; j
<printed_toks
.size(); j
++)
4140 if (printed_toks
[j
] == resolved_toks
[i
])
4146 string nm
= (current_function
? current_function
->name
:
4147 current_probe
? current_probe
->name
:
4149 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
4152 //error for possible mismatch in the earlier resolved token
4153 printed_toks
.push_back (resolved_toks
[i
]);
4154 stringstream type_msg
;
4155 type_msg
<< nm
+ " type first inferred here (" << t2
<< ")";
4156 err1
= new semantic_error (type_msg
.str(), resolved_toks
[i
]);
4159 semantic_error
err (msg
.str(), tok
);
4161 session
.print_error (err
);
4167 typeresolution_info::resolved (const token
* tok
, exp_type
)
4169 resolved_toks
.push_back (tok
);
4170 num_newly_resolved
++;
4173 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */