aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRyan Kelly <ryan@rfk.id.au>2014-01-28 20:20:28 +1100
committerRyan Kelly <ryan@rfk.id.au>2014-02-02 08:49:42 +1100
commit47288a40ac04bc7f4fe9734a3b6160735b58f1b2 (patch)
tree17ee178b6d4713e346a12f130c72ad884ebb068e /tools
parentb175281cb1d1e1a27339bddedfa6ff4fc0822fca (diff)
Handle non-breaking case bodies in switch statement.
These don't actually flow through to the next case, but we have to make sure they're properly closed in order to keep our invariants in order.
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js22
1 files changed, 12 insertions, 10 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index d12f4f4d..a3ed24d3 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -2490,8 +2490,8 @@ function registerizeHarder(ast) {
case 'switch':
// Emscripten generates switch statements of a very limited
// form: all case clauses are numeric literals, and all
- // case bodies end with a break. So it's basically equivalent
- // to a multi-way 'if' statement.
+ // case bodies end with a (maybe implicit) break. So it's
+ // basically equivalent to a multi-way 'if' statement.
isInExpr++;
buildFlowGraph(node[1]);
isInExpr--;
@@ -2501,20 +2501,22 @@ function registerizeHarder(ast) {
var hasDefault = false;
for (var i=0; i<node[2].length; i++) {
setJunction(jCheckExit);
+ // All case clauses are either 'default' or a numeric literal.
if (!node[2][i][0]) {
hasDefault = true;
- } else {
- if (node[2][i][0][0] !== 'num') {
- if (node[2][i][0][0] !== 'unary-prefix' || node[2][i][0][2][0] !== 'num') {
- assert(false, 'non-numeric switch case clause');
- }
- }
- addPreCondTrue(['binary', '==', node[1], node[2][i][0]]);
}
for (var j = 0; j < node[2][i][1].length; j++) {
buildFlowGraph(node[2][i][1][j]);
}
- assert(currEntryJunction === null, 'switch case body did not break');
+ // Control flow will never actually reach the end of the case body.
+ // If there's live code here, assume it jumps to case exit.
+ if (currEntryJunction !== null && nextBasicBlock.nodes.length > 0) {
+ if (node[2][i][0]) {
+ markNonLocalJump('return');
+ } else {
+ joinJunction(jExit);
+ }
+ }
}
// If there was no default case, we also need an empty block
// linking straight from the test evaluation to the exit.