From cf6c4cff644b87b4c9688931e2924e2d73b9998f Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Tue, 11 Jul 2017 14:18:52 -0700 Subject: infinite loops have side effects --- src/ast/effects.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ast/effects.h b/src/ast/effects.h index a7a5d8fb2..6e4bb617e 100644 --- a/src/ast/effects.h +++ b/src/ast/effects.h @@ -39,7 +39,7 @@ struct EffectAnalyzer : public PostWalker { if (breakNames.size() > 0) branches = true; } - bool branches = false; // branches out of this expression + bool branches = false; // branches out of this expression, returns, infinite loops, etc bool calls = false; std::set localsRead; std::set localsWritten; @@ -138,6 +138,18 @@ struct EffectAnalyzer : public PostWalker { } void visitLoop(Loop* curr) { if (curr->name.is()) breakNames.erase(curr->name); // these were internal breaks + // if the loop is unreachable, then there is branching control flow: + // (1) if the body is unreachable because of a (return), uncaught (br) etc., then we + // already noted branching, so it is ok to mark it again (if we have *caught* + // (br)s, then they did not lead to the loop body being unreachable). + // (same logic applies to blocks) + // (2) if the loop is unreachable because it only has branches up to the loop + // top, but no way to get out, then it is an infinite loop, and we consider + // that a branching side effect (note how the same logic does not apply to + // blocks). + if (curr->type == unreachable) { + branches = true; + } } void visitCall(Call *curr) { calls = true; } @@ -182,6 +194,7 @@ struct EffectAnalyzer : public PostWalker { case TruncUFloat64ToInt32: case TruncUFloat64ToInt64: { implicitTrap = true; + break; } default: {} } @@ -199,6 +212,7 @@ struct EffectAnalyzer : public PostWalker { case RemSInt64: case RemUInt64: { implicitTrap = true; + break; } default: {} } -- cgit v1.2.3