aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js11
-rw-r--r--src/jsifier.js38
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 ++;