diff options
Diffstat (limited to 'src/analyzer.js')
-rw-r--r-- | src/analyzer.js | 68 |
1 files changed, 55 insertions, 13 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 1c643303..593b4650 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -11,11 +11,8 @@ var VAR_EMULATED = 'emulated'; var ENTRY_IDENT = toNiceIdent('%0'); var ENTRY_IDENTS = set(toNiceIdent('%0'), toNiceIdent('%1')); -function cleanFunc(func) { - func.lines = func.lines.filter(function(line) { return line.intertype !== null }); - func.labels.forEach(function(label) { - label.lines = label.lines.filter(function(line) { return line.intertype !== null }); - }); +function recomputeLines(func) { + func.lines = func.labels.map(function(label) { return label.lines }).reduce(concatenator, []); } // Handy sets @@ -71,6 +68,7 @@ function analyzer(data, sidePass) { subItem.endLineNum = null; subItem.lines = []; // We will fill in the function lines after the legalizer, since it can modify them subItem.labels = []; + subItem.forceEmulated = false; // no explicit 'entry' label in clang on LLVM 2.8 - most of the time, but not all the time! - so we add one if necessary if (item.items[i+1].intertype !== 'label') { @@ -142,7 +140,7 @@ function analyzer(data, sidePass) { var ret = new Array(Math.ceil(bits/32)); var i = 0; while (bits > 0) { - ret[i] = { ident: parsed[i].toString(), bits: Math.min(32, bits) }; + ret[i] = { ident: (parsed[i]|0).toString(), bits: Math.min(32, bits) }; // resign all values bits -= 32; i++; } @@ -1111,10 +1109,9 @@ function analyzer(data, sidePass) { }); func.labelIds[toNiceIdent('%0')] = -1; // entry is always -1 - func.hasIndirectBr = false; func.lines.forEach(function(line) { if (line.intertype == 'indirectbr') { - func.hasIndirectBr = true; + func.forceEmulated = true; } }); @@ -1129,6 +1126,52 @@ function analyzer(data, sidePass) { return null; } + // Basic longjmp support, see library.js setjmp/longjmp + var setjmp = toNiceIdent('@setjmp'); + func.setjmpTable = null; + for (var i = 0; i < func.labels.length; i++) { + var label = func.labels[i]; + for (var j = 0; j < label.lines.length; j++) { + var line = label.lines[j]; + if (line.intertype == 'call' && line.ident == setjmp) { + // Add a new label + var oldIdent = label.ident; + var newIdent = oldIdent + '$$' + i; + if (!func.setjmpTable) func.setjmpTable = []; + func.setjmpTable.push([oldIdent, newIdent, line.assignTo]); + func.labels.splice(i+1, 0, { + intertype: 'label', + ident: newIdent, + lineNum: label.lineNum + 0.5, + lines: label.lines.slice(j+1) + }); + label.lines = label.lines.slice(0, j+1); + label.lines.push({ + intertype: 'branch', + label: toNiceIdent(newIdent), + lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this + }); + // 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++) { + var sourceLabelId = getActualLabelId(phi.params[i].label); + if (sourceLabelId == oldIdent) { + phi.params[i].label = newIdent; + } + } + } + }); + }); + } + } + } + if (func.setjmpTable) { + func.forceEmulated = true; + recomputeLines(func); + } + if (!MICRO_OPTS) { // 'Emulate' phis, by doing an if where the phi appears in the .ll. For this // we need __lastLabel__. @@ -1223,8 +1266,7 @@ function analyzer(data, sidePass) { var lines = func.labels[0].lines; for (var i = 0; i < lines.length; i++) { var item = lines[i]; - if (!item.assignTo || item.intertype != 'alloca') break; - assert(isNumber(item.allocatedNum)); + if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break; item.allocatedSize = func.variables[item.assignTo].impl === VAR_EMULATED ? calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0; if (USE_TYPED_ARRAYS === 2) { @@ -1235,7 +1277,7 @@ function analyzer(data, sidePass) { var index = 0; for (var i = 0; i < lines.length; i++) { var item = lines[i]; - if (!item.assignTo || item.intertype != 'alloca') break; + if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break; item.allocatedIndex = index; index += item.allocatedSize; delete item.allocatedSize; @@ -1260,7 +1302,7 @@ function analyzer(data, sidePass) { var finishedInitial = false; for (var i = 0; i < lines.length; i++) { var item = lines[i]; - if (!item.assignTo || item.intertype != 'alloca') { + if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) { finishedInitial = true; continue; } @@ -1745,7 +1787,7 @@ function analyzer(data, sidePass) { // TODO: each of these can be run in parallel item.functions.forEach(function(func) { dprint('relooping', "// relooping function: " + func.ident); - func.block = makeBlock(func.labels, [toNiceIdent(func.labels[0].ident)], func.labelsDict, func.hasIndirectBr); + func.block = makeBlock(func.labels, [toNiceIdent(func.labels[0].ident)], func.labelsDict, func.forceEmulated); }); return finish(); |