diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 11 | ||||
-rw-r--r-- | src/jsifier.js | 38 |
2 files changed, 43 insertions, 6 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index c4773b95..c3cdf573 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -774,6 +774,17 @@ function analyzer(data) { replaceLabelLabels(block.labels, set('BREAK|*|' + block.willGetTo), 'BNOPP'); } + if (block.type === 'emulated' && block.next && block.next.type === 'multiple') { + assert(block.labels.length == 1); + var lastLine = block.labels[0].lines.slice(-1)[0]; + if (lastLine.intertype == 'branch' && lastLine.ident) { // TODO: handle switch, and other non-branch2 things + // 'Steal' the condition + block.next.stolenCondition = lastLine; + lastLine.intertype = 'deleted'; + dprint('relooping', 'steal condition: ' + block.next.stolenCondition.ident); + } + } + recurseBlock(block, optimizeBlock); if (block.type === 'multiple') { diff --git a/src/jsifier.js b/src/jsifier.js index 0395b5f9..13d2642d 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -348,12 +348,35 @@ function JSify(data) { ret += indent + ((block.entry in usedLabels) ? '' : (block.entry+':')) + ' do { \n'; multipleIdent = ' '; } - block.entryLabels.forEach(function(entryLabel) { - ret += indent + multipleIdent + (first ? '' : 'else ') + 'if (__label__ == ' + getLabelId(entryLabel.ident) + ') {\n'; - ret += walkBlock(entryLabel.block, indent + ' ' + multipleIdent); - ret += indent + multipleIdent + '}\n'; - first = false; - }); + var stolen = block.stolenCondition; + if (stolen) { + function getActualLabelId(labelId) { + return labelId.split('|').slice(-1)[0]; + } + var intendedTrueLabel = stolen.labelTrue; + assert(block.entryLabels.length <= 2); + [stolen.labelTrue, stolen.labelFalse].forEach(function(entry) { + var branch = makeBranch(entry); + entryLabel = block.entryLabels.filter(function(possible) { return possible.ident === getActualLabelId(entry) })[0]; + if (branch.length < 5 && !entryLabel) return; + //ret += indent + multipleIdent + (first ? '' : 'else ') + + // 'if (' + (entry == intendedTrueLabel ? '' : '!') + stolen.ident + ')' + ' {\n'; + ret += indent + multipleIdent + (first ? 'if (' + (entry == intendedTrueLabel ? '' : '!') + stolen.ident + ')' : 'else') + ' {\n'; + ret += indent + multipleIdent + ' ' + branch + '\n'; + if (entryLabel) { + ret += walkBlock(entryLabel.block, indent + ' ' + multipleIdent); + } + ret += indent + multipleIdent + '}\n'; + first = false; + }); + } else { + block.entryLabels.forEach(function(entryLabel) { + ret += indent + multipleIdent + (first ? '' : 'else ') + 'if (__label__ == ' + getLabelId(entryLabel.ident) + ') {\n'; + ret += walkBlock(entryLabel.block, indent + ' ' + multipleIdent); + ret += indent + multipleIdent + '}\n'; + first = false; + }); + } if (GUARD_LABELS) { ret += indent + multipleIdent + 'else { throw "Bad multiple branching: " + __label__ + " : " + (new Error().stack); }\n'; } @@ -477,12 +500,15 @@ function JSify(data) { } }); + makeFuncLineZyme('deleted', function(item) { return ';' }); + var LABEL_IDs = {}; var LABEL_ID_COUNTER = 0; function getLabelId(label) { label = label.substr(1); if (label === 'entry') return '-1'; if (label === parseInt(label)) return label; // clang + //return '"' + label + '"'; // XXX debugging label = toNiceIdent(label); if (label in LABEL_IDs) return LABEL_IDs[label]; return LABEL_IDs[label] = LABEL_ID_COUNTER ++; |