summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dwflpp.cxx73
-rw-r--r--dwflpp.h3
-rw-r--r--elaborate.cxx62
-rw-r--r--parse.cxx74
-rw-r--r--parse.h3
-rw-r--r--staptree.cxx101
-rw-r--r--staptree.h29
-rw-r--r--tapset-mark.cxx36
-rw-r--r--tapset-perfmon.cxx19
-rw-r--r--tapset-procfs.cxx19
-rw-r--r--tapset-utrace.cxx38
-rw-r--r--tapsets.cxx90
-rw-r--r--testsuite/systemtap.base/pointer_array.stp11
-rw-r--r--translate.cxx2
14 files changed, 311 insertions, 249 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index e6e7b471..6ede1d68 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<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;
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<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);
}
diff --git a/parse.cxx b/parse.cxx
index 35c78abe..41a13ca5 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,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 : */
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);
};
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);
}
diff --git a/staptree.h b/staptree.h
index 16f0256a..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,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);
}