diff options
author | Josh Stone <jistone@redhat.com> | 2009-08-03 15:16:09 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-08-03 15:16:09 -0700 |
commit | 0164a29cfb80344dced2e1683df05f6b62fe6cb3 (patch) | |
tree | f1135402bc2f45e03718733eb8490cd1f9df52f6 | |
parent | 28ad563d57d03e0d21936e394061e3380607d83b (diff) | |
parent | 6fda2dff51c667a8c73545dd397b844108715310 (diff) | |
download | systemtap-steved-0164a29cfb80344dced2e1683df05f6b62fe6cb3.tar.gz systemtap-steved-0164a29cfb80344dced2e1683df05f6b62fe6cb3.tar.xz systemtap-steved-0164a29cfb80344dced2e1683df05f6b62fe6cb3.zip |
Merge branch 'array_index'
-rw-r--r-- | dwflpp.cxx | 73 | ||||
-rw-r--r-- | dwflpp.h | 3 | ||||
-rw-r--r-- | elaborate.cxx | 62 | ||||
-rw-r--r-- | parse.cxx | 74 | ||||
-rw-r--r-- | parse.h | 3 | ||||
-rw-r--r-- | staptree.cxx | 101 | ||||
-rw-r--r-- | staptree.h | 29 | ||||
-rw-r--r-- | tapset-mark.cxx | 36 | ||||
-rw-r--r-- | tapset-perfmon.cxx | 19 | ||||
-rw-r--r-- | tapset-procfs.cxx | 19 | ||||
-rw-r--r-- | tapset-utrace.cxx | 38 | ||||
-rw-r--r-- | tapsets.cxx | 90 | ||||
-rw-r--r-- | testsuite/systemtap.base/pointer_array.stp | 11 | ||||
-rw-r--r-- | translate.cxx | 2 |
14 files changed, 311 insertions, 249 deletions
@@ -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<Dwarf_Attribute>& 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) ?: "<anonymous>") + 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,53 @@ 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 && + c.type != target_symbol::comp_expression_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<Dwarf_Word>(e->components[i].second)); + NULL, c.num_index); + ++i; + } + else if (c.type == target_symbol::comp_expression_array_index) + { + string index = "THIS->index" + lex_cast<string>(i); + c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, + index.c_str(), 0); ++i; } else - throw semantic_error("bad field '" - + e->components[i].second - + "' for array type", - e->tok); + throw semantic_error ("invalid access '" + + lex_cast<string>(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<string>(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) ?: "<anonymous>"), - e->tok); + c.tok); *die_mem = *tmpdie; } { vector<Dwarf_Attribute> 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 +1785,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) ?: "<unknown>") + alternatives, - e->tok); + c.tok); } for (unsigned j = 0; j < locs.size(); ++j) @@ -1784,39 +1799,41 @@ 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<string>(c) + "' vs. enum type " + string(dwarf_diename_integrate (die) ?: "<anonymous type>"), - 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<string>(c) + "' vs. base type " + string(dwarf_diename_integrate (die) ?: "<anonymous type>"), - 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) ?: "<anonymous type>") + ": unexpected type tag " + lex_cast<string>(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 || + e->components.back().type == target_symbol::comp_expression_array_index) die = dwarf_formref_die (attr_mem, die_mem); return die; @@ -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<Dwarf_Attribute>& locs); 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 @@ -2803,16 +2804,73 @@ void_statement_reducer::visit_print_format (print_format* 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; i<e->components.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; i<e->components.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); } @@ -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,33 @@ parser::parse_symbol () return sym; } + +void +parser::parse_target_symbol_components (target_symbol* e) +{ + while (true) + { + if (peek_op ("->")) + { + const token* t = next(); + string member; + expect_ident_or_keyword (member); + e->components.push_back (target_symbol::component(t, member)); + } + else if (peek_op ("[")) + { + const token* t = next(); + expression* index = parse_expression(); + literal_number* ln = dynamic_cast<literal_number*>(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 + break; + } +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ @@ -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); }; diff --git a/staptree.cxx b/staptree.cxx index 9e2ca8da..50d9980f 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -186,6 +186,31 @@ 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: + case target_symbol::comp_expression_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 @@ -259,27 +284,41 @@ void symbol::print (ostream& o) const } -void target_symbol::print (std::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; + case comp_expression_array_index: + o << '[' << *expr_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]; } -void cast_op::print (std::ostream& o) const +void cast_op::print (ostream& o) const { if (addressof) o << "&"; @@ -289,17 +328,7 @@ void cast_op::print (std::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]; } @@ -1246,6 +1275,22 @@ target_symbol::visit (visitor* u) } 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) { u->visit_cast_op(this); @@ -1613,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 @@ -1715,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 @@ -2348,6 +2397,7 @@ update_visitor::visit_symbol (symbol* e) void update_visitor::visit_target_symbol (target_symbol* e) { + e->visit_components (this); provide (e); } @@ -2355,6 +2405,7 @@ void update_visitor::visit_cast_op (cast_op* e) { e->operand = require (e->operand); + e->visit_components (this); provide (e); } @@ -58,6 +58,7 @@ std::ostream& operator << (std::ostream& o, const exp_type& e); struct token; struct visitor; +struct update_visitor; struct expression { @@ -227,18 +228,42 @@ 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 + { + const token* tok; + 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) {} + 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; + }; + bool addressof; std::string base_name; - std::vector<std::pair<component_type, std::string> > components; + std::vector<component> components; std::string probe_context_var; semantic_error* saved_conversion_error; 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); }; +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..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].first) - { - 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].first) - { - 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 0fb567f7..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].first) - { - 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<string>(counter_number) + "].reg_num;"; diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index a996ee32..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].first) - { - 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 a3a4ca3d..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<int>(argnum_s); - if (e->components.size() > 0) - { - switch (e->components[0].first) - { - 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].first) - { - 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 bd33fb0b..ba344c51 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 } @@ -2269,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<string>(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a single pe_long formal @@ -2293,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 @@ -2522,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<string>(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a second pe_long formal @@ -2550,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 @@ -3278,7 +3310,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) cast->type = probe_name + "_arg" + lex_cast<string>(argno); cast->module = process_name; - provide(cast); + cast->visit(this); } @@ -5262,19 +5294,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].first) - { - 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); @@ -5323,7 +5344,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 } @@ -5340,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<string>(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a pe_long formal @@ -5367,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) { @@ -5395,18 +5432,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].first) - { - 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") { 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); } |