aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyzer.js')
-rw-r--r--src/analyzer.js52
1 files changed, 43 insertions, 9 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index ae40896d..f79217bd 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -443,7 +443,13 @@ function analyzer(data, givenTypes) {
ret.push(item[id]);
dprint('relooping', 'zz ' + id + ' replace ' + item[id] + ' with ' + toLabelId);
if (toLabelId) {
- item[id] = toLabelId + '|' + item[id];
+ // replace wildcards in new value with old parts
+ var oldParts = item[id].split('|');
+ var newParts = toLabelId.split('|');
+ for (var i = 1; i < 3; i++) {
+ if (newParts[i] === '*') newParts[i] = oldParts[i];
+ }
+ item[id] = newParts.join('|') + '|' + item[id];
}
}
});
@@ -640,6 +646,7 @@ function analyzer(data, givenTypes) {
var ret = {
type: 'reloop',
id: blockId,
+ needBlockId: true,
entries: entries,
labels: labels
};
@@ -767,6 +774,7 @@ function analyzer(data, givenTypes) {
return {
type: 'multiple',
id: blockId,
+ needBlockId: true,
entries: actualEntries,
entryLabels: actualEntryLabels,
labels: handlingNow,
@@ -798,7 +806,7 @@ function analyzer(data, givenTypes) {
if (!RELOOP) return finish();
// Find where each block will 'naturally' get to, just by the flow of code
- function exploreBlock(block, endOfTheWorld) { // endoftheworld - where we will get, if we have nothing else to get to - 'fall off the face of the earth'
+ function exploreBlockEndings(block, endOfTheWorld) { // endoftheworld - where we will get, if we have nothing else to get to - 'fall off the face of the earth'
if (!block) return;
function singular(block) {
@@ -814,9 +822,9 @@ function analyzer(data, givenTypes) {
dprint('relooping', "// exploring block: " + block.type + ' : ' + block.entries);
if (block.type == 'reloop') {
- exploreBlock(block.inner, singular(block.inner));
+ exploreBlockEndings(block.inner, singular(block.inner));
} else if (block.type == 'multiple') {
- block.entryLabels.forEach(function(entryLabel) { exploreBlock(entryLabel.block, singular(block.next)) });
+ block.entryLabels.forEach(function(entryLabel) { exploreBlockEndings(entryLabel.block, singular(block.next)) });
} else if (block.type === 'emulated' && block.next && block.next.type === 'multiple') {
assert(block.labels.length == 1);
var lastLine = block.labels[0].lines.slice(-1)[0];
@@ -828,7 +836,7 @@ function analyzer(data, givenTypes) {
}
}
- exploreBlock(block.next, endOfTheWorld);
+ exploreBlockEndings(block.next, endOfTheWorld);
if (block.next) {
block.willGetTo = singular(block.next);
@@ -840,12 +848,12 @@ function analyzer(data, givenTypes) {
}
// Remove unneeded label settings, if we set it to where we will get anyhow
- function optimizeBlock(block) {
+ function optimizeBlockEndings(block) {
if (!block) return;
dprint('relooping', "// optimizing block: " + block.type + ' : ' + block.entries);
- recurseBlock(block, optimizeBlock);
+ recurseBlock(block, optimizeBlockEndings);
if (block.type === 'emulated' && block.willGetTo) {
dprint('relooping', '// removing (trying): ' + block.willGetTo);
@@ -873,11 +881,37 @@ function analyzer(data, givenTypes) {
}
}
+ // Checks whether we actually need labels. We return whether we have a loop nested inside us.
+ function optimizeOutUnneededLabels(block) {
+ if (!block) return false;
+
+ dprint('relooping', "// optimizing (2) block: " + block.type + ' : ' + block.entries);
+
+ var containLoop = sum(recurseBlock(block, optimizeOutUnneededLabels)) > 0;
+
+ if (block.type === 'emulated') {
+ return containLoop;
+ } else if (block.type === 'multiple') {
+ // TODO: Apply the same optimization below for 'reloop', to looped multiples
+ return containLoop || !block.loopless;
+ } else if (block.type === 'reloop') {
+ if (!containLoop) {
+ block.needBlockId = false;
+
+ replaceLabelLabels(block.labels, set('BCONT|' + block.id + '|*'), 'BCONT||*');
+ replaceLabelLabels(block.labels, set('BREAK|' + block.id + '|*'), 'BREAK||*');
+ }
+ return true;
+ }
+ assert(false);
+ }
+
// TODO: Parallelize
item.functions.forEach(function(func) {
dprint('relooping', "// loopOptimizing function: " + func.ident);
- exploreBlock(func.block);
- optimizeBlock(func.block);
+ exploreBlockEndings(func.block);
+ optimizeBlockEndings(func.block);
+ optimizeOutUnneededLabels(func.block);
});
return finish();
}