From 8eb285ac4ec3a34b29ebf20fde0e28cc647d940f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 13:29:18 -0700 Subject: Drop a couple of unnecessary std:: qualifiers * staptree.cxx (target_symbol::print): Drop std:: from parameter o. (cast_op::print): Ditto. --- staptree.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staptree.cxx b/staptree.cxx index 9e2ca8da..b14a5c44 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -259,7 +259,7 @@ void symbol::print (ostream& o) const } -void target_symbol::print (std::ostream& o) const +void target_symbol::print (ostream& o) const { if (addressof) o << "&"; @@ -279,7 +279,7 @@ void target_symbol::print (std::ostream& o) const } -void cast_op::print (std::ostream& o) const +void cast_op::print (ostream& o) const { if (addressof) o << "&"; -- cgit From 81931eaba5dcd0727f33328bf4b0ff511b791990 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 13:46:54 -0700 Subject: Refactor parser for target_symbol->components The components were being parsed for both target_symbols and cast_ops, so this change refactors that code into a single function. * parse.cxx (parser::parse_target_symbol_components): New. (parser::parse_symbol): Use the new function. --- parse.cxx | 72 ++++++++++++++++++++++++++------------------------------------- parse.h | 3 +++ 2 files changed, 33 insertions(+), 42 deletions(-) diff --git a/parse.cxx b/parse.cxx index 35c78abe..29d97589 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2346,27 +2346,8 @@ parser::parse_symbol () expect_unknown(tok_string, cop->module); } expect_op(")"); - while (true) - { - string c; - if (peek_op ("->")) - { - next(); - expect_ident_or_keyword (c); - cop->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); - } - else if (peek_op ("[")) - { - next(); - expect_unknown (tok_number, c); - expect_op ("]"); - cop->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); - } - else - break; - } + parse_target_symbol_components(cop); + // if there aren't any dereferences, then the cast is pointless if (cop->components.empty()) { @@ -2494,27 +2475,7 @@ parser::parse_symbol () target_symbol *tsym = new target_symbol; tsym->tok = t; tsym->base_name = name; - while (true) - { - string c; - if (peek_op ("->")) - { - next(); - expect_ident_or_keyword (c); - tsym->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); - } - else if (peek_op ("[")) - { - next(); - expect_unknown (tok_number, c); - expect_op ("]"); - tsym->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); - } - else - break; - } + parse_target_symbol_components(tsym); return tsym; } @@ -2604,4 +2565,31 @@ parser::parse_symbol () return sym; } + +void +parser::parse_target_symbol_components (target_symbol* e) +{ + while (true) + { + string c; + if (peek_op ("->")) + { + next(); + expect_ident_or_keyword (c); + e->components.push_back + (make_pair (target_symbol::comp_struct_member, c)); + } + else if (peek_op ("[")) + { + next(); + expect_unknown (tok_number, c); + expect_op ("]"); + e->components.push_back + (make_pair (target_symbol::comp_literal_array_index, c)); + } + else + break; + } +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/parse.h b/parse.h index cae49b65..5587586e 100644 --- a/parse.h +++ b/parse.h @@ -112,6 +112,7 @@ struct next_statement; struct continue_statement; struct indexable; struct expression; +struct target_symbol; struct hist_op; class parser @@ -203,6 +204,8 @@ private: // nonterminals expression* parse_crement (); expression* parse_value (); expression* parse_symbol (); + + void parse_target_symbol_components (target_symbol* e); }; -- cgit From c67847a0d05f8c7207513e79378fc8d84563e109 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 17:00:09 -0700 Subject: Make a real type for target_symbol->components Now the dereferences on target_symbol and cast_op are tracked with a struct instead of just a generic pair. The first immediate benefit is that we can track the token for more exact error reporting. * staptree.h (target_symbol): Add a new component type. * staptree.cxx (target_symbol::component::print): New. (operator<<(ostream&, target_symbol::component&): New. (target_symbol::print): Adapt component printing. (cast_op::print): Ditto. * parse.cxx (parser::parse_target_symbol_components): Adapt to the new component construction. * dwflpp.cxx (dwflpp::find_struct_member): take the component as a parameter for a better token in error messages (dwflpp::translate_components): Adapt to the new component type. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Don't overwrite the token in target_symbol saved errors. (tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto. --- dwflpp.cxx | 64 ++++++++++++++++++++++++++++++------------------------ dwflpp.h | 3 +-- parse.cxx | 17 +++++++-------- staptree.cxx | 45 +++++++++++++++++++------------------- staptree.h | 19 +++++++++++++++- tapset-mark.cxx | 4 ++-- tapset-perfmon.cxx | 2 +- tapset-procfs.cxx | 2 +- tapset-utrace.cxx | 4 ++-- tapsets.cxx | 6 ++--- 10 files changed, 94 insertions(+), 72 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index e6e7b471..090aa70a 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1620,9 +1620,8 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o) bool -dwflpp::find_struct_member(const string& member, +dwflpp::find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, - const target_symbol *e, Dwarf_Die *memberdie, vector& locs) { @@ -1640,7 +1639,7 @@ dwflpp::find_struct_member(const string& member, throw semantic_error (string (dwarf_tag(&die) == DW_TAG_union_type ? "union" : "struct") + string (dwarf_diename_integrate (&die) ?: "") + string (dwarf_errmsg (-1)), - e->tok); + c.tok); } do @@ -1658,10 +1657,10 @@ dwflpp::find_struct_member(const string& member, !dwarf_formref_die (&attr, &subdie)) continue; - if (find_struct_member(member, &subdie, e, memberdie, locs)) + if (find_struct_member(c, &subdie, memberdie, locs)) goto success; } - else if (name == member) + else if (name == c.member) { *memberdie = die; goto success; @@ -1680,9 +1679,9 @@ success: /* Union members don't usually have a location, * but just use the containing union's location. */ else if (dwarf_tag(parentdie) != DW_TAG_union_type) - throw semantic_error ("no location for field '" + member + throw semantic_error ("no location for field '" + c.member + "': " + string(dwarf_errmsg (-1)), - e->tok); + c.tok); return true; } @@ -1709,6 +1708,8 @@ dwflpp::translate_components(struct obstack *pool, while (i < e->components.size()) { + const target_symbol::component& c = e->components[i]; + /* XXX: This would be desirable, but we don't get the target_symbol token, and printing that gives us the file:line number too early anyway. */ #if 0 @@ -1730,39 +1731,45 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_pointer_type: c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail); - if (e->components[i].first != target_symbol::comp_literal_array_index) + if (c.type != target_symbol::comp_literal_array_index) break; /* else fall through as an array access */ case DW_TAG_array_type: - if (e->components[i].first == target_symbol::comp_literal_array_index) + if (c.type == target_symbol::comp_literal_array_index) { c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, - NULL, lex_cast(e->components[i].second)); + NULL, c.num_index); ++i; } else - throw semantic_error("bad field '" - + e->components[i].second - + "' for array type", - e->tok); + throw semantic_error ("invalid access '" + + lex_cast(c) + + "' for array type", + c.tok); break; case DW_TAG_structure_type: case DW_TAG_union_type: + if (c.type != target_symbol::comp_struct_member) + throw semantic_error ("invalid access '" + + lex_cast(c) + + "' for struct/union type", + c.tok); + if (dwarf_hasattr(die, DW_AT_declaration)) { Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die)); if (tmpdie == NULL) throw semantic_error ("unresolved struct " + string (dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); *die_mem = *tmpdie; } { vector locs; - if (!find_struct_member(e->components[i].second, die, e, die, locs)) + if (!find_struct_member(c, die, die, locs)) { string alternatives; stringstream members; @@ -1770,10 +1777,10 @@ dwflpp::translate_components(struct obstack *pool, if (members.str().size() != 0) alternatives = " (alternatives:" + members.str(); throw semantic_error("unable to find member '" + - e->components[i].second + "' for struct " + c.member + "' for struct " + string(dwarf_diename_integrate(die) ?: "") + alternatives, - e->tok); + c.tok); } for (unsigned j = 0; j < locs.size(); ++j) @@ -1784,39 +1791,40 @@ dwflpp::translate_components(struct obstack *pool, break; case DW_TAG_enumeration_type: - throw semantic_error ("field '" - + e->components[i].second + throw semantic_error ("invalid access '" + + lex_cast(c) + "' vs. enum type " + string(dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); break; case DW_TAG_base_type: - throw semantic_error ("field '" - + e->components[i].second + throw semantic_error ("invalid access '" + + lex_cast(c) + "' vs. base type " + string(dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); break; case -1: throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)), - e->tok); + c.tok); break; default: throw semantic_error (string(dwarf_diename_integrate (die) ?: "") + ": unexpected type tag " + lex_cast(dwarf_tag (die)), - e->tok); + c.tok); break; } /* Now iterate on the type in DIE's attribute. */ if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL) - throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok); + throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), + c.tok); } /* For an array index, we need to dereference the final DIE */ - if (e->components.back().first == target_symbol::comp_literal_array_index) + if (e->components.back().type == target_symbol::comp_literal_array_index) die = dwarf_formref_die (attr_mem, die_mem); return die; diff --git a/dwflpp.h b/dwflpp.h index 20bcc0d0..3cada4f8 100644 --- a/dwflpp.h +++ b/dwflpp.h @@ -333,9 +333,8 @@ private: struct location **tail, const target_symbol *e); - bool find_struct_member(const std::string& member, + bool find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, - const target_symbol *e, Dwarf_Die *memberdie, std::vector& locs); diff --git a/parse.cxx b/parse.cxx index 29d97589..9d4a06a6 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2571,21 +2571,20 @@ parser::parse_target_symbol_components (target_symbol* e) { while (true) { - string c; if (peek_op ("->")) { - next(); - expect_ident_or_keyword (c); - e->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); + const token* t = next(); + string member; + expect_ident_or_keyword (member); + e->components.push_back (target_symbol::component(t, member)); } else if (peek_op ("[")) { - next(); - expect_unknown (tok_number, c); + const token* t = next(); + int64_t index; + expect_number (index); + e->components.push_back (target_symbol::component(t, index)); expect_op ("]"); - e->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); } else break; diff --git a/staptree.cxx b/staptree.cxx index b14a5c44..1231f74d 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -259,23 +259,34 @@ void symbol::print (ostream& o) const } +void target_symbol::component::print (ostream& o) const +{ + switch (type) + { + case comp_struct_member: + o << "->" << member; + break; + case comp_literal_array_index: + o << '[' << num_index << ']'; + break; + } +} + + +std::ostream& operator << (std::ostream& o, const target_symbol::component& c) +{ + c.print (o); + return o; +} + + void target_symbol::print (ostream& o) const { if (addressof) o << "&"; o << base_name; for (unsigned i = 0; i < components.size(); ++i) - { - switch (components[i].first) - { - case comp_literal_array_index: - o << '[' << components[i].second << ']'; - break; - case comp_struct_member: - o << "->" << components[i].second; - break; - } - } + o << components[i]; } @@ -289,17 +300,7 @@ void cast_op::print (ostream& o) const o << ", " << lex_cast_qstring (module); o << ')'; for (unsigned i = 0; i < components.size(); ++i) - { - switch (components[i].first) - { - case comp_literal_array_index: - o << '[' << components[i].second << ']'; - break; - case comp_struct_member: - o << "->" << components[i].second; - break; - } - } + o << components[i]; } diff --git a/staptree.h b/staptree.h index 16f0256a..70746f31 100644 --- a/staptree.h +++ b/staptree.h @@ -229,9 +229,24 @@ struct target_symbol: public symbol comp_struct_member, comp_literal_array_index }; + + struct component + { + const token* tok; + component_type type; + std::string member; // comp_struct_member + int64_t num_index; // comp_literal_array_index + + component(const token* t, const std::string& m): + tok(t), type(comp_struct_member), member(m), num_index(0) {} + component(const token* t, int64_t n): + tok(t), type(comp_literal_array_index), num_index(n) {} + void print (std::ostream& o) const; + }; + bool addressof; std::string base_name; - std::vector > components; + std::vector components; std::string probe_context_var; semantic_error* saved_conversion_error; target_symbol(): addressof(false), saved_conversion_error (0) {} @@ -239,6 +254,8 @@ struct target_symbol: public symbol void visit (visitor* u); }; +std::ostream& operator << (std::ostream& o, const target_symbol::component& c); + struct cast_op: public target_symbol { diff --git a/tapset-mark.cxx b/tapset-mark.cxx index a358a20e..fcde9ed5 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -105,7 +105,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("marker argument may not be used as array", @@ -140,7 +140,7 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("marker '" + sname + "' may not be used as array", diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index 0fb567f7..dfdc55e6 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -69,7 +69,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("perfmon probe '$counter' variable may not be used as array", diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index a996ee32..58bb0f0d 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -360,7 +360,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("procfs target variable '$value' may not be used as array", diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index a3a4ca3d..3befcbd5 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -457,7 +457,7 @@ utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("utrace target variable '$argN' may not be used as array", @@ -507,7 +507,7 @@ utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("utrace target variable '" + sname + "' may not be used as array", diff --git a/tapsets.cxx b/tapsets.cxx index bd33fb0b..70edc7d8 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2244,7 +2244,6 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) // quietly. provide (e); semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines // NB: we can have multiple errors, since a $target variable // may be expanded in several different contexts: // function ("*") { $var } @@ -5263,7 +5262,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // make sure we're not dereferencing base types if (!e->components.empty() && !arg->isptr) - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("tracepoint variable '" + e->base_name @@ -5323,7 +5322,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // up not being referenced after all, so it can be optimized out // quietly. semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to dw code generation routines // NB: we can have multiple errors, since a target variable // may be expanded in several different contexts: // trace ("*") { $foo->bar } @@ -5396,7 +5394,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) throw semantic_error("write to tracepoint '" + e->base_name + "' not permitted", e->tok); if (!e->components.empty()) - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("tracepoint '" + e->base_name + "' may not be used as array", -- cgit From dc5a09fc9a61c8b33078164b6855dea54a33627c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 17:24:13 -0700 Subject: Unify no-component assertions on target variables There are several tapsets that can't deal with component dereferences on their target variables, and they all check-and-throw in the same way. This refactors the checks into a target_symbol member. * staptree.cxx (target_symbol::assert_no_components): New. * tapsets.cxx (tracepoint_var_expanding_visitor::visit_target_symbol_arg, tracepoint_var_expanding_visitor::visit_target_symbol_context): Use the new assertion function to check for no components. * tapset-mark.cxx (mark_var_expanding_visitor::visit_target_symbol_arg, mark_var_expanding_visitor::visit_target_symbol_context): Ditto. * tapset-perfmon.cxx (perfmon_var_expanding_visitor::visit_target_symbol): Ditto. * tapset-procfs.cxx (procfs_var_expanding_visitor::visit_target_symbol): Ditto. * tapset-utrace.cxx (utrace_var_expanding_visitor::visit_target_symbol_arg, utrace_var_expanding_visitor::visit_target_symbol_context): Ditto. --- staptree.cxx | 24 ++++++++++++++++++++++++ staptree.h | 1 + tapset-mark.cxx | 36 ++---------------------------------- tapset-perfmon.cxx | 19 +------------------ tapset-procfs.cxx | 19 +------------------ tapset-utrace.cxx | 38 ++------------------------------------ tapsets.cxx | 28 +++------------------------- 7 files changed, 34 insertions(+), 131 deletions(-) diff --git a/staptree.cxx b/staptree.cxx index 1231f74d..321650eb 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -186,6 +186,30 @@ operator << (ostream& o, const exp_type& e) } +void +target_symbol::assert_no_components(const std::string& tapset) +{ + if (components.empty()) + return; + + switch (components[0].type) + { + case target_symbol::comp_literal_array_index: + throw semantic_error(tapset + " variable '" + base_name + + "' may not be used as array", + components[0].tok); + case target_symbol::comp_struct_member: + throw semantic_error(tapset + " variable '" + base_name + + "' may not be used as a structure", + components[0].tok); + default: + throw semantic_error ("invalid use of " + tapset + + " variable '" + base_name + "'", + components[0].tok); + } +} + + // ------------------------------------------------------------------------ // parse tree printing diff --git a/staptree.h b/staptree.h index 70746f31..9ade2a42 100644 --- a/staptree.h +++ b/staptree.h @@ -252,6 +252,7 @@ struct target_symbol: public symbol target_symbol(): addressof(false), saved_conversion_error (0) {} void print (std::ostream& o) const; void visit (visitor* u); + void assert_no_components(const std::string& tapset); }; std::ostream& operator << (std::ostream& o, const target_symbol::component& c); diff --git a/tapset-mark.cxx b/tapset-mark.cxx index fcde9ed5..59334729 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -103,23 +103,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to marker parameter not permitted", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("marker argument may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("marker argument may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid marker argument use", e->tok); - break; - } - } + e->assert_no_components("marker"); // Remember that we've seen a target variable. target_symbol_seen = true; @@ -138,23 +122,7 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to marker '" + sname + "' not permitted", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("marker '" + sname + "' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("marker '" + sname + "' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid marker '" + sname + "' use", e->tok); - break; - } - } + e->assert_no_components("marker"); if (e->base_name == "$format" || e->base_name == "$name") { string fname; diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index dfdc55e6..d524aa03 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -67,24 +67,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) if (e->addressof) throw semantic_error("cannot take address of perfmon variable", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("perfmon probe '$counter' variable may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("perfmon probe '$counter' variable may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of perfmon probe '$counter' variable", - e->tok); - break; - } - } + e->assert_no_components("perfmon"); ec->code = "THIS->__retvalue = _pfm_pmd_x[" + lex_cast(counter_number) + "].reg_num;"; diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index 58bb0f0d..3302057c 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -358,24 +358,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) throw semantic_error ("invalid target symbol for procfs probe, $value expected", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("procfs target variable '$value' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("procfs target variable '$value' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of procfs target variable '$value'", - e->tok); - break; - } - } + e->assert_no_components("procfs"); bool lvalue = is_active_lvalue(e); if (write_probe && lvalue) diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 3befcbd5..87053f7d 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -455,24 +455,7 @@ utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = lex_cast(argnum_s); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("utrace target variable '$argN' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("utrace target variable '$argN' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of utrace target variable '$argN'", - e->tok); - break; - } - } + e->assert_no_components("utrace"); // FIXME: max argnument number should not be hardcoded. if (argnum < 1 || argnum > 6) @@ -505,24 +488,7 @@ utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("utrace target variable '" + sname + "' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("utrace target variable '" + sname + "' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of utrace target variable '" + sname + "'", - e->tok); - break; - } - } + e->assert_no_components("utrace"); bool lvalue = is_active_lvalue(e); if (lvalue) diff --git a/tapsets.cxx b/tapsets.cxx index 70edc7d8..537c33e7 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5261,19 +5261,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) } // make sure we're not dereferencing base types - if (!e->components.empty() && !arg->isptr) - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("tracepoint variable '" + e->base_name - + "' may not be used as array", e->tok); - case target_symbol::comp_struct_member: - throw semantic_error("tracepoint variable '" + e->base_name - + "' may not be used as a structure", e->tok); - default: - throw semantic_error("invalid use of tracepoint variable '" - + e->base_name + "'", e->tok); - } + if (!arg->isptr) + e->assert_no_components("tracepoint"); // we can only write to dereferenced fields, and only if guru mode is on bool lvalue = is_active_lvalue(e); @@ -5393,18 +5382,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to tracepoint '" + e->base_name + "' not permitted", e->tok); - if (!e->components.empty()) - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("tracepoint '" + e->base_name + "' may not be used as array", - e->tok); - case target_symbol::comp_struct_member: - throw semantic_error("tracepoint '" + e->base_name + "' may not be used as a structure", - e->tok); - default: - throw semantic_error("invalid tracepoint '" + e->base_name + "' use", e->tok); - } + e->assert_no_components("tracepoint"); if (e->base_name == "$$name") { -- cgit From 6fda2dff51c667a8c73545dd397b844108715310 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 14:45:21 -0700 Subject: PR2049: support arbitrary $target-array indexing Rather than just numeric literals, we can now support arbitrary expressions for the index value. Note that loc2c won't allow this for noncontiguous arrays, as the access methods need to be statically computed, but for contiguous arrays and pointers-as-arrays it works just fine. * staptree.h (target_symbol::component): Add expression_array_index. * staptree.cxx (target_symbol::visit_components): New helper. (target_symbol::assert_no_components): Recognize new array type. (target_symbol::component::print): Print subexpressions. (traversing_visitor::visit_target_symbol, visit_cast_op): Visit the indexing components too. (varuse_collecting_visitor::visit_target_symbol): Ditto. (update_visitor::visit_target_symbol, visit_cast_op): Ditto. * elaborate.cxx (void_statement_reducer::visit_target_symbol): New. (void_statement_reducer::visit_cast_op): Save indexes too. * parse.cxx (parser::parse_target_symbol_components): Parse expressions. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Pass expression-indexes as parameters (indexN) to the dwarf function. (dwarf_cast_expanding_visitor::visit_cast_op): Ditto. (tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto. (sdt_var_expanding_visitor::visit_target_symbol): Visit the new @cast. * dwflpp.cxx (dwflpp::translate_components): Use THIS->indexN. * translate.cxx (c_unparser::visit_target_symbol): Correct error msg. * testsuite/systemtap.base/pointer_array.stp: Use a simple index. --- dwflpp.cxx | 13 ++++++- elaborate.cxx | 62 +++++++++++++++++++++++++++++- parse.cxx | 9 +++-- staptree.cxx | 28 +++++++++++++- staptree.h | 11 +++++- tapsets.cxx | 60 ++++++++++++++++++++++++++--- testsuite/systemtap.base/pointer_array.stp | 11 +----- translate.cxx | 2 +- 8 files changed, 171 insertions(+), 25 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index 090aa70a..6ede1d68 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1731,7 +1731,8 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_pointer_type: c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail); - if (c.type != target_symbol::comp_literal_array_index) + if (c.type != target_symbol::comp_literal_array_index && + c.type != target_symbol::comp_expression_array_index) break; /* else fall through as an array access */ @@ -1742,6 +1743,13 @@ dwflpp::translate_components(struct obstack *pool, NULL, c.num_index); ++i; } + else if (c.type == target_symbol::comp_expression_array_index) + { + string index = "THIS->index" + lex_cast(i); + c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, + index.c_str(), 0); + ++i; + } else throw semantic_error ("invalid access '" + lex_cast(c) @@ -1824,7 +1832,8 @@ dwflpp::translate_components(struct obstack *pool, } /* For an array index, we need to dereference the final DIE */ - if (e->components.back().type == target_symbol::comp_literal_array_index) + if (e->components.back().type == target_symbol::comp_literal_array_index || + e->components.back().type == target_symbol::comp_expression_array_index) die = dwarf_formref_die (attr_mem, die_mem); return die; diff --git a/elaborate.cxx b/elaborate.cxx index fafc5e63..d1ebe326 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2534,6 +2534,7 @@ struct void_statement_reducer: public update_visitor void visit_concatenation (concatenation* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); + void visit_target_symbol (target_symbol* e); void visit_cast_op (cast_op* e); // these are a bit hairy to grok due to the intricacies of indexables and @@ -2802,17 +2803,74 @@ void_statement_reducer::visit_print_format (print_format* e) provide (e); } +void +void_statement_reducer::visit_target_symbol (target_symbol* e) +{ + // When target_symbol isn't needed, it's just as good to + // evaluate any array indexes directly + + block *b = new block; + b->tok = e->tok; + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + expr_statement *es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } + + if (b->statements.empty()) + { + delete b; + provide (e); + return; + } + + if (session.verbose>2) + clog << "Eliding unused target symbol " << *e->tok << endl; + + b->visit(this); + relaxed_p = false; + e = 0; + provide (e); +} + void void_statement_reducer::visit_cast_op (cast_op* e) { // When the result of a cast operation isn't needed, it's just as good to - // evaluate the operand directly + // evaluate the operand and any array indexes directly + + block *b = new block; + b->tok = e->tok; + + expr_statement *es = new expr_statement; + es->value = e->operand; + es->tok = es->value->tok; + b->statements.push_back(es); + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } if (session.verbose>2) clog << "Eliding unused typecast " << *e->tok << endl; + b->visit(this); relaxed_p = false; - e->operand->visit(this); + e = 0; + provide (e); } diff --git a/parse.cxx b/parse.cxx index 9d4a06a6..41a13ca5 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2581,9 +2581,12 @@ parser::parse_target_symbol_components (target_symbol* e) else if (peek_op ("[")) { const token* t = next(); - int64_t index; - expect_number (index); - e->components.push_back (target_symbol::component(t, index)); + expression* index = parse_expression(); + literal_number* ln = dynamic_cast(index); + if (ln) + e->components.push_back (target_symbol::component(t, ln->value)); + else + e->components.push_back (target_symbol::component(t, index)); expect_op ("]"); } else diff --git a/staptree.cxx b/staptree.cxx index 321650eb..50d9980f 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -195,6 +195,7 @@ target_symbol::assert_no_components(const std::string& tapset) switch (components[0].type) { case target_symbol::comp_literal_array_index: + case target_symbol::comp_expression_array_index: throw semantic_error(tapset + " variable '" + base_name + "' may not be used as array", components[0].tok); @@ -293,6 +294,9 @@ void target_symbol::component::print (ostream& o) const case comp_literal_array_index: o << '[' << num_index << ']'; break; + case comp_expression_array_index: + o << '[' << *expr_index << ']'; + break; } } @@ -1270,6 +1274,22 @@ target_symbol::visit (visitor* u) u->visit_target_symbol(this); } +void +target_symbol::visit_components (visitor* u) +{ + for (unsigned i = 0; i < components.size(); ++i) + if (components[i].type == comp_expression_array_index) + components[i].expr_index->visit (u); +} + +void +target_symbol::visit_components (update_visitor* u) +{ + for (unsigned i = 0; i < components.size(); ++i) + if (components[i].type == comp_expression_array_index) + components[i].expr_index = u->require (components[i].expr_index); +} + void cast_op::visit (visitor* u) { @@ -1638,14 +1658,16 @@ traversing_visitor::visit_symbol (symbol*) } void -traversing_visitor::visit_target_symbol (target_symbol*) +traversing_visitor::visit_target_symbol (target_symbol* e) { + e->visit_components (this); } void traversing_visitor::visit_cast_op (cast_op* e) { e->operand->visit (this); + e->visit_components (this); } void @@ -1740,6 +1762,8 @@ varuse_collecting_visitor::visit_target_symbol (target_symbol *e) if (is_active_lvalue (e)) embedded_seen = true; + + functioncall_traversing_visitor::visit_target_symbol (e); } void @@ -2373,6 +2397,7 @@ update_visitor::visit_symbol (symbol* e) void update_visitor::visit_target_symbol (target_symbol* e) { + e->visit_components (this); provide (e); } @@ -2380,6 +2405,7 @@ void update_visitor::visit_cast_op (cast_op* e) { e->operand = require (e->operand); + e->visit_components (this); provide (e); } diff --git a/staptree.h b/staptree.h index 9ade2a42..146d0e34 100644 --- a/staptree.h +++ b/staptree.h @@ -58,6 +58,7 @@ std::ostream& operator << (std::ostream& o, const exp_type& e); struct token; struct visitor; +struct update_visitor; struct expression { @@ -227,7 +228,8 @@ struct target_symbol: public symbol enum component_type { comp_struct_member, - comp_literal_array_index + comp_literal_array_index, + comp_expression_array_index, }; struct component @@ -236,11 +238,14 @@ struct target_symbol: public symbol component_type type; std::string member; // comp_struct_member int64_t num_index; // comp_literal_array_index + expression* expr_index; // comp_expression_array_index component(const token* t, const std::string& m): - tok(t), type(comp_struct_member), member(m), num_index(0) {} + tok(t), type(comp_struct_member), member(m) {} component(const token* t, int64_t n): tok(t), type(comp_literal_array_index), num_index(n) {} + component(const token* t, expression* e): + tok(t), type(comp_expression_array_index), expr_index(e) {} void print (std::ostream& o) const; }; @@ -252,6 +257,8 @@ struct target_symbol: public symbol target_symbol(): addressof(false), saved_conversion_error (0) {} void print (std::ostream& o) const; void visit (visitor* u); + void visit_components (visitor* u); + void visit_components (update_visitor* u); void assert_no_components(const std::string& tapset); }; diff --git a/tapsets.cxx b/tapsets.cxx index 537c33e7..ba344c51 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2268,6 +2268,18 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) fdecl->name = fname; fdecl->body = ec; + + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a single pe_long formal @@ -2292,6 +2304,11 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); + if (lvalue) { // Provide the functioncall to our parent, so that it can be @@ -2521,6 +2538,17 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) v1->tok = e->tok; fdecl->formal_args.push_back(v1); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a second pe_long formal @@ -2549,6 +2577,11 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session n->args.push_back(e->operand); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); + if (lvalue) { // Provide the functioncall to our parent, so that it can be @@ -3277,7 +3310,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) cast->type = probe_name + "_arg" + lex_cast(argno); cast->module = process_name; - provide(cast); + cast->visit(this); } @@ -5327,6 +5360,17 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) v1->tok = e->tok; fdecl->formal_args.push_back(v1); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a pe_long formal @@ -5354,10 +5398,16 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - // make the original a bare target symbol for the tracepoint value, - // which will be passed into the dwarf dereferencing code - e->components.clear(); - n->args.push_back(require(e)); + // make a copy of the original as a bare target symbol for the tracepoint + // value, which will be passed into the dwarf dereferencing code + target_symbol* e2 = deep_copy_visitor::deep_copy(e); + e2->components.clear(); + n->args.push_back(require(e2)); + + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); if (lvalue) { diff --git a/testsuite/systemtap.base/pointer_array.stp b/testsuite/systemtap.base/pointer_array.stp index 1d15ebf4..cd420604 100644 --- a/testsuite/systemtap.base/pointer_array.stp +++ b/testsuite/systemtap.base/pointer_array.stp @@ -2,15 +2,8 @@ probe syscall.execve { if (pid() == target()) { println(user_string($argv[0])) - printf("%c\n", $argv[0][0]) - printf("%c\n", $argv[0][1]) - printf("%c\n", $argv[0][2]) - printf("%c\n", $argv[0][3]) - printf("%c\n", $argv[0][4]) - printf("%c\n", $argv[0][5]) - printf("%c\n", $argv[0][6]) - printf("%c\n", $argv[0][7]) - printf("%c\n", $argv[0][8]) + for (i=0; i<9; ++i) + printf("%c\n", $argv[0][i]) println($argv[0][9]) } } diff --git a/translate.cxx b/translate.cxx index f2e04d7d..a26e4085 100644 --- a/translate.cxx +++ b/translate.cxx @@ -3515,7 +3515,7 @@ c_unparser::visit_target_symbol (target_symbol* e) if (!e->probe_context_var.empty()) o->line() << "l->" << e->probe_context_var; else - throw semantic_error("cannot translate general cast expression", e->tok); + throw semantic_error("cannot translate general target expression", e->tok); } -- cgit