diff options
Diffstat (limited to 'src/analyzer.js')
-rw-r--r-- | src/analyzer.js | 128 |
1 files changed, 46 insertions, 82 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 8ded86f1..4bf2255e 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -9,7 +9,7 @@ var VAR_NATIVIZED = 'nativized'; var VAR_EMULATED = 'emulated'; var ENTRY_IDENT = toNiceIdent('%0'); -var ENTRY_IDENTS = set(toNiceIdent('%0'), toNiceIdent('%1')); +var ENTRY_IDENT_IDS = set(0, 1); // XXX function recomputeLines(func) { func.lines = func.labels.map(function(label) { return label.lines }).reduce(concatenator, []); @@ -544,6 +544,10 @@ function analyzer(data, sidePass) { params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null], type: 'i32', }; + if (j == 0 && isUnsignedOp(value.op) && sourceBits < 32) { + // zext sign correction + result.ident = makeSignOp(result.ident, 'i' + sourceBits, 'un', 1, 1); + } if (fraction != 0) { var other = { intertype: 'value', @@ -1176,7 +1180,9 @@ function analyzer(data, sidePass) { func.labelIdsInverse = {}; func.labelIds[toNiceIdent('%0')] = 0; func.labelIdsInverse[0] = toNiceIdent('%0'); - func.labelIdCounter = 1; + func.labelIds[toNiceIdent('%1')] = 1; + func.labelIdsInverse[1] = toNiceIdent('%1'); + func.labelIdCounter = 2; func.labels.forEach(function(label) { func.labelIds[label.ident] = func.labelIdCounter++; func.labelIdsInverse[func.labelIdCounter-1] = label.ident; @@ -1202,6 +1208,7 @@ function analyzer(data, sidePass) { if (phi.intertype == 'phi') { for (var i = 0; i < phi.params.length; i++) { phi.params[i].label = func.labelIds[phi.params[i].label]; + if (!phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum); } } }); @@ -1217,9 +1224,10 @@ function analyzer(data, sidePass) { // So we need to handle that in a special way here. function getActualLabelId(labelId) { if (func.labelsDict[labelId]) return labelId; - if (labelId in ENTRY_IDENTS) { - assert(func.labelsDict[ENTRY_IDENT]); - return ENTRY_IDENT; + if (labelId in ENTRY_IDENT_IDS) { + labelId = func.labelIds[ENTRY_IDENT]; + assert(func.labelsDict[labelId]); + return labelId; } return null; } @@ -1270,88 +1278,44 @@ function analyzer(data, sidePass) { recomputeLines(func); } - if (!MICRO_OPTS) { - // 'Emulate' phis, by doing an if where the phi appears in the .ll. For this - // we need __lastLabel__. - func.needsLastLabel = false; - func.labels.forEach(function(label) { - var phis = []; - 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) { - var sourceLabel = func.labelsDict[sourceLabelId]; - var lastLine = sourceLabel.lines.slice(-1)[0]; - assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]); - lastLine.currLabelId = sourceLabelId; - } - } - phis.push(phi); - func.needsLastLabel = true; - } - }); + // Properly implement phis, by pushing them back into the branch + // that leads to here. We will only have the |var| definition in this location. - if (phis.length >= 2) { - // Multiple phis have the semantics that they all occur 'in parallel', i.e., changes to - // a variable that is the result of a phi should *not* affect the other results. We must - // therefore be careful! - phis[phis.length-1].postSet = '; /* post-phi: */'; - for (var i = 0; i < phis.length-1; i++) { - var ident = phis[i].assignTo; - var phid = ident+'$phi' - phis[phis.length-1].postSet += ident + '=' + phid + ';'; - phis[i].assignTo = phid; - func.variables[phid] = { - ident: phid, - type: func.variables[ident].type, - origin: func.variables[ident].origin, - lineNum: func.variables[ident].lineNum, - uses: 1, - impl: VAR_EMULATED - }; - } - } - }); - } else { - // MICRO_OPTS == 1: Properly implement phis, by pushing them back into the branch - // that leads to here. We will only have the |var| definition in this location. - - // First, push phis back - func.labels.forEach(function(label) { - label.lines.forEach(function(phi) { - if (phi.intertype == 'phi') { - for (var i = 0; i < phi.params.length; i++) { - var param = phi.params[i]; - var sourceLabelId = getActualLabelId(param.label); - if (sourceLabelId) { - var sourceLabel = func.labelsDict[sourceLabelId]; - var lastLine = sourceLabel.lines.slice(-1)[0]; - assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]); - if (!lastLine.phi) { - lastLine.phi = true; - assert(!lastLine.dependent); - lastLine.dependent = { - intertype: 'phiassigns', - params: [] - }; + // First, push phis back + func.labels.forEach(function(label) { + label.lines.forEach(function(phi) { + if (phi.intertype == 'phi') { + for (var i = 0; i < phi.params.length; i++) { + var param = phi.params[i]; + if (!param.label) warn('phi refers to nonexistent label on line ' + phi.lineNum); + var sourceLabelId = getActualLabelId(param.label); + if (sourceLabelId) { + var sourceLabel = func.labelsDict[sourceLabelId]; + var lastLine = sourceLabel.lines.slice(-1)[0]; + assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]); + if (!lastLine.phi) { + lastLine.phi = true; + assert(!lastLine.dependent); + lastLine.dependent = { + intertype: 'phiassigns', + params: [] }; - lastLine.dependent.params.push({ - intertype: 'phiassign', - ident: phi.assignTo, - value: param.value, - targetLabel: label.ident - }); - } + }; + lastLine.dependent.params.push({ + intertype: 'phiassign', + ident: phi.assignTo, + value: param.value, + targetLabel: label.ident + }); } - // The assign to phi is now just a var - phi.intertype = 'var'; - phi.ident = phi.assignTo; - phi.assignTo = null; } - }); + // The assign to phi is now just a var + phi.intertype = 'var'; + phi.ident = phi.assignTo; + phi.assignTo = null; + } }); - } + }); }); this.forwardItem(item, 'StackAnalyzer'); } |