aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyzer.js')
-rw-r--r--src/analyzer.js20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 54f766cc..b44165b1 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -348,7 +348,7 @@ function analyzer(data) {
labels.forEach(function(label) {
label.lines.forEach(function(line) {
function process(item) {
- ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel'].forEach(function(id) {
+ ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
if (item[id]) {
if (item[id][0] == 'B') { // BREAK, BCONT, BNOPP
label.hasBreak = true;
@@ -460,7 +460,7 @@ function analyzer(data) {
if (entries.length > 1) return emulated();
var entry = entries[0];
assert(entry);
- dprint('relooping', 'Relooping: ' + entry + ',' + labels.length + ' labels');
+ dprint('relooping', 'makeBlock: ' + entry + ',' + labels.length + ' labels');
var entryLabel = labelsDict[entry];
assert(entryLabel);
@@ -469,11 +469,12 @@ function analyzer(data) {
var canReturn = values(entryLabel.inLabels).length > 0;
+ labels = labels.filter(function(label) { return label === entryLabel || label.ident in entryLabel.allOutLabels }); // ignore unreachables
+
// === (simple) 'emulated' ===
if (!canReturn && values(entryLabel.outLabels).length == 1) {
dprint('relooping', ' Creating simple emulated, outlabels: ' + keys(entryLabel.outLabels));
- assertEq(lastLine.intertype, 'branch');
var next = keys(entryLabel.outLabels)[0];
if (next in exitLabels) {
exitLabelsHit[next] = true;
@@ -506,6 +507,19 @@ function analyzer(data) {
var internals = split_.leftIn;
var currExitLabels = set(getLabelIds(externals));
+ // Verify that no external can reach an internal
+ var inLabels = set(getLabelIds(internals));
+ var fail = false;
+ externals.forEach(function(external) {
+ if (fail || values(setIntersect(external.outLabels, inLabels)).length > 0) {
+ fail = true;
+ }
+ });
+ if (fail) {
+ dprint('relooping', 'Found an external that wants to reach an internal, fallback to flow emulation');
+ return emulated();
+ }
+
dprint('relooping', function() { return ' Creating reloop: Inner: ' + dump(getLabelIds(internals)) + ', Exxer: ' + dump(currExitLabels) });
replaceLabelLabels(internals, searchable(entry), 'BCONT' + entry); // we will be in a loop, |continue| gets us back to the entry