]> sourceware.org Git - systemtap.git/commitdiff
PR18079: support nested autocast / @defined
authorFrank Ch. Eigler <fche@redhat.com>
Wed, 22 Jun 2016 15:43:33 +0000 (11:43 -0400)
committerCody Santing <csanting@redhat.com>
Mon, 25 Jul 2016 14:06:55 +0000 (10:06 -0400)
We now perform const-folding & dead-code-elision during the type
resolution loop, whenever an autocast expression gets evaluated.  This
way, @defined(foo()->mm) type expressions can work as nature intended.

This requires @defined() not to be short-circuit evaluated to 0 during
a random const_folding process, so a flag is introduced to control its
preservation or collapsing.  For the last (assert_resolvability) pass
in the type resolution loop, this flag is set to true, so that
genuinely unresolvable @defined($expressions) do get mapped to 0 in
time for a last elision.

elaborate.cxx
testsuite/semok/autocast14.stp

index 3b4a780bab97d2fce64ea21e71db27067dcf882b..eb7d544dd62e0b91ac428fec4f7a2e4dbc58fda5 100644 (file)
@@ -3985,9 +3985,10 @@ struct const_folder: public update_visitor
 {
   systemtap_session& session;
   bool& relaxed_p;
-
-  const_folder(systemtap_session& s, bool& r):
-    session(s), relaxed_p(r), last_number(0), last_string(0) {}
+  bool collapse_defines_p;
+  
+  const_folder(systemtap_session& s, bool& r, bool collapse_defines = false):
+    session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {}
 
   literal_number* last_number;
   literal_number* get_number(expression*& e);
@@ -4507,15 +4508,26 @@ const_folder::visit_ternary_expression (ternary_expression* e)
 void
 const_folder::visit_defined_op (defined_op* e)
 {
-  // If a @defined makes it this far, then it is, de facto, undefined.
-
-  if (session.verbose>2)
-    clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
-  relaxed_p = false;
+  // If a @defined makes it this far, then it was not resolved by
+  // previous efforts.  We could assume that therefore it is a big fat
+  // zero, but for the @defined(autocast) case PR18079, this just
+  // means that we didn't know yet.
 
-  literal_number* n = new literal_number (0);
-  n->tok = e->tok;
-  n->visit (this);
+  if (collapse_defines_p)
+    {
+      if (session.verbose>2)
+        clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
+       relaxed_p = false;
+       literal_number* n = new literal_number (0);
+       n->tok = e->tok;
+       n->visit (this);
+    }
+  else
+    {
+      if (session.verbose>2)
+        clog << _("Preserving unresolved @defined check ") << *e->tok << endl;
+      provide (e);
+    }
 }
 
 void
@@ -5388,6 +5400,21 @@ semantic_pass_types (systemtap_session& s)
             ti.current_probe = 0;
             ti.current_function = fd;
             ti.t = pe_unknown;
+
+            if (ti.assert_resolvability)
+              {
+                // PR18079, rerun the const-folder / dead-block-remover
+                // one last time, in case an unresolvable
+                // @defined($foobar) still persists.  This should map
+                // those to 0.
+                bool relaxed_p;
+                const_folder cf (s, relaxed_p, true); // NB: true
+                cf.replace (fd->body);
+                dead_control_remover dc (s, relaxed_p);
+                fd->body->visit (&dc);
+                (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+              }
+              
             fd->body->visit (& ti);
             // NB: we don't have to assert a known type for
             // functions here, to permit a "void" function.
@@ -5403,6 +5430,16 @@ semantic_pass_types (systemtap_session& s)
               {
                 autocast_expanding_visitor aev (ti);
                 aev.replace (fd->body);
+
+                // PR18079, rerun the const-folder / dead-block-remover
+                // in case autocast evaluation enabled a @defined()
+                bool relaxed_p;
+                const_folder cf (s, relaxed_p);
+                cf.replace (fd->body);
+                dead_control_remover dc (s, relaxed_p);
+                fd->body->visit (&dc);
+                (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+
                 ti.num_available_autocasts = 0;
               }
           }
@@ -5421,6 +5458,21 @@ semantic_pass_types (systemtap_session& s)
             ti.current_function = 0;
             ti.current_probe = pn;
             ti.t = pe_unknown;
+
+            if (ti.assert_resolvability)
+              {
+                // PR18079, rerun the const-folder / dead-block-remover
+                // one last time, in case an unresolvable
+                // @defined($foobar) still persists.  This should map
+                // those to 0.
+                bool relaxed_p;
+                const_folder cf (s, relaxed_p, true); // NB: true
+                cf.replace (pn->body);
+                dead_control_remover dc (s, relaxed_p);
+                pn->body->visit (&dc);
+                (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+              }
+            
             pn->body->visit (& ti);
             for (unsigned i=0; i < pn->locals.size(); ++i)
               ti.check_local (pn->locals[i]);
@@ -5430,6 +5482,16 @@ semantic_pass_types (systemtap_session& s)
               {
                 autocast_expanding_visitor aev (ti);
                 aev.replace (pn->body);
+
+                // PR18079, rerun the const-folder / dead-block-remover
+                // in case autocast evaluation enabled a @defined()
+                bool relaxed_p;
+                const_folder cf (s, relaxed_p);
+                cf.replace (pn->body);
+                dead_control_remover dc (s, relaxed_p);
+                pn->body->visit (&dc);
+                (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
+
                 ti.num_available_autocasts = 0;
               }
             
@@ -5908,7 +5970,15 @@ typeresolution_info::visit_target_symbol (target_symbol* e)
   // later unused-expression-elimination pass didn't get rid of it
   // either.  So we have a target symbol that is believed to be of
   // genuine use, yet unresolved by the provider.
-
+  //
+  // PR18079, or it can happen if a $target expression is nested within
+  // a @defined() test that has not yet been resolved (but can be soon).
+  if (! assert_resolvability)
+    {
+      num_still_unresolved ++;
+      return;
+    }
+  
   if (session.verbose > 2)
     {
       clog << _("Resolution problem with ");
@@ -5975,7 +6045,15 @@ typeresolution_info::visit_atvar_op (atvar_op* e)
 void
 typeresolution_info::visit_defined_op (defined_op* e)
 {
-  throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
+  // PR18079: if a @defined is still around, it may have a parameter that
+  // wasn't resolvable one way or another earlier.  Maybe an autocast_op.
+  // Let's give it a visit just in case. 
+  e->operand->visit(this);
+
+  if (assert_resolvability)
+    throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
+  else
+    num_still_unresolved ++;
 }
 
 
index 55c06c419d41bb3fdfeddb69b8299514c370ded8..1b32d8052712fec75c7937f2f29d090314721062 100755 (executable)
@@ -1,7 +1,7 @@
 #! stap -p2
 
-probe oneshot
-{
+
+@define STUFF %(
     // precheck, it should work with @cast
     if (!@defined(@task(0)->mm)) {
         println($cast_failed_mm)
@@ -17,4 +17,16 @@ probe oneshot
     if (@defined(task_current()->systemtap)) {
         println($autocast_succeeded_systemtap)
     }
+%)
+
+
+probe oneshot
+{
+  @STUFF
+  foo() // from a function too, to test PR18079 function processing
 }
+
+function foo ()
+{
+  @STUFF
+}
\ No newline at end of file
This page took 0.040982 seconds and 5 git commands to generate.