diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 52 | ||||
-rw-r--r-- | src/jsifier.js | 22 | ||||
-rw-r--r-- | src/parseTools.js | 10 |
3 files changed, 60 insertions, 24 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 1195c68b..6cfb2b6d 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -621,19 +621,15 @@ function analyzer(data) { // we need __lastLabel__. func.needsLastLabel = false; func.labels.forEach(function(label) { - var phis = []; + var phis = [], phi; label.lines.forEach(function(line) { - if (line.value && line.value.intertype == 'phi') { - for (var i = 0; i < line.value.params.length; i++) { - var remarkableLabelId = line.value.params[i].label; - var remarkableLabel = func.labelsDict[remarkableLabelId]; - assert(remarkableLabel); - var lastLine = remarkableLabel.lines.slice(-1)[0]; - if (lastLine.intertype === 'assign') { - lastLine.value.currLabelId = remarkableLabelId; - } else { - lastLine.currLabelId = remarkableLabelId; - } + if ((phi = line.value) && phi.intertype == 'phi') { + for (var i = 0; i < phi.params.length; i++) { + var sourceLabelId = phi.params[i].label; + var sourceLabel = func.labelsDict[sourceLabelId]; + var lastLine = sourceLabel.lines.slice(-1)[0]; + assert(lastLine.intertype == 'branch', 'Only branches can lead to labels with phis'); + lastLine.currLabelId = sourceLabelId; } phis.push(line); func.needsLastLabel = true; @@ -661,8 +657,36 @@ function analyzer(data) { } } }); - } else { // MICRO_OPTS - assert(0, 'TODO'); + } 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(line) { + var phi; + if ((phi = line.value) && phi.intertype == 'phi') { + for (var i = 0; i < phi.params.length; i++) { + var param = phi.params[i]; + var sourceLabelId = param.label; + var sourceLabel = func.labelsDict[sourceLabelId]; + var lastLine = sourceLabel.lines.slice(-1)[0]; + assert(lastLine.intertype == 'branch', 'Only branches can lead to labels with phis'); + if (!lastLine.phi) { + // We store the phi assignments in the branch's params (which are otherwise unused) + lastLine.phi = true; + assert(!lastLine.params); + lastLine.params = []; + }; + lastLine.params.push({ + intertype: 'phiassign', + ident: line.ident, + value: param.value + }); + } + } + }); + }); } }); this.forwardItem(item, 'StackAnalyzer'); diff --git a/src/jsifier.js b/src/jsifier.js index 604e8b8c..d158a9b9 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -671,7 +671,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { function makeBranch(label, lastLabel, labelIsVariable) { var pre = ''; - if (lastLabel) { + if (!MICRO_OPTS && lastLabel) { pre = '__lastLabel__ = ' + getLabelId(lastLabel) + '; '; } if (label[0] == 'B') { @@ -819,16 +819,20 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { }); makeFuncLineActor('phi', function(item) { var params = item.params; - function makeOne(i) { - if (i === params.length-1) { - return finalizeLLVMParameter(params[i].value); + if (!MICRO_OPTS) { + function makeOne(i) { + if (i === params.length-1) { + return finalizeLLVMParameter(params[i].value); + } + return '__lastLabel__ == ' + getLabelId(params[i].label) + ' ? ' + + finalizeLLVMParameter(params[i].value) + ' : (' + makeOne(i+1) + ')'; } - return '__lastLabel__ == ' + getLabelId(params[i].label) + ' ? ' + - finalizeLLVMParameter(params[i].value) + ' : (' + makeOne(i+1) + ')'; + var ret = makeOne(0); + if (item.postSet) ret += item.postSet; + return ret; + } else { // MICRO_OPTS == 1 + assert(0, 'TODO'); } - var ret = makeOne(0); - if (item.postSet) ret += item.postSet; - return ret; }); makeFuncLineActor('mathop', processMathop); diff --git a/src/parseTools.js b/src/parseTools.js index d7514ef5..591e6add 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1339,6 +1339,7 @@ function getGetElementPtrIndexes(item) { } function handleOverflow(text, bits) { + // TODO: handle overflows of i64s if (!bits) return text; var correct = correctOverflows(); warn(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits + ' at line ' + Framework.currItem.lineNum); @@ -1393,6 +1394,10 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) { } function makeSignOp(value, type, op, force) { + if (I64_MODE == 1 && type == 'i64') { + return '(tempPair=' + value + ',[' + makeSignOp('tempPair[0]', 'i32', op, force) + ',' + makeSignOp('tempPair[1]', 'i32', op, force) + '])'; + } + if (isPointerType(type)) type = 'i32'; // Pointers are treated as 32-bit ints if (!value) return value; var bits, full; @@ -1430,6 +1435,8 @@ function makeSignOp(value, type, op, force) { } function makeRounding(value, bits, signed) { + // TODO: handle roundings of i64s + // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that. // With 32 bits and less, and a signed value, |0 will round it like C does. if (bits && bits <= 32 && signed) return '(('+value+')|0)'; @@ -1531,7 +1538,8 @@ function processMathop(item) { with(item) { default: throw 'Unknown icmp variant: ' + variant; } } - case 'zext': case 'sext': return makeI64(ident1, 0); + case 'zext': return makeI64(ident1, 0); + case 'sext': return '(tempInt=' + ident1 + ',' + makeI64('tempInt', 'tempInt<0 ? 4294967295 : 0') + ')'; case 'trunc': { return '((' + ident1 + '[0]) & ' + (Math.pow(2, bitsLeft)-1) + ')'; } |