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
):
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
):
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 : end(NULL
), 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
)
286 throw semantic_error("duplicate probe point pattern");
291 match_node::bind(string
const & k
)
293 return bind(match_key(k
));
297 match_node::bind_str(string
const & k
)
299 return bind(match_key(k
).with_string());
303 match_node::bind_num(string
const & k
)
305 return bind(match_key(k
).with_number());
309 match_node::allow_unprivileged (bool b
)
316 match_node::unprivileged_allowed () const
318 return unprivileged_ok
;
322 match_node::find_and_build (systemtap_session
& s
,
323 probe
* p
, probe_point
*loc
, unsigned pos
,
324 vector
<derived_probe
*>& results
)
326 assert (pos
<= loc
->components
.size());
327 if (pos
== loc
->components
.size()) // matched all probe point components so far
329 derived_probe_builder
*b
= end
; // may be 0 if only nested names are bound
334 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
335 alternatives
+= string(" ") + i
->first
.str();
337 throw semantic_error (string("probe point truncated at position ") +
338 lex_cast
<string
> (pos
) +
339 " (follow:" + alternatives
+ ")", loc
->tok
);
342 map
<string
, literal
*> param_map
;
343 for (unsigned i
=0; i
<pos
; i
++)
344 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
347 // Are we compiling for unprivileged users? */
350 // Is this probe point ok for unprivileged users?
351 if (! unprivileged_allowed ())
352 throw semantic_error (string("probe point is not allowed for unprivileged users"));
355 b
->build (s
, p
, loc
, param_map
, results
);
357 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
359 match_key
match (* loc
->components
[pos
]);
361 // Call find_and_build for each possible match. Ignore errors -
362 // unless we don't find any match.
363 unsigned int num_results
= results
.size();
364 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
366 const match_key
& subkey
= i
->first
;
367 match_node
* subnode
= i
->second
;
369 if (pending_interrupts
) break;
371 if (match
.globmatch(subkey
))
374 clog
<< "wildcard '" << loc
->components
[pos
]->functor
375 << "' matched '" << subkey
.name
<< "'" << endl
;
377 // When we have a wildcard, we need to create a copy of
378 // the probe point. Then we'll create a copy of the
379 // wildcard component, and substitute the non-wildcard
381 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
382 probe_point::component
*non_wildcard_component
383 = new probe_point::component(*loc
->components
[pos
]);
384 non_wildcard_component
->functor
= subkey
.name
;
385 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
387 // NB: probe conditions are not attached at the wildcard
388 // (component/functor) level, but at the overall
389 // probe_point level.
391 // recurse (with the non-wildcard probe point)
394 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
397 catch (const semantic_error
& e
)
399 // Ignore semantic_errors while expanding wildcards.
400 // If we get done and nothing was expanded, the code
401 // following the loop will complain.
403 // If this wildcard didn't match, cleanup.
404 delete non_wildcard_pp
;
405 delete non_wildcard_component
;
409 if (! loc
->optional
&& num_results
== results
.size())
411 // We didn't find any wildcard matches (since the size of
412 // the result vector didn't change). Throw an error.
414 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
415 alternatives
+= string(" ") + i
->first
.str();
417 throw semantic_error(string("probe point mismatch at position ") +
418 lex_cast
<string
> (pos
) +
419 " (alternatives:" + alternatives
+ ")" +
420 " didn't find any wildcard matches",
426 match_key
match (* loc
->components
[pos
]);
427 sub_map_iterator_t i
= sub
.find (match
);
428 if (i
== sub
.end()) // no match
431 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
432 alternatives
+= string(" ") + i
->first
.str();
434 throw semantic_error (string("probe point mismatch at position ") +
435 lex_cast
<string
> (pos
) +
436 " (alternatives:" + alternatives
+ ")",
440 match_node
* subnode
= i
->second
;
442 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
448 match_node::build_no_more (systemtap_session
& s
)
450 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
451 i
->second
->build_no_more (s
);
452 if (end
) end
->build_no_more (s
);
456 // ------------------------------------------------------------------------
458 // ------------------------------------------------------------------------
460 struct alias_derived_probe
: public derived_probe
462 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
):
463 derived_probe (base
, l
), alias(a
) {}
465 void upchuck () { throw semantic_error ("inappropriate", this->tok
); }
467 // Alias probes are immediately expanded to other derived_probe
468 // types, and are not themselves emitted or listed in
469 // systemtap_session.probes
471 void join_group (systemtap_session
&) { upchuck (); }
473 virtual const probe_alias
*get_alias () const { return alias
; }
476 const probe_alias
*alias
; // Used to check for recursion
481 alias_expansion_builder
482 : public derived_probe_builder
486 alias_expansion_builder(probe_alias
* a
)
490 virtual void build(systemtap_session
& sess
,
492 probe_point
* location
,
493 std::map
<std::string
, literal
*> const &,
494 vector
<derived_probe
*> & finished_results
)
496 // Don't build the alias expansion if infinite recursion is detected.
497 if (checkForRecursiveExpansion (use
)) {
499 msg
<< "Recursive loop in alias expansion of " << *location
<< " at " << location
->tok
->location
;
500 // semantic_errors thrown here are ignored.
501 sess
.print_error (semantic_error (msg
.str()));
505 // We're going to build a new probe and wrap it up in an
506 // alias_expansion_probe so that the expansion loop recognizes it as
507 // such and re-expands its expansion.
509 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
);
510 n
->body
= new block();
512 // The new probe gets a deep copy of the location list of
513 // the alias (with incoming condition joined)
514 n
->locations
.clear();
515 for (unsigned i
=0; i
<alias
->locations
.size(); i
++)
517 probe_point
*pp
= new probe_point(*alias
->locations
[i
]);
518 pp
->condition
= add_condition (pp
->condition
, location
->condition
);
519 n
->locations
.push_back(pp
);
522 // the token location of the alias,
523 n
->tok
= location
->tok
;
525 // and statements representing the concatenation of the alias'
526 // body with the use's.
528 // NB: locals are *not* copied forward, from either alias or
529 // use. The expansion should have its locals re-inferred since
530 // there's concatenated code here and we only want one vardecl per
531 // resulting variable.
533 if (alias
->epilogue_style
)
534 n
->body
= new block (use
->body
, alias
->body
);
536 n
->body
= new block (alias
->body
, use
->body
);
538 derive_probes (sess
, n
, finished_results
, location
->optional
);
541 bool checkForRecursiveExpansion (probe
*use
)
543 // Collect the derivation chain of this probe.
544 vector
<probe
*>derivations
;
545 use
->collect_derivation_chain (derivations
);
547 // Check all probe points in the alias expansion against the currently-being-expanded probe point
548 // of each of the probes in the derivation chain, looking for a match. This
549 // indicates infinite recursion.
550 // The first element of the derivation chain will be the derived_probe representing 'use', so
551 // start the search with the second element.
552 assert (derivations
.size() > 0);
553 assert (derivations
[0] == use
);
554 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
555 if (use
->get_alias() == derivations
[d
]->get_alias())
556 return true; // recursion detected
563 // ------------------------------------------------------------------------
565 // ------------------------------------------------------------------------
568 // Register all the aliases we've seen in library files, and the user
569 // file, as patterns.
572 systemtap_session::register_library_aliases()
574 vector
<stapfile
*> files(library_files
);
575 files
.push_back(user_file
);
577 for (unsigned f
= 0; f
< files
.size(); ++f
)
579 stapfile
* file
= files
[f
];
580 for (unsigned a
= 0; a
< file
->aliases
.size(); ++a
)
582 probe_alias
* alias
= file
->aliases
[a
];
585 for (unsigned n
= 0; n
< alias
->alias_names
.size(); ++n
)
587 probe_point
* name
= alias
->alias_names
[n
];
588 match_node
* n
= pattern_root
;
589 for (unsigned c
= 0; c
< name
->components
.size(); ++c
)
591 probe_point::component
* comp
= name
->components
[c
];
592 // XXX: alias parameters
594 throw semantic_error("alias component "
596 + " contains illegal parameter");
597 n
= n
->bind(comp
->functor
);
599 n
->bind(new alias_expansion_builder(alias
));
602 catch (const semantic_error
& e
)
604 semantic_error
* er
= new semantic_error (e
); // copy it
607 msg
<< " while registering probe alias ";
608 alias
->printsig(msg
);
609 er
->msg2
= msg
.str();
618 static unsigned max_recursion
= 100;
624 recursion_guard(unsigned & i
) : i(i
)
626 if (i
> max_recursion
)
627 throw semantic_error("recursion limit reached");
636 // The match-and-expand loop.
638 derive_probes (systemtap_session
& s
,
639 probe
*p
, vector
<derived_probe
*>& dps
,
642 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
644 if (pending_interrupts
) break;
646 probe_point
*loc
= p
->locations
[i
];
650 unsigned num_atbegin
= dps
.size();
652 // Pass down optional flag from e.g. alias reference to each
653 // probe_point instance. We do this by temporarily overriding
654 // the probe_point optional flag. We could instead deep-copy
655 // and set a flag on the copy permanently.
656 bool old_loc_opt
= loc
->optional
;
657 loc
->optional
= loc
->optional
|| optional
;
660 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
662 catch (const semantic_error
& e
)
665 throw semantic_error(e
);
666 else /* tolerate failure for optional probe */
670 loc
->optional
= old_loc_opt
;
671 unsigned num_atend
= dps
.size();
673 if (! (loc
->optional
||optional
) && // something required, but
674 num_atbegin
== num_atend
) // nothing new derived!
675 throw semantic_error ("no match");
677 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
681 clog
<< "Probe point ";
682 p
->locations
[i
]->print(clog
);
683 clog
<< " sufficient, skipped";
684 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
687 p
->locations
[j
]->print(clog
);
691 break; // we need not try to derive for any other locations
694 catch (const semantic_error
& e
)
696 // XXX: prefer not to print_error at every nest/unroll level
698 semantic_error
* er
= new semantic_error (e
); // copy it
701 msg
<< " while resolving probe point " << *loc
;
702 er
->msg2
= msg
.str();
703 s
.print_error (* er
);
712 // ------------------------------------------------------------------------
714 // Indexable usage checks
717 struct symbol_fetcher
718 : public throwing_visitor
722 symbol_fetcher (symbol
*&sym
): sym(sym
)
725 void visit_symbol (symbol
* e
)
730 void visit_target_symbol (target_symbol
* e
)
735 void visit_arrayindex (arrayindex
* e
)
737 e
->base
->visit_indexable (this);
740 void visit_cast_op (cast_op
* e
)
745 void throwone (const token
* t
)
747 throw semantic_error ("Expecting symbol or array index expression", t
);
752 get_symbol_within_expression (expression
*e
)
755 symbol_fetcher
fetcher(sym
);
757 return sym
; // NB: may be null!
761 get_symbol_within_indexable (indexable
*ix
)
763 symbol
*array
= NULL
;
764 hist_op
*hist
= NULL
;
765 classify_indexable(ix
, array
, hist
);
769 return get_symbol_within_expression (hist
->stat
);
772 struct mutated_var_collector
773 : public traversing_visitor
775 set
<vardecl
*> * mutated_vars
;
777 mutated_var_collector (set
<vardecl
*> * mm
)
781 void visit_assignment(assignment
* e
)
783 if (e
->type
== pe_stats
&& e
->op
== "<<<")
785 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
787 mutated_vars
->insert (vd
);
789 traversing_visitor::visit_assignment(e
);
792 void visit_arrayindex (arrayindex
*e
)
794 if (is_active_lvalue (e
))
797 if (e
->base
->is_symbol (sym
))
798 mutated_vars
->insert (sym
->referent
);
800 throw semantic_error("Assignment to read-only histogram bucket", e
->tok
);
802 traversing_visitor::visit_arrayindex (e
);
807 struct no_var_mutation_during_iteration_check
808 : public traversing_visitor
810 systemtap_session
& session
;
811 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
812 vector
<vardecl
*> vars_being_iterated
;
814 no_var_mutation_during_iteration_check
815 (systemtap_session
& sess
,
816 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
817 : session(sess
), function_mutates_vars (fmv
)
820 void visit_arrayindex (arrayindex
*e
)
822 if (is_active_lvalue(e
))
824 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
827 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
829 vardecl
*v
= vars_being_iterated
[i
];
832 string err
= ("variable '" + v
->name
+
833 "' modified during 'foreach' iteration");
834 session
.print_error (semantic_error (err
, e
->tok
));
839 traversing_visitor::visit_arrayindex (e
);
842 void visit_functioncall (functioncall
* e
)
844 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
845 = function_mutates_vars
.find (e
->referent
);
847 if (i
!= function_mutates_vars
.end())
849 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
851 vardecl
*m
= vars_being_iterated
[j
];
852 if (i
->second
->find (m
) != i
->second
->end())
854 string err
= ("function call modifies var '" + m
->name
+
855 "' during 'foreach' iteration");
856 session
.print_error (semantic_error (err
, e
->tok
));
861 traversing_visitor::visit_functioncall (e
);
864 void visit_foreach_loop(foreach_loop
* s
)
866 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
869 vars_being_iterated
.push_back (vd
);
871 traversing_visitor::visit_foreach_loop (s
);
874 vars_being_iterated
.pop_back();
879 // ------------------------------------------------------------------------
881 struct stat_decl_collector
882 : public traversing_visitor
884 systemtap_session
& session
;
886 stat_decl_collector(systemtap_session
& sess
)
890 void visit_stat_op (stat_op
* e
)
892 symbol
*sym
= get_symbol_within_expression (e
->stat
);
893 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
894 session
.stat_decls
[sym
->name
] = statistic_decl();
897 void visit_assignment (assignment
* e
)
901 symbol
*sym
= get_symbol_within_expression (e
->left
);
902 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
903 session
.stat_decls
[sym
->name
] = statistic_decl();
906 traversing_visitor::visit_assignment(e
);
909 void visit_hist_op (hist_op
* e
)
911 symbol
*sym
= get_symbol_within_expression (e
->stat
);
912 statistic_decl new_stat
;
914 if (e
->htype
== hist_linear
)
916 new_stat
.type
= statistic_decl::linear
;
917 assert (e
->params
.size() == 3);
918 new_stat
.linear_low
= e
->params
[0];
919 new_stat
.linear_high
= e
->params
[1];
920 new_stat
.linear_step
= e
->params
[2];
924 assert (e
->htype
== hist_log
);
925 new_stat
.type
= statistic_decl::logarithmic
;
926 assert (e
->params
.size() == 0);
929 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
930 if (i
== session
.stat_decls
.end())
931 session
.stat_decls
[sym
->name
] = new_stat
;
934 statistic_decl
& old_stat
= i
->second
;
935 if (!(old_stat
== new_stat
))
937 if (old_stat
.type
== statistic_decl::none
)
938 i
->second
= new_stat
;
941 // FIXME: Support multiple co-declared histogram types
942 semantic_error
se("multiple histogram types declared on '" + sym
->name
+ "'",
944 session
.print_error (se
);
953 semantic_pass_stats (systemtap_session
& sess
)
955 stat_decl_collector
sdc(sess
);
957 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
958 it
->second
->body
->visit (&sdc
);
960 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
961 sess
.probes
[i
]->body
->visit (&sdc
);
963 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
965 vardecl
*v
= sess
.globals
[i
];
966 if (v
->type
== pe_stats
)
969 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
971 semantic_error
se("unable to infer statistic parameters for global '" + v
->name
+ "'");
972 sess
.print_error (se
);
977 return sess
.num_errors();
980 // ------------------------------------------------------------------------
982 // Enforce variable-related invariants: no modification of
983 // a foreach()-iterated array.
985 semantic_pass_vars (systemtap_session
& sess
)
988 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
989 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
991 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
993 functiondecl
* fn
= it
->second
;
996 set
<vardecl
*> * m
= new set
<vardecl
*>();
997 mutated_var_collector
mc (m
);
998 fn
->body
->visit (&mc
);
1003 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
1005 functiondecl
* fn
= it
->second
;
1006 if (fn
->body
) fn
->body
->visit (&chk
);
1009 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1011 if (sess
.probes
[i
]->body
)
1012 sess
.probes
[i
]->body
->visit (&chk
);
1015 return sess
.num_errors();
1019 // ------------------------------------------------------------------------
1021 // Rewrite probe condition expressions into probe bodies. Tricky and
1022 // exciting business, this. This:
1024 // probe foo if (g1 || g2) { ... }
1025 // probe bar { ... g1 ++ ... }
1029 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
1030 // probe foo { if (! (g1 || g2)) next; ... }
1031 // probe bar { ... g1 ++ ...;
1032 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
1035 // XXX: As a first cut, do only the "inline probe condition" part of the
1039 semantic_pass_conditions (systemtap_session
& sess
)
1041 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1043 derived_probe
* p
= sess
.probes
[i
];
1044 expression
* e
= p
->sole_location()->condition
;
1047 varuse_collecting_visitor
vut(sess
);
1050 if (! vut
.written
.empty())
1052 string err
= ("probe condition must not modify any variables");
1053 sess
.print_error (semantic_error (err
, e
->tok
));
1055 else if (vut
.embedded_seen
)
1057 sess
.print_error (semantic_error ("probe condition must not include impure embedded-C", e
->tok
));
1060 // Add the condition expression to the front of the
1061 // derived_probe body.
1062 if_statement
*ifs
= new if_statement ();
1064 ifs
->thenblock
= new next_statement ();
1065 ifs
->thenblock
->tok
= e
->tok
;
1066 ifs
->elseblock
= NULL
;
1067 unary_expression
*notex
= new unary_expression ();
1069 notex
->tok
= e
->tok
;
1071 ifs
->condition
= notex
;
1072 p
->body
= new block (ifs
, p
->body
);
1076 return sess
.num_errors();
1080 // ------------------------------------------------------------------------
1083 static int semantic_pass_symbols (systemtap_session
&);
1084 static int semantic_pass_optimize1 (systemtap_session
&);
1085 static int semantic_pass_optimize2 (systemtap_session
&);
1086 static int semantic_pass_types (systemtap_session
&);
1087 static int semantic_pass_vars (systemtap_session
&);
1088 static int semantic_pass_stats (systemtap_session
&);
1089 static int semantic_pass_conditions (systemtap_session
&);
1092 // Link up symbols to their declarations. Set the session's
1093 // files/probes/functions/globals vectors from the transitively
1094 // reached set of stapfiles in s.library_files, starting from
1095 // s.user_file. Perform automatic tapset inclusion and probe
1098 semantic_pass_symbols (systemtap_session
& s
)
1100 symresolution_info
sym (s
);
1102 // NB: s.files can grow during this iteration, so size() can
1103 // return gradually increasing numbers.
1104 s
.files
.push_back (s
.user_file
);
1105 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1107 if (pending_interrupts
) break;
1108 stapfile
* dome
= s
.files
[i
];
1110 // Pass 1: add globals and functions to systemtap-session master list,
1111 // so the find_* functions find them
1113 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1114 s
.globals
.push_back (dome
->globals
[i
]);
1116 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1117 s
.functions
[dome
->functions
[i
]->name
] = dome
->functions
[i
];
1119 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1120 s
.embeds
.push_back (dome
->embeds
[i
]);
1122 // Pass 2: process functions
1124 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1126 if (pending_interrupts
) break;
1127 functiondecl
* fd
= dome
->functions
[i
];
1131 for (unsigned j
=0; j
<s
.code_filters
.size(); j
++)
1132 s
.code_filters
[j
]->replace (fd
->body
);
1134 sym
.current_function
= fd
;
1135 sym
.current_probe
= 0;
1136 fd
->body
->visit (& sym
);
1138 catch (const semantic_error
& e
)
1144 // Pass 3: derive probes and resolve any further symbols in the
1147 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1149 if (pending_interrupts
) break;
1150 probe
* p
= dome
->probes
[i
];
1151 vector
<derived_probe
*> dps
;
1153 // much magic happens here: probe alias expansion, wildcard
1154 // matching, low-level derived_probe construction.
1155 derive_probes (s
, p
, dps
);
1157 for (unsigned j
=0; j
<dps
.size(); j
++)
1159 if (pending_interrupts
) break;
1160 derived_probe
* dp
= dps
[j
];
1161 s
.probes
.push_back (dp
);
1166 for (unsigned k
=0; k
<s
.code_filters
.size(); k
++)
1167 s
.code_filters
[k
]->replace (dp
->body
);
1169 sym
.current_function
= 0;
1170 sym
.current_probe
= dp
;
1171 dp
->body
->visit (& sym
);
1173 // Process the probe-point condition expression.
1174 sym
.current_function
= 0;
1175 sym
.current_probe
= 0;
1176 if (dp
->sole_location()->condition
)
1177 dp
->sole_location()->condition
->visit (& sym
);
1179 catch (const semantic_error
& e
)
1187 // Inform all derived_probe builders that we're done with
1188 // all resolution, so it's time to release caches.
1189 s
.pattern_root
->build_no_more (s
);
1191 return s
.num_errors(); // all those print_error calls
1195 // Keep unread global variables for probe end value display.
1196 void add_global_var_display (systemtap_session
& s
)
1198 // Don't generate synthetic end probes when in listings mode;
1199 // it would clutter up the list of probe points with "end ...".
1200 if (s
.listing_mode
) return;
1202 varuse_collecting_visitor
vut(s
);
1203 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1205 s
.probes
[i
]->body
->visit (& vut
);
1207 if (s
.probes
[i
]->sole_location()->condition
)
1208 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1211 for (unsigned g
=0; g
< s
.globals
.size(); g
++)
1213 vardecl
* l
= s
.globals
[g
];
1214 if (vut
.read
.find (l
) != vut
.read
.end()
1215 || vut
.written
.find (l
) == vut
.written
.end())
1218 // Don't generate synthetic end probes for unread globals
1219 // declared only within tapsets. (RHBZ 468139), but rather
1220 // only within the end-user script.
1222 bool tapset_global
= false;
1223 for (size_t m
=0; m
< s
.library_files
.size(); m
++)
1225 for (size_t n
=0; n
< s
.library_files
[m
]->globals
.size(); n
++)
1227 if (l
->name
== s
.library_files
[m
]->globals
[n
]->name
)
1228 {tapset_global
= true; break;}
1234 print_format
* pf
= new print_format
;
1235 probe
* p
= new probe
;
1236 probe_point
* pl
= new probe_point
;
1237 probe_point::component
* c
= new probe_point::component("end");
1238 token
* print_tok
= new token
;
1239 vector
<derived_probe
*> dps
;
1240 block
*b
= new block
;
1242 pl
->components
.push_back (c
);
1244 p
->locations
.push_back (pl
);
1245 print_tok
->type
= tok_identifier
;
1246 print_tok
->content
= "printf";
1249 symbol
* g_sym
= new symbol
;
1250 g_sym
->name
= l
->name
;
1251 g_sym
->tok
= l
->tok
;
1252 g_sym
->type
= l
->type
;
1253 g_sym
->referent
= l
;
1255 pf
->print_to_stream
= true;
1256 pf
->print_with_format
= true;
1257 pf
->print_with_delim
= false;
1258 pf
->print_with_newline
= false;
1259 pf
->print_char
= false;
1260 pf
->raw_components
+= l
->name
;
1261 pf
->tok
= print_tok
;
1263 if (l
->index_types
.size() == 0) // Scalar
1265 if (l
->type
== pe_stats
)
1266 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1267 else if (l
->type
== pe_string
)
1268 pf
->raw_components
+= "=\"%#s\"\\n";
1270 pf
->raw_components
+= "=%#x\\n";
1271 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1272 expr_statement
* feb
= new expr_statement
;
1274 feb
->tok
= print_tok
;
1275 if (l
->type
== pe_stats
)
1277 struct stat_op
* so
[5];
1278 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1280 for (unsigned si
= 0;
1281 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1284 so
[si
]= new stat_op
;
1285 so
[si
]->ctype
= stypes
[si
];
1286 so
[si
]->type
= pe_long
;
1287 so
[si
]->stat
= g_sym
;
1288 so
[si
]->tok
= l
->tok
;
1289 pf
->args
.push_back(so
[si
]);
1293 pf
->args
.push_back(g_sym
);
1295 /* PR7053: Checking empty aggregate for global variable */
1296 if (l
->type
== pe_stats
) {
1297 stat_op
*so
= new stat_op
;
1298 so
->ctype
= sc_count
;
1302 comparison
*be
= new comparison
;
1306 be
->right
= new literal_number(0);
1308 /* Create printf @count=0x0 in else block */
1309 print_format
* pf_0
= new print_format
;
1310 pf_0
->print_to_stream
= true;
1311 pf_0
->print_with_format
= true;
1312 pf_0
->print_with_delim
= false;
1313 pf_0
->print_with_newline
= false;
1314 pf_0
->print_char
= false;
1315 pf_0
->raw_components
+= l
->name
;
1316 pf_0
->raw_components
+= " @count=0x0\\n";
1317 pf_0
->tok
= print_tok
;
1318 pf_0
->components
= print_format::string_to_components(pf_0
->raw_components
);
1319 expr_statement
* feb_else
= new expr_statement
;
1320 feb_else
->value
= pf_0
;
1321 feb_else
->tok
= print_tok
;
1322 if_statement
*ifs
= new if_statement
;
1324 ifs
->condition
= be
;
1325 ifs
->thenblock
= feb
;
1326 ifs
->elseblock
= feb_else
;
1327 b
->statements
.push_back(ifs
);
1329 else /* other non-stat cases */
1330 b
->statements
.push_back(feb
);
1334 int idx_count
= l
->index_types
.size();
1335 symbol
* idx_sym
[idx_count
];
1336 vardecl
* idx_v
[idx_count
];
1337 // Create a foreach loop
1338 foreach_loop
* fe
= new foreach_loop
;
1339 fe
->sort_direction
= -1; // imply decreasing sort on value
1340 fe
->sort_column
= 0; // as in foreach ([a,b,c] in array-) { }
1343 // Create indices for the foreach loop
1344 for (int i
=0; i
< idx_count
; i
++)
1347 if (asprintf (&idx_name
, "idx%d", i
) < 0)
1349 idx_sym
[i
] = new symbol
;
1350 idx_sym
[i
]->name
= idx_name
;
1351 idx_sym
[i
]->tok
= l
->tok
;
1352 idx_v
[i
] = new vardecl
;
1353 idx_v
[i
]->name
= idx_name
;
1354 idx_v
[i
]->type
= l
->index_types
[i
];
1355 idx_v
[i
]->tok
= l
->tok
;
1356 idx_sym
[i
]->referent
= idx_v
[i
];
1357 fe
->indexes
.push_back (idx_sym
[i
]);
1360 // Create a printf for the foreach loop
1361 pf
->raw_components
+= "[";
1362 for (int i
=0; i
< idx_count
; i
++)
1365 pf
->raw_components
+= ",";
1366 if (l
->index_types
[i
] == pe_string
)
1367 pf
->raw_components
+= "\"%#s\"";
1369 pf
->raw_components
+= "%#d";
1371 pf
->raw_components
+= "]";
1372 if (l
->type
== pe_stats
)
1373 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1374 else if (l
->type
== pe_string
)
1375 pf
->raw_components
+= "=\"%#s\"\\n";
1377 pf
->raw_components
+= "=%#x\\n";
1379 // Create an index for the array
1380 struct arrayindex
* ai
= new arrayindex
;
1384 for (int i
=0; i
< idx_count
; i
++)
1386 ai
->indexes
.push_back (idx_sym
[i
]);
1387 pf
->args
.push_back(idx_sym
[i
]);
1389 if (l
->type
== pe_stats
)
1391 struct stat_op
* so
[5];
1392 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1394 ai
->type
= pe_stats
;
1395 for (unsigned si
= 0;
1396 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1399 so
[si
]= new stat_op
;
1400 so
[si
]->ctype
= stypes
[si
];
1401 so
[si
]->type
= pe_long
;
1403 so
[si
]->tok
= l
->tok
;
1404 pf
->args
.push_back(so
[si
]);
1408 pf
->args
.push_back(ai
);
1410 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1411 expr_statement
* feb
= new expr_statement
;
1414 fe
->block
= (statement
*)feb
;
1415 b
->statements
.push_back(fe
);
1418 // Add created probe
1420 derive_probes (s
, p
, dps
);
1421 for (unsigned i
= 0; i
< dps
.size(); i
++)
1423 derived_probe
* dp
= dps
[i
];
1424 s
.probes
.push_back (dp
);
1427 // Repopulate symbol and type info
1428 symresolution_info
sym (s
);
1429 sym
.current_function
= 0;
1430 sym
.current_probe
= dps
[0];
1431 dps
[0]->body
->visit (& sym
);
1433 semantic_pass_types(s
);
1434 // Mark that variable is read
1435 vut
.read
.insert (l
);
1440 semantic_pass (systemtap_session
& s
)
1446 s
.register_library_aliases();
1447 register_standard_tapsets(s
);
1449 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1450 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1451 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize1 (s
);
1452 if (rc
== 0) rc
= semantic_pass_types (s
);
1453 if (rc
== 0) add_global_var_display (s
);
1454 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize2 (s
);
1455 if (rc
== 0) rc
= semantic_pass_vars (s
);
1456 if (rc
== 0) rc
= semantic_pass_stats (s
);
1458 if (s
.probes
.size() == 0 && !s
.listing_mode
)
1459 throw semantic_error ("no probes found");
1461 catch (const semantic_error
& e
)
1471 // ------------------------------------------------------------------------
1474 systemtap_session::systemtap_session ():
1475 // NB: pointer members must be manually initialized!
1476 pattern_root(new match_node
),
1478 be_derived_probes(0),
1479 dwarf_derived_probes(0),
1480 kprobe_derived_probes(0),
1481 uprobe_derived_probes(0),
1482 utrace_derived_probes(0),
1483 itrace_derived_probes(0),
1484 task_finder_derived_probes(0),
1485 timer_derived_probes(0),
1486 profile_derived_probes(0),
1487 mark_derived_probes(0),
1488 tracepoint_derived_probes(0),
1489 hrtimer_derived_probes(0),
1490 perfmon_derived_probes(0),
1491 procfs_derived_probes(0),
1493 sym_kprobes_text_start (0),
1494 sym_kprobes_text_end (0),
1502 // Print this given token, but abbreviate it if the last one had the
1505 systemtap_session::print_token (ostream
& o
, const token
* tok
)
1509 if (last_token
&& last_token
->location
.file
== tok
->location
.file
)
1513 string ts
= tmpo
.str();
1514 // search & replace the file name with nothing
1515 size_t idx
= ts
.find (tok
->location
.file
->name
);
1516 if (idx
!= string::npos
)
1517 ts
.replace (idx
, tok
->location
.file
->name
.size(), "");
1530 systemtap_session::print_error (const semantic_error
& e
)
1532 string message_str
[2];
1533 string
align_semantic_error (" ");
1535 // We generate two messages. The second one ([1]) is printed
1536 // without token compression, for purposes of duplicate elimination.
1537 // This way, the same message that may be generated once with a
1538 // compressed and once with an uncompressed token still only gets
1540 for (int i
=0; i
<2; i
++)
1542 stringstream message
;
1544 message
<< "semantic error: " << e
.what ();
1545 if (e
.tok1
|| e
.tok2
)
1549 if (i
== 0) print_token (message
, e
.tok1
);
1550 else message
<< *e
.tok1
;
1555 if (i
== 0) print_token (message
, e
.tok2
);
1556 else message
<< *e
.tok2
;
1559 message_str
[i
] = message
.str();
1562 // Duplicate elimination
1563 if (seen_errors
.find (message_str
[1]) == seen_errors
.end())
1565 seen_errors
.insert (message_str
[1]);
1566 cerr
<< message_str
[0];
1569 print_error_source (cerr
, align_semantic_error
, e
.tok1
);
1572 print_error_source (cerr
, align_semantic_error
, e
.tok2
);
1576 print_error (* e
.chain
);
1580 systemtap_session::print_error_source (std::ostream
& message
,
1581 std::string
& align
, const token
* tok
)
1586 if (!tok
->location
.file
)
1587 //No source to print, silently exit
1590 unsigned line
= tok
->location
.line
;
1591 unsigned col
= tok
->location
.column
;
1592 const string
&file_contents
= tok
->location
.file
->file_contents
;
1594 size_t start_pos
= 0, end_pos
= 0;
1595 //Navigate to the appropriate line
1596 while (i
!= line
&& end_pos
!= std::string::npos
)
1598 start_pos
= end_pos
;
1599 end_pos
= file_contents
.find ('\n', start_pos
) + 1;
1602 message
<< align
<< "source: " << file_contents
.substr (start_pos
, end_pos
-start_pos
-1) << endl
;
1603 message
<< align
<< " ";
1604 //Navigate to the appropriate column
1605 for (i
=start_pos
; i
<start_pos
+col
-1; i
++)
1607 if(isspace(file_contents
[i
]))
1608 message
<< file_contents
[i
];
1612 message
<< "^" << endl
;
1616 systemtap_session::print_warning (const string
& message_str
, const token
* tok
)
1618 // Duplicate elimination
1619 string
align_warning (" ");
1620 if (seen_warnings
.find (message_str
) == seen_warnings
.end())
1622 seen_warnings
.insert (message_str
);
1623 clog
<< "WARNING: " << message_str
;
1624 if (tok
) { clog
<< ": "; print_token (clog
, tok
); }
1626 if (tok
) { print_error_source (clog
, align_warning
, tok
); }
1631 // ------------------------------------------------------------------------
1632 // semantic processing: symbol resolution
1635 symresolution_info::symresolution_info (systemtap_session
& s
):
1636 session (s
), current_function (0), current_probe (0)
1642 symresolution_info::visit_block (block
* e
)
1644 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
1648 e
->statements
[i
]->visit (this);
1650 catch (const semantic_error
& e
)
1652 session
.print_error (e
);
1659 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
1661 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1662 e
->indexes
[i
]->visit (this);
1664 symbol
*array
= NULL
;
1665 hist_op
*hist
= NULL
;
1666 classify_indexable (e
->base
, array
, hist
);
1670 if (!array
->referent
)
1672 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1674 array
->referent
= d
;
1678 msg
<< "unresolved arity-" << e
->indexes
.size()
1679 << " global array " << array
->name
;
1680 throw semantic_error (msg
.str(), e
->tok
);
1691 e
->limit
->visit (this);
1693 e
->block
->visit (this);
1698 delete_statement_symresolution_info
:
1699 public traversing_visitor
1701 symresolution_info
*parent
;
1703 delete_statement_symresolution_info (symresolution_info
*p
):
1707 void visit_arrayindex (arrayindex
* e
)
1709 parent
->visit_arrayindex (e
);
1711 void visit_functioncall (functioncall
* e
)
1713 parent
->visit_functioncall (e
);
1716 void visit_symbol (symbol
* e
)
1721 vardecl
* d
= parent
->find_var (e
->name
, -1);
1725 throw semantic_error ("unresolved array in delete statement", e
->tok
);
1730 symresolution_info::visit_delete_statement (delete_statement
* s
)
1732 delete_statement_symresolution_info
di (this);
1733 s
->value
->visit (&di
);
1738 symresolution_info::visit_symbol (symbol
* e
)
1743 vardecl
* d
= find_var (e
->name
, 0);
1749 vardecl
* v
= new vardecl
;
1752 if (current_function
)
1753 current_function
->locals
.push_back (v
);
1754 else if (current_probe
)
1755 current_probe
->locals
.push_back (v
);
1757 // must be probe-condition expression
1758 throw semantic_error ("probe condition must not reference undeclared global", e
->tok
);
1765 symresolution_info::visit_arrayindex (arrayindex
* e
)
1767 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1768 e
->indexes
[i
]->visit (this);
1770 symbol
*array
= NULL
;
1771 hist_op
*hist
= NULL
;
1772 classify_indexable(e
->base
, array
, hist
);
1776 if (array
->referent
)
1779 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1781 array
->referent
= d
;
1785 vardecl
* v
= new vardecl
;
1786 v
->set_arity(e
->indexes
.size());
1787 v
->name
= array
->name
;
1788 v
->tok
= array
->tok
;
1789 if (current_function
)
1790 current_function
->locals
.push_back (v
);
1791 else if (current_probe
)
1792 current_probe
->locals
.push_back (v
);
1795 throw semantic_error ("no current probe/function", e
->tok
);
1796 array
->referent
= v
;
1808 symresolution_info::visit_functioncall (functioncall
* e
)
1810 // XXX: we could relax this, if we're going to examine the
1811 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1812 if (! (current_function
|| current_probe
))
1814 // must be probe-condition expression
1815 throw semantic_error ("probe condition must not reference function", e
->tok
);
1818 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1819 e
->args
[i
]->visit (this);
1824 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
1830 msg
<< "unresolved arity-" << e
->args
.size()
1832 throw semantic_error (msg
.str(), e
->tok
);
1838 symresolution_info::find_var (const string
& name
, int arity
)
1840 if (current_function
|| current_probe
)
1843 vector
<vardecl
*>& locals
= (current_function
?
1844 current_function
->locals
:
1845 current_probe
->locals
);
1848 for (unsigned i
=0; i
<locals
.size(); i
++)
1849 if (locals
[i
]->name
== name
1850 && locals
[i
]->compatible_arity(arity
))
1852 locals
[i
]->set_arity (arity
);
1857 // search function formal parameters (for scalars)
1858 if (arity
== 0 && current_function
)
1859 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
1860 if (current_function
->formal_args
[i
]->name
== name
)
1862 // NB: no need to check arity here: formal args always scalar
1863 current_function
->formal_args
[i
]->set_arity (0);
1864 return current_function
->formal_args
[i
];
1867 // search processed globals
1868 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
1869 if (session
.globals
[i
]->name
== name
1870 && session
.globals
[i
]->compatible_arity(arity
))
1872 session
.globals
[i
]->set_arity (arity
);
1873 return session
.globals
[i
];
1876 // search library globals
1877 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1879 stapfile
* f
= session
.library_files
[i
];
1880 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
1882 vardecl
* g
= f
->globals
[j
];
1883 if (g
->name
== name
&& g
->compatible_arity (arity
))
1885 g
->set_arity (arity
);
1887 // put library into the queue if not already there
1888 if (find (session
.files
.begin(), session
.files
.end(), f
)
1889 == session
.files
.end())
1890 session
.files
.push_back (f
);
1902 symresolution_info::find_function (const string
& name
, unsigned arity
)
1905 if (session
.functions
.find(name
) != session
.functions
.end())
1907 functiondecl
* fd
= session
.functions
[name
];
1908 assert (fd
->name
== name
);
1909 if (fd
->formal_args
.size() == arity
)
1913 // search library globals
1914 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1916 stapfile
* f
= session
.library_files
[i
];
1917 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1918 if (f
->functions
[j
]->name
== name
&&
1919 f
->functions
[j
]->formal_args
.size() == arity
)
1921 // put library into the queue if not already there
1922 if (0) // session.verbose_resolution
1923 cerr
<< " function " << name
<< " "
1924 << "is defined from " << f
->name
<< endl
;
1926 if (find (session
.files
.begin(), session
.files
.end(), f
)
1927 == session
.files
.end())
1928 session
.files
.push_back (f
);
1929 // else .. print different message?
1931 return f
->functions
[j
];
1940 // ------------------------------------------------------------------------
1944 // Do away with functiondecls that are never (transitively) called
1946 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1948 functioncall_traversing_visitor ftv
;
1949 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1951 s
.probes
[i
]->body
->visit (& ftv
);
1952 if (s
.probes
[i
]->sole_location()->condition
)
1953 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1955 vector
<functiondecl
*> new_unused_functions
;
1956 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
1958 functiondecl
* fd
= it
->second
;
1959 if (ftv
.traversed
.find(fd
) == ftv
.traversed
.end())
1961 if (fd
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
1962 ! s
.suppress_warnings
)
1963 s
.print_warning ("eliding unused function '" + fd
->name
+ "'", fd
->tok
);
1964 else if (s
.verbose
>2)
1965 clog
<< "Eliding unused function " << fd
->name
1967 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
1968 new_unused_functions
.push_back (fd
);
1972 for (unsigned i
=0; i
<new_unused_functions
.size(); i
++)
1974 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (new_unused_functions
[i
]->name
);
1975 assert (where
!= s
.functions
.end());
1976 s
.functions
.erase (where
);
1977 if (s
.tapset_compile_coverage
)
1978 s
.unused_functions
.push_back (new_unused_functions
[i
]);
1983 // ------------------------------------------------------------------------
1985 // Do away with local & global variables that are never
1986 // written nor read.
1987 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
1989 varuse_collecting_visitor
vut(s
);
1991 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1993 s
.probes
[i
]->body
->visit (& vut
);
1995 if (s
.probes
[i
]->sole_location()->condition
)
1996 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1999 // NB: Since varuse_collecting_visitor also traverses down
2000 // actually called functions, we don't need to explicitly
2001 // iterate over them. Uncalled ones should have been pruned
2004 // for (unsigned i=0; i<s.functions.size(); i++)
2005 // s.functions[i]->body->visit (& vut);
2007 // Now in vut.read/written, we have a mixture of all locals, globals
2009 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2010 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
2012 vardecl
* l
= s
.probes
[i
]->locals
[j
];
2014 if (vut
.read
.find (l
) == vut
.read
.end() &&
2015 vut
.written
.find (l
) == vut
.written
.end())
2017 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2018 ! s
.suppress_warnings
)
2019 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2020 else if (s
.verbose
>2)
2021 clog
<< "Eliding unused local variable "
2022 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
2023 if (s
.tapset_compile_coverage
) {
2024 s
.probes
[i
]->unused_locals
.push_back
2025 (s
.probes
[i
]->locals
[j
]);
2027 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
2029 // don't increment j
2033 if (vut
.written
.find (l
) == vut
.written
.end())
2034 if (iterations
== 0 && ! s
.suppress_warnings
)
2037 vector
<vardecl
*>::iterator it
;
2038 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
2039 if (l
->name
!= (*it
)->name
)
2040 o
<< " " << (*it
)->name
;
2041 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2042 if (l
->name
!= (*it
)->name
)
2043 o
<< " " << (*it
)->name
;
2045 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
2046 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2052 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2054 functiondecl
*fd
= it
->second
;
2055 for (unsigned j
=0; j
<fd
->locals
.size(); /* see below */)
2057 vardecl
* l
= fd
->locals
[j
];
2058 if (vut
.read
.find (l
) == vut
.read
.end() &&
2059 vut
.written
.find (l
) == vut
.written
.end())
2061 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2062 ! s
.suppress_warnings
)
2063 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2064 else if (s
.verbose
>2)
2065 clog
<< "Eliding unused local variable "
2066 << l
->name
<< " in function " << fd
->name
2068 if (s
.tapset_compile_coverage
) {
2069 fd
->unused_locals
.push_back (fd
->locals
[j
]);
2071 fd
->locals
.erase(fd
->locals
.begin() + j
);
2073 // don't increment j
2077 if (vut
.written
.find (l
) == vut
.written
.end())
2078 if (iterations
== 0 && ! s
.suppress_warnings
)
2081 vector
<vardecl
*>::iterator it
;
2082 for (it
= fd
->formal_args
.begin() ;
2083 it
!= fd
->formal_args
.end(); it
++)
2084 if (l
->name
!= (*it
)->name
)
2085 o
<< " " << (*it
)->name
;
2086 for (it
= fd
->locals
.begin(); it
!= fd
->locals
.end(); it
++)
2087 if (l
->name
!= (*it
)->name
)
2088 o
<< " " << (*it
)->name
;
2089 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2090 if (l
->name
!= (*it
)->name
)
2091 o
<< " " << (*it
)->name
;
2093 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
2094 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2101 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
2103 vardecl
* l
= s
.globals
[i
];
2104 if (vut
.read
.find (l
) == vut
.read
.end() &&
2105 vut
.written
.find (l
) == vut
.written
.end())
2107 if (l
->tok
->location
.file
->name
== s
.user_file
->name
&& // !tapset
2108 ! s
.suppress_warnings
)
2109 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
2110 else if (s
.verbose
>2)
2111 clog
<< "Eliding unused global variable "
2113 if (s
.tapset_compile_coverage
) {
2114 s
.unused_globals
.push_back(s
.globals
[i
]);
2116 s
.globals
.erase(s
.globals
.begin() + i
);
2118 // don't increment i
2122 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
2123 if (iterations
== 0 && ! s
.suppress_warnings
)
2126 vector
<vardecl
*>::iterator it
;
2127 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
2128 if (l
->name
!= (*it
)->name
)
2129 o
<< " " << (*it
)->name
;
2131 s
.print_warning ("read-only global variable '" + l
->name
+ "' " +
2132 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
2141 // ------------------------------------------------------------------------
2143 struct dead_assignment_remover
: public update_visitor
2145 systemtap_session
& session
;
2147 const varuse_collecting_visitor
& vut
;
2149 dead_assignment_remover(systemtap_session
& s
, bool& r
,
2150 const varuse_collecting_visitor
& v
):
2151 session(s
), relaxed_p(r
), vut(v
) {}
2153 void visit_assignment (assignment
* e
);
2158 dead_assignment_remover::visit_assignment (assignment
* e
)
2163 symbol
* left
= get_symbol_within_expression (e
->left
);
2164 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2165 if (leftvar
) // not unresolved $target, so intended sideeffect may be elided
2167 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2169 // NB: Not so fast! The left side could be an array whose
2170 // index expressions may have side-effects. This would be
2171 // OK if we could replace the array assignment with a
2172 // statement-expression containing all the index expressions
2173 // and the rvalue... but we can't.
2174 // Another possibility is that we have an unread global variable
2175 // which are kept for probe end value display.
2177 bool is_global
= false;
2178 vector
<vardecl
*>::iterator it
;
2179 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2180 if (leftvar
->name
== (*it
)->name
)
2186 varuse_collecting_visitor
lvut(session
);
2187 e
->left
->visit (& lvut
);
2188 if (lvut
.side_effect_free () && !is_global
) // XXX: use _wrt() once we track focal_vars
2190 /* PR 1119: NB: This is not necessary here. A write-only
2191 variable will also be elided soon at the next _opt2 iteration.
2192 if (e->left->tok->location.file == session.user_file->name && // !tapset
2193 ! session.suppress_warnings)
2194 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
2197 if (session
.verbose
>2)
2198 clog
<< "Eliding assignment to " << leftvar
->name
2199 << " at " << *e
->tok
<< endl
;
2201 provide (e
->right
); // goodbye assignment*
2210 // Let's remove assignments to variables that are never read. We
2211 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2212 // be optimized away as an unused variable, and expr a candidate to be
2213 // removed as a side-effect-free statement expression. Wahoo!
2214 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2216 // Recompute the varuse data, which will probably match the opt2
2217 // copy of the computation, except for those totally unused
2218 // variables that opt2 removed.
2219 varuse_collecting_visitor
vut(s
);
2220 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2221 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2223 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2224 // This instance may be reused for multiple probe/function body trims.
2226 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2227 dar
.replace (s
.probes
[i
]->body
);
2228 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2229 it
!= s
.functions
.end(); it
++)
2230 dar
.replace (it
->second
->body
);
2231 // The rewrite operation is performed within the visitor.
2233 // XXX: we could also zap write-only globals here
2237 // ------------------------------------------------------------------------
2239 struct dead_stmtexpr_remover
: public update_visitor
2241 systemtap_session
& session
;
2243 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2245 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2246 session(s
), relaxed_p(r
) {}
2248 void visit_block (block
*s
);
2249 void visit_null_statement (null_statement
*s
);
2250 void visit_if_statement (if_statement
* s
);
2251 void visit_foreach_loop (foreach_loop
*s
);
2252 void visit_for_loop (for_loop
*s
);
2253 // XXX: and other places where stmt_expr's might be nested
2255 void visit_expr_statement (expr_statement
*s
);
2260 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2263 if (session
.verbose
>2)
2264 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
2271 dead_stmtexpr_remover::visit_block (block
*s
)
2273 vector
<statement
*> new_stmts
;
2274 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2276 statement
* new_stmt
= require (s
->statements
[i
], true);
2279 // flatten nested blocks into this one
2280 block
*b
= dynamic_cast<block
*>(new_stmt
);
2283 if (session
.verbose
>2)
2284 clog
<< "Flattening nested block " << *b
->tok
<< endl
;
2285 new_stmts
.insert(new_stmts
.end(),
2286 b
->statements
.begin(), b
->statements
.end());
2290 new_stmts
.push_back (new_stmt
);
2293 if (new_stmts
.size() == 0)
2295 if (session
.verbose
>2)
2296 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
2299 else if (new_stmts
.size() == 1)
2301 if (session
.verbose
>2)
2302 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
2303 provide (new_stmts
[0]);
2307 s
->statements
= new_stmts
;
2312 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2314 replace (s
->thenblock
, true);
2315 replace (s
->elseblock
, true);
2317 if (s
->thenblock
== 0)
2319 if (s
->elseblock
== 0)
2321 // We may be able to elide this statement, if the condition
2322 // expression is side-effect-free.
2323 varuse_collecting_visitor
vct(session
);
2324 s
->condition
->visit(& vct
);
2325 if (vct
.side_effect_free ())
2327 if (session
.verbose
>2)
2328 clog
<< "Eliding side-effect-free if statement "
2330 s
= 0; // yeah, baby
2334 // We can still turn it into a simple expr_statement though...
2335 if (session
.verbose
>2)
2336 clog
<< "Creating simple evaluation from if statement "
2338 expr_statement
*es
= new expr_statement
;
2339 es
->value
= s
->condition
;
2340 es
->tok
= es
->value
->tok
;
2347 // For an else without a then, we can invert the condition logic to
2348 // avoid having a null statement in the thenblock
2349 if (session
.verbose
>2)
2350 clog
<< "Inverting the condition of if statement "
2352 unary_expression
*ue
= new unary_expression
;
2353 ue
->operand
= s
->condition
;
2354 ue
->tok
= ue
->operand
->tok
;
2357 s
->thenblock
= s
->elseblock
;
2365 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2367 replace (s
->block
, true);
2371 if (session
.verbose
>2)
2372 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2373 s
= 0; // yeah, baby
2379 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2381 replace (s
->block
, true);
2385 // We may be able to elide this statement, if the condition
2386 // expression is side-effect-free.
2387 varuse_collecting_visitor
vct(session
);
2388 if (s
->init
) s
->init
->visit(& vct
);
2389 s
->cond
->visit(& vct
);
2390 if (s
->incr
) s
->incr
->visit(& vct
);
2391 if (vct
.side_effect_free ())
2393 if (session
.verbose
>2)
2394 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2395 s
= 0; // yeah, baby
2399 // Can't elide this whole statement; put a null in there.
2400 s
->block
= new null_statement();
2401 s
->block
->tok
= s
->tok
;
2410 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2412 // Run a varuse query against the operand expression. If it has no
2413 // side-effects, replace the entire statement expression by a null
2414 // statement with the provide() call.
2416 // Unlike many other visitors, we do *not* traverse this outermost
2417 // one into the expression subtrees. There is no need - no
2418 // expr_statement nodes will be found there. (Function bodies
2419 // need to be visited explicitly by our caller.)
2421 // NB. While we don't share nodes in the parse tree, let's not
2422 // deallocate *s anyway, just in case...
2424 varuse_collecting_visitor
vut(session
);
2425 s
->value
->visit (& vut
);
2427 if (vut
.side_effect_free_wrt (focal_vars
))
2429 /* PR 1119: NB: this message is not a good idea here. It can
2430 name some arbitrary RHS expression of an assignment.
2431 if (s->value->tok->location.file == session.user_file->name && // not tapset
2432 ! session.suppress_warnings)
2433 clog << "WARNING: eliding read-only " << *s->value->tok << endl;
2436 if (session
.verbose
>2)
2437 clog
<< "Eliding side-effect-free expression "
2440 // NB: this 0 pointer is invalid to leave around for any length of
2441 // time, but the parent parse tree objects above handle it.
2449 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2451 // Finally, let's remove some statement-expressions that have no
2452 // side-effect. These should be exactly those whose private varuse
2453 // visitors come back with an empty "written" and "embedded" lists.
2455 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2456 // This instance may be reused for multiple probe/function body trims.
2458 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2460 if (pending_interrupts
) break;
2462 derived_probe
* p
= s
.probes
[i
];
2464 duv
.focal_vars
.clear ();
2465 duv
.focal_vars
.insert (s
.globals
.begin(),
2467 duv
.focal_vars
.insert (p
->locals
.begin(),
2470 duv
.replace (p
->body
, true);
2473 if (! s
.suppress_warnings
2474 && ! s
.timing
) // PR10070
2475 s
.print_warning ("side-effect-free probe '" + p
->name
+ "'", p
->tok
);
2477 p
->body
= new null_statement();
2478 p
->body
->tok
= p
->tok
;
2480 // XXX: possible duplicate warnings; see below
2483 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2485 if (pending_interrupts
) break;
2487 functiondecl
* fn
= it
->second
;
2488 duv
.focal_vars
.clear ();
2489 duv
.focal_vars
.insert (fn
->locals
.begin(),
2491 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2492 fn
->formal_args
.end());
2493 duv
.focal_vars
.insert (s
.globals
.begin(),
2496 duv
.replace (fn
->body
, true);
2499 if (! s
.suppress_warnings
)
2500 s
.print_warning ("side-effect-free function '" + fn
->name
+ "'", fn
->tok
);
2502 fn
->body
= new null_statement();
2503 fn
->body
->tok
= fn
->tok
;
2505 // XXX: the next iteration of the outer optimization loop may
2506 // take this new null_statement away again, and thus give us a
2507 // fresh warning. It would be better if this fixup was performed
2508 // only after the relaxation iterations.
2509 // XXX: or else see bug #6469.
2515 // ------------------------------------------------------------------------
2517 // The goal of this visitor is to reduce top-level expressions in void context
2518 // into separate statements that evaluate each subcomponent of the expression.
2519 // The dead-statement-remover can later remove some parts if they have no side
2522 // All expressions must be overridden here so we never visit their subexpressions
2523 // accidentally. Thus, the only visited expressions should be value of an
2526 // For an expression to replace its expr_statement with something else, it will
2527 // let the new statement provide(), and then provide(0) for itself. The
2528 // expr_statement will take this as a sign that it's been replaced.
2529 struct void_statement_reducer
: public update_visitor
2531 systemtap_session
& session
;
2533 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2535 void_statement_reducer(systemtap_session
& s
, bool& r
):
2536 session(s
), relaxed_p(r
) {}
2538 void visit_expr_statement (expr_statement
* s
);
2540 // expressions in conditional / loop controls are definitely a side effect,
2541 // but still recurse into the child statements
2542 void visit_if_statement (if_statement
* s
);
2543 void visit_for_loop (for_loop
* s
);
2544 void visit_foreach_loop (foreach_loop
* s
);
2546 // these expressions get rewritten into their statement equivalents
2547 void visit_logical_or_expr (logical_or_expr
* e
);
2548 void visit_logical_and_expr (logical_and_expr
* e
);
2549 void visit_ternary_expression (ternary_expression
* e
);
2551 // all of these can be reduced into simpler statements
2552 void visit_binary_expression (binary_expression
* e
);
2553 void visit_unary_expression (unary_expression
* e
);
2554 void visit_comparison (comparison
* e
);
2555 void visit_concatenation (concatenation
* e
);
2556 void visit_functioncall (functioncall
* e
);
2557 void visit_print_format (print_format
* e
);
2558 void visit_target_symbol (target_symbol
* e
);
2559 void visit_cast_op (cast_op
* e
);
2561 // these are a bit hairy to grok due to the intricacies of indexables and
2562 // stats, so I'm chickening out and skipping them...
2563 void visit_array_in (array_in
* e
) { provide (e
); }
2564 void visit_arrayindex (arrayindex
* e
) { provide (e
); }
2565 void visit_stat_op (stat_op
* e
) { provide (e
); }
2566 void visit_hist_op (hist_op
* e
) { provide (e
); }
2568 // these can't be reduced because they always have an effect
2569 void visit_return_statement (return_statement
* s
) { provide (s
); }
2570 void visit_delete_statement (delete_statement
* s
) { provide (s
); }
2571 void visit_pre_crement (pre_crement
* e
) { provide (e
); }
2572 void visit_post_crement (post_crement
* e
) { provide (e
); }
2573 void visit_assignment (assignment
* e
) { provide (e
); }
2578 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2580 replace (s
->value
, true);
2582 // if the expression provides 0, that's our signal that a new
2583 // statement has been provided, so we shouldn't provide this one.
2589 void_statement_reducer::visit_if_statement (if_statement
* s
)
2591 // s->condition is never void
2592 replace (s
->thenblock
);
2593 replace (s
->elseblock
);
2598 void_statement_reducer::visit_for_loop (for_loop
* s
)
2600 // s->init/cond/incr are never void
2606 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
2608 // s->indexes/base/limit are never void
2614 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
2616 // In void context, the evaluation of "a || b" is exactly like
2617 // "if (!a) b", so let's do that instead.
2619 if (session
.verbose
>2)
2620 clog
<< "Creating if statement from unused logical-or "
2623 if_statement
*is
= new if_statement
;
2627 unary_expression
*ue
= new unary_expression
;
2628 ue
->operand
= e
->left
;
2633 expr_statement
*es
= new expr_statement
;
2634 es
->value
= e
->right
;
2635 es
->tok
= es
->value
->tok
;
2645 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
2647 // In void context, the evaluation of "a && b" is exactly like
2648 // "if (a) b", so let's do that instead.
2650 if (session
.verbose
>2)
2651 clog
<< "Creating if statement from unused logical-and "
2654 if_statement
*is
= new if_statement
;
2657 is
->condition
= e
->left
;
2659 expr_statement
*es
= new expr_statement
;
2660 es
->value
= e
->right
;
2661 es
->tok
= es
->value
->tok
;
2671 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
2673 // In void context, the evaluation of "a ? b : c" is exactly like
2674 // "if (a) b else c", so let's do that instead.
2676 if (session
.verbose
>2)
2677 clog
<< "Creating if statement from unused ternary expression "
2680 if_statement
*is
= new if_statement
;
2682 is
->condition
= e
->cond
;
2684 expr_statement
*es
= new expr_statement
;
2685 es
->value
= e
->truevalue
;
2686 es
->tok
= es
->value
->tok
;
2689 es
= new expr_statement
;
2690 es
->value
= e
->falsevalue
;
2691 es
->tok
= es
->value
->tok
;
2701 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
2703 // When the result of a binary operation isn't needed, it's just as good to
2704 // evaluate the operands as sequential statements in a block.
2706 if (session
.verbose
>2)
2707 clog
<< "Eliding unused binary " << *e
->tok
<< endl
;
2709 block
*b
= new block
;
2712 expr_statement
*es
= new expr_statement
;
2713 es
->value
= e
->left
;
2714 es
->tok
= es
->value
->tok
;
2715 b
->statements
.push_back(es
);
2717 es
= new expr_statement
;
2718 es
->value
= e
->right
;
2719 es
->tok
= es
->value
->tok
;
2720 b
->statements
.push_back(es
);
2729 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
2731 // When the result of a unary operation isn't needed, it's just as good to
2732 // evaluate the operand directly
2734 if (session
.verbose
>2)
2735 clog
<< "Eliding unused unary " << *e
->tok
<< endl
;
2738 e
->operand
->visit(this);
2742 void_statement_reducer::visit_comparison (comparison
* e
)
2744 visit_binary_expression(e
);
2748 void_statement_reducer::visit_concatenation (concatenation
* e
)
2750 visit_binary_expression(e
);
2754 void_statement_reducer::visit_functioncall (functioncall
* e
)
2756 // If a function call is pure and its result ignored, we can elide the call
2757 // and just evaluate the arguments in sequence
2759 if (!e
->args
.size())
2765 varuse_collecting_visitor
vut(session
);
2766 vut
.traversed
.insert (e
->referent
);
2767 vut
.current_function
= e
->referent
;
2768 e
->referent
->body
->visit (& vut
);
2769 if (!vut
.side_effect_free_wrt (focal_vars
))
2775 if (session
.verbose
>2)
2776 clog
<< "Eliding side-effect-free function call " << *e
->tok
<< endl
;
2778 block
*b
= new block
;
2781 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2783 expr_statement
*es
= new expr_statement
;
2784 es
->value
= e
->args
[i
];
2785 es
->tok
= es
->value
->tok
;
2786 b
->statements
.push_back(es
);
2796 void_statement_reducer::visit_print_format (print_format
* e
)
2798 // When an sprint's return value is ignored, we can simply evaluate the
2799 // arguments in sequence
2801 if (e
->print_to_stream
|| !e
->args
.size())
2807 if (session
.verbose
>2)
2808 clog
<< "Eliding unused print " << *e
->tok
<< endl
;
2810 block
*b
= new block
;
2813 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2815 expr_statement
*es
= new expr_statement
;
2816 es
->value
= e
->args
[i
];
2817 es
->tok
= es
->value
->tok
;
2818 b
->statements
.push_back(es
);
2828 void_statement_reducer::visit_target_symbol (target_symbol
* e
)
2830 // When target_symbol isn't needed, it's just as good to
2831 // evaluate any array indexes directly
2833 block
*b
= new block
;
2836 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2838 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2841 expr_statement
*es
= new expr_statement
;
2842 es
->value
= e
->components
[i
].expr_index
;
2843 es
->tok
= es
->value
->tok
;
2844 b
->statements
.push_back(es
);
2847 if (b
->statements
.empty())
2854 if (session
.verbose
>2)
2855 clog
<< "Eliding unused target symbol " << *e
->tok
<< endl
;
2864 void_statement_reducer::visit_cast_op (cast_op
* e
)
2866 // When the result of a cast operation isn't needed, it's just as good to
2867 // evaluate the operand and any array indexes directly
2869 block
*b
= new block
;
2872 expr_statement
*es
= new expr_statement
;
2873 es
->value
= e
->operand
;
2874 es
->tok
= es
->value
->tok
;
2875 b
->statements
.push_back(es
);
2877 for (unsigned i
=0; i
<e
->components
.size(); i
++ )
2879 if (e
->components
[i
].type
!= target_symbol::comp_expression_array_index
)
2882 es
= new expr_statement
;
2883 es
->value
= e
->components
[i
].expr_index
;
2884 es
->tok
= es
->value
->tok
;
2885 b
->statements
.push_back(es
);
2888 if (session
.verbose
>2)
2889 clog
<< "Eliding unused typecast " << *e
->tok
<< endl
;
2898 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2900 // Let's simplify statements with unused computed values.
2902 void_statement_reducer
vuv (s
, relaxed_p
);
2903 // This instance may be reused for multiple probe/function body trims.
2905 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
2907 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2908 vuv
.replace (s
.probes
[i
]->body
);
2909 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin();
2910 it
!= s
.functions
.end(); it
++)
2911 vuv
.replace (it
->second
->body
);
2915 struct duplicate_function_remover
: public functioncall_traversing_visitor
2917 systemtap_session
& s
;
2918 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
2920 duplicate_function_remover(systemtap_session
& sess
,
2921 map
<functiondecl
*, functiondecl
*>&dfm
):
2922 s(sess
), duplicate_function_map(dfm
) {};
2924 void visit_functioncall (functioncall
* e
);
2928 duplicate_function_remover::visit_functioncall (functioncall
*e
)
2930 functioncall_traversing_visitor::visit_functioncall (e
);
2932 // If the current function call reference points to a function that
2933 // is a duplicate, replace it.
2934 if (duplicate_function_map
.count(e
->referent
) != 0)
2937 clog
<< "Changing " << e
->referent
->name
2939 << duplicate_function_map
[e
->referent
]->name
2941 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
2942 e
->function
= duplicate_function_map
[e
->referent
]->name
;
2943 e
->referent
= duplicate_function_map
[e
->referent
];
2948 get_functionsig (functiondecl
* f
)
2952 // Get the "name:args body" of the function in s. We have to
2953 // include the args since the function 'x1(a, b)' is different than
2954 // the function 'x2(b, a)' even if the bodies of the two functions
2955 // are exactly the same.
2959 // printsig puts f->name + ':' on the front. Remove this
2960 // (otherwise, functions would never compare equal).
2961 string str
= s
.str().erase(0, f
->name
.size() + 1);
2963 // Return the function signature.
2967 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
2969 // Walk through all the functions, looking for duplicates.
2970 map
<string
, functiondecl
*> functionsig_map
;
2971 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
2974 vector
<functiondecl
*> newly_zapped_functions
;
2975 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2977 functiondecl
*fd
= it
->second
;
2978 string functionsig
= get_functionsig(fd
);
2980 if (functionsig_map
.count(functionsig
) == 0)
2982 // This function is unique. Remember it.
2983 functionsig_map
[functionsig
] = fd
;
2987 // This function is a duplicate.
2988 duplicate_function_map
[fd
] = functionsig_map
[functionsig
];
2989 newly_zapped_functions
.push_back (fd
);
2993 for (unsigned i
=0; i
<newly_zapped_functions
.size(); i
++)
2995 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (newly_zapped_functions
[i
]->name
);
2996 assert (where
!= s
.functions
.end());
2997 s
.functions
.erase (where
);
3001 // If we have duplicate functions, traverse down the tree, replacing
3002 // the appropriate function calls.
3003 // duplicate_function_remover::visit_functioncall() handles the
3004 // details of replacing the function calls.
3005 if (duplicate_function_map
.size() != 0)
3007 duplicate_function_remover
dfr (s
, duplicate_function_map
);
3009 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
3010 s
.probes
[i
]->body
->visit(&dfr
);
3016 semantic_pass_optimize1 (systemtap_session
& s
)
3018 // In this pass, we attempt to rewrite probe/function bodies to
3019 // eliminate some blatantly unnecessary code. This is run before
3020 // type inference, but after symbol resolution and derived_probe
3021 // creation. We run an outer "relaxation" loop that repeats the
3022 // optimizations until none of them find anything to remove.
3026 bool relaxed_p
= false;
3027 unsigned iterations
= 0;
3030 if (pending_interrupts
) break;
3032 relaxed_p
= true; // until proven otherwise
3034 semantic_pass_opt1 (s
, relaxed_p
);
3035 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
3036 semantic_pass_opt3 (s
, relaxed_p
);
3037 semantic_pass_opt4 (s
, relaxed_p
);
3038 semantic_pass_opt5 (s
, relaxed_p
);
3048 semantic_pass_optimize2 (systemtap_session
& s
)
3050 // This is run after type inference. We run an outer "relaxation"
3051 // loop that repeats the optimizations until none of them find
3052 // anything to remove.
3056 bool relaxed_p
= false;
3059 if (pending_interrupts
) break;
3060 relaxed_p
= true; // until proven otherwise
3062 semantic_pass_opt6 (s
, relaxed_p
);
3070 // ------------------------------------------------------------------------
3075 semantic_pass_types (systemtap_session
& s
)
3079 // next pass: type inference
3080 unsigned iterations
= 0;
3081 typeresolution_info
ti (s
);
3083 ti
.assert_resolvability
= false;
3084 // XXX: maybe convert to exception-based error signalling
3087 if (pending_interrupts
) break;
3090 ti
.num_newly_resolved
= 0;
3091 ti
.num_still_unresolved
= 0;
3093 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
3095 if (pending_interrupts
) break;
3097 functiondecl
* fd
= it
->second
;
3098 ti
.current_probe
= 0;
3099 ti
.current_function
= fd
;
3101 fd
->body
->visit (& ti
);
3102 // NB: we don't have to assert a known type for
3103 // functions here, to permit a "void" function.
3104 // The translator phase will omit the "retvalue".
3106 // if (fd->type == pe_unknown)
3107 // ti.unresolved (fd->tok);
3110 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
3112 if (pending_interrupts
) break;
3114 derived_probe
* pn
= s
.probes
[j
];
3115 ti
.current_function
= 0;
3116 ti
.current_probe
= pn
;
3118 pn
->body
->visit (& ti
);
3120 probe_point
* pp
= pn
->sole_location();
3123 ti
.current_function
= 0;
3124 ti
.current_probe
= 0;
3125 ti
.t
= pe_long
; // NB: expected type
3126 pp
->condition
->visit (& ti
);
3130 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
3132 vardecl
* gd
= s
.globals
[j
];
3133 if (gd
->type
== pe_unknown
)
3134 ti
.unresolved (gd
->tok
);
3137 if (ti
.num_newly_resolved
== 0) // converged
3139 if (ti
.num_still_unresolved
== 0)
3140 break; // successfully
3141 else if (! ti
.assert_resolvability
)
3142 ti
.assert_resolvability
= true; // last pass, with error msgs
3144 { // unsuccessful conclusion
3151 return rc
+ s
.num_errors();
3156 typeresolution_info::typeresolution_info (systemtap_session
& s
):
3157 session(s
), current_function(0), current_probe(0)
3163 typeresolution_info::visit_literal_number (literal_number
* e
)
3165 assert (e
->type
== pe_long
);
3166 if ((t
== e
->type
) || (t
== pe_unknown
))
3169 mismatch (e
->tok
, e
->type
, t
);
3174 typeresolution_info::visit_literal_string (literal_string
* e
)
3176 assert (e
->type
== pe_string
);
3177 if ((t
== e
->type
) || (t
== pe_unknown
))
3180 mismatch (e
->tok
, e
->type
, t
);
3185 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
3187 visit_binary_expression (e
);
3192 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
3194 visit_binary_expression (e
);
3199 typeresolution_info::visit_comparison (comparison
*e
)
3201 // NB: result of any comparison is an integer!
3202 if (t
== pe_stats
|| t
== pe_string
)
3203 invalid (e
->tok
, t
);
3205 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
3206 e
->left
->visit (this);
3207 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
3208 e
->right
->visit (this);
3210 if (e
->left
->type
!= pe_unknown
&&
3211 e
->right
->type
!= pe_unknown
&&
3212 e
->left
->type
!= e
->right
->type
)
3213 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3215 if (e
->type
== pe_unknown
)
3218 resolved (e
->tok
, e
->type
);
3224 typeresolution_info::visit_concatenation (concatenation
*e
)
3226 if (t
!= pe_unknown
&& t
!= pe_string
)
3227 invalid (e
->tok
, t
);
3230 e
->left
->visit (this);
3232 e
->right
->visit (this);
3234 if (e
->type
== pe_unknown
)
3236 e
->type
= pe_string
;
3237 resolved (e
->tok
, e
->type
);
3243 typeresolution_info::visit_assignment (assignment
*e
)
3246 invalid (e
->tok
, t
);
3248 if (e
->op
== "<<<") // stats aggregation
3251 invalid (e
->tok
, t
);
3254 e
->left
->visit (this);
3256 e
->right
->visit (this);
3257 if (e
->type
== pe_unknown
||
3258 e
->type
== pe_stats
)
3261 resolved (e
->tok
, e
->type
);
3265 else if (e
->left
->type
== pe_stats
)
3266 invalid (e
->left
->tok
, e
->left
->type
);
3268 else if (e
->right
->type
== pe_stats
)
3269 invalid (e
->right
->tok
, e
->right
->type
);
3271 else if (e
->op
== "+=" || // numeric only
3283 visit_binary_expression (e
);
3285 else if (e
->op
== ".=" || // string only
3288 if (t
== pe_long
|| t
== pe_stats
)
3289 invalid (e
->tok
, t
);
3292 e
->left
->visit (this);
3294 e
->right
->visit (this);
3295 if (e
->type
== pe_unknown
)
3297 e
->type
= pe_string
;
3298 resolved (e
->tok
, e
->type
);
3301 else if (e
->op
== "=") // overloaded = for string & numeric operands
3303 // logic similar to ternary_expression
3304 exp_type sub_type
= t
;
3306 // Infer types across the l/r values
3307 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3310 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3311 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
3313 e
->left
->visit (this);
3314 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3315 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
3317 e
->right
->visit (this);
3319 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3322 resolved (e
->tok
, e
->type
);
3324 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
3326 e
->type
= e
->left
->type
;
3327 resolved (e
->tok
, e
->type
);
3330 if (e
->left
->type
!= pe_unknown
&&
3331 e
->right
->type
!= pe_unknown
&&
3332 e
->left
->type
!= e
->right
->type
)
3333 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3337 throw semantic_error ("unsupported assignment operator " + e
->op
);
3342 typeresolution_info::visit_binary_expression (binary_expression
* e
)
3344 if (t
== pe_stats
|| t
== pe_string
)
3345 invalid (e
->tok
, t
);
3348 e
->left
->visit (this);
3350 e
->right
->visit (this);
3352 if (e
->left
->type
!= pe_unknown
&&
3353 e
->right
->type
!= pe_unknown
&&
3354 e
->left
->type
!= e
->right
->type
)
3355 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3357 if (e
->type
== pe_unknown
)
3360 resolved (e
->tok
, e
->type
);
3366 typeresolution_info::visit_pre_crement (pre_crement
*e
)
3368 visit_unary_expression (e
);
3373 typeresolution_info::visit_post_crement (post_crement
*e
)
3375 visit_unary_expression (e
);
3380 typeresolution_info::visit_unary_expression (unary_expression
* e
)
3382 if (t
== pe_stats
|| t
== pe_string
)
3383 invalid (e
->tok
, t
);
3386 e
->operand
->visit (this);
3388 if (e
->type
== pe_unknown
)
3391 resolved (e
->tok
, e
->type
);
3397 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
3399 exp_type sub_type
= t
;
3402 e
->cond
->visit (this);
3404 // Infer types across the true/false arms of the ternary expression.
3406 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3409 e
->truevalue
->visit (this);
3411 e
->falsevalue
->visit (this);
3413 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
3414 ; // already resolved
3415 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3418 resolved (e
->tok
, e
->type
);
3420 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
3422 e
->type
= e
->truevalue
->type
;
3423 resolved (e
->tok
, e
->type
);
3425 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
3427 e
->type
= e
->falsevalue
->type
;
3428 resolved (e
->tok
, e
->type
);
3430 else if (e
->type
!= sub_type
)
3431 mismatch (e
->tok
, sub_type
, e
->type
);
3435 template <class Referrer
, class Referent
>
3436 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
3437 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
3439 exp_type
& re_type
= referrer
->type
;
3440 const token
* re_tok
= referrer
->tok
;
3441 exp_type
& te_type
= referent
->type
;
3442 const token
* te_tok
= referent
->tok
;
3444 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
3445 ; // do nothing: all three e->types in agreement
3446 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
3447 ; // do nothing: two known e->types in agreement
3448 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
3449 r
->mismatch (re_tok
, re_type
, te_type
);
3450 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
3451 r
->mismatch (re_tok
, re_type
, t
);
3452 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
3453 r
->mismatch (te_tok
, te_type
, t
);
3454 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
3456 // propagate from upstream
3458 r
->resolved (re_tok
, re_type
);
3459 // catch re_type/te_type mismatch later
3461 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
3463 // propagate from referent
3465 r
->resolved (re_tok
, re_type
);
3466 // catch re_type/t mismatch later
3468 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
3470 // propagate to referent
3472 r
->resolved (te_tok
, te_type
);
3473 // catch re_type/t mismatch later
3475 else if (! accept_unknown
)
3476 r
->unresolved (re_tok
);
3481 typeresolution_info::visit_symbol (symbol
* e
)
3483 assert (e
->referent
!= 0);
3484 resolve_2types (e
, e
->referent
, this, t
);
3489 typeresolution_info::visit_target_symbol (target_symbol
* e
)
3491 if (!e
->probe_context_var
.empty())
3494 // This occurs only if a target symbol was not resolved over in
3495 // tapset.cxx land, that error was properly suppressed, and the
3496 // later unused-expression-elimination pass didn't get rid of it
3497 // either. So we have a target symbol that is believed to be of
3498 // genuine use, yet unresolved by the provider.
3500 if (session
.verbose
> 2)
3502 clog
<< "Resolution problem with ";
3503 if (current_function
)
3505 clog
<< "function " << current_function
->name
<< endl
;
3506 current_function
->body
->print (clog
);
3509 else if (current_probe
)
3511 clog
<< "probe " << current_probe
->name
<< endl
;
3512 current_probe
->body
->print (clog
);
3516 clog
<< "other" << endl
;
3519 if (e
->saved_conversion_error
)
3520 throw (* (e
->saved_conversion_error
));
3522 throw semantic_error("unresolved target-symbol expression", e
->tok
);
3527 typeresolution_info::visit_cast_op (cast_op
* e
)
3529 // Like target_symbol, a cast_op shouldn't survive this far
3530 // unless it was not resolved and its value is really needed.
3531 if (e
->saved_conversion_error
)
3532 throw (* (e
->saved_conversion_error
));
3534 throw semantic_error("type definition '" + e
->type
+ "' not found", e
->tok
);
3539 typeresolution_info::visit_arrayindex (arrayindex
* e
)
3542 symbol
*array
= NULL
;
3543 hist_op
*hist
= NULL
;
3544 classify_indexable(e
->base
, array
, hist
);
3546 // Every hist_op has type [int]:int, that is to say, every hist_op
3547 // is a pseudo-one-dimensional integer array type indexed by
3548 // integers (bucket numbers).
3552 if (e
->indexes
.size() != 1)
3553 unresolved (e
->tok
);
3555 e
->indexes
[0]->visit (this);
3556 if (e
->indexes
[0]->type
!= pe_long
)
3557 unresolved (e
->tok
);
3559 if (e
->type
!= pe_long
)
3562 resolved (e
->tok
, pe_long
);
3567 // Now we are left with "normal" map inference and index checking.
3570 assert (array
->referent
!= 0);
3571 resolve_2types (e
, array
->referent
, this, t
);
3573 // now resolve the array indexes
3575 // if (e->referent->index_types.size() == 0)
3576 // // redesignate referent as array
3577 // e->referent->set_arity (e->indexes.size ());
3579 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3580 unresolved (e
->tok
); // symbol resolution should prevent this
3581 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3583 expression
* ee
= e
->indexes
[i
];
3584 exp_type
& ft
= array
->referent
->index_types
[i
];
3587 exp_type at
= ee
->type
;
3589 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3591 // propagate to formal type
3593 resolved (array
->referent
->tok
, ft
);
3594 // uses array decl as there is no token for "formal type"
3597 invalid (ee
->tok
, at
);
3599 invalid (ee
->tok
, ft
);
3600 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3601 mismatch (e
->tok
, at
, ft
);
3602 if (at
== pe_unknown
)
3603 unresolved (ee
->tok
);
3609 typeresolution_info::visit_functioncall (functioncall
* e
)
3611 assert (e
->referent
!= 0);
3613 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
3615 if (e
->type
== pe_stats
)
3616 invalid (e
->tok
, e
->type
);
3618 // now resolve the function parameters
3619 if (e
->args
.size() != e
->referent
->formal_args
.size())
3620 unresolved (e
->tok
); // symbol resolution should prevent this
3621 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
3623 expression
* ee
= e
->args
[i
];
3624 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
3625 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
3628 exp_type at
= ee
->type
;
3630 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
3632 // propagate to formal arg
3634 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
3637 invalid (e
->tok
, at
);
3639 invalid (fe_tok
, ft
);
3640 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3641 mismatch (e
->tok
, at
, ft
);
3642 if (at
== pe_unknown
)
3643 unresolved (e
->tok
);
3649 typeresolution_info::visit_block (block
* e
)
3651 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
3656 e
->statements
[i
]->visit (this);
3658 catch (const semantic_error
& e
)
3660 session
.print_error (e
);
3667 typeresolution_info::visit_embeddedcode (embeddedcode
*)
3673 typeresolution_info::visit_if_statement (if_statement
* e
)
3676 e
->condition
->visit (this);
3679 e
->thenblock
->visit (this);
3684 e
->elseblock
->visit (this);
3690 typeresolution_info::visit_for_loop (for_loop
* e
)
3693 if (e
->init
) e
->init
->visit (this);
3695 e
->cond
->visit (this);
3697 if (e
->incr
) e
->incr
->visit (this);
3699 e
->block
->visit (this);
3704 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
3706 // See also visit_arrayindex.
3707 // This is different in that, being a statement, we can't assign
3708 // a type to the outer array, only propagate to/from the indexes
3710 // if (e->referent->index_types.size() == 0)
3711 // // redesignate referent as array
3712 // e->referent->set_arity (e->indexes.size ());
3714 symbol
*array
= NULL
;
3715 hist_op
*hist
= NULL
;
3716 classify_indexable(e
->base
, array
, hist
);
3720 if (e
->indexes
.size() != 1)
3721 unresolved (e
->tok
);
3723 e
->indexes
[0]->visit (this);
3724 if (e
->indexes
[0]->type
!= pe_long
)
3725 unresolved (e
->tok
);
3731 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3732 unresolved (e
->tok
); // symbol resolution should prevent this
3733 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3735 expression
* ee
= e
->indexes
[i
];
3736 exp_type
& ft
= array
->referent
->index_types
[i
];
3739 exp_type at
= ee
->type
;
3741 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3743 // propagate to formal type
3745 resolved (array
->referent
->tok
, ft
);
3746 // uses array decl as there is no token for "formal type"
3749 invalid (ee
->tok
, at
);
3751 invalid (ee
->tok
, ft
);
3752 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3753 mismatch (e
->tok
, at
, ft
);
3754 if (at
== pe_unknown
)
3755 unresolved (ee
->tok
);
3762 e
->limit
->visit (this);
3766 e
->block
->visit (this);
3771 typeresolution_info::visit_null_statement (null_statement
*)
3777 typeresolution_info::visit_expr_statement (expr_statement
* e
)
3780 e
->value
->visit (this);
3784 struct delete_statement_typeresolution_info
:
3785 public throwing_visitor
3787 typeresolution_info
*parent
;
3788 delete_statement_typeresolution_info (typeresolution_info
*p
):
3789 throwing_visitor ("invalid operand of delete expression"),
3793 void visit_arrayindex (arrayindex
* e
)
3795 parent
->visit_arrayindex (e
);
3798 void visit_symbol (symbol
* e
)
3800 exp_type ignored
= pe_unknown
;
3801 assert (e
->referent
!= 0);
3802 resolve_2types (e
, e
->referent
, parent
, ignored
);
3808 typeresolution_info::visit_delete_statement (delete_statement
* e
)
3810 delete_statement_typeresolution_info
di (this);
3812 e
->value
->visit (&di
);
3817 typeresolution_info::visit_next_statement (next_statement
*)
3823 typeresolution_info::visit_break_statement (break_statement
*)
3829 typeresolution_info::visit_continue_statement (continue_statement
*)
3835 typeresolution_info::visit_array_in (array_in
* e
)
3837 // all unary operators only work on numerics
3839 t
= pe_unknown
; // array value can be anything
3840 e
->operand
->visit (this);
3842 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
3843 ; // already resolved
3844 else if (t1
== pe_string
|| t1
== pe_stats
)
3845 mismatch (e
->tok
, t1
, pe_long
);
3846 else if (e
->type
== pe_unknown
)
3849 resolved (e
->tok
, e
->type
);
3855 typeresolution_info::visit_return_statement (return_statement
* e
)
3857 // This is like symbol, where the referent is
3858 // the return value of the function.
3860 // translation pass will print error
3861 if (current_function
== 0)
3864 exp_type
& e_type
= current_function
->type
;
3865 t
= current_function
->type
;
3866 e
->value
->visit (this);
3868 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
3869 && e_type
!= e
->value
->type
)
3870 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
3871 if (e_type
== pe_unknown
&&
3872 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
3874 // propagate non-statistics from value
3875 e_type
= e
->value
->type
;
3876 resolved (current_function
->tok
, e
->value
->type
);
3878 if (e
->value
->type
== pe_stats
)
3879 invalid (e
->value
->tok
, e
->value
->type
);
3883 typeresolution_info::visit_print_format (print_format
* e
)
3885 size_t unresolved_args
= 0;
3889 e
->hist
->visit(this);
3892 else if (e
->print_with_format
)
3894 // If there's a format string, we can do both inference *and*
3897 // First we extract the subsequence of formatting components
3898 // which are conversions (not just literal string components)
3900 unsigned expected_num_args
= 0;
3901 std::vector
<print_format::format_component
> components
;
3902 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
3904 if (e
->components
[i
].type
== print_format::conv_unspecified
)
3905 throw semantic_error ("Unspecified conversion in print operator format string",
3907 else if (e
->components
[i
].type
== print_format::conv_literal
)
3909 components
.push_back(e
->components
[i
]);
3910 ++expected_num_args
;
3911 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
3912 ++expected_num_args
;
3913 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
3914 ++expected_num_args
;
3917 // Then we check that the number of conversions and the number
3920 if (expected_num_args
!= e
->args
.size())
3921 throw semantic_error ("Wrong number of args to formatted print operator",
3924 // Then we check that the types of the conversions match the types
3927 for (size_t i
= 0; i
< components
.size(); ++i
)
3929 // Check the dynamic width, if specified
3930 if (components
[i
].widthtype
== print_format::width_dynamic
)
3932 check_arg_type (pe_long
, e
->args
[argno
]);
3936 // Check the dynamic precision, if specified
3937 if (components
[i
].prectype
== print_format::prec_dynamic
)
3939 check_arg_type (pe_long
, e
->args
[argno
]);
3943 exp_type wanted
= pe_unknown
;
3945 switch (components
[i
].type
)
3947 case print_format::conv_unspecified
:
3948 case print_format::conv_literal
:
3952 case print_format::conv_signed_decimal
:
3953 case print_format::conv_unsigned_decimal
:
3954 case print_format::conv_unsigned_octal
:
3955 case print_format::conv_unsigned_ptr
:
3956 case print_format::conv_unsigned_uppercase_hex
:
3957 case print_format::conv_unsigned_lowercase_hex
:
3958 case print_format::conv_binary
:
3959 case print_format::conv_char
:
3960 case print_format::conv_memory
:
3961 case print_format::conv_memory_hex
:
3965 case print_format::conv_string
:
3970 assert (wanted
!= pe_unknown
);
3971 check_arg_type (wanted
, e
->args
[argno
]);
3977 // Without a format string, the best we can do is require that
3978 // each argument resolve to a concrete type.
3979 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
3982 e
->args
[i
]->visit (this);
3983 if (e
->args
[i
]->type
== pe_unknown
)
3985 unresolved (e
->args
[i
]->tok
);
3991 if (unresolved_args
== 0)
3993 if (e
->type
== pe_unknown
)
3995 if (e
->print_to_stream
)
3998 e
->type
= pe_string
;
3999 resolved (e
->tok
, e
->type
);
4004 e
->type
= pe_unknown
;
4005 unresolved (e
->tok
);
4011 typeresolution_info::visit_stat_op (stat_op
* e
)
4014 e
->stat
->visit (this);
4015 if (e
->type
== pe_unknown
)
4018 resolved (e
->tok
, e
->type
);
4020 else if (e
->type
!= pe_long
)
4021 mismatch (e
->tok
, e
->type
, pe_long
);
4025 typeresolution_info::visit_hist_op (hist_op
* e
)
4028 e
->stat
->visit (this);
4033 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
4038 if (arg
->type
== pe_unknown
)
4041 resolved (arg
->tok
, wanted
);
4043 else if (arg
->type
!= wanted
)
4045 mismatch (arg
->tok
, arg
->type
, wanted
);
4051 typeresolution_info::unresolved (const token
* tok
)
4053 num_still_unresolved
++;
4055 if (assert_resolvability
)
4058 string nm
= (current_function
? current_function
->name
:
4059 current_probe
? current_probe
->name
:
4061 msg
<< nm
+ " with unresolved type";
4062 session
.print_error (semantic_error (msg
.str(), tok
));
4068 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
4070 num_still_unresolved
++;
4072 if (assert_resolvability
)
4075 string nm
= (current_function
? current_function
->name
:
4076 current_probe
? current_probe
->name
:
4078 if (tok
&& tok
->type
== tok_operator
)
4079 msg
<< nm
+ " uses invalid operator";
4081 msg
<< nm
+ " with invalid type " << pe
;
4082 session
.print_error (semantic_error (msg
.str(), tok
));
4088 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
4090 bool tok_resolved
= false;
4092 semantic_error
* err1
= 0;
4093 num_still_unresolved
++;
4095 //BZ 9719: for improving type mismatch messages, a semantic error is
4096 //generated with the token where type was first resolved. All such
4097 //resolved tokens, stored in a vector, are matched against their
4098 //content. If an error for the matching token hasn't been printed out
4099 //already, it is and the token pushed in another printed_toks vector
4101 if (assert_resolvability
)
4104 for (i
=0; i
<resolved_toks
.size(); i
++)
4106 if (resolved_toks
[i
]->content
== tok
->content
)
4108 tok_resolved
= true;
4114 string nm
= (current_function
? current_function
->name
:
4115 current_probe
? current_probe
->name
:
4117 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
4121 bool tok_printed
= false;
4122 for (size_t j
=0; j
<printed_toks
.size(); j
++)
4124 if (printed_toks
[j
] == resolved_toks
[i
])
4130 string nm
= (current_function
? current_function
->name
:
4131 current_probe
? current_probe
->name
:
4133 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
4136 //error for possible mismatch in the earlier resolved token
4137 printed_toks
.push_back (resolved_toks
[i
]);
4138 stringstream type_msg
;
4139 type_msg
<< nm
+ " type first inferred here (" << t2
<< ")";
4140 err1
= new semantic_error (type_msg
.str(), resolved_toks
[i
]);
4143 semantic_error
err (msg
.str(), tok
);
4145 session
.print_error (err
);
4151 typeresolution_info::resolved (const token
* tok
, exp_type
)
4153 resolved_toks
.push_back (tok
);
4154 num_newly_resolved
++;
4157 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */