1 // elaboration functions
2 // Copyright (C) 2005-2008 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()
268 match_node::bind(match_key
const & k
)
271 throw semantic_error("invalid use of wildcard probe point component");
273 map
<match_key
, match_node
*>::const_iterator i
= sub
.find(k
);
276 match_node
* n
= new match_node();
277 sub
.insert(make_pair(k
, n
));
282 match_node::bind(derived_probe_builder
* e
)
285 throw semantic_error("duplicate probe point pattern");
290 match_node::bind(string
const & k
)
292 return bind(match_key(k
));
296 match_node::bind_str(string
const & k
)
298 return bind(match_key(k
).with_string());
302 match_node::bind_num(string
const & k
)
304 return bind(match_key(k
).with_number());
309 match_node::find_and_build (systemtap_session
& s
,
310 probe
* p
, probe_point
*loc
, unsigned pos
,
311 vector
<derived_probe
*>& results
)
313 assert (pos
<= loc
->components
.size());
314 if (pos
== loc
->components
.size()) // matched all probe point components so far
316 derived_probe_builder
*b
= end
; // may be 0 if only nested names are bound
321 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
322 alternatives
+= string(" ") + i
->first
.str();
324 throw semantic_error (string("probe point truncated at position ") +
325 lex_cast
<string
> (pos
) +
326 " (follow:" + alternatives
+ ")", loc
->tok
);
329 map
<string
, literal
*> param_map
;
330 for (unsigned i
=0; i
<pos
; i
++)
331 param_map
[loc
->components
[i
]->functor
] = loc
->components
[i
]->arg
;
334 b
->build (s
, p
, loc
, param_map
, results
);
336 else if (isglob(loc
->components
[pos
]->functor
)) // wildcard?
338 match_key
match (* loc
->components
[pos
]);
340 // Call find_and_build for each possible match. Ignore errors -
341 // unless we don't find any match.
342 unsigned int num_results
= results
.size();
343 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
345 const match_key
& subkey
= i
->first
;
346 match_node
* subnode
= i
->second
;
348 if (pending_interrupts
) break;
350 if (match
.globmatch(subkey
))
353 clog
<< "wildcard '" << loc
->components
[pos
]->functor
354 << "' matched '" << subkey
.name
<< "'" << endl
;
356 // When we have a wildcard, we need to create a copy of
357 // the probe point. Then we'll create a copy of the
358 // wildcard component, and substitute the non-wildcard
360 probe_point
*non_wildcard_pp
= new probe_point(*loc
);
361 probe_point::component
*non_wildcard_component
362 = new probe_point::component(*loc
->components
[pos
]);
363 non_wildcard_component
->functor
= subkey
.name
;
364 non_wildcard_pp
->components
[pos
] = non_wildcard_component
;
366 // NB: probe conditions are not attached at the wildcard
367 // (component/functor) level, but at the overall
368 // probe_point level.
370 // recurse (with the non-wildcard probe point)
373 subnode
->find_and_build (s
, p
, non_wildcard_pp
, pos
+1,
376 catch (const semantic_error
& e
)
378 // Ignore semantic_errors while expanding wildcards.
379 // If we get done and nothing was expanded, the code
380 // following the loop will complain.
382 // If this wildcard didn't match, cleanup.
383 delete non_wildcard_pp
;
384 delete non_wildcard_component
;
388 if (! loc
->optional
&& num_results
== results
.size())
390 // We didn't find any wildcard matches (since the size of
391 // the result vector didn't change). Throw an error.
393 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
394 alternatives
+= string(" ") + i
->first
.str();
396 throw semantic_error(string("probe point mismatch at position ") +
397 lex_cast
<string
> (pos
) +
398 " (alternatives:" + alternatives
+ ")",
404 match_key
match (* loc
->components
[pos
]);
405 sub_map_iterator_t i
= sub
.find (match
);
406 if (i
== sub
.end()) // no match
409 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
410 alternatives
+= string(" ") + i
->first
.str();
412 throw semantic_error (string("probe point mismatch at position ") +
413 lex_cast
<string
> (pos
) +
414 " (alternatives:" + alternatives
+ ")",
418 match_node
* subnode
= i
->second
;
420 subnode
->find_and_build (s
, p
, loc
, pos
+1, results
);
426 match_node::build_no_more (systemtap_session
& s
)
428 for (sub_map_iterator_t i
= sub
.begin(); i
!= sub
.end(); i
++)
429 i
->second
->build_no_more (s
);
430 if (end
) end
->build_no_more (s
);
434 // ------------------------------------------------------------------------
436 // ------------------------------------------------------------------------
438 struct alias_derived_probe
: public derived_probe
440 alias_derived_probe (probe
* base
, probe_point
*l
, const probe_alias
*a
):
441 derived_probe (base
, l
), alias(a
) {}
443 void upchuck () { throw semantic_error ("inappropriate", this->tok
); }
445 // Alias probes are immediately expanded to other derived_probe
446 // types, and are not themselves emitted or listed in
447 // systemtap_session.probes
449 void join_group (systemtap_session
&) { upchuck (); }
451 virtual const probe_alias
*get_alias () const { return alias
; }
454 const probe_alias
*alias
; // Used to check for recursion
459 alias_expansion_builder
460 : public derived_probe_builder
464 alias_expansion_builder(probe_alias
* a
)
468 virtual void build(systemtap_session
& sess
,
470 probe_point
* location
,
471 std::map
<std::string
, literal
*> const &,
472 vector
<derived_probe
*> & finished_results
)
474 // Don't build the alias expansion if infinite recursion is detected.
475 if (checkForRecursiveExpansion (use
)) {
477 msg
<< "Recursive loop in alias expansion of " << *location
<< " at " << location
->tok
->location
;
478 // semantic_errors thrown here are ignored.
479 sess
.print_error (semantic_error (msg
.str()));
483 // We're going to build a new probe and wrap it up in an
484 // alias_expansion_probe so that the expansion loop recognizes it as
485 // such and re-expands its expansion.
487 alias_derived_probe
* n
= new alias_derived_probe (use
, location
/* soon overwritten */, this->alias
);
488 n
->body
= new block();
490 // The new probe gets the location list of the alias (with incoming condition joined)
491 n
->locations
= alias
->locations
;
492 for (unsigned i
=0; i
<n
->locations
.size(); i
++)
493 n
->locations
[i
]->condition
= add_condition (n
->locations
[i
]->condition
,
494 location
->condition
);
496 // the token location of the alias,
497 n
->tok
= location
->tok
;
499 // and statements representing the concatenation of the alias'
500 // body with the use's.
502 // NB: locals are *not* copied forward, from either alias or
503 // use. The expansion should have its locals re-inferred since
504 // there's concatenated code here and we only want one vardecl per
505 // resulting variable.
507 if (alias
->epilogue_style
)
508 n
->body
= new block (use
->body
, alias
->body
);
510 n
->body
= new block (alias
->body
, use
->body
);
512 derive_probes (sess
, n
, finished_results
, location
->optional
);
515 bool checkForRecursiveExpansion (probe
*use
)
517 // Collect the derivation chain of this probe.
518 vector
<probe
*>derivations
;
519 use
->collect_derivation_chain (derivations
);
521 // Check all probe points in the alias expansion against the currently-being-expanded probe point
522 // of each of the probes in the derivation chain, looking for a match. This
523 // indicates infinite recursion.
524 // The first element of the derivation chain will be the derived_probe representing 'use', so
525 // start the search with the second element.
526 assert (derivations
.size() > 0);
527 assert (derivations
[0] == use
);
528 for (unsigned d
= 1; d
< derivations
.size(); ++d
) {
529 if (use
->get_alias() == derivations
[d
]->get_alias())
530 return true; // recursion detected
537 // ------------------------------------------------------------------------
539 // ------------------------------------------------------------------------
542 // Register all the aliases we've seen in library files, and the user
543 // file, as patterns.
546 systemtap_session::register_library_aliases()
548 vector
<stapfile
*> files(library_files
);
549 files
.push_back(user_file
);
551 for (unsigned f
= 0; f
< files
.size(); ++f
)
553 stapfile
* file
= files
[f
];
554 for (unsigned a
= 0; a
< file
->aliases
.size(); ++a
)
556 probe_alias
* alias
= file
->aliases
[a
];
559 for (unsigned n
= 0; n
< alias
->alias_names
.size(); ++n
)
561 probe_point
* name
= alias
->alias_names
[n
];
562 match_node
* n
= pattern_root
;
563 for (unsigned c
= 0; c
< name
->components
.size(); ++c
)
565 probe_point::component
* comp
= name
->components
[c
];
566 // XXX: alias parameters
568 throw semantic_error("alias component "
570 + " contains illegal parameter");
571 n
= n
->bind(comp
->functor
);
573 n
->bind(new alias_expansion_builder(alias
));
576 catch (const semantic_error
& e
)
578 semantic_error
* er
= new semantic_error (e
); // copy it
581 msg
<< " while registering probe alias ";
582 alias
->printsig(msg
);
583 er
->msg2
= msg
.str();
592 static unsigned max_recursion
= 100;
598 recursion_guard(unsigned & i
) : i(i
)
600 if (i
> max_recursion
)
601 throw semantic_error("recursion limit reached");
610 // The match-and-expand loop.
612 derive_probes (systemtap_session
& s
,
613 probe
*p
, vector
<derived_probe
*>& dps
,
616 for (unsigned i
= 0; i
< p
->locations
.size(); ++i
)
618 if (pending_interrupts
) break;
620 probe_point
*loc
= p
->locations
[i
];
624 unsigned num_atbegin
= dps
.size();
626 // Pass down optional flag from e.g. alias reference to each
627 // probe_point instance. We do this by temporarily overriding
628 // the probe_point optional flag. We could instead deep-copy
629 // and set a flag on the copy permanently.
630 bool old_loc_opt
= loc
->optional
;
631 loc
->optional
= loc
->optional
|| optional
;
632 s
.pattern_root
->find_and_build (s
, p
, loc
, 0, dps
); // <-- actual derivation!
633 loc
->optional
= old_loc_opt
;
634 unsigned num_atend
= dps
.size();
636 if (! (loc
->optional
||optional
) && // something required, but
637 num_atbegin
== num_atend
) // nothing new derived!
638 throw semantic_error ("no match");
640 if (loc
->sufficient
&& (num_atend
> num_atbegin
))
644 clog
<< "Probe point ";
645 p
->locations
[i
]->print(clog
);
646 clog
<< " sufficient, skipped";
647 for (unsigned j
= i
+1; j
< p
->locations
.size(); ++j
)
650 p
->locations
[j
]->print(clog
);
654 break; // we need not try to derive for any other locations
657 catch (const semantic_error
& e
)
659 // XXX: prefer not to print_error at every nest/unroll level
661 semantic_error
* er
= new semantic_error (e
); // copy it
664 msg
<< " while resolving probe point " << *loc
;
665 er
->msg2
= msg
.str();
666 s
.print_error (* er
);
675 // ------------------------------------------------------------------------
677 // Indexable usage checks
680 struct symbol_fetcher
681 : public throwing_visitor
685 symbol_fetcher (symbol
*&sym
): sym(sym
)
688 void visit_symbol (symbol
* e
)
693 void visit_target_symbol (target_symbol
* e
)
698 void visit_arrayindex (arrayindex
* e
)
700 e
->base
->visit_indexable (this);
703 void throwone (const token
* t
)
705 throw semantic_error ("Expecting symbol or array index expression", t
);
710 get_symbol_within_expression (expression
*e
)
713 symbol_fetcher
fetcher(sym
);
715 return sym
; // NB: may be null!
719 get_symbol_within_indexable (indexable
*ix
)
721 symbol
*array
= NULL
;
722 hist_op
*hist
= NULL
;
723 classify_indexable(ix
, array
, hist
);
727 return get_symbol_within_expression (hist
->stat
);
730 struct mutated_var_collector
731 : public traversing_visitor
733 set
<vardecl
*> * mutated_vars
;
735 mutated_var_collector (set
<vardecl
*> * mm
)
739 void visit_assignment(assignment
* e
)
741 if (e
->type
== pe_stats
&& e
->op
== "<<<")
743 vardecl
*vd
= get_symbol_within_expression (e
->left
)->referent
;
745 mutated_vars
->insert (vd
);
747 traversing_visitor::visit_assignment(e
);
750 void visit_arrayindex (arrayindex
*e
)
752 if (is_active_lvalue (e
))
755 if (e
->base
->is_symbol (sym
))
756 mutated_vars
->insert (sym
->referent
);
758 throw semantic_error("Assignment to read-only histogram bucket", e
->tok
);
760 traversing_visitor::visit_arrayindex (e
);
765 struct no_var_mutation_during_iteration_check
766 : public traversing_visitor
768 systemtap_session
& session
;
769 map
<functiondecl
*,set
<vardecl
*> *> & function_mutates_vars
;
770 vector
<vardecl
*> vars_being_iterated
;
772 no_var_mutation_during_iteration_check
773 (systemtap_session
& sess
,
774 map
<functiondecl
*,set
<vardecl
*> *> & fmv
)
775 : session(sess
), function_mutates_vars (fmv
)
778 void visit_arrayindex (arrayindex
*e
)
780 if (is_active_lvalue(e
))
782 vardecl
*vd
= get_symbol_within_indexable (e
->base
)->referent
;
785 for (unsigned i
= 0; i
< vars_being_iterated
.size(); ++i
)
787 vardecl
*v
= vars_being_iterated
[i
];
790 string err
= ("variable '" + v
->name
+
791 "' modified during 'foreach' iteration");
792 session
.print_error (semantic_error (err
, e
->tok
));
797 traversing_visitor::visit_arrayindex (e
);
800 void visit_functioncall (functioncall
* e
)
802 map
<functiondecl
*,set
<vardecl
*> *>::const_iterator i
803 = function_mutates_vars
.find (e
->referent
);
805 if (i
!= function_mutates_vars
.end())
807 for (unsigned j
= 0; j
< vars_being_iterated
.size(); ++j
)
809 vardecl
*m
= vars_being_iterated
[j
];
810 if (i
->second
->find (m
) != i
->second
->end())
812 string err
= ("function call modifies var '" + m
->name
+
813 "' during 'foreach' iteration");
814 session
.print_error (semantic_error (err
, e
->tok
));
819 traversing_visitor::visit_functioncall (e
);
822 void visit_foreach_loop(foreach_loop
* s
)
824 vardecl
*vd
= get_symbol_within_indexable (s
->base
)->referent
;
827 vars_being_iterated
.push_back (vd
);
829 traversing_visitor::visit_foreach_loop (s
);
832 vars_being_iterated
.pop_back();
837 // ------------------------------------------------------------------------
839 struct stat_decl_collector
840 : public traversing_visitor
842 systemtap_session
& session
;
844 stat_decl_collector(systemtap_session
& sess
)
848 void visit_stat_op (stat_op
* e
)
850 symbol
*sym
= get_symbol_within_expression (e
->stat
);
851 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
852 session
.stat_decls
[sym
->name
] = statistic_decl();
855 void visit_assignment (assignment
* e
)
859 symbol
*sym
= get_symbol_within_expression (e
->left
);
860 if (session
.stat_decls
.find(sym
->name
) == session
.stat_decls
.end())
861 session
.stat_decls
[sym
->name
] = statistic_decl();
864 traversing_visitor::visit_assignment(e
);
867 void visit_hist_op (hist_op
* e
)
869 symbol
*sym
= get_symbol_within_expression (e
->stat
);
870 statistic_decl new_stat
;
872 if (e
->htype
== hist_linear
)
874 new_stat
.type
= statistic_decl::linear
;
875 assert (e
->params
.size() == 3);
876 new_stat
.linear_low
= e
->params
[0];
877 new_stat
.linear_high
= e
->params
[1];
878 new_stat
.linear_step
= e
->params
[2];
882 assert (e
->htype
== hist_log
);
883 new_stat
.type
= statistic_decl::logarithmic
;
884 assert (e
->params
.size() == 0);
887 map
<string
, statistic_decl
>::iterator i
= session
.stat_decls
.find(sym
->name
);
888 if (i
== session
.stat_decls
.end())
889 session
.stat_decls
[sym
->name
] = new_stat
;
892 statistic_decl
& old_stat
= i
->second
;
893 if (!(old_stat
== new_stat
))
895 if (old_stat
.type
== statistic_decl::none
)
896 i
->second
= new_stat
;
899 // FIXME: Support multiple co-declared histogram types
900 semantic_error
se("multiple histogram types declared on '" + sym
->name
+ "'",
902 session
.print_error (se
);
911 semantic_pass_stats (systemtap_session
& sess
)
913 stat_decl_collector
sdc(sess
);
915 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
916 it
->second
->body
->visit (&sdc
);
918 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
919 sess
.probes
[i
]->body
->visit (&sdc
);
921 for (unsigned i
= 0; i
< sess
.globals
.size(); ++i
)
923 vardecl
*v
= sess
.globals
[i
];
924 if (v
->type
== pe_stats
)
927 if (sess
.stat_decls
.find(v
->name
) == sess
.stat_decls
.end())
929 semantic_error
se("unable to infer statistic parameters for global '" + v
->name
+ "'");
930 sess
.print_error (se
);
935 return sess
.num_errors();
938 // ------------------------------------------------------------------------
940 // Enforce variable-related invariants: no modification of
941 // a foreach()-iterated array.
943 semantic_pass_vars (systemtap_session
& sess
)
946 map
<functiondecl
*, set
<vardecl
*> *> fmv
;
947 no_var_mutation_during_iteration_check
chk(sess
, fmv
);
949 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
951 functiondecl
* fn
= it
->second
;
954 set
<vardecl
*> * m
= new set
<vardecl
*>();
955 mutated_var_collector
mc (m
);
956 fn
->body
->visit (&mc
);
961 for (map
<string
,functiondecl
*>::iterator it
= sess
.functions
.begin(); it
!= sess
.functions
.end(); it
++)
963 functiondecl
* fn
= it
->second
;
964 if (fn
->body
) fn
->body
->visit (&chk
);
967 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
969 if (sess
.probes
[i
]->body
)
970 sess
.probes
[i
]->body
->visit (&chk
);
973 return sess
.num_errors();
977 // ------------------------------------------------------------------------
979 // Rewrite probe condition expressions into probe bodies. Tricky and
980 // exciting business, this. This:
982 // probe foo if (g1 || g2) { ... }
983 // probe bar { ... g1 ++ ... }
987 // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
988 // probe foo { if (! (g1 || g2)) next; ... }
989 // probe bar { ... g1 ++ ...;
990 // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
993 // XXX: As a first cut, do only the "inline probe condition" part of the
997 semantic_pass_conditions (systemtap_session
& sess
)
999 for (unsigned i
= 0; i
< sess
.probes
.size(); ++i
)
1001 derived_probe
* p
= sess
.probes
[i
];
1002 expression
* e
= p
->sole_location()->condition
;
1005 varuse_collecting_visitor vut
;
1008 if (! vut
.written
.empty())
1010 string err
= ("probe condition must not modify any variables");
1011 sess
.print_error (semantic_error (err
, e
->tok
));
1013 else if (vut
.embedded_seen
)
1015 sess
.print_error (semantic_error ("probe condition must not include impure embedded-C", e
->tok
));
1018 // Add the condition expression to the front of the
1019 // derived_probe body.
1020 if_statement
*ifs
= new if_statement ();
1022 ifs
->thenblock
= new next_statement ();
1023 ifs
->thenblock
->tok
= e
->tok
;
1024 ifs
->elseblock
= NULL
;
1025 unary_expression
*notex
= new unary_expression ();
1027 notex
->tok
= e
->tok
;
1029 ifs
->condition
= notex
;
1030 p
->body
= new block (ifs
, p
->body
);
1034 return sess
.num_errors();
1038 // ------------------------------------------------------------------------
1041 static int semantic_pass_symbols (systemtap_session
&);
1042 static int semantic_pass_optimize1 (systemtap_session
&);
1043 static int semantic_pass_optimize2 (systemtap_session
&);
1044 static int semantic_pass_types (systemtap_session
&);
1045 static int semantic_pass_vars (systemtap_session
&);
1046 static int semantic_pass_stats (systemtap_session
&);
1047 static int semantic_pass_conditions (systemtap_session
&);
1050 // Link up symbols to their declarations. Set the session's
1051 // files/probes/functions/globals vectors from the transitively
1052 // reached set of stapfiles in s.library_files, starting from
1053 // s.user_file. Perform automatic tapset inclusion and probe
1056 semantic_pass_symbols (systemtap_session
& s
)
1058 symresolution_info
sym (s
);
1060 // NB: s.files can grow during this iteration, so size() can
1061 // return gradually increasing numbers.
1062 s
.files
.push_back (s
.user_file
);
1063 for (unsigned i
= 0; i
< s
.files
.size(); i
++)
1065 if (pending_interrupts
) break;
1066 stapfile
* dome
= s
.files
[i
];
1068 // Pass 1: add globals and functions to systemtap-session master list,
1069 // so the find_* functions find them
1071 for (unsigned i
=0; i
<dome
->globals
.size(); i
++)
1072 s
.globals
.push_back (dome
->globals
[i
]);
1074 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1075 s
.functions
[dome
->functions
[i
]->name
] = dome
->functions
[i
];
1077 for (unsigned i
=0; i
<dome
->embeds
.size(); i
++)
1078 s
.embeds
.push_back (dome
->embeds
[i
]);
1080 // Pass 2: process functions
1082 for (unsigned i
=0; i
<dome
->functions
.size(); i
++)
1084 if (pending_interrupts
) break;
1085 functiondecl
* fd
= dome
->functions
[i
];
1089 sym
.current_function
= fd
;
1090 sym
.current_probe
= 0;
1091 fd
->body
->visit (& sym
);
1093 catch (const semantic_error
& e
)
1099 // Pass 3: derive probes and resolve any further symbols in the
1102 for (unsigned i
=0; i
<dome
->probes
.size(); i
++)
1104 if (pending_interrupts
) break;
1105 probe
* p
= dome
->probes
[i
];
1106 vector
<derived_probe
*> dps
;
1108 // much magic happens here: probe alias expansion, wildcard
1109 // matching, low-level derived_probe construction.
1110 derive_probes (s
, p
, dps
);
1112 for (unsigned j
=0; j
<dps
.size(); j
++)
1114 if (pending_interrupts
) break;
1115 derived_probe
* dp
= dps
[j
];
1116 s
.probes
.push_back (dp
);
1121 sym
.current_function
= 0;
1122 sym
.current_probe
= dp
;
1123 dp
->body
->visit (& sym
);
1125 // Process the probe-point condition expression.
1126 sym
.current_function
= 0;
1127 sym
.current_probe
= 0;
1128 if (dp
->sole_location()->condition
)
1129 dp
->sole_location()->condition
->visit (& sym
);
1131 catch (const semantic_error
& e
)
1139 // Inform all derived_probe builders that we're done with
1140 // all resolution, so it's time to release caches.
1141 s
.pattern_root
->build_no_more (s
);
1143 return s
.num_errors(); // all those print_error calls
1147 // Keep unread global variables for probe end value display.
1148 void add_global_var_display (systemtap_session
& s
)
1150 varuse_collecting_visitor vut
;
1151 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1153 s
.probes
[i
]->body
->visit (& vut
);
1155 if (s
.probes
[i
]->sole_location()->condition
)
1156 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1159 for (unsigned g
=0; g
< s
.globals
.size(); g
++)
1161 vardecl
* l
= s
.globals
[g
];
1162 if (vut
.read
.find (l
) != vut
.read
.end()
1163 || vut
.written
.find (l
) == vut
.written
.end())
1166 print_format
* pf
= new print_format
;
1167 probe
* p
= new probe
;
1168 probe_point
* pl
= new probe_point
;
1169 probe_point::component
* c
= new probe_point::component("end");
1170 token
* print_tok
= new token
;
1171 vector
<derived_probe
*> dps
;
1172 block
*b
= new block
;
1174 pl
->components
.push_back (c
);
1176 p
->locations
.push_back (pl
);
1177 print_tok
->type
= tok_identifier
;
1178 print_tok
->content
= "printf";
1181 symbol
* g_sym
= new symbol
;
1182 g_sym
->name
= l
->name
;
1183 g_sym
->tok
= l
->tok
;
1184 g_sym
->type
= l
->type
;
1185 g_sym
->referent
= l
;
1187 pf
->print_to_stream
= true;
1188 pf
->print_with_format
= true;
1189 pf
->print_with_delim
= false;
1190 pf
->print_with_newline
= false;
1191 pf
->print_char
= false;
1192 pf
->raw_components
+= l
->name
;
1193 pf
->tok
= print_tok
;
1195 if (l
->index_types
.size() == 0) // Scalar
1197 if (l
->type
== pe_stats
)
1198 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1199 else if (l
->type
== pe_string
)
1200 pf
->raw_components
+= "=\"%#s\"\\n";
1202 pf
->raw_components
+= "=%#x\\n";
1203 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1204 expr_statement
* feb
= new expr_statement
;
1206 feb
->tok
= print_tok
;
1207 if (l
->type
== pe_stats
)
1209 struct stat_op
* so
[5];
1210 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1212 for (unsigned si
= 0;
1213 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1216 so
[si
]= new stat_op
;
1217 so
[si
]->ctype
= stypes
[si
];
1218 so
[si
]->type
= pe_long
;
1219 so
[si
]->stat
= g_sym
;
1220 so
[si
]->tok
= l
->tok
;
1221 pf
->args
.push_back(so
[si
]);
1225 pf
->args
.push_back(g_sym
);
1226 b
->statements
.push_back(feb
);
1230 int idx_count
= l
->index_types
.size();
1231 symbol
* idx_sym
[idx_count
];
1232 vardecl
* idx_v
[idx_count
];
1233 // Create a foreach loop
1234 foreach_loop
* fe
= new foreach_loop
;
1235 fe
->sort_direction
= 0;
1238 // Create indices for the foreach loop
1239 for (int i
=0; i
< idx_count
; i
++)
1242 if (asprintf (&idx_name
, "idx%d", i
) < 0)
1244 idx_sym
[i
] = new symbol
;
1245 idx_sym
[i
]->name
= idx_name
;
1246 idx_sym
[i
]->tok
= l
->tok
;
1247 idx_v
[i
] = new vardecl
;
1248 idx_v
[i
]->name
= idx_name
;
1249 idx_v
[i
]->type
= l
->index_types
[i
];
1250 idx_v
[i
]->tok
= l
->tok
;
1251 idx_sym
[i
]->referent
= idx_v
[i
];
1252 fe
->indexes
.push_back (idx_sym
[i
]);
1255 // Create a printf for the foreach loop
1256 pf
->raw_components
+= "[";
1257 for (int i
=0; i
< idx_count
; i
++)
1260 pf
->raw_components
+= ",";
1261 if (l
->index_types
[i
] == pe_string
)
1262 pf
->raw_components
+= "\"%#s\"";
1264 pf
->raw_components
+= "%#d";
1266 pf
->raw_components
+= "]";
1267 if (l
->type
== pe_stats
)
1268 pf
->raw_components
+= " @count=%#x @min=%#x @max=%#x @sum=%#x @avg=%#x\\n";
1269 else if (l
->type
== pe_string
)
1270 pf
->raw_components
+= "=\"%#s\"\\n";
1272 pf
->raw_components
+= "=%#x\\n";
1274 // Create an index for the array
1275 struct arrayindex
* ai
= new arrayindex
;
1279 for (int i
=0; i
< idx_count
; i
++)
1281 ai
->indexes
.push_back (idx_sym
[i
]);
1282 pf
->args
.push_back(idx_sym
[i
]);
1284 if (l
->type
== pe_stats
)
1286 struct stat_op
* so
[5];
1287 const stat_component_type stypes
[] = {sc_count
, sc_min
, sc_max
, sc_sum
, sc_average
};
1289 ai
->type
= pe_stats
;
1290 for (unsigned si
= 0;
1291 si
< (sizeof(so
)/sizeof(struct stat_op
*));
1294 so
[si
]= new stat_op
;
1295 so
[si
]->ctype
= stypes
[si
];
1296 so
[si
]->type
= pe_long
;
1298 so
[si
]->tok
= l
->tok
;
1299 pf
->args
.push_back(so
[si
]);
1303 pf
->args
.push_back(ai
);
1305 pf
->components
= print_format::string_to_components(pf
->raw_components
);
1306 expr_statement
* feb
= new expr_statement
;
1309 fe
->block
= (statement
*)feb
;
1310 b
->statements
.push_back(fe
);
1313 // Add created probe
1315 derive_probes (s
, p
, dps
);
1316 for (unsigned i
= 0; i
< dps
.size(); i
++)
1318 derived_probe
* dp
= dps
[i
];
1319 s
.probes
.push_back (dp
);
1322 // Repopulate symbol and type info
1323 symresolution_info
sym (s
);
1324 sym
.current_function
= 0;
1325 sym
.current_probe
= dps
[0];
1326 dps
[0]->body
->visit (& sym
);
1328 semantic_pass_types(s
);
1329 // Mark that variable is read
1330 vut
.read
.insert (l
);
1335 semantic_pass (systemtap_session
& s
)
1341 s
.register_library_aliases();
1342 register_standard_tapsets(s
);
1344 if (rc
== 0) rc
= semantic_pass_symbols (s
);
1345 if (rc
== 0) rc
= semantic_pass_conditions (s
);
1346 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize1 (s
);
1347 if (rc
== 0) rc
= semantic_pass_types (s
);
1348 if (rc
== 0) add_global_var_display (s
);
1349 if (rc
== 0 && ! s
.unoptimized
) rc
= semantic_pass_optimize2 (s
);
1350 if (rc
== 0) rc
= semantic_pass_vars (s
);
1351 if (rc
== 0) rc
= semantic_pass_stats (s
);
1353 if (s
.probes
.size() == 0 && !s
.listing_mode
)
1354 throw semantic_error ("no probes found");
1356 catch (const semantic_error
& e
)
1366 // ------------------------------------------------------------------------
1369 systemtap_session::systemtap_session ():
1370 // NB: pointer members must be manually initialized!
1371 pattern_root(new match_node
),
1373 be_derived_probes(0),
1374 dwarf_derived_probes(0),
1375 uprobe_derived_probes(0),
1376 utrace_derived_probes(0),
1377 itrace_derived_probes(0),
1378 task_finder_derived_probes(0),
1379 timer_derived_probes(0),
1380 profile_derived_probes(0),
1381 mark_derived_probes(0),
1382 hrtimer_derived_probes(0),
1383 perfmon_derived_probes(0),
1384 procfs_derived_probes(0),
1386 sym_kprobes_text_start (0),
1387 sym_kprobes_text_end (0),
1395 // Print this given token, but abbreviate it if the last one had the
1398 systemtap_session::print_token (ostream
& o
, const token
* tok
)
1402 if (last_token
&& last_token
->location
.file
== tok
->location
.file
)
1406 string ts
= tmpo
.str();
1407 // search & replace the file name with nothing
1408 size_t idx
= ts
.find (tok
->location
.file
);
1409 if (idx
!= string::npos
)
1410 ts
.replace (idx
, tok
->location
.file
.size(), "");
1423 systemtap_session::print_error (const semantic_error
& e
)
1426 stringstream message
;
1428 // NB: we don't print error messages during listing mode.
1429 if (listing_mode
) return;
1431 message
<< "semantic error: " << e
.what ();
1432 if (e
.tok1
|| e
.tok2
)
1434 if (e
.tok1
) print_token (message
, e
.tok1
);
1436 if (e
.tok2
) print_token (message
, e
.tok2
);
1438 message_str
= message
.str();
1440 // Duplicate elimination
1441 if (seen_errors
.find (message_str
) == seen_errors
.end())
1443 seen_errors
.insert (message_str
);
1444 cerr
<< message_str
;
1448 print_error (* e
.chain
);
1452 systemtap_session::print_warning (const string
& message_str
, const token
* tok
)
1454 // Duplicate elimination
1455 if (seen_warnings
.find (message_str
) == seen_warnings
.end())
1457 seen_warnings
.insert (message_str
);
1458 clog
<< "WARNING: " << message_str
;
1459 if (tok
) { clog
<< ": "; print_token (clog
, tok
); }
1465 // ------------------------------------------------------------------------
1466 // semantic processing: symbol resolution
1469 symresolution_info::symresolution_info (systemtap_session
& s
):
1470 session (s
), current_function (0), current_probe (0)
1476 symresolution_info::visit_block (block
* e
)
1478 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
1482 e
->statements
[i
]->visit (this);
1484 catch (const semantic_error
& e
)
1486 session
.print_error (e
);
1493 symresolution_info::visit_foreach_loop (foreach_loop
* e
)
1495 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1496 e
->indexes
[i
]->visit (this);
1498 symbol
*array
= NULL
;
1499 hist_op
*hist
= NULL
;
1500 classify_indexable (e
->base
, array
, hist
);
1504 if (!array
->referent
)
1506 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1508 array
->referent
= d
;
1512 msg
<< "unresolved arity-" << e
->indexes
.size()
1513 << " global array " << array
->name
;
1514 throw semantic_error (msg
.str(), e
->tok
);
1525 e
->limit
->visit (this);
1527 e
->block
->visit (this);
1532 delete_statement_symresolution_info
:
1533 public traversing_visitor
1535 symresolution_info
*parent
;
1537 delete_statement_symresolution_info (symresolution_info
*p
):
1541 void visit_arrayindex (arrayindex
* e
)
1543 parent
->visit_arrayindex (e
);
1545 void visit_functioncall (functioncall
* e
)
1547 parent
->visit_functioncall (e
);
1550 void visit_symbol (symbol
* e
)
1555 vardecl
* d
= parent
->find_var (e
->name
, -1);
1559 throw semantic_error ("unresolved array in delete statement", e
->tok
);
1564 symresolution_info::visit_delete_statement (delete_statement
* s
)
1566 delete_statement_symresolution_info
di (this);
1567 s
->value
->visit (&di
);
1572 symresolution_info::visit_symbol (symbol
* e
)
1577 vardecl
* d
= find_var (e
->name
, 0);
1583 vardecl
* v
= new vardecl
;
1586 if (current_function
)
1587 current_function
->locals
.push_back (v
);
1588 else if (current_probe
)
1589 current_probe
->locals
.push_back (v
);
1591 // must be probe-condition expression
1592 throw semantic_error ("probe condition must not reference undeclared global", e
->tok
);
1599 symresolution_info::visit_arrayindex (arrayindex
* e
)
1601 for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
1602 e
->indexes
[i
]->visit (this);
1604 symbol
*array
= NULL
;
1605 hist_op
*hist
= NULL
;
1606 classify_indexable(e
->base
, array
, hist
);
1610 if (array
->referent
)
1613 vardecl
* d
= find_var (array
->name
, e
->indexes
.size ());
1615 array
->referent
= d
;
1619 vardecl
* v
= new vardecl
;
1620 v
->set_arity(e
->indexes
.size());
1621 v
->name
= array
->name
;
1622 v
->tok
= array
->tok
;
1623 if (current_function
)
1624 current_function
->locals
.push_back (v
);
1625 else if (current_probe
)
1626 current_probe
->locals
.push_back (v
);
1629 throw semantic_error ("no current probe/function", e
->tok
);
1630 array
->referent
= v
;
1642 symresolution_info::visit_functioncall (functioncall
* e
)
1644 // XXX: we could relax this, if we're going to examine the
1645 // vartracking data recursively. See testsuite/semko/fortytwo.stp.
1646 if (! (current_function
|| current_probe
))
1648 // must be probe-condition expression
1649 throw semantic_error ("probe condition must not reference function", e
->tok
);
1652 for (unsigned i
=0; i
<e
->args
.size(); i
++)
1653 e
->args
[i
]->visit (this);
1658 functiondecl
* d
= find_function (e
->function
, e
->args
.size ());
1664 msg
<< "unresolved arity-" << e
->args
.size()
1666 throw semantic_error (msg
.str(), e
->tok
);
1672 symresolution_info::find_var (const string
& name
, int arity
)
1674 if (current_function
|| current_probe
)
1677 vector
<vardecl
*>& locals
= (current_function
?
1678 current_function
->locals
:
1679 current_probe
->locals
);
1682 for (unsigned i
=0; i
<locals
.size(); i
++)
1683 if (locals
[i
]->name
== name
1684 && locals
[i
]->compatible_arity(arity
))
1686 locals
[i
]->set_arity (arity
);
1691 // search function formal parameters (for scalars)
1692 if (arity
== 0 && current_function
)
1693 for (unsigned i
=0; i
<current_function
->formal_args
.size(); i
++)
1694 if (current_function
->formal_args
[i
]->name
== name
)
1696 // NB: no need to check arity here: formal args always scalar
1697 current_function
->formal_args
[i
]->set_arity (0);
1698 return current_function
->formal_args
[i
];
1701 // search processed globals
1702 for (unsigned i
=0; i
<session
.globals
.size(); i
++)
1703 if (session
.globals
[i
]->name
== name
1704 && session
.globals
[i
]->compatible_arity(arity
))
1706 session
.globals
[i
]->set_arity (arity
);
1707 return session
.globals
[i
];
1710 // search library globals
1711 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1713 stapfile
* f
= session
.library_files
[i
];
1714 for (unsigned j
=0; j
<f
->globals
.size(); j
++)
1716 vardecl
* g
= f
->globals
[j
];
1717 if (g
->name
== name
&& g
->compatible_arity (arity
))
1719 g
->set_arity (arity
);
1721 // put library into the queue if not already there
1722 if (find (session
.files
.begin(), session
.files
.end(), f
)
1723 == session
.files
.end())
1724 session
.files
.push_back (f
);
1736 symresolution_info::find_function (const string
& name
, unsigned arity
)
1739 if (session
.functions
.find(name
) != session
.functions
.end())
1741 functiondecl
* fd
= session
.functions
[name
];
1742 assert (fd
->name
== name
);
1743 if (fd
->formal_args
.size() == arity
)
1747 // search library globals
1748 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1750 stapfile
* f
= session
.library_files
[i
];
1751 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1752 if (f
->functions
[j
]->name
== name
&&
1753 f
->functions
[j
]->formal_args
.size() == arity
)
1755 // put library into the queue if not already there
1756 if (0) // session.verbose_resolution
1757 cerr
<< " function " << name
<< " "
1758 << "is defined from " << f
->name
<< endl
;
1760 if (find (session
.files
.begin(), session
.files
.end(), f
)
1761 == session
.files
.end())
1762 session
.files
.push_back (f
);
1763 // else .. print different message?
1765 return f
->functions
[j
];
1774 // ------------------------------------------------------------------------
1778 // Do away with functiondecls that are never (transitively) called
1780 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1782 functioncall_traversing_visitor ftv
;
1783 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1785 s
.probes
[i
]->body
->visit (& ftv
);
1786 if (s
.probes
[i
]->sole_location()->condition
)
1787 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1789 vector
<functiondecl
*> new_unused_functions
;
1790 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
1792 functiondecl
* fd
= it
->second
;
1793 if (ftv
.traversed
.find(fd
) == ftv
.traversed
.end())
1795 if (fd
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1796 ! s
.suppress_warnings
)
1797 s
.print_warning ("eliding unused function '" + fd
->name
+ "'", fd
->tok
);
1798 else if (s
.verbose
>2)
1799 clog
<< "Eliding unused function " << fd
->name
1801 // s.functions.erase (it); // NB: can't, since we're already iterating upon it
1802 new_unused_functions
.push_back (fd
);
1806 for (unsigned i
=0; i
<new_unused_functions
.size(); i
++)
1808 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (new_unused_functions
[i
]->name
);
1809 assert (where
!= s
.functions
.end());
1810 s
.functions
.erase (where
);
1811 if (s
.tapset_compile_coverage
)
1812 s
.unused_functions
.push_back (new_unused_functions
[i
]);
1817 // ------------------------------------------------------------------------
1819 // Do away with local & global variables that are never
1820 // written nor read.
1821 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
1823 varuse_collecting_visitor vut
;
1825 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1827 s
.probes
[i
]->body
->visit (& vut
);
1829 if (s
.probes
[i
]->sole_location()->condition
)
1830 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1833 // NB: Since varuse_collecting_visitor also traverses down
1834 // actually called functions, we don't need to explicitly
1835 // iterate over them. Uncalled ones should have been pruned
1838 // for (unsigned i=0; i<s.functions.size(); i++)
1839 // s.functions[i]->body->visit (& vut);
1841 // Now in vut.read/written, we have a mixture of all locals, globals
1843 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1844 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
1846 vardecl
* l
= s
.probes
[i
]->locals
[j
];
1848 if (vut
.read
.find (l
) == vut
.read
.end() &&
1849 vut
.written
.find (l
) == vut
.written
.end())
1851 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1852 ! s
.suppress_warnings
)
1853 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1854 else if (s
.verbose
>2)
1855 clog
<< "Eliding unused local variable "
1856 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
1857 if (s
.tapset_compile_coverage
) {
1858 s
.probes
[i
]->unused_locals
.push_back
1859 (s
.probes
[i
]->locals
[j
]);
1861 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
1863 // don't increment j
1867 if (vut
.written
.find (l
) == vut
.written
.end())
1868 if (iterations
== 0 && ! s
.suppress_warnings
)
1871 vector
<vardecl
*>::iterator it
;
1872 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
1873 if (l
->name
!= (*it
)->name
)
1874 o
<< " " << (*it
)->name
;
1875 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1876 if (l
->name
!= (*it
)->name
)
1877 o
<< " " << (*it
)->name
;
1879 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
1880 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1886 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
1888 functiondecl
*fd
= it
->second
;
1889 for (unsigned j
=0; j
<fd
->locals
.size(); /* see below */)
1891 vardecl
* l
= fd
->locals
[j
];
1892 if (vut
.read
.find (l
) == vut
.read
.end() &&
1893 vut
.written
.find (l
) == vut
.written
.end())
1895 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1896 ! s
.suppress_warnings
)
1897 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1898 else if (s
.verbose
>2)
1899 clog
<< "Eliding unused local variable "
1900 << l
->name
<< " in function " << fd
->name
1902 if (s
.tapset_compile_coverage
) {
1903 fd
->unused_locals
.push_back (fd
->locals
[j
]);
1905 fd
->locals
.erase(fd
->locals
.begin() + j
);
1907 // don't increment j
1911 if (vut
.written
.find (l
) == vut
.written
.end())
1912 if (iterations
== 0 && ! s
.suppress_warnings
)
1915 vector
<vardecl
*>::iterator it
;
1916 for (it
= fd
->formal_args
.begin() ;
1917 it
!= fd
->formal_args
.end(); it
++)
1918 if (l
->name
!= (*it
)->name
)
1919 o
<< " " << (*it
)->name
;
1920 for (it
= fd
->locals
.begin(); it
!= fd
->locals
.end(); it
++)
1921 if (l
->name
!= (*it
)->name
)
1922 o
<< " " << (*it
)->name
;
1923 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1924 if (l
->name
!= (*it
)->name
)
1925 o
<< " " << (*it
)->name
;
1927 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
1928 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1935 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
1937 vardecl
* l
= s
.globals
[i
];
1938 if (vut
.read
.find (l
) == vut
.read
.end() &&
1939 vut
.written
.find (l
) == vut
.written
.end())
1941 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1942 ! s
.suppress_warnings
)
1943 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1944 else if (s
.verbose
>2)
1945 clog
<< "Eliding unused global variable "
1947 if (s
.tapset_compile_coverage
) {
1948 s
.unused_globals
.push_back(s
.globals
[i
]);
1950 s
.globals
.erase(s
.globals
.begin() + i
);
1952 // don't increment i
1956 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
1957 if (iterations
== 0 && ! s
.suppress_warnings
)
1960 vector
<vardecl
*>::iterator it
;
1961 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1962 if (l
->name
!= (*it
)->name
)
1963 o
<< " " << (*it
)->name
;
1965 s
.print_warning ("read-only global variable '" + l
->name
+ "' " +
1966 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1975 // ------------------------------------------------------------------------
1977 struct dead_assignment_remover
: public traversing_visitor
1979 systemtap_session
& session
;
1981 const varuse_collecting_visitor
& vut
;
1982 expression
** current_expr
;
1984 dead_assignment_remover(systemtap_session
& s
, bool& r
,
1985 const varuse_collecting_visitor
& v
):
1986 session(s
), relaxed_p(r
), vut(v
), current_expr(0) {}
1988 void visit_expr_statement (expr_statement
* s
);
1989 // XXX: other places where an assignment may be nested should be
1990 // handled too (e.g., loop/if conditionals, array indexes, function
1991 // parameters). Until then, they result in visit_assignment() being
1992 // called with null current_expr.
1994 void visit_assignment (assignment
* e
);
1995 void visit_binary_expression (binary_expression
* e
);
1996 void visit_arrayindex (arrayindex
* e
);
1997 void visit_functioncall (functioncall
* e
);
1998 void visit_if_statement (if_statement
* e
);
1999 void visit_for_loop (for_loop
* e
);
2004 dead_assignment_remover::visit_expr_statement (expr_statement
* s
)
2006 expression
** last_expr
= current_expr
;
2007 current_expr
= & s
->value
;
2008 s
->value
->visit (this);
2009 s
->tok
= s
->value
->tok
; // in case it was replaced
2010 current_expr
= last_expr
;
2015 dead_assignment_remover::visit_assignment (assignment
* e
)
2017 symbol
* left
= get_symbol_within_expression (e
->left
);
2018 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2019 if (current_expr
&& // see XXX above: this case represents a missed
2020 // optimization opportunity
2021 *current_expr
== e
&& // we're not nested any deeper than expected
2022 leftvar
) // not unresolved $target; intended sideeffect cannot be elided
2024 expression
** last_expr
= current_expr
;
2025 e
->left
->visit (this);
2026 current_expr
= &e
->right
;
2027 e
->right
->visit (this);
2028 current_expr
= last_expr
;
2030 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2032 // NB: Not so fast! The left side could be an array whose
2033 // index expressions may have side-effects. This would be
2034 // OK if we could replace the array assignment with a
2035 // statement-expression containing all the index expressions
2036 // and the rvalue... but we can't.
2037 // Another possibility is that we have an unread global variable
2038 // which are kept for probe end value display.
2040 bool is_global
= false;
2041 vector
<vardecl
*>::iterator it
;
2042 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2043 if (leftvar
->name
== (*it
)->name
)
2049 varuse_collecting_visitor vut
;
2050 e
->left
->visit (& vut
);
2051 if (vut
.side_effect_free () && !is_global
) // XXX: use _wrt() once we track focal_vars
2053 /* PR 1119: NB: This is not necessary here. A write-only
2054 variable will also be elided soon at the next _opt2 iteration.
2055 if (e->left->tok->location.file == session.user_file->name && // !tapset
2056 ! session.suppress_warnings)
2057 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
2060 if (session
.verbose
>2)
2061 clog
<< "Eliding assignment to " << leftvar
->name
2062 << " at " << *e
->tok
<< endl
;
2064 *current_expr
= e
->right
; // goodbye assignment*
2072 dead_assignment_remover::visit_binary_expression (binary_expression
* e
)
2074 expression
** last_expr
= current_expr
;
2075 current_expr
= &e
->left
;
2076 e
->left
->visit (this);
2077 current_expr
= &e
->right
;
2078 e
->right
->visit (this);
2079 current_expr
= last_expr
;
2083 dead_assignment_remover::visit_arrayindex (arrayindex
*e
)
2085 symbol
*array
= NULL
;
2086 hist_op
*hist
= NULL
;
2087 classify_indexable(e
->base
, array
, hist
);
2091 expression
** last_expr
= current_expr
;
2092 for (unsigned i
=0; i
< e
->indexes
.size(); i
++)
2094 current_expr
= & e
->indexes
[i
];
2095 e
->indexes
[i
]->visit (this);
2097 current_expr
= last_expr
;
2102 dead_assignment_remover::visit_functioncall (functioncall
* e
)
2104 expression
** last_expr
= current_expr
;
2105 for (unsigned i
=0; i
<e
->args
.size(); i
++)
2107 current_expr
= & e
->args
[i
];
2108 e
->args
[i
]->visit (this);
2110 current_expr
= last_expr
;
2114 dead_assignment_remover::visit_if_statement (if_statement
* s
)
2116 expression
** last_expr
= current_expr
;
2117 current_expr
= & s
->condition
;
2118 s
->condition
->visit (this);
2119 s
->thenblock
->visit (this);
2121 s
->elseblock
->visit (this);
2122 current_expr
= last_expr
;
2126 dead_assignment_remover::visit_for_loop (for_loop
* s
)
2128 expression
** last_expr
= current_expr
;
2129 if (s
->init
) s
->init
->visit (this);
2130 current_expr
= & s
->cond
;
2131 s
->cond
->visit (this);
2132 if (s
->incr
) s
->incr
->visit (this);
2133 s
->block
->visit (this);
2134 current_expr
= last_expr
;
2137 // Let's remove assignments to variables that are never read. We
2138 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2139 // be optimized away as an unused variable, and expr a candidate to be
2140 // removed as a side-effect-free statement expression. Wahoo!
2141 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2143 // Recompute the varuse data, which will probably match the opt2
2144 // copy of the computation, except for those totally unused
2145 // variables that opt2 removed.
2146 varuse_collecting_visitor vut
;
2147 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2148 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2150 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2151 // This instance may be reused for multiple probe/function body trims.
2153 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2154 s
.probes
[i
]->body
->visit (& dar
);
2155 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2156 it
->second
->body
->visit (& dar
);
2157 // The rewrite operation is performed within the visitor.
2159 // XXX: we could also zap write-only globals here
2163 // ------------------------------------------------------------------------
2165 struct dead_stmtexpr_remover
: public traversing_visitor
2167 systemtap_session
& session
;
2169 statement
** current_stmt
; // pointer to current stmt* being iterated
2170 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2172 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2173 session(s
), relaxed_p(r
), current_stmt(0) {}
2175 void visit_block (block
*s
);
2176 void visit_null_statement (null_statement
*s
);
2177 void visit_if_statement (if_statement
* s
);
2178 void visit_foreach_loop (foreach_loop
*s
);
2179 void visit_for_loop (for_loop
*s
);
2180 // XXX: and other places where stmt_expr's might be nested
2182 void visit_expr_statement (expr_statement
*s
);
2187 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2190 if (session
.verbose
>2)
2191 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
2197 dead_stmtexpr_remover::visit_block (block
*s
)
2199 vector
<statement
*> new_stmts
;
2200 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2202 statement
** last_stmt
= current_stmt
;
2203 current_stmt
= & s
->statements
[i
];
2204 s
->statements
[i
]->visit (this);
2205 if (*current_stmt
!= 0)
2207 // flatten nested blocks into this one
2208 block
*b
= dynamic_cast<block
*>(*current_stmt
);
2211 if (session
.verbose
>2)
2212 clog
<< "Flattening nested block " << *b
->tok
<< endl
;
2213 new_stmts
.insert(new_stmts
.end(),
2214 b
->statements
.begin(), b
->statements
.end());
2218 new_stmts
.push_back (*current_stmt
);
2220 current_stmt
= last_stmt
;
2222 if (new_stmts
.size() == 0)
2224 if (session
.verbose
>2)
2225 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
2228 else if (new_stmts
.size() == 1)
2230 if (session
.verbose
>2)
2231 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
2232 *current_stmt
= new_stmts
[0];
2236 s
->statements
= new_stmts
;
2241 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2243 statement
** last_stmt
= current_stmt
;
2244 current_stmt
= & s
->thenblock
;
2245 s
->thenblock
->visit (this);
2249 current_stmt
= & s
->elseblock
;
2250 s
->elseblock
->visit (this);
2251 // null *current_stmt is OK here.
2253 current_stmt
= last_stmt
;
2255 if (s
->thenblock
== 0)
2257 if (s
->elseblock
== 0)
2259 // We may be able to elide this statement, if the condition
2260 // expression is side-effect-free.
2261 varuse_collecting_visitor vct
;
2262 s
->condition
->visit(& vct
);
2263 if (vct
.side_effect_free ())
2265 if (session
.verbose
>2)
2266 clog
<< "Eliding side-effect-free if statement "
2268 *current_stmt
= 0; // yeah, baby
2272 // We can still turn it into a simple expr_statement though...
2273 if (session
.verbose
>2)
2274 clog
<< "Creating simple evaluation from if statement "
2276 expr_statement
*es
= new expr_statement
;
2277 es
->value
= s
->condition
;
2278 es
->tok
= es
->value
->tok
;
2284 // For an else without a then, we can invert the condition logic to
2285 // avoid having a null statement in the thenblock
2286 if (session
.verbose
>2)
2287 clog
<< "Inverting the condition of if statement "
2289 unary_expression
*ue
= new unary_expression
;
2290 ue
->operand
= s
->condition
;
2291 ue
->tok
= ue
->operand
->tok
;
2294 s
->thenblock
= s
->elseblock
;
2301 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2303 statement
** last_stmt
= current_stmt
;
2304 current_stmt
= & s
->block
;
2305 s
->block
->visit (this);
2306 current_stmt
= last_stmt
;
2310 if (session
.verbose
>2)
2311 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2312 *current_stmt
= 0; // yeah, baby
2317 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2319 statement
** last_stmt
= current_stmt
;
2320 current_stmt
= & s
->block
;
2321 s
->block
->visit (this);
2322 current_stmt
= last_stmt
;
2326 // We may be able to elide this statement, if the condition
2327 // expression is side-effect-free.
2328 varuse_collecting_visitor vct
;
2329 if (s
->init
) s
->init
->visit(& vct
);
2330 s
->cond
->visit(& vct
);
2331 if (s
->incr
) s
->incr
->visit(& vct
);
2332 if (vct
.side_effect_free ())
2334 if (session
.verbose
>2)
2335 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2336 *current_stmt
= 0; // yeah, baby
2340 // Can't elide this whole statement; put a null in there.
2341 s
->block
= new null_statement();
2342 s
->block
->tok
= s
->tok
;
2349 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2351 // Run a varuse query against the operand expression. If it has no
2352 // side-effects, replace the entire statement expression by a null
2353 // statement. This replacement is done by overwriting the
2354 // current_stmt pointer.
2356 // Unlike many other visitors, we do *not* traverse this outermost
2357 // one into the expression subtrees. There is no need - no
2358 // expr_statement nodes will be found there. (Function bodies
2359 // need to be visited explicitly by our caller.)
2361 // NB. While we don't share nodes in the parse tree, let's not
2362 // deallocate *s anyway, just in case...
2364 varuse_collecting_visitor vut
;
2365 s
->value
->visit (& vut
);
2367 if (vut
.side_effect_free_wrt (focal_vars
) &&
2368 *current_stmt
== s
) // we're not nested any deeper than expected
2370 /* PR 1119: NB: this message is not a good idea here. It can
2371 name some arbitrary RHS expression of an assignment.
2372 if (s->value->tok->location.file == session.user_file->name && // not tapset
2373 ! session.suppress_warnings)
2374 clog << "WARNING: eliding read-only " << *s->value->tok << endl;
2377 if (session
.verbose
>2)
2378 clog
<< "Eliding side-effect-free expression "
2381 // NB: this 0 pointer is invalid to leave around for any length of
2382 // time, but the parent parse tree objects above handle it.
2390 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2392 // Finally, let's remove some statement-expressions that have no
2393 // side-effect. These should be exactly those whose private varuse
2394 // visitors come back with an empty "written" and "embedded" lists.
2396 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2397 // This instance may be reused for multiple probe/function body trims.
2399 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2401 if (pending_interrupts
) break;
2403 derived_probe
* p
= s
.probes
[i
];
2405 duv
.focal_vars
.clear ();
2406 duv
.focal_vars
.insert (s
.globals
.begin(),
2408 duv
.focal_vars
.insert (p
->locals
.begin(),
2411 duv
.current_stmt
= & p
->body
;
2412 p
->body
->visit (& duv
);
2415 if (! s
.suppress_warnings
)
2416 s
.print_warning ("side-effect-free probe '" + p
->name
+ "'", p
->tok
);
2418 p
->body
= new null_statement();
2419 p
->body
->tok
= p
->tok
;
2421 // XXX: possible duplicate warnings; see below
2424 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2426 if (pending_interrupts
) break;
2428 functiondecl
* fn
= it
->second
;
2429 duv
.focal_vars
.clear ();
2430 duv
.focal_vars
.insert (fn
->locals
.begin(),
2432 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2433 fn
->formal_args
.end());
2434 duv
.focal_vars
.insert (s
.globals
.begin(),
2437 duv
.current_stmt
= & fn
->body
;
2438 fn
->body
->visit (& duv
);
2441 if (! s
.suppress_warnings
)
2442 s
.print_warning ("side-effect-free function '" + fn
->name
+ "'", fn
->tok
);
2444 fn
->body
= new null_statement();
2445 fn
->body
->tok
= fn
->tok
;
2447 // XXX: the next iteration of the outer optimization loop may
2448 // take this new null_statement away again, and thus give us a
2449 // fresh warning. It would be better if this fixup was performed
2450 // only after the relaxation iterations.
2451 // XXX: or else see bug #6469.
2457 // ------------------------------------------------------------------------
2459 // The goal of this visitor is to reduce top-level expressions in void context
2460 // into separate statements that evaluate each subcomponent of the expression.
2461 // The dead-statement-remover can later remove some parts if they have no side
2463 struct void_statement_reducer
: public traversing_visitor
2465 systemtap_session
& session
;
2467 statement
** current_stmt
; // pointer to current stmt* being iterated
2468 expr_statement
* current_expr
; // pointer to current expr being iterated
2469 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2471 void_statement_reducer(systemtap_session
& s
, bool& r
):
2472 session(s
), relaxed_p(r
), current_stmt(0), current_expr(0) {}
2474 // these just maintain current_stmt while recursing, but don't visit
2475 // expressions in the conditional / loop controls.
2476 void visit_expr_statement (expr_statement
* s
);
2477 void visit_block (block
*s
);
2478 void visit_if_statement (if_statement
* s
);
2479 void visit_for_loop (for_loop
* s
);
2480 void visit_foreach_loop (foreach_loop
* s
);
2482 // these expressions get rewritten into their statement equivalents
2483 void visit_logical_or_expr (logical_or_expr
* e
);
2484 void visit_logical_and_expr (logical_and_expr
* e
);
2485 void visit_ternary_expression (ternary_expression
* e
);
2487 // all of these can be reduced into simpler statements
2488 void visit_binary_expression (binary_expression
* e
);
2489 void visit_unary_expression (unary_expression
* e
);
2490 void visit_comparison (comparison
* e
);
2491 void visit_concatenation (concatenation
* e
);
2492 void visit_functioncall (functioncall
* e
);
2493 void visit_print_format (print_format
* e
);
2495 // these are a bit hairy to grok due to the intricacies of indexables and
2496 // stats, so I'm chickening out and skipping them...
2497 void visit_array_in (array_in
* e
) {}
2498 void visit_arrayindex (arrayindex
* e
) {}
2499 void visit_stat_op (stat_op
* e
) {}
2500 void visit_hist_op (hist_op
* e
) {}
2502 // these can't be reduced because they always have an effect
2503 void visit_return_statement (return_statement
* s
) {}
2504 void visit_delete_statement (delete_statement
* s
) {}
2505 void visit_pre_crement (pre_crement
* e
) {}
2506 void visit_post_crement (post_crement
* e
) {}
2507 void visit_assignment (assignment
* e
) {}
2512 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2514 assert(!current_expr
); // it shouldn't be possible to have nested expr's
2516 s
->value
->visit (this);
2517 current_expr
= NULL
;
2521 void_statement_reducer::visit_block (block
*s
)
2523 statement
** last_stmt
= current_stmt
;
2524 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2526 current_stmt
= & s
->statements
[i
];
2527 s
->statements
[i
]->visit (this);
2529 current_stmt
= last_stmt
;
2533 void_statement_reducer::visit_if_statement (if_statement
* s
)
2535 statement
** last_stmt
= current_stmt
;
2536 current_stmt
= & s
->thenblock
;
2537 s
->thenblock
->visit (this);
2541 current_stmt
= & s
->elseblock
;
2542 s
->elseblock
->visit (this);
2544 current_stmt
= last_stmt
;
2548 void_statement_reducer::visit_for_loop (for_loop
* s
)
2550 statement
** last_stmt
= current_stmt
;
2551 current_stmt
= & s
->block
;
2552 s
->block
->visit (this);
2553 current_stmt
= last_stmt
;
2557 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
2559 statement
** last_stmt
= current_stmt
;
2560 current_stmt
= & s
->block
;
2561 s
->block
->visit (this);
2562 current_stmt
= last_stmt
;
2566 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
2568 // In void context, the evaluation of "a || b" is exactly like
2569 // "if (!a) b", so let's do that instead.
2571 assert(current_expr
&& current_expr
->value
== e
);
2573 if (session
.verbose
>2)
2574 clog
<< "Creating if statement from unused logical-or "
2577 if_statement
*is
= new if_statement
;
2581 current_expr
= NULL
;
2583 unary_expression
*ue
= new unary_expression
;
2584 ue
->operand
= e
->left
;
2589 expr_statement
*es
= new expr_statement
;
2590 es
->value
= e
->right
;
2591 es
->tok
= es
->value
->tok
;
2599 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
2601 // In void context, the evaluation of "a && b" is exactly like
2602 // "if (a) b", so let's do that instead.
2604 assert(current_expr
&& current_expr
->value
== e
);
2606 if (session
.verbose
>2)
2607 clog
<< "Creating if statement from unused logical-and "
2610 if_statement
*is
= new if_statement
;
2613 is
->condition
= e
->left
;
2615 current_expr
= NULL
;
2617 expr_statement
*es
= new expr_statement
;
2618 es
->value
= e
->right
;
2619 es
->tok
= es
->value
->tok
;
2627 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
2629 // In void context, the evaluation of "a ? b : c" is exactly like
2630 // "if (a) b else c", so let's do that instead.
2632 assert(current_expr
&& current_expr
->value
== e
);
2634 if (session
.verbose
>2)
2635 clog
<< "Creating if statement from unused ternary expression "
2638 if_statement
*is
= new if_statement
;
2640 is
->condition
= e
->cond
;
2642 current_expr
= NULL
;
2644 expr_statement
*es
= new expr_statement
;
2645 es
->value
= e
->truevalue
;
2646 es
->tok
= es
->value
->tok
;
2649 es
= new expr_statement
;
2650 es
->value
= e
->falsevalue
;
2651 es
->tok
= es
->value
->tok
;
2659 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
2661 // When the result of a binary operation isn't needed, it's just as good to
2662 // evaluate the operands as sequential statements in a block.
2664 assert(current_expr
&& current_expr
->value
== e
);
2666 if (session
.verbose
>2)
2667 clog
<< "Eliding unused binary " << *e
->tok
<< endl
;
2669 block
*b
= new block
;
2670 b
->tok
= current_expr
->tok
;
2672 current_expr
= NULL
;
2674 expr_statement
*es
= new expr_statement
;
2675 es
->value
= e
->left
;
2676 es
->tok
= es
->value
->tok
;
2677 b
->statements
.push_back(es
);
2679 es
= new expr_statement
;
2680 es
->value
= e
->right
;
2681 es
->tok
= es
->value
->tok
;
2682 b
->statements
.push_back(es
);
2689 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
2691 // When the result of a unary operation isn't needed, it's just as good to
2692 // evaluate the operand directly
2694 assert(current_expr
&& current_expr
->value
== e
);
2696 if (session
.verbose
>2)
2697 clog
<< "Eliding unused unary " << *e
->tok
<< endl
;
2699 current_expr
->value
= e
->operand
;
2700 current_expr
->tok
= current_expr
->value
->tok
;
2701 current_expr
->value
->visit(this);
2707 void_statement_reducer::visit_comparison (comparison
* e
)
2709 visit_binary_expression(e
);
2713 void_statement_reducer::visit_concatenation (concatenation
* e
)
2715 visit_binary_expression(e
);
2719 void_statement_reducer::visit_functioncall (functioncall
* e
)
2721 // If a function call is pure and its result ignored, we can elide the call
2722 // and just evaluate the arguments in sequence
2724 if (!e
->args
.size())
2727 varuse_collecting_visitor vut
;
2728 vut
.traversed
.insert (e
->referent
);
2729 vut
.current_function
= e
->referent
;
2730 e
->referent
->body
->visit (& vut
);
2731 if (!vut
.side_effect_free_wrt (focal_vars
))
2734 assert(current_expr
&& current_expr
->value
== e
);
2736 if (session
.verbose
>2)
2737 clog
<< "Eliding side-effect-free function call " << *e
->tok
<< endl
;
2739 block
*b
= new block
;
2742 current_expr
= NULL
;
2744 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2746 expr_statement
*es
= new expr_statement
;
2747 es
->value
= e
->args
[i
];
2748 es
->tok
= es
->value
->tok
;
2749 b
->statements
.push_back(es
);
2757 void_statement_reducer::visit_print_format (print_format
* e
)
2759 // When an sprint's return value is ignored, we can simply evaluate the
2760 // arguments in sequence
2762 if (e
->print_to_stream
|| !e
->args
.size())
2765 assert(current_expr
&& current_expr
->value
== e
);
2767 if (session
.verbose
>2)
2768 clog
<< "Eliding unused print " << *e
->tok
<< endl
;
2770 block
*b
= new block
;
2773 current_expr
= NULL
;
2775 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2777 expr_statement
*es
= new expr_statement
;
2778 es
->value
= e
->args
[i
];
2779 es
->tok
= es
->value
->tok
;
2780 b
->statements
.push_back(es
);
2788 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2790 // Let's simplify statements with unused computed values.
2792 void_statement_reducer
vuv (s
, relaxed_p
);
2793 // This instance may be reused for multiple probe/function body trims.
2795 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
2797 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2799 derived_probe
* p
= s
.probes
[i
];
2800 vuv
.current_stmt
= & p
->body
;
2801 p
->body
->visit (& vuv
);
2803 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2805 functiondecl
* fn
= it
->second
;
2806 vuv
.current_stmt
= & fn
->body
;
2807 fn
->body
->visit (& vuv
);
2812 struct duplicate_function_remover
: public functioncall_traversing_visitor
2814 systemtap_session
& s
;
2815 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
2817 duplicate_function_remover(systemtap_session
& sess
,
2818 map
<functiondecl
*, functiondecl
*>&dfm
):
2819 s(sess
), duplicate_function_map(dfm
) {};
2821 void visit_functioncall (functioncall
* e
);
2825 duplicate_function_remover::visit_functioncall (functioncall
*e
)
2827 functioncall_traversing_visitor::visit_functioncall (e
);
2829 // If the current function call reference points to a function that
2830 // is a duplicate, replace it.
2831 if (duplicate_function_map
.count(e
->referent
) != 0)
2834 clog
<< "Changing " << e
->referent
->name
2836 << duplicate_function_map
[e
->referent
]->name
2838 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
2839 e
->function
= duplicate_function_map
[e
->referent
]->name
;
2840 e
->referent
= duplicate_function_map
[e
->referent
];
2845 get_functionsig (functiondecl
* f
)
2849 // Get the "name:args body" of the function in s. We have to
2850 // include the args since the function 'x1(a, b)' is different than
2851 // the function 'x2(b, a)' even if the bodies of the two functions
2852 // are exactly the same.
2856 // printsig puts f->name + ':' on the front. Remove this
2857 // (otherwise, functions would never compare equal).
2858 string str
= s
.str().erase(0, f
->name
.size() + 1);
2860 // Return the function signature.
2864 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
2866 // Walk through all the functions, looking for duplicates.
2867 map
<string
, functiondecl
*> functionsig_map
;
2868 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
2871 vector
<functiondecl
*> newly_zapped_functions
;
2872 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2874 functiondecl
*fd
= it
->second
;
2875 string functionsig
= get_functionsig(fd
);
2877 if (functionsig_map
.count(functionsig
) == 0)
2879 // This function is unique. Remember it.
2880 functionsig_map
[functionsig
] = fd
;
2884 // This function is a duplicate.
2885 duplicate_function_map
[fd
] = functionsig_map
[functionsig
];
2886 newly_zapped_functions
.push_back (fd
);
2890 for (unsigned i
=0; i
<newly_zapped_functions
.size(); i
++)
2892 map
<string
,functiondecl
*>::iterator where
= s
.functions
.find (newly_zapped_functions
[i
]->name
);
2893 assert (where
!= s
.functions
.end());
2894 s
.functions
.erase (where
);
2898 // If we have duplicate functions, traverse down the tree, replacing
2899 // the appropriate function calls.
2900 // duplicate_function_remover::visit_functioncall() handles the
2901 // details of replacing the function calls.
2902 if (duplicate_function_map
.size() != 0)
2904 duplicate_function_remover
dfr (s
, duplicate_function_map
);
2906 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
2907 s
.probes
[i
]->body
->visit(&dfr
);
2913 semantic_pass_optimize1 (systemtap_session
& s
)
2915 // In this pass, we attempt to rewrite probe/function bodies to
2916 // eliminate some blatantly unnecessary code. This is run before
2917 // type inference, but after symbol resolution and derived_probe
2918 // creation. We run an outer "relaxation" loop that repeats the
2919 // optimizations until none of them find anything to remove.
2923 bool relaxed_p
= false;
2924 unsigned iterations
= 0;
2927 if (pending_interrupts
) break;
2929 relaxed_p
= true; // until proven otherwise
2931 semantic_pass_opt1 (s
, relaxed_p
);
2932 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
2933 semantic_pass_opt3 (s
, relaxed_p
);
2934 semantic_pass_opt4 (s
, relaxed_p
);
2935 semantic_pass_opt5 (s
, relaxed_p
);
2945 semantic_pass_optimize2 (systemtap_session
& s
)
2947 // This is run after type inference. We run an outer "relaxation"
2948 // loop that repeats the optimizations until none of them find
2949 // anything to remove.
2953 bool relaxed_p
= false;
2956 if (pending_interrupts
) break;
2957 relaxed_p
= true; // until proven otherwise
2959 semantic_pass_opt6 (s
, relaxed_p
);
2967 // ------------------------------------------------------------------------
2972 semantic_pass_types (systemtap_session
& s
)
2976 // next pass: type inference
2977 unsigned iterations
= 0;
2978 typeresolution_info
ti (s
);
2980 ti
.assert_resolvability
= false;
2981 // XXX: maybe convert to exception-based error signalling
2984 if (pending_interrupts
) break;
2987 ti
.num_newly_resolved
= 0;
2988 ti
.num_still_unresolved
= 0;
2990 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
2992 if (pending_interrupts
) break;
2994 functiondecl
* fd
= it
->second
;
2995 ti
.current_probe
= 0;
2996 ti
.current_function
= fd
;
2998 fd
->body
->visit (& ti
);
2999 // NB: we don't have to assert a known type for
3000 // functions here, to permit a "void" function.
3001 // The translator phase will omit the "retvalue".
3003 // if (fd->type == pe_unknown)
3004 // ti.unresolved (fd->tok);
3007 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
3009 if (pending_interrupts
) break;
3011 derived_probe
* pn
= s
.probes
[j
];
3012 ti
.current_function
= 0;
3013 ti
.current_probe
= pn
;
3015 pn
->body
->visit (& ti
);
3017 probe_point
* pp
= pn
->sole_location();
3020 ti
.current_function
= 0;
3021 ti
.current_probe
= 0;
3022 ti
.t
= pe_long
; // NB: expected type
3023 pp
->condition
->visit (& ti
);
3027 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
3029 vardecl
* gd
= s
.globals
[j
];
3030 if (gd
->type
== pe_unknown
)
3031 ti
.unresolved (gd
->tok
);
3034 if (ti
.num_newly_resolved
== 0) // converged
3036 if (ti
.num_still_unresolved
== 0)
3037 break; // successfully
3038 else if (! ti
.assert_resolvability
)
3039 ti
.assert_resolvability
= true; // last pass, with error msgs
3041 { // unsuccessful conclusion
3048 return rc
+ s
.num_errors();
3053 typeresolution_info::typeresolution_info (systemtap_session
& s
):
3054 session(s
), current_function(0), current_probe(0)
3060 typeresolution_info::visit_literal_number (literal_number
* e
)
3062 assert (e
->type
== pe_long
);
3063 if ((t
== e
->type
) || (t
== pe_unknown
))
3066 mismatch (e
->tok
, e
->type
, t
);
3071 typeresolution_info::visit_literal_string (literal_string
* e
)
3073 assert (e
->type
== pe_string
);
3074 if ((t
== e
->type
) || (t
== pe_unknown
))
3077 mismatch (e
->tok
, e
->type
, t
);
3082 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
3084 visit_binary_expression (e
);
3089 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
3091 visit_binary_expression (e
);
3096 typeresolution_info::visit_comparison (comparison
*e
)
3098 // NB: result of any comparison is an integer!
3099 if (t
== pe_stats
|| t
== pe_string
)
3100 invalid (e
->tok
, t
);
3102 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
3103 e
->left
->visit (this);
3104 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
3105 e
->right
->visit (this);
3107 if (e
->left
->type
!= pe_unknown
&&
3108 e
->right
->type
!= pe_unknown
&&
3109 e
->left
->type
!= e
->right
->type
)
3110 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3112 if (e
->type
== pe_unknown
)
3115 resolved (e
->tok
, e
->type
);
3121 typeresolution_info::visit_concatenation (concatenation
*e
)
3123 if (t
!= pe_unknown
&& t
!= pe_string
)
3124 invalid (e
->tok
, t
);
3127 e
->left
->visit (this);
3129 e
->right
->visit (this);
3131 if (e
->type
== pe_unknown
)
3133 e
->type
= pe_string
;
3134 resolved (e
->tok
, e
->type
);
3140 typeresolution_info::visit_assignment (assignment
*e
)
3143 invalid (e
->tok
, t
);
3145 if (e
->op
== "<<<") // stats aggregation
3148 invalid (e
->tok
, t
);
3151 e
->left
->visit (this);
3153 e
->right
->visit (this);
3154 if (e
->type
== pe_unknown
||
3155 e
->type
== pe_stats
)
3158 resolved (e
->tok
, e
->type
);
3162 else if (e
->left
->type
== pe_stats
)
3163 invalid (e
->left
->tok
, e
->left
->type
);
3165 else if (e
->right
->type
== pe_stats
)
3166 invalid (e
->right
->tok
, e
->right
->type
);
3168 else if (e
->op
== "+=" || // numeric only
3180 visit_binary_expression (e
);
3182 else if (e
->op
== ".=" || // string only
3185 if (t
== pe_long
|| t
== pe_stats
)
3186 invalid (e
->tok
, t
);
3189 e
->left
->visit (this);
3191 e
->right
->visit (this);
3192 if (e
->type
== pe_unknown
)
3194 e
->type
= pe_string
;
3195 resolved (e
->tok
, e
->type
);
3198 else if (e
->op
== "=") // overloaded = for string & numeric operands
3200 // logic similar to ternary_expression
3201 exp_type sub_type
= t
;
3203 // Infer types across the l/r values
3204 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3207 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3208 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
3210 e
->left
->visit (this);
3211 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3212 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
3214 e
->right
->visit (this);
3216 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3219 resolved (e
->tok
, e
->type
);
3221 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
3223 e
->type
= e
->left
->type
;
3224 resolved (e
->tok
, e
->type
);
3227 if (e
->left
->type
!= pe_unknown
&&
3228 e
->right
->type
!= pe_unknown
&&
3229 e
->left
->type
!= e
->right
->type
)
3230 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3234 throw semantic_error ("unsupported assignment operator " + e
->op
);
3239 typeresolution_info::visit_binary_expression (binary_expression
* e
)
3241 if (t
== pe_stats
|| t
== pe_string
)
3242 invalid (e
->tok
, t
);
3245 e
->left
->visit (this);
3247 e
->right
->visit (this);
3249 if (e
->left
->type
!= pe_unknown
&&
3250 e
->right
->type
!= pe_unknown
&&
3251 e
->left
->type
!= e
->right
->type
)
3252 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3254 if (e
->type
== pe_unknown
)
3257 resolved (e
->tok
, e
->type
);
3263 typeresolution_info::visit_pre_crement (pre_crement
*e
)
3265 visit_unary_expression (e
);
3270 typeresolution_info::visit_post_crement (post_crement
*e
)
3272 visit_unary_expression (e
);
3277 typeresolution_info::visit_unary_expression (unary_expression
* e
)
3279 if (t
== pe_stats
|| t
== pe_string
)
3280 invalid (e
->tok
, t
);
3283 e
->operand
->visit (this);
3285 if (e
->type
== pe_unknown
)
3288 resolved (e
->tok
, e
->type
);
3294 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
3296 exp_type sub_type
= t
;
3299 e
->cond
->visit (this);
3301 // Infer types across the true/false arms of the ternary expression.
3303 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3306 e
->truevalue
->visit (this);
3308 e
->falsevalue
->visit (this);
3310 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
3311 ; // already resolved
3312 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3315 resolved (e
->tok
, e
->type
);
3317 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
3319 e
->type
= e
->truevalue
->type
;
3320 resolved (e
->tok
, e
->type
);
3322 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
3324 e
->type
= e
->falsevalue
->type
;
3325 resolved (e
->tok
, e
->type
);
3327 else if (e
->type
!= sub_type
)
3328 mismatch (e
->tok
, sub_type
, e
->type
);
3332 template <class Referrer
, class Referent
>
3333 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
3334 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
3336 exp_type
& re_type
= referrer
->type
;
3337 const token
* re_tok
= referrer
->tok
;
3338 exp_type
& te_type
= referent
->type
;
3339 const token
* te_tok
= referent
->tok
;
3341 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
3342 ; // do nothing: all three e->types in agreement
3343 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
3344 ; // do nothing: two known e->types in agreement
3345 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
3346 r
->mismatch (re_tok
, re_type
, te_type
);
3347 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
3348 r
->mismatch (re_tok
, re_type
, t
);
3349 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
3350 r
->mismatch (te_tok
, te_type
, t
);
3351 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
3353 // propagate from upstream
3355 r
->resolved (re_tok
, re_type
);
3356 // catch re_type/te_type mismatch later
3358 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
3360 // propagate from referent
3362 r
->resolved (re_tok
, re_type
);
3363 // catch re_type/t mismatch later
3365 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
3367 // propagate to referent
3369 r
->resolved (te_tok
, te_type
);
3370 // catch re_type/t mismatch later
3372 else if (! accept_unknown
)
3373 r
->unresolved (re_tok
);
3378 typeresolution_info::visit_symbol (symbol
* e
)
3380 assert (e
->referent
!= 0);
3381 resolve_2types (e
, e
->referent
, this, t
);
3386 typeresolution_info::visit_target_symbol (target_symbol
* e
)
3388 // This occurs only if a target symbol was not resolved over in
3389 // tapset.cxx land, that error was properly suppressed, and the
3390 // later unused-expression-elimination pass didn't get rid of it
3391 // either. So we have a target symbol that is believed to be of
3392 // genuine use, yet unresolved by the provider.
3394 if (session
.verbose
> 2)
3396 clog
<< "Resolution problem with ";
3397 if (current_function
)
3399 clog
<< "function " << current_function
->name
<< endl
;
3400 current_function
->body
->print (clog
);
3403 else if (current_probe
)
3405 clog
<< "probe " << current_probe
->name
<< endl
;
3406 current_probe
->body
->print (clog
);
3410 clog
<< "other" << endl
;
3413 if (e
->saved_conversion_error
)
3414 throw (* (e
->saved_conversion_error
));
3416 throw semantic_error("unresolved target-symbol expression", e
->tok
);
3421 typeresolution_info::visit_arrayindex (arrayindex
* e
)
3424 symbol
*array
= NULL
;
3425 hist_op
*hist
= NULL
;
3426 classify_indexable(e
->base
, array
, hist
);
3428 // Every hist_op has type [int]:int, that is to say, every hist_op
3429 // is a pseudo-one-dimensional integer array type indexed by
3430 // integers (bucket numbers).
3434 if (e
->indexes
.size() != 1)
3435 unresolved (e
->tok
);
3437 e
->indexes
[0]->visit (this);
3438 if (e
->indexes
[0]->type
!= pe_long
)
3439 unresolved (e
->tok
);
3441 if (e
->type
!= pe_long
)
3444 resolved (e
->tok
, pe_long
);
3449 // Now we are left with "normal" map inference and index checking.
3452 assert (array
->referent
!= 0);
3453 resolve_2types (e
, array
->referent
, this, t
);
3455 // now resolve the array indexes
3457 // if (e->referent->index_types.size() == 0)
3458 // // redesignate referent as array
3459 // e->referent->set_arity (e->indexes.size ());
3461 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3462 unresolved (e
->tok
); // symbol resolution should prevent this
3463 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3465 expression
* ee
= e
->indexes
[i
];
3466 exp_type
& ft
= array
->referent
->index_types
[i
];
3469 exp_type at
= ee
->type
;
3471 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3473 // propagate to formal type
3475 resolved (array
->referent
->tok
, ft
);
3476 // uses array decl as there is no token for "formal type"
3479 invalid (ee
->tok
, at
);
3481 invalid (ee
->tok
, ft
);
3482 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3483 mismatch (e
->tok
, at
, ft
);
3484 if (at
== pe_unknown
)
3485 unresolved (ee
->tok
);
3491 typeresolution_info::visit_functioncall (functioncall
* e
)
3493 assert (e
->referent
!= 0);
3495 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
3497 if (e
->type
== pe_stats
)
3498 invalid (e
->tok
, e
->type
);
3500 // now resolve the function parameters
3501 if (e
->args
.size() != e
->referent
->formal_args
.size())
3502 unresolved (e
->tok
); // symbol resolution should prevent this
3503 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
3505 expression
* ee
= e
->args
[i
];
3506 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
3507 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
3510 exp_type at
= ee
->type
;
3512 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
3514 // propagate to formal arg
3516 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
3519 invalid (e
->tok
, at
);
3521 invalid (fe_tok
, ft
);
3522 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3523 mismatch (e
->tok
, at
, ft
);
3524 if (at
== pe_unknown
)
3525 unresolved (e
->tok
);
3531 typeresolution_info::visit_block (block
* e
)
3533 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
3538 e
->statements
[i
]->visit (this);
3540 catch (const semantic_error
& e
)
3542 session
.print_error (e
);
3549 typeresolution_info::visit_embeddedcode (embeddedcode
*)
3555 typeresolution_info::visit_if_statement (if_statement
* e
)
3558 e
->condition
->visit (this);
3561 e
->thenblock
->visit (this);
3566 e
->elseblock
->visit (this);
3572 typeresolution_info::visit_for_loop (for_loop
* e
)
3575 if (e
->init
) e
->init
->visit (this);
3577 e
->cond
->visit (this);
3579 if (e
->incr
) e
->incr
->visit (this);
3581 e
->block
->visit (this);
3586 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
3588 // See also visit_arrayindex.
3589 // This is different in that, being a statement, we can't assign
3590 // a type to the outer array, only propagate to/from the indexes
3592 // if (e->referent->index_types.size() == 0)
3593 // // redesignate referent as array
3594 // e->referent->set_arity (e->indexes.size ());
3596 symbol
*array
= NULL
;
3597 hist_op
*hist
= NULL
;
3598 classify_indexable(e
->base
, array
, hist
);
3602 if (e
->indexes
.size() != 1)
3603 unresolved (e
->tok
);
3605 e
->indexes
[0]->visit (this);
3606 if (e
->indexes
[0]->type
!= pe_long
)
3607 unresolved (e
->tok
);
3613 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3614 unresolved (e
->tok
); // symbol resolution should prevent this
3615 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3617 expression
* ee
= e
->indexes
[i
];
3618 exp_type
& ft
= array
->referent
->index_types
[i
];
3621 exp_type at
= ee
->type
;
3623 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3625 // propagate to formal type
3627 resolved (array
->referent
->tok
, ft
);
3628 // uses array decl as there is no token for "formal type"
3631 invalid (ee
->tok
, at
);
3633 invalid (ee
->tok
, ft
);
3634 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3635 mismatch (e
->tok
, at
, ft
);
3636 if (at
== pe_unknown
)
3637 unresolved (ee
->tok
);
3644 e
->limit
->visit (this);
3648 e
->block
->visit (this);
3653 typeresolution_info::visit_null_statement (null_statement
*)
3659 typeresolution_info::visit_expr_statement (expr_statement
* e
)
3662 e
->value
->visit (this);
3666 struct delete_statement_typeresolution_info
:
3667 public throwing_visitor
3669 typeresolution_info
*parent
;
3670 delete_statement_typeresolution_info (typeresolution_info
*p
):
3671 throwing_visitor ("invalid operand of delete expression"),
3675 void visit_arrayindex (arrayindex
* e
)
3677 parent
->visit_arrayindex (e
);
3680 void visit_symbol (symbol
* e
)
3682 exp_type ignored
= pe_unknown
;
3683 assert (e
->referent
!= 0);
3684 resolve_2types (e
, e
->referent
, parent
, ignored
);
3690 typeresolution_info::visit_delete_statement (delete_statement
* e
)
3692 delete_statement_typeresolution_info
di (this);
3694 e
->value
->visit (&di
);
3699 typeresolution_info::visit_next_statement (next_statement
*)
3705 typeresolution_info::visit_break_statement (break_statement
*)
3711 typeresolution_info::visit_continue_statement (continue_statement
*)
3717 typeresolution_info::visit_array_in (array_in
* e
)
3719 // all unary operators only work on numerics
3721 t
= pe_unknown
; // array value can be anything
3722 e
->operand
->visit (this);
3724 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
3725 ; // already resolved
3726 else if (t1
== pe_string
|| t1
== pe_stats
)
3727 mismatch (e
->tok
, t1
, pe_long
);
3728 else if (e
->type
== pe_unknown
)
3731 resolved (e
->tok
, e
->type
);
3737 typeresolution_info::visit_return_statement (return_statement
* e
)
3739 // This is like symbol, where the referent is
3740 // the return value of the function.
3742 // translation pass will print error
3743 if (current_function
== 0)
3746 exp_type
& e_type
= current_function
->type
;
3747 t
= current_function
->type
;
3748 e
->value
->visit (this);
3750 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
3751 && e_type
!= e
->value
->type
)
3752 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
3753 if (e_type
== pe_unknown
&&
3754 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
3756 // propagate non-statistics from value
3757 e_type
= e
->value
->type
;
3758 resolved (current_function
->tok
, e
->value
->type
);
3760 if (e
->value
->type
== pe_stats
)
3761 invalid (e
->value
->tok
, e
->value
->type
);
3765 typeresolution_info::visit_print_format (print_format
* e
)
3767 size_t unresolved_args
= 0;
3771 e
->hist
->visit(this);
3774 else if (e
->print_with_format
)
3776 // If there's a format string, we can do both inference *and*
3779 // First we extract the subsequence of formatting components
3780 // which are conversions (not just literal string components)
3782 unsigned expected_num_args
= 0;
3783 std::vector
<print_format::format_component
> components
;
3784 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
3786 if (e
->components
[i
].type
== print_format::conv_unspecified
)
3787 throw semantic_error ("Unspecified conversion in print operator format string",
3789 else if (e
->components
[i
].type
== print_format::conv_literal
3790 || e
->components
[i
].type
== print_format::conv_size
)
3792 components
.push_back(e
->components
[i
]);
3793 ++expected_num_args
;
3794 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
3795 ++expected_num_args
;
3796 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
3797 ++expected_num_args
;
3800 // Then we check that the number of conversions and the number
3803 if (expected_num_args
!= e
->args
.size())
3804 throw semantic_error ("Wrong number of args to formatted print operator",
3807 // Then we check that the types of the conversions match the types
3810 for (size_t i
= 0; i
< components
.size(); ++i
)
3812 // Check the dynamic width, if specified
3813 if (components
[i
].widthtype
== print_format::width_dynamic
)
3815 check_arg_type (pe_long
, e
->args
[argno
]);
3819 // Check the dynamic precision, if specified
3820 if (components
[i
].prectype
== print_format::prec_dynamic
)
3822 check_arg_type (pe_long
, e
->args
[argno
]);
3826 exp_type wanted
= pe_unknown
;
3828 switch (components
[i
].type
)
3830 case print_format::conv_unspecified
:
3831 case print_format::conv_literal
:
3832 case print_format::conv_size
:
3836 case print_format::conv_signed_decimal
:
3837 case print_format::conv_unsigned_decimal
:
3838 case print_format::conv_unsigned_octal
:
3839 case print_format::conv_unsigned_ptr
:
3840 case print_format::conv_unsigned_uppercase_hex
:
3841 case print_format::conv_unsigned_lowercase_hex
:
3842 case print_format::conv_binary
:
3843 case print_format::conv_memory
:
3847 case print_format::conv_string
:
3852 assert (wanted
!= pe_unknown
);
3853 check_arg_type (wanted
, e
->args
[argno
]);
3859 // Without a format string, the best we can do is require that
3860 // each argument resolve to a concrete type.
3861 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
3864 e
->args
[i
]->visit (this);
3865 if (e
->args
[i
]->type
== pe_unknown
)
3867 unresolved (e
->args
[i
]->tok
);
3873 if (unresolved_args
== 0)
3875 if (e
->type
== pe_unknown
)
3877 if (e
->print_to_stream
)
3880 e
->type
= pe_string
;
3881 resolved (e
->tok
, e
->type
);
3886 e
->type
= pe_unknown
;
3887 unresolved (e
->tok
);
3893 typeresolution_info::visit_stat_op (stat_op
* e
)
3896 e
->stat
->visit (this);
3897 if (e
->type
== pe_unknown
)
3900 resolved (e
->tok
, e
->type
);
3902 else if (e
->type
!= pe_long
)
3903 mismatch (e
->tok
, e
->type
, pe_long
);
3907 typeresolution_info::visit_hist_op (hist_op
* e
)
3910 e
->stat
->visit (this);
3915 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
3920 if (arg
->type
== pe_unknown
)
3923 resolved (arg
->tok
, wanted
);
3925 else if (arg
->type
!= wanted
)
3927 mismatch (arg
->tok
, arg
->type
, wanted
);
3933 typeresolution_info::unresolved (const token
* tok
)
3935 num_still_unresolved
++;
3937 if (assert_resolvability
)
3940 string nm
= (current_function
? current_function
->name
:
3941 current_probe
? current_probe
->name
:
3943 msg
<< nm
+ " with unresolved type";
3944 session
.print_error (semantic_error (msg
.str(), tok
));
3950 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
3952 num_still_unresolved
++;
3954 if (assert_resolvability
)
3957 string nm
= (current_function
? current_function
->name
:
3958 current_probe
? current_probe
->name
:
3960 if (tok
&& tok
->type
== tok_operator
)
3961 msg
<< nm
+ " uses invalid operator";
3963 msg
<< nm
+ " with invalid type " << pe
;
3964 session
.print_error (semantic_error (msg
.str(), tok
));
3970 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
3972 num_still_unresolved
++;
3974 if (assert_resolvability
)
3977 string nm
= (current_function
? current_function
->name
:
3978 current_probe
? current_probe
->name
:
3980 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
3981 session
.print_error (semantic_error (msg
.str(), tok
));
3987 typeresolution_info::resolved (const token
*, exp_type
)
3989 num_newly_resolved
++;