]> sourceware.org Git - systemtap.git/commitdiff
Make autocast distinct from cast
authorJosh Stone <jistone@redhat.com>
Thu, 3 Apr 2014 00:34:25 +0000 (17:34 -0700)
committerJosh Stone <jistone@redhat.com>
Sat, 5 Apr 2014 00:33:55 +0000 (17:33 -0700)
Some dwarf probes try to be helpful and fill in empty @cast modules, but
we don't want that for an automatic @cast that will determine its module
and type from its operand.  So let's just make autocast separate.

* parse.cxx (parser::parse_dwarf_value): Create autocast_op, and assign
  its token as that of the first addressof or peeked component.
* elaborate.cxx (void_statement_reducer::reduce_target_symbol): New,
  collapse any kind of target_symbol to its operand and indexes.  Call
  this in all the void_statement_reducer target_symbol-like visitors.
* [Lots of added visitor::visit_autocast_op...]

elaborate.cxx
elaborate.h
parse.cxx
staptree.cxx
staptree.h
tapsets.cxx
translate.cxx

index 054f6da38e51402306fc338671d9481e89b721ab..5ad72d739f91c24b990ca730b5a31d5850da0797 100644 (file)
@@ -1126,6 +1126,11 @@ struct symbol_fetcher
     sym = e;
   }
 
+  void visit_autocast_op (autocast_op* e)
+  {
+    sym = e;
+  }
+
   void throwone (const token* t)
   {
     if (t->type == tok_operator && t->content == ".") // guess someone misused . in $foo->bar.baz expression
@@ -2937,6 +2942,7 @@ struct void_statement_reducer: public update_visitor
   void visit_target_symbol (target_symbol* e);
   void visit_atvar_op (atvar_op* e);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_defined_op (defined_op* e);
 
   // these are a bit hairy to grok due to the intricacies of indexables and
@@ -2952,6 +2958,9 @@ struct void_statement_reducer: public update_visitor
   void visit_pre_crement (pre_crement* e) { provide (e); }
   void visit_post_crement (post_crement* e) { provide (e); }
   void visit_assignment (assignment* e) { provide (e); }
+
+private:
+  void reduce_target_symbol (target_symbol* e, expression* operand=NULL);
 };
 
 
@@ -3228,20 +3237,23 @@ void_statement_reducer::visit_print_format (print_format* e)
 }
 
 void
-void_statement_reducer::visit_atvar_op (atvar_op* e)
+void_statement_reducer::reduce_target_symbol (target_symbol* e,
+                                              expression* operand)
 {
-  visit_target_symbol (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
+  // When the result of any target_symbol isn't needed, it's just as good to
+  // evaluate the operand and any array indexes directly
 
   block *b = new block;
   b->tok = e->tok;
 
+  if (operand)
+    {
+      expr_statement *es = new expr_statement;
+      es->value = 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)
@@ -3253,16 +3265,6 @@ void_statement_reducer::visit_target_symbol (target_symbol* e)
       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;
@@ -3270,37 +3272,35 @@ void_statement_reducer::visit_target_symbol (target_symbol* e)
 }
 
 void
-void_statement_reducer::visit_cast_op (cast_op* e)
+void_statement_reducer::visit_atvar_op (atvar_op* e)
 {
-  // When the result of a cast operation isn't needed, it's just as good to
-  // 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;
+  if (session.verbose>2)
+    clog << _("Eliding unused target symbol ") << *e->tok << endl;
+  reduce_target_symbol (e);
+}
 
-      es = new expr_statement;
-      es->value = e->components[i].expr_index;
-      es->tok = es->value->tok;
-      b->statements.push_back(es);
-    }
+void
+void_statement_reducer::visit_target_symbol (target_symbol* e)
+{
+  if (session.verbose>2)
+    clog << _("Eliding unused target symbol ") << *e->tok << endl;
+  reduce_target_symbol (e);
+}
 
+void
+void_statement_reducer::visit_cast_op (cast_op* e)
+{
   if (session.verbose>2)
     clog << _("Eliding unused typecast ") << *e->tok << endl;
+  reduce_target_symbol (e, e->operand);
+}
 
-  b->visit(this);
-  relaxed_p = false;
-  e = 0;
-  provide (e);
+void
+void_statement_reducer::visit_autocast_op (autocast_op* e)
+{
+  if (session.verbose>2)
+    clog << _("Eliding unused autocast ") << *e->tok << endl;
+  reduce_target_symbol (e, e->operand);
 }
 
 
@@ -4692,6 +4692,18 @@ typeresolution_info::visit_cast_op (cast_op* e)
 }
 
 
+void
+typeresolution_info::visit_autocast_op (autocast_op* e)
+{
+  // Like cast_op, a implicit autocast_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(_("unknown type in dereference"), e->tok);
+}
+
+
 void
 typeresolution_info::visit_perf_op (perf_op* e)
 {
index 3e30da0798f96c0490ba355164e6d005fa7f3e72..9cc59bb752cf976bfffe10e0b345947968cd1870 100644 (file)
@@ -146,6 +146,7 @@ struct typeresolution_info: public visitor
   void visit_stat_op (stat_op* e);
   void visit_hist_op (hist_op* e);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_atvar_op (atvar_op* e);
   void visit_defined_op (defined_op* e);
   void visit_entry_op (entry_op* e);
index c16221c8d213ab510ae81259a1c27761e7377f55..143db696833fdfddb1099b71422d5992c37985be 100644 (file)
--- a/parse.cxx
+++ b/parse.cxx
@@ -3328,12 +3328,8 @@ parser::parse_dwarf_value ()
   target_symbol* tsym = NULL;
 
   // With '&' we'll definitely be making a target symbol of some sort
-  bool addressof = false;
-  if (peek_op ("&"))
-    {
-      swallow ();
-      addressof = true;
-    }
+  const token* addrtok = peek_op ("&") ? next () : NULL;
+  bool addressof = (addrtok != NULL);
 
   // First try target_symbol types: $var, @cast, and @var.
   const token* t = peek ();
@@ -3355,8 +3351,8 @@ parser::parse_dwarf_value ()
   if (!tsym && (addressof || peek_target_symbol_components ())
       && strverscmp(session.compatible.c_str(), "2.6") >= 0)
     {
-      cast_op *cop = new cast_op;
-      cop->tok = expr->tok;
+      autocast_op *cop = new autocast_op;
+      cop->tok = addrtok ?: peek ();
       cop->operand = expr;
       expr = tsym = cop;
     }
index a3b4637ac74788d919766986664c9d0e3ece6639..718c0b754b1097a2383888f27588717061e365bf 100644 (file)
@@ -446,7 +446,6 @@ void cast_op::print (ostream& o) const
   if (addressof)
     o << "&";
   o << name << '(' << *operand;
-  if (type_name.length() > 0)
   o << ", " << lex_cast_qstring (type_name);
   if (module.length() > 0)
     o << ", " << lex_cast_qstring (module);
@@ -456,6 +455,16 @@ void cast_op::print (ostream& o) const
 }
 
 
+void autocast_op::print (ostream& o) const
+{
+  if (addressof)
+    o << "&";
+  o << '(' << *operand << ')';
+  for (unsigned i = 0; i < components.size(); ++i)
+    o << components[i];
+}
+
+
 void defined_op::print (ostream& o) const
 {
   o << "@defined(" << *operand << ")";
@@ -1575,6 +1584,13 @@ cast_op::visit (visitor* u)
 }
 
 
+void
+autocast_op::visit (visitor* u)
+{
+  u->visit_autocast_op(this);
+}
+
+
 void
 atvar_op::visit (visitor* u)
 {
@@ -1918,6 +1934,13 @@ traversing_visitor::visit_cast_op (cast_op* e)
   e->visit_components (this);
 }
 
+void
+traversing_visitor::visit_autocast_op (autocast_op* e)
+{
+  e->operand->visit (this);
+  e->visit_components (this);
+}
+
 void
 traversing_visitor::visit_atvar_op (atvar_op* e)
 {
@@ -2134,6 +2157,17 @@ varuse_collecting_visitor::visit_cast_op (cast_op *e)
   functioncall_traversing_visitor::visit_cast_op (e);
 }
 
+void
+varuse_collecting_visitor::visit_autocast_op (autocast_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_autocast_op (e);
+}
+
 void
 varuse_collecting_visitor::visit_defined_op (defined_op *e)
 {
@@ -2580,6 +2614,12 @@ throwing_visitor::visit_cast_op (cast_op* e)
   throwone (e->tok);
 }
 
+void
+throwing_visitor::visit_autocast_op (autocast_op* e)
+{
+  throwone (e->tok);
+}
+
 void
 throwing_visitor::visit_defined_op (defined_op* e)
 {
@@ -2866,6 +2906,14 @@ update_visitor::visit_cast_op (cast_op* e)
   provide (e);
 }
 
+void
+update_visitor::visit_autocast_op (autocast_op* e)
+{
+  replace (e->operand);
+  e->visit_components (this);
+  provide (e);
+}
+
 void
 update_visitor::visit_atvar_op (atvar_op* e)
 {
@@ -3129,6 +3177,12 @@ deep_copy_visitor::visit_cast_op (cast_op* e)
   update_visitor::visit_cast_op(new cast_op(*e));
 }
 
+void
+deep_copy_visitor::visit_autocast_op (autocast_op* e)
+{
+  update_visitor::visit_autocast_op(new autocast_op(*e));
+}
+
 void
 deep_copy_visitor::visit_atvar_op (atvar_op* e)
 {
index c1621fc961f74f5234c46eac9094a3a888e73865..a436271808f8df94d832f3f08a5593f03fd06559 100644 (file)
@@ -328,6 +328,15 @@ struct cast_op: public target_symbol
   void visit (visitor* u);
 };
 
+// An autocast is like an implicit @cast on any expression, like
+// (expr)->foo->var[baz], and the type is gleaned from the expr.
+struct autocast_op: public target_symbol
+{
+  expression *operand;
+  void print (std::ostream& o) const;
+  void visit (visitor* u);
+};
+
 struct atvar_op: public target_symbol
 {
   std::string target_name, cu_name, module;
@@ -837,6 +846,7 @@ struct visitor
   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;
+  virtual void visit_autocast_op (autocast_op* e) = 0;
   virtual void visit_atvar_op (atvar_op* e) = 0;
   virtual void visit_defined_op (defined_op* e) = 0;
   virtual void visit_entry_op (entry_op* e) = 0;
@@ -885,6 +895,7 @@ struct traversing_visitor: public visitor
   void visit_stat_op (stat_op* e);
   void visit_hist_op (hist_op* e);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_atvar_op (atvar_op* e);
   void visit_defined_op (defined_op* e);
   void visit_entry_op (entry_op* e);
@@ -936,6 +947,7 @@ struct varuse_collecting_visitor: public functioncall_traversing_visitor
   void visit_post_crement (post_crement *e);
   void visit_foreach_loop (foreach_loop *s);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_atvar_op (atvar_op *e);
   void visit_defined_op (defined_op* e);
   void visit_entry_op (entry_op* e);
@@ -992,6 +1004,7 @@ struct throwing_visitor: public visitor
   void visit_stat_op (stat_op* e);
   void visit_hist_op (hist_op* e);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_atvar_op (atvar_op* e);
   void visit_defined_op (defined_op* e);
   void visit_entry_op (entry_op* e);
@@ -1071,6 +1084,7 @@ struct update_visitor: public visitor
   virtual void visit_stat_op (stat_op* e);
   virtual void visit_hist_op (hist_op* e);
   virtual void visit_cast_op (cast_op* e);
+  virtual void visit_autocast_op (autocast_op* e);
   virtual void visit_atvar_op (atvar_op* e);
   virtual void visit_defined_op (defined_op* e);
   virtual void visit_entry_op (entry_op* e);
@@ -1130,6 +1144,7 @@ struct deep_copy_visitor: public update_visitor
   virtual void visit_stat_op (stat_op* e);
   virtual void visit_hist_op (hist_op* e);
   virtual void visit_cast_op (cast_op* e);
+  virtual void visit_autocast_op (autocast_op* e);
   virtual void visit_atvar_op (atvar_op* e);
   virtual void visit_defined_op (defined_op* e);
   virtual void visit_entry_op (entry_op* e);
index eae63ab16d30114755fe373a55a46a6417a93974..a17fb3abc4bd57fee5c33d858ffb245ef400cff6 100644 (file)
@@ -4301,6 +4301,24 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
 }
 
 
+struct dwarf_autocast_expanding_visitor: public var_expanding_visitor
+{
+  systemtap_session& s;
+
+  dwarf_autocast_expanding_visitor(systemtap_session& s): s(s) {}
+  void visit_autocast_op (autocast_op* e);
+};
+
+
+void
+dwarf_autocast_expanding_visitor::visit_autocast_op (autocast_op* e)
+{
+  // TODO PR13664, glean the type from e->operand, then expand like @cast.
+
+  var_expanding_visitor::visit_autocast_op (e);
+}
+
+
 struct dwarf_atvar_expanding_visitor: public var_expanding_visitor
 {
   systemtap_session& s;
@@ -5137,6 +5155,10 @@ dwarf_derived_probe::register_patterns(systemtap_session& s)
   filter = new dwarf_atvar_expanding_visitor(s, *dw);
   s.code_filters.push_back(filter);
 
+  // NB: visit autocast last, so it can use types resolved from @cast/@var
+  filter = new dwarf_autocast_expanding_visitor(s);
+  s.code_filters.push_back(filter);
+
   register_function_and_statement_variants(s, root->bind(TOK_KERNEL), dw, pr_privileged);
   register_function_and_statement_variants(s, root->bind_str(TOK_MODULE), dw, pr_privileged);
   root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
index 5cb041bc6f5e2002f1e4befdc49f003546ccd5ad..2731f5ac7f1c61915f820d05f8a709178724eb14 100644 (file)
@@ -201,6 +201,7 @@ struct c_unparser: public unparser, public visitor
   void visit_stat_op (stat_op* e);
   void visit_hist_op (hist_op* e);
   void visit_cast_op (cast_op* e);
+  void visit_autocast_op (autocast_op* e);
   void visit_atvar_op (atvar_op* e);
   void visit_defined_op (defined_op* e);
   void visit_entry_op (entry_op* e);
@@ -4401,6 +4402,13 @@ c_unparser::visit_cast_op (cast_op* e)
 }
 
 
+void
+c_unparser::visit_autocast_op (autocast_op* e)
+{
+  throw SEMANTIC_ERROR(_("cannot translate general dereference expression"), e->tok);
+}
+
+
 void
 c_unparser::visit_defined_op (defined_op* e)
 {
This page took 0.069736 seconds and 5 git commands to generate.