|
|
9201c6 |
commit 056cb27baac1ce3ab4d675dbbe4881afde801ca3
|
|
|
9201c6 |
Author: Frank Ch. Eigler <fche@redhat.com>
|
|
|
9201c6 |
Date: Wed Jun 22 11:43:33 2016 -0400
|
|
|
9201c6 |
|
|
|
9201c6 |
PR18079: support nested autocast / @defined
|
|
|
9201c6 |
|
|
|
9201c6 |
We now perform const-folding & dead-code-elision during the type
|
|
|
9201c6 |
resolution loop, whenever an autocast expression gets evaluated. This
|
|
|
9201c6 |
way, @defined(foo()->mm) type expressions can work as nature intended.
|
|
|
9201c6 |
|
|
|
9201c6 |
This requires @defined() not to be short-circuit evaluated to 0 during
|
|
|
9201c6 |
a random const_folding process, so a flag is introduced to control its
|
|
|
9201c6 |
preservation or collapsing. For the last (assert_resolvability) pass
|
|
|
9201c6 |
in the type resolution loop, this flag is set to true, so that
|
|
|
9201c6 |
genuinely unresolvable @defined($expressions) do get mapped to 0 in
|
|
|
9201c6 |
time for a last elision.
|
|
|
9201c6 |
|
|
|
9201c6 |
diff --git a/elaborate.cxx b/elaborate.cxx
|
|
|
9201c6 |
index 4a375d9..a1088a1 100644
|
|
|
9201c6 |
--- a/elaborate.cxx
|
|
|
9201c6 |
+++ b/elaborate.cxx
|
|
|
9201c6 |
@@ -3984,9 +3984,10 @@ struct const_folder: public update_visitor
|
|
|
9201c6 |
{
|
|
|
9201c6 |
systemtap_session& session;
|
|
|
9201c6 |
bool& relaxed_p;
|
|
|
9201c6 |
-
|
|
|
9201c6 |
- const_folder(systemtap_session& s, bool& r):
|
|
|
9201c6 |
- session(s), relaxed_p(r), last_number(0), last_string(0) {}
|
|
|
9201c6 |
+ bool collapse_defines_p;
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ const_folder(systemtap_session& s, bool& r, bool collapse_defines = false):
|
|
|
9201c6 |
+ session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {}
|
|
|
9201c6 |
|
|
|
9201c6 |
literal_number* last_number;
|
|
|
9201c6 |
literal_number* get_number(expression*& e);
|
|
|
9201c6 |
@@ -4506,15 +4507,26 @@ const_folder::visit_ternary_expression (ternary_expression* e)
|
|
|
9201c6 |
void
|
|
|
9201c6 |
const_folder::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
- // If a @defined makes it this far, then it is, de facto, undefined.
|
|
|
9201c6 |
-
|
|
|
9201c6 |
- if (session.verbose>2)
|
|
|
9201c6 |
- clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
|
|
|
9201c6 |
- relaxed_p = false;
|
|
|
9201c6 |
+ // If a @defined makes it this far, then it was not resolved by
|
|
|
9201c6 |
+ // previous efforts. We could assume that therefore it is a big fat
|
|
|
9201c6 |
+ // zero, but for the @defined(autocast) case PR18079, this just
|
|
|
9201c6 |
+ // means that we didn't know yet.
|
|
|
9201c6 |
|
|
|
9201c6 |
- literal_number* n = new literal_number (0);
|
|
|
9201c6 |
- n->tok = e->tok;
|
|
|
9201c6 |
- n->visit (this);
|
|
|
9201c6 |
+ if (collapse_defines_p)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ if (session.verbose>2)
|
|
|
9201c6 |
+ clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
|
|
|
9201c6 |
+ relaxed_p = false;
|
|
|
9201c6 |
+ literal_number* n = new literal_number (0);
|
|
|
9201c6 |
+ n->tok = e->tok;
|
|
|
9201c6 |
+ n->visit (this);
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+ else
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ if (session.verbose>2)
|
|
|
9201c6 |
+ clog << _("Preserving unresolved @defined check ") << *e->tok << endl;
|
|
|
9201c6 |
+ provide (e);
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
void
|
|
|
9201c6 |
@@ -5387,6 +5399,21 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
ti.current_probe = 0;
|
|
|
9201c6 |
ti.current_function = fd;
|
|
|
9201c6 |
ti.t = pe_unknown;
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (ti.assert_resolvability)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
+ // one last time, in case an unresolvable
|
|
|
9201c6 |
+ // @defined($foobar) still persists. This should map
|
|
|
9201c6 |
+ // those to 0.
|
|
|
9201c6 |
+ bool relaxed_p;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p, true); // NB: true
|
|
|
9201c6 |
+ cf.replace (fd->body);
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ fd->body->visit (&dc);
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+
|
|
|
9201c6 |
fd->body->visit (& ti);
|
|
|
9201c6 |
// NB: we don't have to assert a known type for
|
|
|
9201c6 |
// functions here, to permit a "void" function.
|
|
|
9201c6 |
@@ -5402,6 +5429,16 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
autocast_expanding_visitor aev (ti);
|
|
|
9201c6 |
aev.replace (fd->body);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
+ // in case autocast evaluation enabled a @defined()
|
|
|
9201c6 |
+ bool relaxed_p;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
+ cf.replace (fd->body);
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ fd->body->visit (&dc);
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+
|
|
|
9201c6 |
ti.num_available_autocasts = 0;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
}
|
|
|
9201c6 |
@@ -5420,6 +5457,21 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
ti.current_function = 0;
|
|
|
9201c6 |
ti.current_probe = pn;
|
|
|
9201c6 |
ti.t = pe_unknown;
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (ti.assert_resolvability)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
+ // one last time, in case an unresolvable
|
|
|
9201c6 |
+ // @defined($foobar) still persists. This should map
|
|
|
9201c6 |
+ // those to 0.
|
|
|
9201c6 |
+ bool relaxed_p;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p, true); // NB: true
|
|
|
9201c6 |
+ cf.replace (pn->body);
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ pn->body->visit (&dc);
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+
|
|
|
9201c6 |
pn->body->visit (& ti);
|
|
|
9201c6 |
for (unsigned i=0; i < pn->locals.size(); ++i)
|
|
|
9201c6 |
ti.check_local (pn->locals[i]);
|
|
|
9201c6 |
@@ -5429,6 +5481,16 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
autocast_expanding_visitor aev (ti);
|
|
|
9201c6 |
aev.replace (pn->body);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
+ // in case autocast evaluation enabled a @defined()
|
|
|
9201c6 |
+ bool relaxed_p;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
+ cf.replace (pn->body);
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ pn->body->visit (&dc);
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+
|
|
|
9201c6 |
ti.num_available_autocasts = 0;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
@@ -5907,7 +5969,15 @@ typeresolution_info::visit_target_symbol (target_symbol* e)
|
|
|
9201c6 |
// later unused-expression-elimination pass didn't get rid of it
|
|
|
9201c6 |
// either. So we have a target symbol that is believed to be of
|
|
|
9201c6 |
// genuine use, yet unresolved by the provider.
|
|
|
9201c6 |
-
|
|
|
9201c6 |
+ //
|
|
|
9201c6 |
+ // PR18079, or it can happen if a $target expression is nested within
|
|
|
9201c6 |
+ // a @defined() test that has not yet been resolved (but can be soon).
|
|
|
9201c6 |
+ if (! assert_resolvability)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ num_still_unresolved ++;
|
|
|
9201c6 |
+ return;
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+
|
|
|
9201c6 |
if (session.verbose > 2)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
clog << _("Resolution problem with ");
|
|
|
9201c6 |
@@ -5974,7 +6044,15 @@ typeresolution_info::visit_atvar_op (atvar_op* e)
|
|
|
9201c6 |
void
|
|
|
9201c6 |
typeresolution_info::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
- throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
|
|
|
9201c6 |
+ // PR18079: if a @defined is still around, it may have a parameter that
|
|
|
9201c6 |
+ // wasn't resolvable one way or another earlier. Maybe an autocast_op.
|
|
|
9201c6 |
+ // Let's give it a visit just in case.
|
|
|
9201c6 |
+ e->operand->visit(this);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (assert_resolvability)
|
|
|
9201c6 |
+ throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok);
|
|
|
9201c6 |
+ else
|
|
|
9201c6 |
+ num_still_unresolved ++;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
|
|
|
9201c6 |
diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
index 55c06c4..1b32d80 100755
|
|
|
9201c6 |
--- a/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
+++ b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
@@ -1,7 +1,7 @@
|
|
|
9201c6 |
#! stap -p2
|
|
|
9201c6 |
|
|
|
9201c6 |
-probe oneshot
|
|
|
9201c6 |
-{
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+@define STUFF %(
|
|
|
9201c6 |
// precheck, it should work with @cast
|
|
|
9201c6 |
if (!@defined(@task(0)->mm)) {
|
|
|
9201c6 |
println($cast_failed_mm)
|
|
|
9201c6 |
@@ -17,4 +17,16 @@ probe oneshot
|
|
|
9201c6 |
if (@defined(task_current()->systemtap)) {
|
|
|
9201c6 |
println($autocast_succeeded_systemtap)
|
|
|
9201c6 |
}
|
|
|
9201c6 |
+%)
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+probe oneshot
|
|
|
9201c6 |
+{
|
|
|
9201c6 |
+ @STUFF
|
|
|
9201c6 |
+ foo() // from a function too, to test PR18079 function processing
|
|
|
9201c6 |
}
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+function foo ()
|
|
|
9201c6 |
+{
|
|
|
9201c6 |
+ @STUFF
|
|
|
9201c6 |
+}
|
|
|
9201c6 |
\ No newline at end of file
|
|
|
9201c6 |
|
|
|
9201c6 |
commit 0eda9cd7c9fe3cf7622f6bcf5e9cfba9fdf537dd
|
|
|
9201c6 |
Author: Josh Stone <jistone@redhat.com>
|
|
|
9201c6 |
Date: Wed Jun 22 12:09:05 2016 -0700
|
|
|
9201c6 |
|
|
|
9201c6 |
Increase the difficulty of semok/autocast14.stp
|
|
|
9201c6 |
|
|
|
9201c6 |
diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
index 1b32d80..b9488d7 100755
|
|
|
9201c6 |
--- a/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
+++ b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
@@ -17,6 +17,19 @@
|
|
|
9201c6 |
if (@defined(task_current()->systemtap)) {
|
|
|
9201c6 |
println($autocast_succeeded_systemtap)
|
|
|
9201c6 |
}
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // Test that autocast can resolve on the results of @defined
|
|
|
9201c6 |
+ mm1 = @choose_defined($nonsense, task_current())->mm;
|
|
|
9201c6 |
+ mm2 = @choose_defined(task_current(), $nonsense)->mm;
|
|
|
9201c6 |
+ println(mm1 == mm2)
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // Test an even deeper level of @defined
|
|
|
9201c6 |
+ if (!@defined(mm1->mmap) || !@defined(mm2->mmap)) {
|
|
|
9201c6 |
+ println($autocast_failed_mm_mmap)
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+ if (@defined(mm1->systemtap) || @defined(mm2->systemtap)) {
|
|
|
9201c6 |
+ println($autocast_succeeded_mm_systemtap)
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
%)
|
|
|
9201c6 |
|
|
|
9201c6 |
|
|
|
9201c6 |
@@ -29,4 +42,4 @@ probe oneshot
|
|
|
9201c6 |
function foo ()
|
|
|
9201c6 |
{
|
|
|
9201c6 |
@STUFF
|
|
|
9201c6 |
-}
|
|
|
9201c6 |
\ No newline at end of file
|
|
|
9201c6 |
+}
|
|
|
9201c6 |
|
|
|
9201c6 |
commit 048b546d5645abb6e6ef5148c4ddbd170600e1d3
|
|
|
9201c6 |
Author: Josh Stone <jistone@redhat.com>
|
|
|
9201c6 |
Date: Fri Jul 8 18:21:49 2016 -0700
|
|
|
9201c6 |
|
|
|
9201c6 |
Tweak autocast-defined interactions further
|
|
|
9201c6 |
|
|
|
9201c6 |
- collapse basic @defined($foo) right away.
|
|
|
9201c6 |
- last-ditch collapse other @defined(expr) to 1 or 0 depending on pe_unknown.
|
|
|
9201c6 |
- run that last-ditch effort *before* turning on assert_resolvability.
|
|
|
9201c6 |
- only run extra dead_control_remover for optimized runs
|
|
|
9201c6 |
- in var_expanding_visitor, pass *any* unchanged expr through, so they
|
|
|
9201c6 |
may be decided later. (e.g. for @choose_defined ternaries)
|
|
|
9201c6 |
|
|
|
9201c6 |
diff --git a/elaborate.cxx b/elaborate.cxx
|
|
|
9201c6 |
index a1088a1..fd6ccce 100644
|
|
|
9201c6 |
--- a/elaborate.cxx
|
|
|
9201c6 |
+++ b/elaborate.cxx
|
|
|
9201c6 |
@@ -3987,7 +3987,8 @@ struct const_folder: public update_visitor
|
|
|
9201c6 |
bool collapse_defines_p;
|
|
|
9201c6 |
|
|
|
9201c6 |
const_folder(systemtap_session& s, bool& r, bool collapse_defines = false):
|
|
|
9201c6 |
- session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {}
|
|
|
9201c6 |
+ session(s), relaxed_p(r), collapse_defines_p(collapse_defines),
|
|
|
9201c6 |
+ last_number(0), last_string(0), last_target_symbol(0) {}
|
|
|
9201c6 |
|
|
|
9201c6 |
literal_number* last_number;
|
|
|
9201c6 |
literal_number* get_number(expression*& e);
|
|
|
9201c6 |
@@ -4011,6 +4012,9 @@ struct const_folder: public update_visitor
|
|
|
9201c6 |
void visit_concatenation (concatenation* e);
|
|
|
9201c6 |
void visit_ternary_expression (ternary_expression* e);
|
|
|
9201c6 |
void visit_defined_op (defined_op* e);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ target_symbol* last_target_symbol;
|
|
|
9201c6 |
+ target_symbol* get_target_symbol(expression*& e);
|
|
|
9201c6 |
void visit_target_symbol (target_symbol* e);
|
|
|
9201c6 |
};
|
|
|
9201c6 |
|
|
|
9201c6 |
@@ -4511,15 +4515,35 @@ const_folder::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
// previous efforts. We could assume that therefore it is a big fat
|
|
|
9201c6 |
// zero, but for the @defined(autocast) case PR18079, this just
|
|
|
9201c6 |
// means that we didn't know yet.
|
|
|
9201c6 |
+ int64_t value = 0;
|
|
|
9201c6 |
+ bool collapse_this = false;
|
|
|
9201c6 |
|
|
|
9201c6 |
- if (collapse_defines_p)
|
|
|
9201c6 |
+ // We do know that plain target_symbols aren't going anywhere though.
|
|
|
9201c6 |
+ if (get_target_symbol (e->operand))
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ if (session.verbose>2)
|
|
|
9201c6 |
+ clog << _("Collapsing target_symbol @defined check ") << *e->tok << endl;
|
|
|
9201c6 |
+ collapse_this = true;
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+ else if (collapse_defines_p && relaxed_p)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
if (session.verbose>2)
|
|
|
9201c6 |
clog << _("Collapsing untouched @defined check ") << *e->tok << endl;
|
|
|
9201c6 |
- relaxed_p = false;
|
|
|
9201c6 |
- literal_number* n = new literal_number (0);
|
|
|
9201c6 |
- n->tok = e->tok;
|
|
|
9201c6 |
- n->visit (this);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // If we got to an expression with a known type, call it defined.
|
|
|
9201c6 |
+ if (e->operand->type != pe_unknown)
|
|
|
9201c6 |
+ value = 1;
|
|
|
9201c6 |
+ collapse_this = true;
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (collapse_this)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ // Don't be greedy... we'll only collapse one at a time so type
|
|
|
9201c6 |
+ // resolution can have another go at it.
|
|
|
9201c6 |
+ relaxed_p = false;
|
|
|
9201c6 |
+ literal_number* n = new literal_number (value);
|
|
|
9201c6 |
+ n->tok = e->tok;
|
|
|
9201c6 |
+ n->visit (this);
|
|
|
9201c6 |
}
|
|
|
9201c6 |
else
|
|
|
9201c6 |
{
|
|
|
9201c6 |
@@ -4529,6 +4553,13 @@ const_folder::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
}
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
+target_symbol*
|
|
|
9201c6 |
+const_folder::get_target_symbol(expression*& e)
|
|
|
9201c6 |
+{
|
|
|
9201c6 |
+ replace (e);
|
|
|
9201c6 |
+ return (e == last_target_symbol) ? last_target_symbol : NULL;
|
|
|
9201c6 |
+}
|
|
|
9201c6 |
+
|
|
|
9201c6 |
void
|
|
|
9201c6 |
const_folder::visit_target_symbol (target_symbol* e)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
@@ -4545,7 +4576,10 @@ const_folder::visit_target_symbol (target_symbol* e)
|
|
|
9201c6 |
relaxed_p = false;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
else
|
|
|
9201c6 |
- update_visitor::visit_target_symbol (e);
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ update_visitor::visit_target_symbol (e);
|
|
|
9201c6 |
+ last_target_symbol = e;
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
static int initial_typeres_pass(systemtap_session& s);
|
|
|
9201c6 |
@@ -5400,20 +5434,6 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
ti.current_function = fd;
|
|
|
9201c6 |
ti.t = pe_unknown;
|
|
|
9201c6 |
|
|
|
9201c6 |
- if (ti.assert_resolvability)
|
|
|
9201c6 |
- {
|
|
|
9201c6 |
- // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
- // one last time, in case an unresolvable
|
|
|
9201c6 |
- // @defined($foobar) still persists. This should map
|
|
|
9201c6 |
- // those to 0.
|
|
|
9201c6 |
- bool relaxed_p;
|
|
|
9201c6 |
- const_folder cf (s, relaxed_p, true); // NB: true
|
|
|
9201c6 |
- cf.replace (fd->body);
|
|
|
9201c6 |
- dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
- fd->body->visit (&dc);
|
|
|
9201c6 |
- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
- }
|
|
|
9201c6 |
-
|
|
|
9201c6 |
fd->body->visit (& ti);
|
|
|
9201c6 |
// NB: we don't have to assert a known type for
|
|
|
9201c6 |
// functions here, to permit a "void" function.
|
|
|
9201c6 |
@@ -5431,13 +5451,19 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
aev.replace (fd->body);
|
|
|
9201c6 |
|
|
|
9201c6 |
// PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
- // in case autocast evaluation enabled a @defined()
|
|
|
9201c6 |
- bool relaxed_p;
|
|
|
9201c6 |
- const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
- cf.replace (fd->body);
|
|
|
9201c6 |
- dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
- fd->body->visit (&dc);
|
|
|
9201c6 |
- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ // if autocast evaluation enabled a @defined()
|
|
|
9201c6 |
+ if (aev.count_replaced_defined_ops() > 0)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ bool relaxed_p = true;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
+ cf.replace (fd->body);
|
|
|
9201c6 |
+ if (! s.unoptimized)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ fd->body->visit (&dc);
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
|
|
|
9201c6 |
ti.num_available_autocasts = 0;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
@@ -5458,20 +5484,6 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
ti.current_probe = pn;
|
|
|
9201c6 |
ti.t = pe_unknown;
|
|
|
9201c6 |
|
|
|
9201c6 |
- if (ti.assert_resolvability)
|
|
|
9201c6 |
- {
|
|
|
9201c6 |
- // PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
- // one last time, in case an unresolvable
|
|
|
9201c6 |
- // @defined($foobar) still persists. This should map
|
|
|
9201c6 |
- // those to 0.
|
|
|
9201c6 |
- bool relaxed_p;
|
|
|
9201c6 |
- const_folder cf (s, relaxed_p, true); // NB: true
|
|
|
9201c6 |
- cf.replace (pn->body);
|
|
|
9201c6 |
- dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
- pn->body->visit (&dc);
|
|
|
9201c6 |
- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
- }
|
|
|
9201c6 |
-
|
|
|
9201c6 |
pn->body->visit (& ti);
|
|
|
9201c6 |
for (unsigned i=0; i < pn->locals.size(); ++i)
|
|
|
9201c6 |
ti.check_local (pn->locals[i]);
|
|
|
9201c6 |
@@ -5483,13 +5495,19 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
aev.replace (pn->body);
|
|
|
9201c6 |
|
|
|
9201c6 |
// PR18079, rerun the const-folder / dead-block-remover
|
|
|
9201c6 |
- // in case autocast evaluation enabled a @defined()
|
|
|
9201c6 |
- bool relaxed_p;
|
|
|
9201c6 |
- const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
- cf.replace (pn->body);
|
|
|
9201c6 |
- dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
- pn->body->visit (&dc);
|
|
|
9201c6 |
- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ // if autocast evaluation enabled a @defined()
|
|
|
9201c6 |
+ if (aev.count_replaced_defined_ops() > 0)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ bool relaxed_p = true;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p);
|
|
|
9201c6 |
+ cf.replace (pn->body);
|
|
|
9201c6 |
+ if (! s.unoptimized)
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ dead_control_remover dc (s, relaxed_p);
|
|
|
9201c6 |
+ pn->body->visit (&dc);
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
|
|
|
9201c6 |
ti.num_available_autocasts = 0;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
@@ -5526,9 +5544,27 @@ semantic_pass_types (systemtap_session& s)
|
|
|
9201c6 |
break; // successfully
|
|
|
9201c6 |
else if (! ti.assert_resolvability)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
- ti.assert_resolvability = true; // last pass, with error msgs
|
|
|
9201c6 |
- if (s.verbose > 0)
|
|
|
9201c6 |
- ti.mismatch_complexity = 0; // print every kind of mismatch
|
|
|
9201c6 |
+ // PR18079, before we go asserting anything, try to nullify any
|
|
|
9201c6 |
+ // still-unresolved @defined ops.
|
|
|
9201c6 |
+ bool relaxed_p = true;
|
|
|
9201c6 |
+ const_folder cf (s, relaxed_p, true); // NB: true
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ for (auto it = s.probes.begin(); it != s.probes.end(); ++it)
|
|
|
9201c6 |
+ cf.replace ((*it)->body);
|
|
|
9201c6 |
+ for (auto it = s.functions.begin(); it != s.functions.end(); ++it)
|
|
|
9201c6 |
+ cf.replace (it->second->body);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (! s.unoptimized)
|
|
|
9201c6 |
+ semantic_pass_dead_control (s, relaxed_p);
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ if (! relaxed_p)
|
|
|
9201c6 |
+ ti.mismatch_complexity = 0; // reset for next pass
|
|
|
9201c6 |
+ else
|
|
|
9201c6 |
+ {
|
|
|
9201c6 |
+ ti.assert_resolvability = true; // last pass, with error msgs
|
|
|
9201c6 |
+ if (s.verbose > 0)
|
|
|
9201c6 |
+ ti.mismatch_complexity = 0; // print every kind of mismatch
|
|
|
9201c6 |
+ }
|
|
|
9201c6 |
}
|
|
|
9201c6 |
else
|
|
|
9201c6 |
{ // unsuccessful conclusion
|
|
|
9201c6 |
diff --git a/tapsets.cxx b/tapsets.cxx
|
|
|
9201c6 |
index 069966b..6d82069 100644
|
|
|
9201c6 |
--- a/tapsets.cxx
|
|
|
9201c6 |
+++ b/tapsets.cxx
|
|
|
9201c6 |
@@ -2835,7 +2835,8 @@ private:
|
|
|
9201c6 |
unsigned var_expanding_visitor::tick = 0;
|
|
|
9201c6 |
|
|
|
9201c6 |
|
|
|
9201c6 |
-var_expanding_visitor::var_expanding_visitor (): op()
|
|
|
9201c6 |
+var_expanding_visitor::var_expanding_visitor ():
|
|
|
9201c6 |
+ replaced_defined_ops(0), op()
|
|
|
9201c6 |
{
|
|
|
9201c6 |
// FIXME: for the time being, by default we only support plain '$foo
|
|
|
9201c6 |
// = bar', not '+=' or any other op= variant. This is fixable, but a
|
|
|
9201c6 |
@@ -2964,6 +2965,7 @@ var_expanding_visitor::visit_delete_statement (delete_statement* s)
|
|
|
9201c6 |
void
|
|
|
9201c6 |
var_expanding_visitor::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
{
|
|
|
9201c6 |
+ expression * const old_operand = e->operand;
|
|
|
9201c6 |
bool resolved = true;
|
|
|
9201c6 |
|
|
|
9201c6 |
defined_ops.push (e);
|
|
|
9201c6 |
@@ -2999,11 +3001,12 @@ var_expanding_visitor::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
target_symbol* tsym = dynamic_cast<target_symbol*> (e->operand);
|
|
|
9201c6 |
if (tsym && tsym->saved_conversion_error) // failing
|
|
|
9201c6 |
resolved = false;
|
|
|
9201c6 |
- else if (tsym) // unresolved but not marked failing
|
|
|
9201c6 |
+ else if (e->operand == old_operand) // unresolved but not marked failing
|
|
|
9201c6 |
{
|
|
|
9201c6 |
// There are some visitors that won't touch certain target_symbols,
|
|
|
9201c6 |
// e.g. dwarf_var_expanding_visitor won't resolve @cast. We should
|
|
|
9201c6 |
// leave it for now so some other visitor can have a chance.
|
|
|
9201c6 |
+ defined_ops.pop ();
|
|
|
9201c6 |
provide (e);
|
|
|
9201c6 |
return;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
@@ -3017,6 +3020,7 @@ var_expanding_visitor::visit_defined_op (defined_op* e)
|
|
|
9201c6 |
literal_number* ln = new literal_number (resolved ? 1 : 0);
|
|
|
9201c6 |
ln->tok = e->tok;
|
|
|
9201c6 |
provide (ln);
|
|
|
9201c6 |
+ ++replaced_defined_ops;
|
|
|
9201c6 |
}
|
|
|
9201c6 |
|
|
|
9201c6 |
|
|
|
9201c6 |
diff --git a/tapsets.h b/tapsets.h
|
|
|
9201c6 |
index d630dbb..cb73a7e 100644
|
|
|
9201c6 |
--- a/tapsets.h
|
|
|
9201c6 |
+++ b/tapsets.h
|
|
|
9201c6 |
@@ -61,11 +61,6 @@ public:
|
|
|
9201c6 |
|
|
|
9201c6 |
struct var_expanding_visitor: public update_visitor
|
|
|
9201c6 |
{
|
|
|
9201c6 |
- static unsigned tick;
|
|
|
9201c6 |
- std::stack<defined_op*> defined_ops;
|
|
|
9201c6 |
- std::set<std::string> valid_ops;
|
|
|
9201c6 |
- interned_string* op;
|
|
|
9201c6 |
-
|
|
|
9201c6 |
var_expanding_visitor ();
|
|
|
9201c6 |
void visit_assignment (assignment* e);
|
|
|
9201c6 |
void visit_pre_crement (pre_crement* e);
|
|
|
9201c6 |
@@ -73,6 +68,15 @@ struct var_expanding_visitor: public update_visitor
|
|
|
9201c6 |
void visit_delete_statement (delete_statement* s);
|
|
|
9201c6 |
void visit_defined_op (defined_op* e);
|
|
|
9201c6 |
|
|
|
9201c6 |
+ unsigned count_replaced_defined_ops () { return replaced_defined_ops; }
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+protected:
|
|
|
9201c6 |
+ static unsigned tick;
|
|
|
9201c6 |
+ unsigned replaced_defined_ops;
|
|
|
9201c6 |
+ std::stack<defined_op*> defined_ops;
|
|
|
9201c6 |
+ std::set<std::string> valid_ops;
|
|
|
9201c6 |
+ interned_string* op;
|
|
|
9201c6 |
+
|
|
|
9201c6 |
void provide_lvalue_call(functioncall* fcall);
|
|
|
9201c6 |
|
|
|
9201c6 |
private:
|
|
|
9201c6 |
diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
index b9488d7..18028e8 100755
|
|
|
9201c6 |
--- a/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
+++ b/testsuite/semok/autocast14.stp
|
|
|
9201c6 |
@@ -30,6 +30,13 @@
|
|
|
9201c6 |
if (@defined(mm1->systemtap) || @defined(mm2->systemtap)) {
|
|
|
9201c6 |
println($autocast_succeeded_mm_systemtap)
|
|
|
9201c6 |
}
|
|
|
9201c6 |
+
|
|
|
9201c6 |
+ // Test that autocast can resolve through nested @defined
|
|
|
9201c6 |
+ // (especially that the ternary isn't automatically "defined")
|
|
|
9201c6 |
+ mm3 = @choose_defined(@choose_defined($nonsense, $wut), task_current())->mm;
|
|
|
9201c6 |
+ mm4 = @choose_defined(@choose_defined($nonsense, task_current()), $wut)->mm;
|
|
|
9201c6 |
+ mm5 = @choose_defined(@choose_defined(task_current(), $nonsense), $wut)->mm;
|
|
|
9201c6 |
+ println(mm3 == mm4 && mm4 == mm5)
|
|
|
9201c6 |
%)
|
|
|
9201c6 |
|
|
|
9201c6 |
|