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 (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
916 sess
.functions
[i
]->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 (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
951 functiondecl
* fn
= sess
.functions
[i
];
954 set
<vardecl
*> * m
= new set
<vardecl
*>();
955 mutated_var_collector
mc (m
);
956 fn
->body
->visit (&mc
);
961 for (unsigned i
= 0; i
< sess
.functions
.size(); ++i
)
963 if (sess
.functions
[i
]->body
)
964 sess
.functions
[i
]->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
.push_back (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
)
1738 for (unsigned j
= 0; j
< session
.functions
.size(); j
++)
1740 functiondecl
* fd
= session
.functions
[j
];
1741 if (fd
->name
== name
&&
1742 fd
->formal_args
.size() == arity
)
1746 // search library globals
1747 for (unsigned i
=0; i
<session
.library_files
.size(); i
++)
1749 stapfile
* f
= session
.library_files
[i
];
1750 for (unsigned j
=0; j
<f
->functions
.size(); j
++)
1751 if (f
->functions
[j
]->name
== name
&&
1752 f
->functions
[j
]->formal_args
.size() == arity
)
1754 // put library into the queue if not already there
1755 if (0) // session.verbose_resolution
1756 cerr
<< " function " << name
<< " "
1757 << "is defined from " << f
->name
<< endl
;
1759 if (find (session
.files
.begin(), session
.files
.end(), f
)
1760 == session
.files
.end())
1761 session
.files
.push_back (f
);
1762 // else .. print different message?
1764 return f
->functions
[j
];
1773 // ------------------------------------------------------------------------
1777 // Do away with functiondecls that are never (transitively) called
1779 void semantic_pass_opt1 (systemtap_session
& s
, bool& relaxed_p
)
1781 functioncall_traversing_visitor ftv
;
1782 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1784 s
.probes
[i
]->body
->visit (& ftv
);
1785 if (s
.probes
[i
]->sole_location()->condition
)
1786 s
.probes
[i
]->sole_location()->condition
->visit (& ftv
);
1788 for (unsigned i
=0; i
<s
.functions
.size(); /* see below */)
1790 if (ftv
.traversed
.find(s
.functions
[i
]) == ftv
.traversed
.end())
1792 if (s
.functions
[i
]->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1793 ! s
.suppress_warnings
)
1794 s
.print_warning ("eliding unused function '" + s
.functions
[i
]->name
+ "'", s
.functions
[i
]->tok
);
1795 else if (s
.verbose
>2)
1796 clog
<< "Eliding unused function " << s
.functions
[i
]->name
1798 if (s
.tapset_compile_coverage
) {
1799 s
.unused_functions
.push_back (s
.functions
[i
]);
1801 s
.functions
.erase (s
.functions
.begin() + i
);
1803 // NB: don't increment i
1811 // ------------------------------------------------------------------------
1813 // Do away with local & global variables that are never
1814 // written nor read.
1815 void semantic_pass_opt2 (systemtap_session
& s
, bool& relaxed_p
, unsigned iterations
)
1817 varuse_collecting_visitor vut
;
1819 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1821 s
.probes
[i
]->body
->visit (& vut
);
1823 if (s
.probes
[i
]->sole_location()->condition
)
1824 s
.probes
[i
]->sole_location()->condition
->visit (& vut
);
1827 // NB: Since varuse_collecting_visitor also traverses down
1828 // actually called functions, we don't need to explicitly
1829 // iterate over them. Uncalled ones should have been pruned
1832 // for (unsigned i=0; i<s.functions.size(); i++)
1833 // s.functions[i]->body->visit (& vut);
1835 // Now in vut.read/written, we have a mixture of all locals, globals
1837 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
1838 for (unsigned j
=0; j
<s
.probes
[i
]->locals
.size(); /* see below */)
1840 vardecl
* l
= s
.probes
[i
]->locals
[j
];
1842 if (vut
.read
.find (l
) == vut
.read
.end() &&
1843 vut
.written
.find (l
) == vut
.written
.end())
1845 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1846 ! s
.suppress_warnings
)
1847 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1848 else if (s
.verbose
>2)
1849 clog
<< "Eliding unused local variable "
1850 << l
->name
<< " in " << s
.probes
[i
]->name
<< endl
;
1851 if (s
.tapset_compile_coverage
) {
1852 s
.probes
[i
]->unused_locals
.push_back
1853 (s
.probes
[i
]->locals
[j
]);
1855 s
.probes
[i
]->locals
.erase(s
.probes
[i
]->locals
.begin() + j
);
1857 // don't increment j
1861 if (vut
.written
.find (l
) == vut
.written
.end())
1862 if (iterations
== 0 && ! s
.suppress_warnings
)
1865 vector
<vardecl
*>::iterator it
;
1866 for (it
= s
.probes
[i
]->locals
.begin(); it
!= s
.probes
[i
]->locals
.end(); it
++)
1867 if (l
->name
!= (*it
)->name
)
1868 o
<< " " << (*it
)->name
;
1869 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1870 if (l
->name
!= (*it
)->name
)
1871 o
<< " " << (*it
)->name
;
1873 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
1874 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1880 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
1881 for (unsigned j
=0; j
<s
.functions
[i
]->locals
.size(); /* see below */)
1883 vardecl
* l
= s
.functions
[i
]->locals
[j
];
1884 if (vut
.read
.find (l
) == vut
.read
.end() &&
1885 vut
.written
.find (l
) == vut
.written
.end())
1887 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1888 ! s
.suppress_warnings
)
1889 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1890 else if (s
.verbose
>2)
1891 clog
<< "Eliding unused local variable "
1892 << l
->name
<< " in function " << s
.functions
[i
]->name
1894 if (s
.tapset_compile_coverage
) {
1895 s
.functions
[i
]->unused_locals
.push_back
1896 (s
.functions
[i
]->locals
[j
]);
1898 s
.functions
[i
]->locals
.erase(s
.functions
[i
]->locals
.begin() + j
);
1900 // don't increment j
1904 if (vut
.written
.find (l
) == vut
.written
.end())
1905 if (iterations
== 0 && ! s
.suppress_warnings
)
1908 vector
<vardecl
*>::iterator it
;
1909 for ( it
= s
.functions
[i
]->formal_args
.begin() ;
1910 it
!= s
.functions
[i
]->formal_args
.end(); it
++)
1911 if (l
->name
!= (*it
)->name
)
1912 o
<< " " << (*it
)->name
;
1913 for (it
= s
.functions
[i
]->locals
.begin(); it
!= s
.functions
[i
]->locals
.end(); it
++)
1914 if (l
->name
!= (*it
)->name
)
1915 o
<< " " << (*it
)->name
;
1916 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1917 if (l
->name
!= (*it
)->name
)
1918 o
<< " " << (*it
)->name
;
1920 s
.print_warning ("read-only local variable '" + l
->name
+ "' " +
1921 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1927 for (unsigned i
=0; i
<s
.globals
.size(); /* see below */)
1929 vardecl
* l
= s
.globals
[i
];
1930 if (vut
.read
.find (l
) == vut
.read
.end() &&
1931 vut
.written
.find (l
) == vut
.written
.end())
1933 if (l
->tok
->location
.file
== s
.user_file
->name
&& // !tapset
1934 ! s
.suppress_warnings
)
1935 s
.print_warning ("eliding unused variable '" + l
->name
+ "'", l
->tok
);
1936 else if (s
.verbose
>2)
1937 clog
<< "Eliding unused global variable "
1939 if (s
.tapset_compile_coverage
) {
1940 s
.unused_globals
.push_back(s
.globals
[i
]);
1942 s
.globals
.erase(s
.globals
.begin() + i
);
1944 // don't increment i
1948 if (vut
.written
.find (l
) == vut
.written
.end() && ! l
->init
) // no initializer
1949 if (iterations
== 0 && ! s
.suppress_warnings
)
1952 vector
<vardecl
*>::iterator it
;
1953 for (it
= s
.globals
.begin(); it
!= s
.globals
.end(); it
++)
1954 if (l
->name
!= (*it
)->name
)
1955 o
<< " " << (*it
)->name
;
1957 s
.print_warning ("read-only global variable '" + l
->name
+ "' " +
1958 (o
.str() == "" ? "" : ("(alternatives:" + o
.str() + ")")), l
->tok
);
1967 // ------------------------------------------------------------------------
1969 struct dead_assignment_remover
: public traversing_visitor
1971 systemtap_session
& session
;
1973 const varuse_collecting_visitor
& vut
;
1974 expression
** current_expr
;
1976 dead_assignment_remover(systemtap_session
& s
, bool& r
,
1977 const varuse_collecting_visitor
& v
):
1978 session(s
), relaxed_p(r
), vut(v
), current_expr(0) {}
1980 void visit_expr_statement (expr_statement
* s
);
1981 // XXX: other places where an assignment may be nested should be
1982 // handled too (e.g., loop/if conditionals, array indexes, function
1983 // parameters). Until then, they result in visit_assignment() being
1984 // called with null current_expr.
1986 void visit_assignment (assignment
* e
);
1987 void visit_binary_expression (binary_expression
* e
);
1988 void visit_arrayindex (arrayindex
* e
);
1989 void visit_functioncall (functioncall
* e
);
1990 void visit_if_statement (if_statement
* e
);
1991 void visit_for_loop (for_loop
* e
);
1996 dead_assignment_remover::visit_expr_statement (expr_statement
* s
)
1998 expression
** last_expr
= current_expr
;
1999 current_expr
= & s
->value
;
2000 s
->value
->visit (this);
2001 s
->tok
= s
->value
->tok
; // in case it was replaced
2002 current_expr
= last_expr
;
2007 dead_assignment_remover::visit_assignment (assignment
* e
)
2009 symbol
* left
= get_symbol_within_expression (e
->left
);
2010 vardecl
* leftvar
= left
->referent
; // NB: may be 0 for unresolved $target
2011 if (current_expr
&& // see XXX above: this case represents a missed
2012 // optimization opportunity
2013 *current_expr
== e
&& // we're not nested any deeper than expected
2014 leftvar
) // not unresolved $target; intended sideeffect cannot be elided
2016 expression
** last_expr
= current_expr
;
2017 e
->left
->visit (this);
2018 current_expr
= &e
->right
;
2019 e
->right
->visit (this);
2020 current_expr
= last_expr
;
2022 if (vut
.read
.find(leftvar
) == vut
.read
.end()) // var never read?
2024 // NB: Not so fast! The left side could be an array whose
2025 // index expressions may have side-effects. This would be
2026 // OK if we could replace the array assignment with a
2027 // statement-expression containing all the index expressions
2028 // and the rvalue... but we can't.
2029 // Another possibility is that we have an unread global variable
2030 // which are kept for probe end value display.
2032 bool is_global
= false;
2033 vector
<vardecl
*>::iterator it
;
2034 for (it
= session
.globals
.begin(); it
!= session
.globals
.end(); it
++)
2035 if (leftvar
->name
== (*it
)->name
)
2041 varuse_collecting_visitor vut
;
2042 e
->left
->visit (& vut
);
2043 if (vut
.side_effect_free () && !is_global
) // XXX: use _wrt() once we track focal_vars
2045 /* PR 1119: NB: This is not necessary here. A write-only
2046 variable will also be elided soon at the next _opt2 iteration.
2047 if (e->left->tok->location.file == session.user_file->name && // !tapset
2048 ! session.suppress_warnings)
2049 clog << "WARNING: eliding write-only " << *e->left->tok << endl;
2052 if (session
.verbose
>2)
2053 clog
<< "Eliding assignment to " << leftvar
->name
2054 << " at " << *e
->tok
<< endl
;
2056 *current_expr
= e
->right
; // goodbye assignment*
2064 dead_assignment_remover::visit_binary_expression (binary_expression
* e
)
2066 expression
** last_expr
= current_expr
;
2067 current_expr
= &e
->left
;
2068 e
->left
->visit (this);
2069 current_expr
= &e
->right
;
2070 e
->right
->visit (this);
2071 current_expr
= last_expr
;
2075 dead_assignment_remover::visit_arrayindex (arrayindex
*e
)
2077 symbol
*array
= NULL
;
2078 hist_op
*hist
= NULL
;
2079 classify_indexable(e
->base
, array
, hist
);
2083 expression
** last_expr
= current_expr
;
2084 for (unsigned i
=0; i
< e
->indexes
.size(); i
++)
2086 current_expr
= & e
->indexes
[i
];
2087 e
->indexes
[i
]->visit (this);
2089 current_expr
= last_expr
;
2094 dead_assignment_remover::visit_functioncall (functioncall
* e
)
2096 expression
** last_expr
= current_expr
;
2097 for (unsigned i
=0; i
<e
->args
.size(); i
++)
2099 current_expr
= & e
->args
[i
];
2100 e
->args
[i
]->visit (this);
2102 current_expr
= last_expr
;
2106 dead_assignment_remover::visit_if_statement (if_statement
* s
)
2108 expression
** last_expr
= current_expr
;
2109 current_expr
= & s
->condition
;
2110 s
->condition
->visit (this);
2111 s
->thenblock
->visit (this);
2113 s
->elseblock
->visit (this);
2114 current_expr
= last_expr
;
2118 dead_assignment_remover::visit_for_loop (for_loop
* s
)
2120 expression
** last_expr
= current_expr
;
2121 if (s
->init
) s
->init
->visit (this);
2122 current_expr
= & s
->cond
;
2123 s
->cond
->visit (this);
2124 if (s
->incr
) s
->incr
->visit (this);
2125 s
->block
->visit (this);
2126 current_expr
= last_expr
;
2129 // Let's remove assignments to variables that are never read. We
2130 // rewrite "(foo = expr)" as "(expr)". This makes foo a candidate to
2131 // be optimized away as an unused variable, and expr a candidate to be
2132 // removed as a side-effect-free statement expression. Wahoo!
2133 void semantic_pass_opt3 (systemtap_session
& s
, bool& relaxed_p
)
2135 // Recompute the varuse data, which will probably match the opt2
2136 // copy of the computation, except for those totally unused
2137 // variables that opt2 removed.
2138 varuse_collecting_visitor vut
;
2139 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2140 s
.probes
[i
]->body
->visit (& vut
); // includes reachable functions too
2142 dead_assignment_remover
dar (s
, relaxed_p
, vut
);
2143 // This instance may be reused for multiple probe/function body trims.
2145 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2146 s
.probes
[i
]->body
->visit (& dar
);
2147 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
2148 s
.functions
[i
]->body
->visit (& dar
);
2149 // The rewrite operation is performed within the visitor.
2151 // XXX: we could also zap write-only globals here
2155 // ------------------------------------------------------------------------
2157 struct dead_stmtexpr_remover
: public traversing_visitor
2159 systemtap_session
& session
;
2161 statement
** current_stmt
; // pointer to current stmt* being iterated
2162 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2164 dead_stmtexpr_remover(systemtap_session
& s
, bool& r
):
2165 session(s
), relaxed_p(r
), current_stmt(0) {}
2167 void visit_block (block
*s
);
2168 void visit_null_statement (null_statement
*s
);
2169 void visit_if_statement (if_statement
* s
);
2170 void visit_foreach_loop (foreach_loop
*s
);
2171 void visit_for_loop (for_loop
*s
);
2172 // XXX: and other places where stmt_expr's might be nested
2174 void visit_expr_statement (expr_statement
*s
);
2179 dead_stmtexpr_remover::visit_null_statement (null_statement
*s
)
2182 if (session
.verbose
>2)
2183 clog
<< "Eliding side-effect-free null statement " << *s
->tok
<< endl
;
2189 dead_stmtexpr_remover::visit_block (block
*s
)
2191 vector
<statement
*> new_stmts
;
2192 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2194 statement
** last_stmt
= current_stmt
;
2195 current_stmt
= & s
->statements
[i
];
2196 s
->statements
[i
]->visit (this);
2197 if (*current_stmt
!= 0)
2199 // flatten nested blocks into this one
2200 block
*b
= dynamic_cast<block
*>(*current_stmt
);
2203 if (session
.verbose
>2)
2204 clog
<< "Flattening nested block " << *b
->tok
<< endl
;
2205 new_stmts
.insert(new_stmts
.end(),
2206 b
->statements
.begin(), b
->statements
.end());
2210 new_stmts
.push_back (*current_stmt
);
2212 current_stmt
= last_stmt
;
2214 if (new_stmts
.size() == 0)
2216 if (session
.verbose
>2)
2217 clog
<< "Eliding side-effect-free empty block " << *s
->tok
<< endl
;
2220 else if (new_stmts
.size() == 1)
2222 if (session
.verbose
>2)
2223 clog
<< "Eliding side-effect-free singleton block " << *s
->tok
<< endl
;
2224 *current_stmt
= new_stmts
[0];
2228 s
->statements
= new_stmts
;
2233 dead_stmtexpr_remover::visit_if_statement (if_statement
*s
)
2235 statement
** last_stmt
= current_stmt
;
2236 current_stmt
= & s
->thenblock
;
2237 s
->thenblock
->visit (this);
2241 current_stmt
= & s
->elseblock
;
2242 s
->elseblock
->visit (this);
2243 // null *current_stmt is OK here.
2245 current_stmt
= last_stmt
;
2247 if (s
->thenblock
== 0)
2249 if (s
->elseblock
== 0)
2251 // We may be able to elide this statement, if the condition
2252 // expression is side-effect-free.
2253 varuse_collecting_visitor vct
;
2254 s
->condition
->visit(& vct
);
2255 if (vct
.side_effect_free ())
2257 if (session
.verbose
>2)
2258 clog
<< "Eliding side-effect-free if statement "
2260 *current_stmt
= 0; // yeah, baby
2264 // We can still turn it into a simple expr_statement though...
2265 if (session
.verbose
>2)
2266 clog
<< "Creating simple evaluation from if statement "
2268 expr_statement
*es
= new expr_statement
;
2269 es
->value
= s
->condition
;
2270 es
->tok
= es
->value
->tok
;
2276 // For an else without a then, we can invert the condition logic to
2277 // avoid having a null statement in the thenblock
2278 if (session
.verbose
>2)
2279 clog
<< "Inverting the condition of if statement "
2281 unary_expression
*ue
= new unary_expression
;
2282 ue
->operand
= s
->condition
;
2283 ue
->tok
= ue
->operand
->tok
;
2286 s
->thenblock
= s
->elseblock
;
2293 dead_stmtexpr_remover::visit_foreach_loop (foreach_loop
*s
)
2295 statement
** last_stmt
= current_stmt
;
2296 current_stmt
= & s
->block
;
2297 s
->block
->visit (this);
2298 current_stmt
= last_stmt
;
2302 if (session
.verbose
>2)
2303 clog
<< "Eliding side-effect-free foreach statement " << *s
->tok
<< endl
;
2304 *current_stmt
= 0; // yeah, baby
2309 dead_stmtexpr_remover::visit_for_loop (for_loop
*s
)
2311 statement
** last_stmt
= current_stmt
;
2312 current_stmt
= & s
->block
;
2313 s
->block
->visit (this);
2314 current_stmt
= last_stmt
;
2318 // We may be able to elide this statement, if the condition
2319 // expression is side-effect-free.
2320 varuse_collecting_visitor vct
;
2321 if (s
->init
) s
->init
->visit(& vct
);
2322 s
->cond
->visit(& vct
);
2323 if (s
->incr
) s
->incr
->visit(& vct
);
2324 if (vct
.side_effect_free ())
2326 if (session
.verbose
>2)
2327 clog
<< "Eliding side-effect-free for statement " << *s
->tok
<< endl
;
2328 *current_stmt
= 0; // yeah, baby
2332 // Can't elide this whole statement; put a null in there.
2333 s
->block
= new null_statement();
2334 s
->block
->tok
= s
->tok
;
2341 dead_stmtexpr_remover::visit_expr_statement (expr_statement
*s
)
2343 // Run a varuse query against the operand expression. If it has no
2344 // side-effects, replace the entire statement expression by a null
2345 // statement. This replacement is done by overwriting the
2346 // current_stmt pointer.
2348 // Unlike many other visitors, we do *not* traverse this outermost
2349 // one into the expression subtrees. There is no need - no
2350 // expr_statement nodes will be found there. (Function bodies
2351 // need to be visited explicitly by our caller.)
2353 // NB. While we don't share nodes in the parse tree, let's not
2354 // deallocate *s anyway, just in case...
2356 varuse_collecting_visitor vut
;
2357 s
->value
->visit (& vut
);
2359 if (vut
.side_effect_free_wrt (focal_vars
) &&
2360 *current_stmt
== s
) // we're not nested any deeper than expected
2362 /* PR 1119: NB: this message is not a good idea here. It can
2363 name some arbitrary RHS expression of an assignment.
2364 if (s->value->tok->location.file == session.user_file->name && // not tapset
2365 ! session.suppress_warnings)
2366 clog << "WARNING: eliding read-only " << *s->value->tok << endl;
2369 if (session
.verbose
>2)
2370 clog
<< "Eliding side-effect-free expression "
2373 // NB: this 0 pointer is invalid to leave around for any length of
2374 // time, but the parent parse tree objects above handle it.
2382 void semantic_pass_opt4 (systemtap_session
& s
, bool& relaxed_p
)
2384 // Finally, let's remove some statement-expressions that have no
2385 // side-effect. These should be exactly those whose private varuse
2386 // visitors come back with an empty "written" and "embedded" lists.
2388 dead_stmtexpr_remover
duv (s
, relaxed_p
);
2389 // This instance may be reused for multiple probe/function body trims.
2391 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2393 derived_probe
* p
= s
.probes
[i
];
2395 duv
.focal_vars
.clear ();
2396 duv
.focal_vars
.insert (s
.globals
.begin(),
2398 duv
.focal_vars
.insert (p
->locals
.begin(),
2401 duv
.current_stmt
= & p
->body
;
2402 p
->body
->visit (& duv
);
2405 if (! s
.suppress_warnings
)
2406 s
.print_warning ("side-effect-free probe '" + p
->name
+ "'", p
->tok
);
2408 p
->body
= new null_statement();
2409 p
->body
->tok
= p
->tok
;
2411 // XXX: possible duplicate warnings; see below
2414 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
2416 functiondecl
* fn
= s
.functions
[i
];
2417 duv
.focal_vars
.clear ();
2418 duv
.focal_vars
.insert (fn
->locals
.begin(),
2420 duv
.focal_vars
.insert (fn
->formal_args
.begin(),
2421 fn
->formal_args
.end());
2422 duv
.focal_vars
.insert (s
.globals
.begin(),
2425 duv
.current_stmt
= & fn
->body
;
2426 fn
->body
->visit (& duv
);
2429 if (! s
.suppress_warnings
)
2430 s
.print_warning ("side-effect-free function '" + fn
->name
+ "'", fn
->tok
);
2432 fn
->body
= new null_statement();
2433 fn
->body
->tok
= fn
->tok
;
2435 // XXX: the next iteration of the outer optimization loop may
2436 // take this new null_statement away again, and thus give us a
2437 // fresh warning. It would be better if this fixup was performed
2438 // only after the relaxation iterations.
2439 // XXX: or else see bug #6469.
2445 // ------------------------------------------------------------------------
2447 // The goal of this visitor is to reduce top-level expressions in void context
2448 // into separate statements that evaluate each subcomponent of the expression.
2449 // The dead-statement-remover can later remove some parts if they have no side
2451 struct void_statement_reducer
: public traversing_visitor
2453 systemtap_session
& session
;
2455 statement
** current_stmt
; // pointer to current stmt* being iterated
2456 expr_statement
* current_expr
; // pointer to current expr being iterated
2457 set
<vardecl
*> focal_vars
; // vars considered subject to side-effects
2459 void_statement_reducer(systemtap_session
& s
, bool& r
):
2460 session(s
), relaxed_p(r
), current_stmt(0), current_expr(0) {}
2462 // these just maintain current_stmt while recursing, but don't visit
2463 // expressions in the conditional / loop controls.
2464 void visit_expr_statement (expr_statement
* s
);
2465 void visit_block (block
*s
);
2466 void visit_if_statement (if_statement
* s
);
2467 void visit_for_loop (for_loop
* s
);
2468 void visit_foreach_loop (foreach_loop
* s
);
2470 // these expressions get rewritten into their statement equivalents
2471 void visit_logical_or_expr (logical_or_expr
* e
);
2472 void visit_logical_and_expr (logical_and_expr
* e
);
2473 void visit_ternary_expression (ternary_expression
* e
);
2475 // all of these can be reduced into simpler statements
2476 void visit_binary_expression (binary_expression
* e
);
2477 void visit_unary_expression (unary_expression
* e
);
2478 void visit_comparison (comparison
* e
);
2479 void visit_concatenation (concatenation
* e
);
2480 void visit_functioncall (functioncall
* e
);
2481 void visit_print_format (print_format
* e
);
2483 // these are a bit hairy to grok due to the intricacies of indexables and
2484 // stats, so I'm chickening out and skipping them...
2485 void visit_array_in (array_in
* e
) {}
2486 void visit_arrayindex (arrayindex
* e
) {}
2487 void visit_stat_op (stat_op
* e
) {}
2488 void visit_hist_op (hist_op
* e
) {}
2490 // these can't be reduced because they always have an effect
2491 void visit_return_statement (return_statement
* s
) {}
2492 void visit_delete_statement (delete_statement
* s
) {}
2493 void visit_pre_crement (pre_crement
* e
) {}
2494 void visit_post_crement (post_crement
* e
) {}
2495 void visit_assignment (assignment
* e
) {}
2500 void_statement_reducer::visit_expr_statement (expr_statement
* s
)
2502 assert(!current_expr
); // it shouldn't be possible to have nested expr's
2504 s
->value
->visit (this);
2505 current_expr
= NULL
;
2509 void_statement_reducer::visit_block (block
*s
)
2511 statement
** last_stmt
= current_stmt
;
2512 for (unsigned i
=0; i
<s
->statements
.size(); i
++ )
2514 current_stmt
= & s
->statements
[i
];
2515 s
->statements
[i
]->visit (this);
2517 current_stmt
= last_stmt
;
2521 void_statement_reducer::visit_if_statement (if_statement
* s
)
2523 statement
** last_stmt
= current_stmt
;
2524 current_stmt
= & s
->thenblock
;
2525 s
->thenblock
->visit (this);
2529 current_stmt
= & s
->elseblock
;
2530 s
->elseblock
->visit (this);
2532 current_stmt
= last_stmt
;
2536 void_statement_reducer::visit_for_loop (for_loop
* s
)
2538 statement
** last_stmt
= current_stmt
;
2539 current_stmt
= & s
->block
;
2540 s
->block
->visit (this);
2541 current_stmt
= last_stmt
;
2545 void_statement_reducer::visit_foreach_loop (foreach_loop
* s
)
2547 statement
** last_stmt
= current_stmt
;
2548 current_stmt
= & s
->block
;
2549 s
->block
->visit (this);
2550 current_stmt
= last_stmt
;
2554 void_statement_reducer::visit_logical_or_expr (logical_or_expr
* e
)
2556 // In void context, the evaluation of "a || b" is exactly like
2557 // "if (!a) b", so let's do that instead.
2559 assert(current_expr
&& current_expr
->value
== e
);
2561 if (session
.verbose
>2)
2562 clog
<< "Creating if statement from unused logical-or "
2565 if_statement
*is
= new if_statement
;
2569 current_expr
= NULL
;
2571 unary_expression
*ue
= new unary_expression
;
2572 ue
->operand
= e
->left
;
2577 expr_statement
*es
= new expr_statement
;
2578 es
->value
= e
->right
;
2579 es
->tok
= es
->value
->tok
;
2587 void_statement_reducer::visit_logical_and_expr (logical_and_expr
* e
)
2589 // In void context, the evaluation of "a && b" is exactly like
2590 // "if (a) b", so let's do that instead.
2592 assert(current_expr
&& current_expr
->value
== e
);
2594 if (session
.verbose
>2)
2595 clog
<< "Creating if statement from unused logical-and "
2598 if_statement
*is
= new if_statement
;
2601 is
->condition
= e
->left
;
2603 current_expr
= NULL
;
2605 expr_statement
*es
= new expr_statement
;
2606 es
->value
= e
->right
;
2607 es
->tok
= es
->value
->tok
;
2615 void_statement_reducer::visit_ternary_expression (ternary_expression
* e
)
2617 // In void context, the evaluation of "a ? b : c" is exactly like
2618 // "if (a) b else c", so let's do that instead.
2620 assert(current_expr
&& current_expr
->value
== e
);
2622 if (session
.verbose
>2)
2623 clog
<< "Creating if statement from unused ternary expression "
2626 if_statement
*is
= new if_statement
;
2628 is
->condition
= e
->cond
;
2630 current_expr
= NULL
;
2632 expr_statement
*es
= new expr_statement
;
2633 es
->value
= e
->truevalue
;
2634 es
->tok
= es
->value
->tok
;
2637 es
= new expr_statement
;
2638 es
->value
= e
->falsevalue
;
2639 es
->tok
= es
->value
->tok
;
2647 void_statement_reducer::visit_binary_expression (binary_expression
* e
)
2649 // When the result of a binary operation isn't needed, it's just as good to
2650 // evaluate the operands as sequential statements in a block.
2652 assert(current_expr
&& current_expr
->value
== e
);
2654 if (session
.verbose
>2)
2655 clog
<< "Eliding unused binary " << *e
->tok
<< endl
;
2657 block
*b
= new block
;
2658 b
->tok
= current_expr
->tok
;
2660 current_expr
= NULL
;
2662 expr_statement
*es
= new expr_statement
;
2663 es
->value
= e
->left
;
2664 es
->tok
= es
->value
->tok
;
2665 b
->statements
.push_back(es
);
2667 es
= new expr_statement
;
2668 es
->value
= e
->right
;
2669 es
->tok
= es
->value
->tok
;
2670 b
->statements
.push_back(es
);
2677 void_statement_reducer::visit_unary_expression (unary_expression
* e
)
2679 // When the result of a unary operation isn't needed, it's just as good to
2680 // evaluate the operand directly
2682 assert(current_expr
&& current_expr
->value
== e
);
2684 if (session
.verbose
>2)
2685 clog
<< "Eliding unused unary " << *e
->tok
<< endl
;
2687 current_expr
->value
= e
->operand
;
2688 current_expr
->tok
= current_expr
->value
->tok
;
2689 current_expr
->value
->visit(this);
2695 void_statement_reducer::visit_comparison (comparison
* e
)
2697 visit_binary_expression(e
);
2701 void_statement_reducer::visit_concatenation (concatenation
* e
)
2703 visit_binary_expression(e
);
2707 void_statement_reducer::visit_functioncall (functioncall
* e
)
2709 // If a function call is pure and its result ignored, we can elide the call
2710 // and just evaluate the arguments in sequence
2712 if (!e
->args
.size())
2715 varuse_collecting_visitor vut
;
2716 vut
.traversed
.insert (e
->referent
);
2717 vut
.current_function
= e
->referent
;
2718 e
->referent
->body
->visit (& vut
);
2719 if (!vut
.side_effect_free_wrt (focal_vars
))
2722 assert(current_expr
&& current_expr
->value
== e
);
2724 if (session
.verbose
>2)
2725 clog
<< "Eliding side-effect-free function call " << *e
->tok
<< endl
;
2727 block
*b
= new block
;
2730 current_expr
= NULL
;
2732 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2734 expr_statement
*es
= new expr_statement
;
2735 es
->value
= e
->args
[i
];
2736 es
->tok
= es
->value
->tok
;
2737 b
->statements
.push_back(es
);
2745 void_statement_reducer::visit_print_format (print_format
* e
)
2747 // When an sprint's return value is ignored, we can simply evaluate the
2748 // arguments in sequence
2750 if (e
->print_to_stream
|| !e
->args
.size())
2753 assert(current_expr
&& current_expr
->value
== e
);
2755 if (session
.verbose
>2)
2756 clog
<< "Eliding unused print " << *e
->tok
<< endl
;
2758 block
*b
= new block
;
2761 current_expr
= NULL
;
2763 for (unsigned i
=0; i
<e
->args
.size(); i
++ )
2765 expr_statement
*es
= new expr_statement
;
2766 es
->value
= e
->args
[i
];
2767 es
->tok
= es
->value
->tok
;
2768 b
->statements
.push_back(es
);
2776 void semantic_pass_opt5 (systemtap_session
& s
, bool& relaxed_p
)
2778 // Let's simplify statements with unused computed values.
2780 void_statement_reducer
vuv (s
, relaxed_p
);
2781 // This instance may be reused for multiple probe/function body trims.
2783 vuv
.focal_vars
.insert (s
.globals
.begin(), s
.globals
.end());
2785 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
2787 derived_probe
* p
= s
.probes
[i
];
2788 vuv
.current_stmt
= & p
->body
;
2789 p
->body
->visit (& vuv
);
2791 for (unsigned i
=0; i
<s
.functions
.size(); i
++)
2793 functiondecl
* fn
= s
.functions
[i
];
2794 vuv
.current_stmt
= & fn
->body
;
2795 fn
->body
->visit (& vuv
);
2800 struct duplicate_function_remover
: public functioncall_traversing_visitor
2802 systemtap_session
& s
;
2803 map
<functiondecl
*, functiondecl
*>& duplicate_function_map
;
2805 duplicate_function_remover(systemtap_session
& sess
,
2806 map
<functiondecl
*, functiondecl
*>&dfm
):
2807 s(sess
), duplicate_function_map(dfm
) {};
2809 void visit_functioncall (functioncall
* e
);
2813 duplicate_function_remover::visit_functioncall (functioncall
*e
)
2815 functioncall_traversing_visitor::visit_functioncall (e
);
2817 // If the current function call reference points to a function that
2818 // is a duplicate, replace it.
2819 if (duplicate_function_map
.count(e
->referent
) != 0)
2822 clog
<< "Changing " << e
->referent
->name
2824 << duplicate_function_map
[e
->referent
]->name
2826 e
->tok
= duplicate_function_map
[e
->referent
]->tok
;
2827 e
->function
= duplicate_function_map
[e
->referent
]->name
;
2828 e
->referent
= duplicate_function_map
[e
->referent
];
2833 get_functionsig (functiondecl
* f
)
2837 // Get the "name:args body" of the function in s. We have to
2838 // include the args since the function 'x1(a, b)' is different than
2839 // the function 'x2(b, a)' even if the bodies of the two functions
2840 // are exactly the same.
2844 // printsig puts f->name + ':' on the front. Remove this
2845 // (otherwise, functions would never compare equal).
2846 string str
= s
.str().erase(0, f
->name
.size() + 1);
2848 // Return the function signature.
2852 void semantic_pass_opt6 (systemtap_session
& s
, bool& relaxed_p
)
2854 // Walk through all the functions, looking for duplicates.
2855 map
<string
, functiondecl
*> functionsig_map
;
2856 map
<functiondecl
*, functiondecl
*> duplicate_function_map
;
2857 for (unsigned i
=0; i
< s
.functions
.size(); /* see below */)
2859 string functionsig
= get_functionsig(s
.functions
[i
]);
2861 if (functionsig_map
.count(functionsig
) == 0)
2863 // This function is unique. Remember it.
2864 functionsig_map
[functionsig
] = s
.functions
[i
];
2869 // This function is a duplicate.
2870 duplicate_function_map
[s
.functions
[i
]]
2871 = functionsig_map
[functionsig
];
2873 // Remove the duplicate function (since we don't need it
2875 s
.functions
.erase (s
.functions
.begin() + i
);
2878 // NB: don't increment i
2882 // If we have duplicate functions, traverse down the tree, replacing
2883 // the appropriate function calls.
2884 // duplicate_function_remover::visit_functioncall() handles the
2885 // details of replacing the function calls.
2886 if (duplicate_function_map
.size() != 0)
2888 duplicate_function_remover
dfr (s
, duplicate_function_map
);
2890 for (unsigned i
=0; i
< s
.probes
.size(); i
++)
2891 s
.probes
[i
]->body
->visit(&dfr
);
2897 semantic_pass_optimize1 (systemtap_session
& s
)
2899 // In this pass, we attempt to rewrite probe/function bodies to
2900 // eliminate some blatantly unnecessary code. This is run before
2901 // type inference, but after symbol resolution and derived_probe
2902 // creation. We run an outer "relaxation" loop that repeats the
2903 // optimizations until none of them find anything to remove.
2907 bool relaxed_p
= false;
2908 unsigned iterations
= 0;
2911 if (pending_interrupts
) break;
2913 relaxed_p
= true; // until proven otherwise
2915 semantic_pass_opt1 (s
, relaxed_p
);
2916 semantic_pass_opt2 (s
, relaxed_p
, iterations
); // produce some warnings only on iteration=0
2917 semantic_pass_opt3 (s
, relaxed_p
);
2918 semantic_pass_opt4 (s
, relaxed_p
);
2919 semantic_pass_opt5 (s
, relaxed_p
);
2929 semantic_pass_optimize2 (systemtap_session
& s
)
2931 // This is run after type inference. We run an outer "relaxation"
2932 // loop that repeats the optimizations until none of them find
2933 // anything to remove.
2937 bool relaxed_p
= false;
2940 if (pending_interrupts
) break;
2941 relaxed_p
= true; // until proven otherwise
2943 semantic_pass_opt6 (s
, relaxed_p
);
2951 // ------------------------------------------------------------------------
2956 semantic_pass_types (systemtap_session
& s
)
2960 // next pass: type inference
2961 unsigned iterations
= 0;
2962 typeresolution_info
ti (s
);
2964 ti
.assert_resolvability
= false;
2965 // XXX: maybe convert to exception-based error signalling
2968 if (pending_interrupts
) break;
2971 ti
.num_newly_resolved
= 0;
2972 ti
.num_still_unresolved
= 0;
2974 for (unsigned j
=0; j
<s
.functions
.size(); j
++)
2976 if (pending_interrupts
) break;
2978 functiondecl
* fn
= s
.functions
[j
];
2979 ti
.current_probe
= 0;
2980 ti
.current_function
= fn
;
2982 fn
->body
->visit (& ti
);
2983 // NB: we don't have to assert a known type for
2984 // functions here, to permit a "void" function.
2985 // The translator phase will omit the "retvalue".
2987 // if (fn->type == pe_unknown)
2988 // ti.unresolved (fn->tok);
2991 for (unsigned j
=0; j
<s
.probes
.size(); j
++)
2993 if (pending_interrupts
) break;
2995 derived_probe
* pn
= s
.probes
[j
];
2996 ti
.current_function
= 0;
2997 ti
.current_probe
= pn
;
2999 pn
->body
->visit (& ti
);
3001 probe_point
* pp
= pn
->sole_location();
3004 ti
.current_function
= 0;
3005 ti
.current_probe
= 0;
3006 ti
.t
= pe_long
; // NB: expected type
3007 pp
->condition
->visit (& ti
);
3011 for (unsigned j
=0; j
<s
.globals
.size(); j
++)
3013 vardecl
* gd
= s
.globals
[j
];
3014 if (gd
->type
== pe_unknown
)
3015 ti
.unresolved (gd
->tok
);
3018 if (ti
.num_newly_resolved
== 0) // converged
3020 if (ti
.num_still_unresolved
== 0)
3021 break; // successfully
3022 else if (! ti
.assert_resolvability
)
3023 ti
.assert_resolvability
= true; // last pass, with error msgs
3025 { // unsuccessful conclusion
3032 return rc
+ s
.num_errors();
3037 typeresolution_info::typeresolution_info (systemtap_session
& s
):
3038 session(s
), current_function(0), current_probe(0)
3044 typeresolution_info::visit_literal_number (literal_number
* e
)
3046 assert (e
->type
== pe_long
);
3047 if ((t
== e
->type
) || (t
== pe_unknown
))
3050 mismatch (e
->tok
, e
->type
, t
);
3055 typeresolution_info::visit_literal_string (literal_string
* e
)
3057 assert (e
->type
== pe_string
);
3058 if ((t
== e
->type
) || (t
== pe_unknown
))
3061 mismatch (e
->tok
, e
->type
, t
);
3066 typeresolution_info::visit_logical_or_expr (logical_or_expr
*e
)
3068 visit_binary_expression (e
);
3073 typeresolution_info::visit_logical_and_expr (logical_and_expr
*e
)
3075 visit_binary_expression (e
);
3080 typeresolution_info::visit_comparison (comparison
*e
)
3082 // NB: result of any comparison is an integer!
3083 if (t
== pe_stats
|| t
== pe_string
)
3084 invalid (e
->tok
, t
);
3086 t
= (e
->right
->type
!= pe_unknown
) ? e
->right
->type
: pe_unknown
;
3087 e
->left
->visit (this);
3088 t
= (e
->left
->type
!= pe_unknown
) ? e
->left
->type
: pe_unknown
;
3089 e
->right
->visit (this);
3091 if (e
->left
->type
!= pe_unknown
&&
3092 e
->right
->type
!= pe_unknown
&&
3093 e
->left
->type
!= e
->right
->type
)
3094 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3096 if (e
->type
== pe_unknown
)
3099 resolved (e
->tok
, e
->type
);
3105 typeresolution_info::visit_concatenation (concatenation
*e
)
3107 if (t
!= pe_unknown
&& t
!= pe_string
)
3108 invalid (e
->tok
, t
);
3111 e
->left
->visit (this);
3113 e
->right
->visit (this);
3115 if (e
->type
== pe_unknown
)
3117 e
->type
= pe_string
;
3118 resolved (e
->tok
, e
->type
);
3124 typeresolution_info::visit_assignment (assignment
*e
)
3127 invalid (e
->tok
, t
);
3129 if (e
->op
== "<<<") // stats aggregation
3132 invalid (e
->tok
, t
);
3135 e
->left
->visit (this);
3137 e
->right
->visit (this);
3138 if (e
->type
== pe_unknown
||
3139 e
->type
== pe_stats
)
3142 resolved (e
->tok
, e
->type
);
3146 else if (e
->left
->type
== pe_stats
)
3147 invalid (e
->left
->tok
, e
->left
->type
);
3149 else if (e
->right
->type
== pe_stats
)
3150 invalid (e
->right
->tok
, e
->right
->type
);
3152 else if (e
->op
== "+=" || // numeric only
3164 visit_binary_expression (e
);
3166 else if (e
->op
== ".=" || // string only
3169 if (t
== pe_long
|| t
== pe_stats
)
3170 invalid (e
->tok
, t
);
3173 e
->left
->visit (this);
3175 e
->right
->visit (this);
3176 if (e
->type
== pe_unknown
)
3178 e
->type
= pe_string
;
3179 resolved (e
->tok
, e
->type
);
3182 else if (e
->op
== "=") // overloaded = for string & numeric operands
3184 // logic similar to ternary_expression
3185 exp_type sub_type
= t
;
3187 // Infer types across the l/r values
3188 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3191 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3192 (e
->right
->type
!= pe_unknown
) ? e
->right
->type
:
3194 e
->left
->visit (this);
3195 t
= (sub_type
!= pe_unknown
) ? sub_type
:
3196 (e
->left
->type
!= pe_unknown
) ? e
->left
->type
:
3198 e
->right
->visit (this);
3200 if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3203 resolved (e
->tok
, e
->type
);
3205 if ((sub_type
== pe_unknown
) && (e
->left
->type
!= pe_unknown
))
3207 e
->type
= e
->left
->type
;
3208 resolved (e
->tok
, e
->type
);
3211 if (e
->left
->type
!= pe_unknown
&&
3212 e
->right
->type
!= pe_unknown
&&
3213 e
->left
->type
!= e
->right
->type
)
3214 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3218 throw semantic_error ("unsupported assignment operator " + e
->op
);
3223 typeresolution_info::visit_binary_expression (binary_expression
* e
)
3225 if (t
== pe_stats
|| t
== pe_string
)
3226 invalid (e
->tok
, t
);
3229 e
->left
->visit (this);
3231 e
->right
->visit (this);
3233 if (e
->left
->type
!= pe_unknown
&&
3234 e
->right
->type
!= pe_unknown
&&
3235 e
->left
->type
!= e
->right
->type
)
3236 mismatch (e
->tok
, e
->left
->type
, e
->right
->type
);
3238 if (e
->type
== pe_unknown
)
3241 resolved (e
->tok
, e
->type
);
3247 typeresolution_info::visit_pre_crement (pre_crement
*e
)
3249 visit_unary_expression (e
);
3254 typeresolution_info::visit_post_crement (post_crement
*e
)
3256 visit_unary_expression (e
);
3261 typeresolution_info::visit_unary_expression (unary_expression
* e
)
3263 if (t
== pe_stats
|| t
== pe_string
)
3264 invalid (e
->tok
, t
);
3267 e
->operand
->visit (this);
3269 if (e
->type
== pe_unknown
)
3272 resolved (e
->tok
, e
->type
);
3278 typeresolution_info::visit_ternary_expression (ternary_expression
* e
)
3280 exp_type sub_type
= t
;
3283 e
->cond
->visit (this);
3285 // Infer types across the true/false arms of the ternary expression.
3287 if (sub_type
== pe_unknown
&& e
->type
!= pe_unknown
)
3290 e
->truevalue
->visit (this);
3292 e
->falsevalue
->visit (this);
3294 if ((sub_type
== pe_unknown
) && (e
->type
!= pe_unknown
))
3295 ; // already resolved
3296 else if ((sub_type
!= pe_unknown
) && (e
->type
== pe_unknown
))
3299 resolved (e
->tok
, e
->type
);
3301 else if ((sub_type
== pe_unknown
) && (e
->truevalue
->type
!= pe_unknown
))
3303 e
->type
= e
->truevalue
->type
;
3304 resolved (e
->tok
, e
->type
);
3306 else if ((sub_type
== pe_unknown
) && (e
->falsevalue
->type
!= pe_unknown
))
3308 e
->type
= e
->falsevalue
->type
;
3309 resolved (e
->tok
, e
->type
);
3311 else if (e
->type
!= sub_type
)
3312 mismatch (e
->tok
, sub_type
, e
->type
);
3316 template <class Referrer
, class Referent
>
3317 void resolve_2types (Referrer
* referrer
, Referent
* referent
,
3318 typeresolution_info
* r
, exp_type t
, bool accept_unknown
= false)
3320 exp_type
& re_type
= referrer
->type
;
3321 const token
* re_tok
= referrer
->tok
;
3322 exp_type
& te_type
= referent
->type
;
3323 const token
* te_tok
= referent
->tok
;
3325 if (t
!= pe_unknown
&& re_type
== t
&& re_type
== te_type
)
3326 ; // do nothing: all three e->types in agreement
3327 else if (t
== pe_unknown
&& re_type
!= pe_unknown
&& re_type
== te_type
)
3328 ; // do nothing: two known e->types in agreement
3329 else if (re_type
!= pe_unknown
&& te_type
!= pe_unknown
&& re_type
!= te_type
)
3330 r
->mismatch (re_tok
, re_type
, te_type
);
3331 else if (re_type
!= pe_unknown
&& t
!= pe_unknown
&& re_type
!= t
)
3332 r
->mismatch (re_tok
, re_type
, t
);
3333 else if (te_type
!= pe_unknown
&& t
!= pe_unknown
&& te_type
!= t
)
3334 r
->mismatch (te_tok
, te_type
, t
);
3335 else if (re_type
== pe_unknown
&& t
!= pe_unknown
)
3337 // propagate from upstream
3339 r
->resolved (re_tok
, re_type
);
3340 // catch re_type/te_type mismatch later
3342 else if (re_type
== pe_unknown
&& te_type
!= pe_unknown
)
3344 // propagate from referent
3346 r
->resolved (re_tok
, re_type
);
3347 // catch re_type/t mismatch later
3349 else if (re_type
!= pe_unknown
&& te_type
== pe_unknown
)
3351 // propagate to referent
3353 r
->resolved (te_tok
, te_type
);
3354 // catch re_type/t mismatch later
3356 else if (! accept_unknown
)
3357 r
->unresolved (re_tok
);
3362 typeresolution_info::visit_symbol (symbol
* e
)
3364 assert (e
->referent
!= 0);
3365 resolve_2types (e
, e
->referent
, this, t
);
3370 typeresolution_info::visit_target_symbol (target_symbol
* e
)
3372 // This occurs only if a target symbol was not resolved over in
3373 // tapset.cxx land, that error was properly suppressed, and the
3374 // later unused-expression-elimination pass didn't get rid of it
3375 // either. So we have a target symbol that is believed to be of
3376 // genuine use, yet unresolved by the provider.
3378 if (session
.verbose
> 2)
3380 clog
<< "Resolution problem with ";
3381 if (current_function
)
3383 clog
<< "function " << current_function
->name
<< endl
;
3384 current_function
->body
->print (clog
);
3387 else if (current_probe
)
3389 clog
<< "probe " << current_probe
->name
<< endl
;
3390 current_probe
->body
->print (clog
);
3394 clog
<< "other" << endl
;
3397 if (e
->saved_conversion_error
)
3398 throw (* (e
->saved_conversion_error
));
3400 throw semantic_error("unresolved target-symbol expression", e
->tok
);
3405 typeresolution_info::visit_arrayindex (arrayindex
* e
)
3408 symbol
*array
= NULL
;
3409 hist_op
*hist
= NULL
;
3410 classify_indexable(e
->base
, array
, hist
);
3412 // Every hist_op has type [int]:int, that is to say, every hist_op
3413 // is a pseudo-one-dimensional integer array type indexed by
3414 // integers (bucket numbers).
3418 if (e
->indexes
.size() != 1)
3419 unresolved (e
->tok
);
3421 e
->indexes
[0]->visit (this);
3422 if (e
->indexes
[0]->type
!= pe_long
)
3423 unresolved (e
->tok
);
3425 if (e
->type
!= pe_long
)
3428 resolved (e
->tok
, pe_long
);
3433 // Now we are left with "normal" map inference and index checking.
3436 assert (array
->referent
!= 0);
3437 resolve_2types (e
, array
->referent
, this, t
);
3439 // now resolve the array indexes
3441 // if (e->referent->index_types.size() == 0)
3442 // // redesignate referent as array
3443 // e->referent->set_arity (e->indexes.size ());
3445 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3446 unresolved (e
->tok
); // symbol resolution should prevent this
3447 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3449 expression
* ee
= e
->indexes
[i
];
3450 exp_type
& ft
= array
->referent
->index_types
[i
];
3453 exp_type at
= ee
->type
;
3455 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3457 // propagate to formal type
3459 resolved (array
->referent
->tok
, ft
);
3460 // uses array decl as there is no token for "formal type"
3463 invalid (ee
->tok
, at
);
3465 invalid (ee
->tok
, ft
);
3466 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3467 mismatch (e
->tok
, at
, ft
);
3468 if (at
== pe_unknown
)
3469 unresolved (ee
->tok
);
3475 typeresolution_info::visit_functioncall (functioncall
* e
)
3477 assert (e
->referent
!= 0);
3479 resolve_2types (e
, e
->referent
, this, t
, true); // accept unknown type
3481 if (e
->type
== pe_stats
)
3482 invalid (e
->tok
, e
->type
);
3484 // now resolve the function parameters
3485 if (e
->args
.size() != e
->referent
->formal_args
.size())
3486 unresolved (e
->tok
); // symbol resolution should prevent this
3487 else for (unsigned i
=0; i
<e
->args
.size(); i
++)
3489 expression
* ee
= e
->args
[i
];
3490 exp_type
& ft
= e
->referent
->formal_args
[i
]->type
;
3491 const token
* fe_tok
= e
->referent
->formal_args
[i
]->tok
;
3494 exp_type at
= ee
->type
;
3496 if (((at
== pe_string
) || (at
== pe_long
)) && ft
== pe_unknown
)
3498 // propagate to formal arg
3500 resolved (e
->referent
->formal_args
[i
]->tok
, ft
);
3503 invalid (e
->tok
, at
);
3505 invalid (fe_tok
, ft
);
3506 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3507 mismatch (e
->tok
, at
, ft
);
3508 if (at
== pe_unknown
)
3509 unresolved (e
->tok
);
3515 typeresolution_info::visit_block (block
* e
)
3517 for (unsigned i
=0; i
<e
->statements
.size(); i
++)
3522 e
->statements
[i
]->visit (this);
3524 catch (const semantic_error
& e
)
3526 session
.print_error (e
);
3533 typeresolution_info::visit_embeddedcode (embeddedcode
*)
3539 typeresolution_info::visit_if_statement (if_statement
* e
)
3542 e
->condition
->visit (this);
3545 e
->thenblock
->visit (this);
3550 e
->elseblock
->visit (this);
3556 typeresolution_info::visit_for_loop (for_loop
* e
)
3559 if (e
->init
) e
->init
->visit (this);
3561 e
->cond
->visit (this);
3563 if (e
->incr
) e
->incr
->visit (this);
3565 e
->block
->visit (this);
3570 typeresolution_info::visit_foreach_loop (foreach_loop
* e
)
3572 // See also visit_arrayindex.
3573 // This is different in that, being a statement, we can't assign
3574 // a type to the outer array, only propagate to/from the indexes
3576 // if (e->referent->index_types.size() == 0)
3577 // // redesignate referent as array
3578 // e->referent->set_arity (e->indexes.size ());
3580 symbol
*array
= NULL
;
3581 hist_op
*hist
= NULL
;
3582 classify_indexable(e
->base
, array
, hist
);
3586 if (e
->indexes
.size() != 1)
3587 unresolved (e
->tok
);
3589 e
->indexes
[0]->visit (this);
3590 if (e
->indexes
[0]->type
!= pe_long
)
3591 unresolved (e
->tok
);
3597 if (e
->indexes
.size() != array
->referent
->index_types
.size())
3598 unresolved (e
->tok
); // symbol resolution should prevent this
3599 else for (unsigned i
=0; i
<e
->indexes
.size(); i
++)
3601 expression
* ee
= e
->indexes
[i
];
3602 exp_type
& ft
= array
->referent
->index_types
[i
];
3605 exp_type at
= ee
->type
;
3607 if ((at
== pe_string
|| at
== pe_long
) && ft
== pe_unknown
)
3609 // propagate to formal type
3611 resolved (array
->referent
->tok
, ft
);
3612 // uses array decl as there is no token for "formal type"
3615 invalid (ee
->tok
, at
);
3617 invalid (ee
->tok
, ft
);
3618 if (at
!= pe_unknown
&& ft
!= pe_unknown
&& ft
!= at
)
3619 mismatch (e
->tok
, at
, ft
);
3620 if (at
== pe_unknown
)
3621 unresolved (ee
->tok
);
3628 e
->limit
->visit (this);
3632 e
->block
->visit (this);
3637 typeresolution_info::visit_null_statement (null_statement
*)
3643 typeresolution_info::visit_expr_statement (expr_statement
* e
)
3646 e
->value
->visit (this);
3650 struct delete_statement_typeresolution_info
:
3651 public throwing_visitor
3653 typeresolution_info
*parent
;
3654 delete_statement_typeresolution_info (typeresolution_info
*p
):
3655 throwing_visitor ("invalid operand of delete expression"),
3659 void visit_arrayindex (arrayindex
* e
)
3661 parent
->visit_arrayindex (e
);
3664 void visit_symbol (symbol
* e
)
3666 exp_type ignored
= pe_unknown
;
3667 assert (e
->referent
!= 0);
3668 resolve_2types (e
, e
->referent
, parent
, ignored
);
3674 typeresolution_info::visit_delete_statement (delete_statement
* e
)
3676 delete_statement_typeresolution_info
di (this);
3678 e
->value
->visit (&di
);
3683 typeresolution_info::visit_next_statement (next_statement
*)
3689 typeresolution_info::visit_break_statement (break_statement
*)
3695 typeresolution_info::visit_continue_statement (continue_statement
*)
3701 typeresolution_info::visit_array_in (array_in
* e
)
3703 // all unary operators only work on numerics
3705 t
= pe_unknown
; // array value can be anything
3706 e
->operand
->visit (this);
3708 if (t1
== pe_unknown
&& e
->type
!= pe_unknown
)
3709 ; // already resolved
3710 else if (t1
== pe_string
|| t1
== pe_stats
)
3711 mismatch (e
->tok
, t1
, pe_long
);
3712 else if (e
->type
== pe_unknown
)
3715 resolved (e
->tok
, e
->type
);
3721 typeresolution_info::visit_return_statement (return_statement
* e
)
3723 // This is like symbol, where the referent is
3724 // the return value of the function.
3726 // translation pass will print error
3727 if (current_function
== 0)
3730 exp_type
& e_type
= current_function
->type
;
3731 t
= current_function
->type
;
3732 e
->value
->visit (this);
3734 if (e_type
!= pe_unknown
&& e
->value
->type
!= pe_unknown
3735 && e_type
!= e
->value
->type
)
3736 mismatch (current_function
->tok
, e_type
, e
->value
->type
);
3737 if (e_type
== pe_unknown
&&
3738 (e
->value
->type
== pe_long
|| e
->value
->type
== pe_string
))
3740 // propagate non-statistics from value
3741 e_type
= e
->value
->type
;
3742 resolved (current_function
->tok
, e
->value
->type
);
3744 if (e
->value
->type
== pe_stats
)
3745 invalid (e
->value
->tok
, e
->value
->type
);
3749 typeresolution_info::visit_print_format (print_format
* e
)
3751 size_t unresolved_args
= 0;
3755 e
->hist
->visit(this);
3758 else if (e
->print_with_format
)
3760 // If there's a format string, we can do both inference *and*
3763 // First we extract the subsequence of formatting components
3764 // which are conversions (not just literal string components)
3766 unsigned expected_num_args
= 0;
3767 std::vector
<print_format::format_component
> components
;
3768 for (size_t i
= 0; i
< e
->components
.size(); ++i
)
3770 if (e
->components
[i
].type
== print_format::conv_unspecified
)
3771 throw semantic_error ("Unspecified conversion in print operator format string",
3773 else if (e
->components
[i
].type
== print_format::conv_literal
3774 || e
->components
[i
].type
== print_format::conv_size
)
3776 components
.push_back(e
->components
[i
]);
3777 ++expected_num_args
;
3778 if (e
->components
[i
].widthtype
== print_format::width_dynamic
)
3779 ++expected_num_args
;
3780 if (e
->components
[i
].prectype
== print_format::prec_dynamic
)
3781 ++expected_num_args
;
3784 // Then we check that the number of conversions and the number
3787 if (expected_num_args
!= e
->args
.size())
3788 throw semantic_error ("Wrong number of args to formatted print operator",
3791 // Then we check that the types of the conversions match the types
3794 for (size_t i
= 0; i
< components
.size(); ++i
)
3796 // Check the dynamic width, if specified
3797 if (components
[i
].widthtype
== print_format::width_dynamic
)
3799 check_arg_type (pe_long
, e
->args
[argno
]);
3803 // Check the dynamic precision, if specified
3804 if (components
[i
].prectype
== print_format::prec_dynamic
)
3806 check_arg_type (pe_long
, e
->args
[argno
]);
3810 exp_type wanted
= pe_unknown
;
3812 switch (components
[i
].type
)
3814 case print_format::conv_unspecified
:
3815 case print_format::conv_literal
:
3816 case print_format::conv_size
:
3820 case print_format::conv_signed_decimal
:
3821 case print_format::conv_unsigned_decimal
:
3822 case print_format::conv_unsigned_octal
:
3823 case print_format::conv_unsigned_ptr
:
3824 case print_format::conv_unsigned_uppercase_hex
:
3825 case print_format::conv_unsigned_lowercase_hex
:
3826 case print_format::conv_binary
:
3827 case print_format::conv_memory
:
3831 case print_format::conv_string
:
3836 assert (wanted
!= pe_unknown
);
3837 check_arg_type (wanted
, e
->args
[argno
]);
3843 // Without a format string, the best we can do is require that
3844 // each argument resolve to a concrete type.
3845 for (size_t i
= 0; i
< e
->args
.size(); ++i
)
3848 e
->args
[i
]->visit (this);
3849 if (e
->args
[i
]->type
== pe_unknown
)
3851 unresolved (e
->args
[i
]->tok
);
3857 if (unresolved_args
== 0)
3859 if (e
->type
== pe_unknown
)
3861 if (e
->print_to_stream
)
3864 e
->type
= pe_string
;
3865 resolved (e
->tok
, e
->type
);
3870 e
->type
= pe_unknown
;
3871 unresolved (e
->tok
);
3877 typeresolution_info::visit_stat_op (stat_op
* e
)
3880 e
->stat
->visit (this);
3881 if (e
->type
== pe_unknown
)
3884 resolved (e
->tok
, e
->type
);
3886 else if (e
->type
!= pe_long
)
3887 mismatch (e
->tok
, e
->type
, pe_long
);
3891 typeresolution_info::visit_hist_op (hist_op
* e
)
3894 e
->stat
->visit (this);
3899 typeresolution_info::check_arg_type (exp_type wanted
, expression
* arg
)
3904 if (arg
->type
== pe_unknown
)
3907 resolved (arg
->tok
, wanted
);
3909 else if (arg
->type
!= wanted
)
3911 mismatch (arg
->tok
, arg
->type
, wanted
);
3917 typeresolution_info::unresolved (const token
* tok
)
3919 num_still_unresolved
++;
3921 if (assert_resolvability
)
3924 string nm
= (current_function
? current_function
->name
:
3925 current_probe
? current_probe
->name
:
3927 msg
<< nm
+ " with unresolved type";
3928 session
.print_error (semantic_error (msg
.str(), tok
));
3934 typeresolution_info::invalid (const token
* tok
, exp_type pe
)
3936 num_still_unresolved
++;
3938 if (assert_resolvability
)
3941 string nm
= (current_function
? current_function
->name
:
3942 current_probe
? current_probe
->name
:
3944 if (tok
&& tok
->type
== tok_operator
)
3945 msg
<< nm
+ " uses invalid operator";
3947 msg
<< nm
+ " with invalid type " << pe
;
3948 session
.print_error (semantic_error (msg
.str(), tok
));
3954 typeresolution_info::mismatch (const token
* tok
, exp_type t1
, exp_type t2
)
3956 num_still_unresolved
++;
3958 if (assert_resolvability
)
3961 string nm
= (current_function
? current_function
->name
:
3962 current_probe
? current_probe
->name
:
3964 msg
<< nm
+ " with type mismatch (" << t1
<< " vs. " << t2
<< ")";
3965 session
.print_error (semantic_error (msg
.str(), tok
));
3971 typeresolution_info::resolved (const token
*, exp_type
)
3973 num_newly_resolved
++;