summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--elaborate.cxx31
-rw-r--r--elaborate.h1
-rw-r--r--parse.cxx49
-rw-r--r--staptree.cxx64
-rw-r--r--staptree.h15
-rw-r--r--translate.cxx8
7 files changed, 182 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 6a609a62..b641d3b7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-02-11 Josh Stone <jistone@redhat.com>
+
+ * staptree.h (struct cast_op, visitor::visit_cast_op): New.
+ * staptree.cxx (cast_op::print/visit, various visitor::visit_cast_op's):
+ Incorporate cast_op into the basic tree operations.
+ * parse.cxx (parser::parse_symbol): Parse @cast operator with an
+ expression operand, type string, and optional module string.
+ * translate.cxx (c_unparser::visit_cast_op): Error out if a @cast
+ survives to translation.
+ * elaborate.cxx (typeresolution_info::visit_cast_op): Error out if a
+ @cast survives to type resolution.
+ (symbol_fetcher::visit_cast_op): treat @casts as a symbol target
+ (void_statement_reducer::visit_cast_op): unused @casts can be discarded,
+ but the operand should still be evaluated.
+
2009-02-11 Dave Brolley <brolley@redhat.com>
* stap-client: s/jar/zip/.
diff --git a/elaborate.cxx b/elaborate.cxx
index ba50defb..981fc7c7 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -701,6 +701,11 @@ struct symbol_fetcher
e->base->visit_indexable (this);
}
+ void visit_cast_op (cast_op* e)
+ {
+ sym = e;
+ }
+
void throwone (const token* t)
{
throw semantic_error ("Expecting symbol or array index expression", t);
@@ -2505,6 +2510,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_cast_op (cast_op* e);
// these are a bit hairy to grok due to the intricacies of indexables and
// stats, so I'm chickening out and skipping them...
@@ -2772,6 +2778,19 @@ void_statement_reducer::visit_print_format (print_format* e)
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
+
+ if (session.verbose>2)
+ clog << "Eliding unused typecast " << *e->tok << endl;
+
+ relaxed_p = false;
+ e->operand->visit(this);
+}
+
void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
{
@@ -3399,6 +3418,18 @@ typeresolution_info::visit_target_symbol (target_symbol* e)
void
+typeresolution_info::visit_cast_op (cast_op* e)
+{
+ // Like target_symbol, a cast_op shouldn't survive this far
+ // unless it was not resolved and its value is really needed.
+ if (e->saved_conversion_error)
+ throw (* (e->saved_conversion_error));
+ else
+ throw semantic_error("unresolved cast expression", e->tok);
+}
+
+
+void
typeresolution_info::visit_arrayindex (arrayindex* e)
{
diff --git a/elaborate.h b/elaborate.h
index c8697595..9cc4cbda 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -95,6 +95,7 @@ struct typeresolution_info: public visitor
void visit_print_format (print_format* e);
void visit_stat_op (stat_op* e);
void visit_hist_op (hist_op* e);
+ void visit_cast_op (cast_op* e);
};
diff --git a/parse.cxx b/parse.cxx
index 0419dcb9..aeb11998 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -2331,7 +2331,54 @@ parser::parse_symbol ()
bool pf_stream, pf_format, pf_delim, pf_newline, pf_char;
- if (name.size() > 0 && name[0] == '@')
+ if (name == "@cast")
+ {
+ // type-punning time
+ cast_op *cop = new cast_op;
+ cop->tok = t;
+ cop->base_name = name;
+ expect_op("(");
+ cop->operand = parse_expression ();
+ expect_op(",");
+ expect_unknown(tok_string, cop->type);
+ if (peek_op (","))
+ {
+ next();
+ 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;
+ }
+ // if there aren't any dereferences, then the cast is pointless
+ if (cop->components.empty())
+ {
+ expression *op = cop->operand;
+ delete cop;
+ return op;
+ }
+ return cop;
+ }
+
+ else if (name.size() > 0 && name[0] == '@')
{
stat_op *sop = new stat_op;
if (name == "@avg")
diff --git a/staptree.cxx b/staptree.cxx
index 9ffbaf09..d6586d86 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -277,6 +277,28 @@ void target_symbol::print (std::ostream& o) const
}
+void cast_op::print (std::ostream& o) const
+{
+ o << base_name << '(' << *operand;
+ o << ", " << lex_cast_qstring (type);
+ if (module.length() > 0)
+ 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;
+ }
+ }
+}
+
+
void vardecl::print (ostream& o) const
{
o << name;
@@ -1220,6 +1242,12 @@ target_symbol::visit (visitor* u)
}
void
+cast_op::visit (visitor* u)
+{
+ u->visit_cast_op(this);
+}
+
+void
arrayindex::visit (visitor* u)
{
u->visit_arrayindex (this);
@@ -1586,6 +1614,12 @@ traversing_visitor::visit_target_symbol (target_symbol*)
}
void
+traversing_visitor::visit_cast_op (cast_op* e)
+{
+ e->operand->visit (this);
+}
+
+void
traversing_visitor::visit_arrayindex (arrayindex* e)
{
for (unsigned i=0; i<e->indexes.size(); i++)
@@ -1680,6 +1714,17 @@ varuse_collecting_visitor::visit_target_symbol (target_symbol *e)
}
void
+varuse_collecting_visitor::visit_cast_op (cast_op *e)
+{
+ // As with target_symbols, unresolved cast assignments need to preserved
+ // for later error handling.
+ if (is_active_lvalue (e))
+ embedded_seen = true;
+
+ functioncall_traversing_visitor::visit_cast_op (e);
+}
+
+void
varuse_collecting_visitor::visit_print_format (print_format* e)
{
// NB: Instead of being top-level statements, "print" and "printf"
@@ -2064,6 +2109,12 @@ throwing_visitor::visit_target_symbol (target_symbol* e)
}
void
+throwing_visitor::visit_cast_op (cast_op* e)
+{
+ throwone (e->tok);
+}
+
+void
throwing_visitor::visit_arrayindex (arrayindex* e)
{
throwone (e->tok);
@@ -2297,6 +2348,13 @@ update_visitor::visit_target_symbol (target_symbol* e)
}
void
+update_visitor::visit_cast_op (cast_op* e)
+{
+ e->operand = require (e->operand);
+ provide (e);
+}
+
+void
update_visitor::visit_arrayindex (arrayindex* e)
{
e->base = require (e->base);
@@ -2528,6 +2586,12 @@ deep_copy_visitor::visit_target_symbol (target_symbol* e)
}
void
+deep_copy_visitor::visit_cast_op (cast_op* e)
+{
+ update_visitor::visit_cast_op(new cast_op(*e));
+}
+
+void
deep_copy_visitor::visit_arrayindex (arrayindex* e)
{
update_visitor::visit_arrayindex(new arrayindex(*e));
diff --git a/staptree.h b/staptree.h
index 0cd0ee0d..7092f980 100644
--- a/staptree.h
+++ b/staptree.h
@@ -238,6 +238,15 @@ struct target_symbol: public symbol
};
+struct cast_op: public target_symbol
+{
+ expression *operand;
+ std::string type, module;
+ void print (std::ostream& o) const;
+ void visit (visitor* u);
+};
+
+
struct arrayindex: public expression
{
std::vector<expression*> indexes;
@@ -680,6 +689,7 @@ struct visitor
virtual void visit_print_format (print_format* e) = 0;
virtual void visit_stat_op (stat_op* e) = 0;
virtual void visit_hist_op (hist_op* e) = 0;
+ virtual void visit_cast_op (cast_op* e) = 0;
};
@@ -720,6 +730,7 @@ struct traversing_visitor: public visitor
void visit_print_format (print_format* e);
void visit_stat_op (stat_op* e);
void visit_hist_op (hist_op* e);
+ void visit_cast_op (cast_op* e);
};
@@ -759,6 +770,7 @@ struct varuse_collecting_visitor: public functioncall_traversing_visitor
void visit_pre_crement (pre_crement *e);
void visit_post_crement (post_crement *e);
void visit_foreach_loop (foreach_loop *s);
+ void visit_cast_op (cast_op* e);
bool side_effect_free ();
bool side_effect_free_wrt (const std::set<vardecl*>& vars);
@@ -808,6 +820,7 @@ struct throwing_visitor: public visitor
void visit_print_format (print_format* e);
void visit_stat_op (stat_op* e);
void visit_hist_op (hist_op* e);
+ void visit_cast_op (cast_op* e);
};
// A visitor similar to a traversing_visitor, but with the ability to rewrite
@@ -868,6 +881,7 @@ struct update_visitor: public visitor
virtual void visit_print_format (print_format* e);
virtual void visit_stat_op (stat_op* e);
virtual void visit_hist_op (hist_op* e);
+ virtual void visit_cast_op (cast_op* e);
private:
std::stack<void *> targets;
@@ -922,6 +936,7 @@ struct deep_copy_visitor: public update_visitor
virtual void visit_print_format (print_format* e);
virtual void visit_stat_op (stat_op* e);
virtual void visit_hist_op (hist_op* e);
+ virtual void visit_cast_op (cast_op* e);
};
#endif // STAPTREE_H
diff --git a/translate.cxx b/translate.cxx
index 0d430ea3..da647722 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -150,6 +150,7 @@ struct c_unparser: public unparser, public visitor
void visit_print_format (print_format* e);
void visit_stat_op (stat_op* e);
void visit_hist_op (hist_op* e);
+ void visit_cast_op (cast_op* e);
};
// A shadow visitor, meant to generate temporary variable declarations
@@ -3488,6 +3489,13 @@ c_unparser::visit_target_symbol (target_symbol* e)
void
+c_unparser::visit_cast_op (cast_op* e)
+{
+ throw semantic_error("cannot translate general cast expression", e->tok);
+}
+
+
+void
c_tmpcounter::load_map_indices(arrayindex *e)
{
symbol *array;