aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js67
-rw-r--r--src/jsifier.js19
2 files changed, 58 insertions, 28 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index a4b7eb70..cf339188 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -1151,18 +1151,61 @@ function analyzer(data, sidePass) {
}
});
+ function operateOnLabels(line, func) {
+ function process(item, id) {
+ ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
+ if (item[id]) {
+ func(item, id);
+ }
+ });
+ }
+ if (line.intertype in BRANCH_INVOKE) {
+ process(line);
+ } else if (line.intertype == 'switch') {
+ process(line);
+ line.switchLabels.forEach(process);
+ }
+ }
+
// Label analyzer
substrate.addActor('LabelAnalyzer', {
processItem: function(item) {
item.functions.forEach(function(func) {
func.labelsDict = {};
func.labelIds = {};
- func.labelIdCounter = 0;
+ func.labelIdsInverse = {};
+ func.labelIds[toNiceIdent('%0')] = 0;
+ func.labelIdsInverse[0] = toNiceIdent('%0');
+ func.labelIdCounter = 1;
func.labels.forEach(function(label) {
- func.labelsDict[label.ident] = label;
func.labelIds[label.ident] = func.labelIdCounter++;
+ func.labelIdsInverse[func.labelIdCounter-1] = label.ident;
+ });
+
+ // Minify label ids to numeric ids.
+ func.labels.forEach(function(label) {
+ label.ident = func.labelIds[label.ident];
+ label.lines.forEach(function(line) {
+ operateOnLabels(line, function(item, id) {
+ item[id] = func.labelIds[item[id]].toString(); // strings, because we will append as we process
+ });
+ });
+ });
+
+ func.labels.forEach(function(label) {
+ func.labelsDict[label.ident] = label;
+ });
+
+ // Correct phis
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ phi.params[i].label = func.labelIds[phi.params[i].label];
+ }
+ }
+ });
});
- func.labelIds[toNiceIdent('%0')] = -1; // entry is always -1
func.lines.forEach(function(line) {
if (line.intertype == 'indirectbr') {
@@ -1191,7 +1234,7 @@ function analyzer(data, sidePass) {
if (line.intertype == 'call' && line.ident == setjmp) {
// Add a new label
var oldIdent = label.ident;
- var newIdent = oldIdent + '$$' + i;
+ var newIdent = func.labelIdCounter++;
if (!func.setjmpTable) func.setjmpTable = [];
func.setjmpTable.push([oldIdent, newIdent, line.assignTo]);
func.labels.splice(i+1, 0, {
@@ -1385,22 +1428,6 @@ function analyzer(data, sidePass) {
}
});
- function operateOnLabels(line, func) {
- function process(item, id) {
- ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
- if (item[id]) {
- func(item, id);
- }
- });
- }
- if (line.intertype in BRANCH_INVOKE) {
- process(line);
- } else if (line.intertype == 'switch') {
- process(line);
- line.switchLabels.forEach(process);
- }
- }
-
//! @param toLabelId If false, just a dry run - useful to search for labels
function replaceLabels(line, labelIds, toLabelId) {
var ret = [];
diff --git a/src/jsifier.js b/src/jsifier.js
index b93cdf9a..d4d57fc6 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -574,7 +574,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (block.type == 'emulated') {
if (block.labels.length > 1) {
if (block.entries.length == 1) {
- ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + block.entries[0] + ' */' : '') + '\n';
+ ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
} // otherwise, should have been set before!
if (func.setjmpTable) {
var setjmpTable = {};
@@ -591,7 +591,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
ret += 'switch(__label__) {\n';
ret += block.labels.map(function(label) {
- return indent + ' case ' + getLabelId(label.ident) + ': // ' + label.ident + '\n'
+ return indent + ' case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ getLabelLines(label, indent + ' ');
}).join('\n');
ret += '\n' + indent + ' default: assert(0, "bad label: " + __label__);\n' + indent + '}';
@@ -770,11 +770,14 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('deleted', function(item) { return ';' });
- function getLabelId(label) {
+ function getOriginalLabelId(label) {
var funcData = Framework.currItem.funcData;
- var labelIds = funcData.labelIds;
- if (labelIds[label] !== undefined) return labelIds[label];
- return labelIds[label] = funcData.labelIdCounter++;
+ var labelIdsInverse = funcData.labelIdsInverse;
+ return labelIdsInverse[label];
+ }
+
+ function getLabelId(label) {
+ return label;
}
function makeBranch(label, lastLabel, labelIsVariable) {
@@ -788,7 +791,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var trueLabel = parts[1] || '';
var oldLabel = parts[2] || '';
var labelSetting = oldLabel ? '__label__ = ' + getLabelId(oldLabel) + ';' +
- (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : '') : ''; // TODO: optimize away the setting
+ (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(oldLabel)) + ' */' : '') : ''; // TODO: optimize away the setting
if (label[1] == 'R') {
if (label[2] == 'N') { // BRNOL: break, no label setting
labelSetting = '';
@@ -808,7 +811,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
} else {
if (!labelIsVariable) label = getLabelId(label);
- return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(label) + ' */' : '') + ' break;';
+ return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(label)) + ' */' : '') + ' break;';
}
}