summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-08-03 14:45:21 -0700
committerJosh Stone <jistone@redhat.com>2009-08-03 15:14:21 -0700
commit6fda2dff51c667a8c73545dd397b844108715310 (patch)
treeb0a6be2e84f7a9ce8b0f72a3e9b4f2c329ac9ba2
parentdc5a09fc9a61c8b33078164b6855dea54a33627c (diff)
downloadsystemtap-steved-6fda2dff51c667a8c73545dd397b844108715310.tar.gz
systemtap-steved-6fda2dff51c667a8c73545dd397b844108715310.tar.xz
systemtap-steved-6fda2dff51c667a8c73545dd397b844108715310.zip
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.
-rw-r--r--dwflpp.cxx13
-rw-r--r--elaborate.cxx62
-rw-r--r--parse.cxx9
-rw-r--r--staptree.cxx28
-rw-r--r--staptree.h11
-rw-r--r--tapsets.cxx60
-rw-r--r--testsuite/systemtap.base/pointer_array.stp11
-rw-r--r--translate.cxx2
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<string>(i);
+ c_translate_array (pool, 1, 0 /* PR9768 */, die, tail,
+ index.c_str(), 0);
+ ++i;
+ }
else
throw semantic_error ("invalid access '"
+ lex_cast<string>(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
@@ -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 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<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
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;
}
}
@@ -1271,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);
@@ -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<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
@@ -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<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
@@ -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<string>(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<string>(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);
}