diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-02-25 15:47:42 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-02-25 15:47:42 -0800 |
commit | bfb9a540657debce1ba588e003b70c3259150f39 (patch) | |
tree | c56d33205d30356e42c8d761ec7e5dcb9c58410f | |
parent | 55ac19dc9b6cc6e806f3bae5843cca5ee17262b4 (diff) |
refactor out paramX in mathops
-rw-r--r-- | src/analyzer.js | 68 | ||||
-rw-r--r-- | src/intertyper.js | 23 | ||||
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 230 |
4 files changed, 161 insertions, 162 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 593b4650..4dd95e7a 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -388,13 +388,13 @@ function analyzer(data, sidePass) { case 'inttoptr': case 'ptrtoint': { value = { op: item.intertype, - param1: item.params[0] + params: [item.params[0]] // XXX }; // fall through } case 'mathop': { var toAdd = []; - var sourceBits = getBits(value.param1.type); + var sourceBits = getBits(value.params[0].type); // All mathops can be parametrized by how many shifts we do, and how big the source is var shifts = 0; var targetBits = sourceBits; @@ -406,11 +406,11 @@ function analyzer(data, sidePass) { // fall through } case 'lshr': { - shifts = parseInt(value.param2.ident); + shifts = parseInt(value.params[1].ident); break; } case 'shl': { - shifts = -parseInt(value.param2.ident); + shifts = -parseInt(value.params[1].ident); break; } case 'sext': { @@ -418,7 +418,7 @@ function analyzer(data, sidePass) { // fall through } case 'trunc': case 'zext': case 'ptrtoint': { - targetBits = getBits(value.param2.ident); + targetBits = getBits(value.params[1].ident); break; } case 'inttoptr': { @@ -429,31 +429,35 @@ function analyzer(data, sidePass) { break; } case 'select': { - sourceBits = targetBits = getBits(value.param2.type); - var otherElementsA = getLegalVars(value.param2.ident, sourceBits); - var otherElementsB = getLegalVars(value.param3.ident, sourceBits); + sourceBits = targetBits = getBits(value.params[1].type); + var otherElementsA = getLegalVars(value.params[1].ident, sourceBits); + var otherElementsB = getLegalVars(value.params[2].ident, sourceBits); processor = function(result, j) { return { intertype: 'mathop', op: 'select', type: 'i' + otherElementsA[j].bits, - param1: value.param1, - param2: { intertype: 'value', ident: otherElementsA[j].ident, type: 'i' + otherElementsA[j].bits }, - param3: { intertype: 'value', ident: otherElementsB[j].ident, type: 'i' + otherElementsB[j].bits } + params: [ + value.params[0], + { intertype: 'value', ident: otherElementsA[j].ident, type: 'i' + otherElementsA[j].bits }, + { intertype: 'value', ident: otherElementsB[j].ident, type: 'i' + otherElementsB[j].bits } + ] }; }; break; } case 'or': case 'and': case 'xor': { - var otherElements = getLegalVars(value.param2.ident, sourceBits); + var otherElements = getLegalVars(value.params[1].ident, sourceBits); processor = function(result, j) { return { intertype: 'mathop', op: value.op, type: 'i' + otherElements[j].bits, - param1: result, - param2: { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits } - }; + params: [ + result, + { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits } + ] + }; }; break; } @@ -469,16 +473,16 @@ function analyzer(data, sidePass) { var sourceElements; if (sourceBits <= 32) { // The input is a legal type - sourceElements = [{ ident: value.param1.ident, bits: sourceBits }]; + sourceElements = [{ ident: value.params[0].ident, bits: sourceBits }]; } else { - sourceElements = getLegalVars(value.param1.ident, sourceBits); + sourceElements = getLegalVars(value.params[0].ident, sourceBits); } if (!isNumber(shifts)) { // We can't statically legalize this, do the operation at runtime TODO: optimize assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits'); value.intertype = 'value'; value.ident = 'Runtime.bitshift64(' + sourceElements[0].ident + ', ' + - sourceElements[1].ident + ',"' + value.op + '",' + value.param2.ident + '$0);' + + sourceElements[1].ident + ',"' + value.op + '",' + value.params[1].ident + '$0);' + 'var ' + value.assignTo + '$0 = ' + value.assignTo + '[0], ' + value.assignTo + '$1 = ' + value.assignTo + '[1];'; i++; continue; @@ -497,37 +501,43 @@ function analyzer(data, sidePass) { var result = { intertype: 'value', ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : (signed ? signedFill : '0'), - param1: (signed && j + whole > sourceElements.length) ? signedKeepAlive : null, + params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null], type: 'i32', }; if (fraction != 0) { var other = { intertype: 'value', ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : (signed ? signedFill : '0'), - param1: (signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null, + params: [(signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null], type: 'i32', }; other = { intertype: 'mathop', op: shiftOp, type: 'i32', - param1: other, - param2: { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' } + params: [ + other, + { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' } + ] }; result = { intertype: 'mathop', // shifting in 1s from the top is a special case op: (signed && shifts >= 0 && j + sign + whole >= sourceElements.length) ? 'ashr' : shiftOpReverse, type: 'i32', - param1: result, - param2: { intertype: 'value', ident: fraction.toString(), type: 'i32' } + params: [ + result, + { intertype: 'value', ident: fraction.toString(), type: 'i32' } + ] }; result = { intertype: 'mathop', op: 'or', type: 'i32', - param1: result, - param2: other + params: [ + result, + other + ] } } if (targetElements[j].bits < 32 && shifts < 0) { @@ -536,8 +546,10 @@ function analyzer(data, sidePass) { intertype: 'mathop', op: 'and', type: 'i32', - param1: result, - param2: { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' } + params: [ + result, + { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' } + ] } } if (processor) { diff --git a/src/intertyper.js b/src/intertyper.js index cfb12331..6d367b93 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -800,38 +800,39 @@ function intertyper(data, sidePass, baseLineNums) { } if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // TODO: Implement trap values var segments = splitTokenList(item.tokens.slice(1)); + item.params = []; for (var i = 1; i <= 4; i++) { if (segments[i-1]) { if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1 && !isType(segments[i-1][0].text)) { segments[i-1].unshift(segments[0][0]); // Add the type from the first segment, they are all alike } - item['param'+i] = parseLLVMSegment(segments[i-1]); + item.params[i-1] = parseLLVMSegment(segments[i-1]); } } if (item.op === 'select') { - assert(item.param2.type === item.param3.type); - item.type = item.param2.type; + assert(item.params[1].type === item.params[2].type); + item.type = item.params[1].type; } else if (item.op === 'inttoptr' || item.op === 'ptrtoint') { - item.type = item.param2.type; + item.type = item.params[1].type; } else { - item.type = item.param1.type; + item.type = item.params[0].type; } if (item.op != 'ptrtoint') { - for (var i = 1; i <= 4; i++) { - if (item['param'+i]) item['param'+i].type = item.type; // All params have the same type, normally + for (var i = 0; i < 4; i++) { + if (item.params[i]) item.params[i].type = item.type; // All params have the same type, normally } } if (item.op in LLVM.EXTENDS) { - item.type = item.param2.ident; - item.param1.type = item.param2.type; + item.type = item.params[1].ident; + item.params[0].type = item.params[1].type; // TODO: also remove 2nd param? } if (I64_MODE == 1) { // Some specific corrections, since 'i64' is special if (item.op in LLVM.SHIFTS) { - item.param2.type = 'i32'; + item.params[1].type = 'i32'; } else if (item.op == 'select') { - item.param1.type = 'i1'; + item.params[0].type = 'i1'; } } Types.needAnalysis[item.type] = 0; diff --git a/src/jsifier.js b/src/jsifier.js index e1d2921f..70a99020 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1049,7 +1049,7 @@ function JSify(data, functionsOnly, givenFunctions) { var temp = { op: 'bitcast', variant: null, type: item.type, assignTo: item.assignTo, - param1: item.params[0] + params: [item.params[0]] // XXX }; var ret = processMathop(temp); if (!temp.assignTo) item.assignTo = null; // If the assign was stolen, propagate that diff --git a/src/parseTools.js b/src/parseTools.js index 56373535..ee7e5bdd 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1337,13 +1337,9 @@ function finalizeLLVMFunctionCall(item, noIndexizeFunctions) { var temp = { op: item.intertype, variant: item.variant, - type: item.type + type: item.type, + params: item.params.slice(0) // XXX slice? }; - for (var i = 1; i <= 4; i++) { - if (item.params[i-1]) { - temp['param' + i] = item.params[i-1]; - } - } return processMathop(temp); } @@ -1557,48 +1553,45 @@ function processMathop(item) { var variant = item.variant; var type = item.type; var paramTypes = ['', '', '', '']; - for (var i = 1; i <= 3; i++) { - if (item['param'+i]) { - paramTypes[i-1] = item['param'+i].type || type; - item['ident'+i] = finalizeLLVMParameter(item['param'+i]); - if (!isNumber(item['ident'+i]) && !isNiceIdent(item['ident'+i])) { - item['ident'+i] = '(' + item['ident'+i] + ')'; // we may have nested expressions. So enforce the order of operations we want + var idents = []; + for (var i = 0; i < 3; i++) { + if (item.params[i]) { + paramTypes[i] = item.params[i].type || type; + idents[i] = finalizeLLVMParameter(item.params[i]); + if (!isNumber(idents[i]) && !isNiceIdent(idents[i])) { + idents[i] = '(' + idents[i] + ')'; // we may have nested expressions. So enforce the order of operations we want } } else { - item['ident'+i] = null; // just so it exists for purposes of reading ident2 etc. later on, and no exception is thrown + idents[i] = null; // just so it exists for purposes of reading idents[1] etc. later on, and no exception is thrown } } - var ident1 = item.ident1; - var ident2 = item.ident2; - var ident3 = item.ident3; - var originalIdent1 = ident1; - var originalIdent2 = ident2; + var originalIdents = idents.slice(0); if (isUnsignedOp(op, variant)) { - ident1 = makeSignOp(ident1, paramTypes[0], 'un'); - ident2 = makeSignOp(ident2, paramTypes[1], 'un'); + idents[0] = makeSignOp(idents[0], paramTypes[0], 'un'); + idents[1] = makeSignOp(idents[1], paramTypes[0], 'un'); } else if (isSignedOp(op, variant)) { - ident1 = makeSignOp(ident1, paramTypes[0], 're'); - ident2 = makeSignOp(ident2, paramTypes[1], 're'); + idents[0] = makeSignOp(idents[0], paramTypes[0], 're'); + idents[1] = makeSignOp(idents[1], paramTypes[0], 're'); } var bits = null; if (item.type[0] === 'i') { bits = parseInt(item.type.substr(1)); } - var bitsLeft = parseInt(((item.param2 && item.param2.ident) ? item.param2.ident : item.type).substr(1)); // remove i to leave the number of bits left after this operation + var bitsLeft = parseInt(((item.params[1] && item.params[1].ident) ? item.params[1].ident : item.type).substr(1)); // remove i to leave the number of bits left after this operation function integerizeBignum(value) { return makeInlineCalculation('VALUE-VALUE%1', value, 'tempBigIntI'); } - if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || ident2 == '(i64)') && I64_MODE == 1) { + if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)') && I64_MODE == 1) { var warnI64_1 = function() { warnOnce('Arithmetic on 64-bit integers in mode 1 is rounded and flaky, like mode 0!'); }; // In ops that can be either legalized or not, we need to differentiate how we access low and high parts - var low1 = ident1 + (legalizedI64s ? '$0' : '[0]'); - var high1 = ident1 + (legalizedI64s ? '$1' : '[1]'); - var low2 = ident2 + (legalizedI64s ? '$0' : '[0]'); - var high2 = ident2 + (legalizedI64s ? '$1' : '[1]'); + var low1 = idents[0] + (legalizedI64s ? '$0' : '[0]'); + var high1 = idents[0] + (legalizedI64s ? '$1' : '[1]'); + var low2 = idents[1] + (legalizedI64s ? '$0' : '[0]'); + var high2 = idents[1] + (legalizedI64s ? '$1' : '[1]'); function finish(result) { // If this is in legalization mode, steal the assign and assign into two vars if (legalizedI64s) { @@ -1613,56 +1606,56 @@ function processMathop(item) { switch (op) { // basic integer ops case 'or': { - return '[' + ident1 + '[0] | ' + ident2 + '[0], ' + ident1 + '[1] | ' + ident2 + '[1]]'; + return '[' + idents[0] + '[0] | ' + idents[1] + '[0], ' + idents[0] + '[1] | ' + idents[1] + '[1]]'; } case 'and': { - return '[' + ident1 + '[0] & ' + ident2 + '[0], ' + ident1 + '[1] & ' + ident2 + '[1]]'; + return '[' + idents[0] + '[0] & ' + idents[1] + '[0], ' + idents[0] + '[1] & ' + idents[1] + '[1]]'; } case 'xor': { - return '[' + ident1 + '[0] ^ ' + ident2 + '[0], ' + ident1 + '[1] ^ ' + ident2 + '[1]]'; + return '[' + idents[0] + '[0] ^ ' + idents[1] + '[0], ' + idents[0] + '[1] ^ ' + idents[1] + '[1]]'; } case 'shl': case 'ashr': case 'lshr': { - if (!isNumber(ident2)) { - return 'Runtime.bitshift64(' + ident1 + '[0], ' + ident1 + '[1],"' + op + '",' + stripCorrections(ident2) + '[0]|0)'; + if (!isNumber(idents[1])) { + return 'Runtime.bitshift64(' + idents[0] + '[0], ' + idents[0] + '[1],"' + op + '",' + stripCorrections(idents[1]) + '[0]|0)'; } - bits = parseInt(ident2); + bits = parseInt(idents[1]); var ander = Math.pow(2, bits)-1; if (bits < 32) { switch (op) { case 'shl': - return '[' + ident1 + '[0] << ' + ident2 + ', ' + - '('+ident1 + '[1] << ' + ident2 + ') | ((' + ident1 + '[0]&(' + ander + '<<' + (32 - bits) + ')) >>> (32-' + ident2 + '))]'; + return '[' + idents[0] + '[0] << ' + idents[1] + ', ' + + '('+idents[0] + '[1] << ' + idents[1] + ') | ((' + idents[0] + '[0]&(' + ander + '<<' + (32 - bits) + ')) >>> (32-' + idents[1] + '))]'; case 'ashr': - return '[((('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&' + ander + ')<<' + (32 - bits) + ')) >> 0) >>> 0,' + - '(' + ident1 + '[1] >> ' + ident2 + ') >>> 0]'; + return '[((('+idents[0] + '[0] >>> ' + idents[1] + ') | ((' + idents[0] + '[1]&' + ander + ')<<' + (32 - bits) + ')) >> 0) >>> 0,' + + '(' + idents[0] + '[1] >> ' + idents[1] + ') >>> 0]'; case 'lshr': - return '[(('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&' + ander + ')<<' + (32 - bits) + ')) >>> 0,' + - ident1 + '[1] >>> ' + ident2 + ']'; + return '[(('+idents[0] + '[0] >>> ' + idents[1] + ') | ((' + idents[0] + '[1]&' + ander + ')<<' + (32 - bits) + ')) >>> 0,' + + idents[0] + '[1] >>> ' + idents[1] + ']'; } } else if (bits == 32) { switch (op) { case 'shl': - return '[0, ' + ident1 + '[0]]'; + return '[0, ' + idents[0] + '[0]]'; case 'ashr': - return '[' + ident1 + '[1], (' + ident1 + '[1]|0) < 0 ? ' + ander + ' : 0]'; + return '[' + idents[0] + '[1], (' + idents[0] + '[1]|0) < 0 ? ' + ander + ' : 0]'; case 'lshr': - return '[' + ident1 + '[1], 0]'; + return '[' + idents[0] + '[1], 0]'; } } else { // bits > 32 switch (op) { case 'shl': - return '[0, ' + ident1 + '[0] << ' + (bits - 32) + ']'; + return '[0, ' + idents[0] + '[0] << ' + (bits - 32) + ']'; case 'ashr': - return '[(' + ident1 + '[1] >> ' + (bits - 32) + ') >>> 0, (' + ident1 + '[1]|0) < 0 ? ' + ander + ' : 0]'; + return '[(' + idents[0] + '[1] >> ' + (bits - 32) + ') >>> 0, (' + idents[0] + '[1]|0) < 0 ? ' + ander + ' : 0]'; case 'lshr': - return '[' + ident1 + '[1] >>> ' + (bits - 32) + ', 0]'; + return '[' + idents[0] + '[1] >>> ' + (bits - 32) + ', 0]'; } } } case 'uitofp': case 'sitofp': return low1 + ' + ' + high1 + '*4294967296'; - case 'fptoui': case 'fptosi': return finish(splitI64(ident1)); + case 'fptoui': case 'fptosi': return finish(splitI64(idents[0])); case 'icmp': { switch (variant) { case 'uge': return high1 + ' >= ' + high2 + ' && (' + high1 + ' > ' + high2 + ' || ' + @@ -1686,39 +1679,39 @@ function processMathop(item) { default: throw 'Unknown icmp variant: ' + variant; } } - case 'zext': return makeI64(ident1, 0); - case 'sext': return makeInlineCalculation(makeI64('VALUE', 'VALUE<0 ? 4294967295 : 0'), ident1, 'tempBigIntD'); + case 'zext': return makeI64(idents[0], 0); + case 'sext': return makeInlineCalculation(makeI64('VALUE', 'VALUE<0 ? 4294967295 : 0'), idents[0], 'tempBigIntD'); case 'trunc': { - return '((' + ident1 + '[0]) & ' + (Math.pow(2, bitsLeft)-1) + ')'; + return '((' + idents[0] + '[0]) & ' + (Math.pow(2, bitsLeft)-1) + ')'; } - case 'select': return ident1 + ' ? ' + makeCopyI64(ident2) + ' : ' + makeCopyI64(ident3); - case 'ptrtoint': return makeI64(ident1, 0); - case 'inttoptr': return '(' + ident1 + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32 + case 'select': return idents[0] + ' ? ' + makeCopyI64(idents[1]) + ' : ' + makeCopyI64(idents[2]); + case 'ptrtoint': return makeI64(idents[0], 0); + case 'inttoptr': return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32 // Dangerous, rounded operations. TODO: Fully emulate - case 'add': warnI64_1(); return finish(splitI64(mergeI64(ident1) + '+' + mergeI64(ident2))); - case 'sub': warnI64_1(); return finish(splitI64(mergeI64(ident1) + '-' + mergeI64(ident2))); - case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(ident1) + '/' + mergeI64(ident2), bits, op[0] === 's'))); - case 'mul': warnI64_1(); return finish(splitI64(mergeI64(ident1) + '*' + mergeI64(ident2))); - case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(ident1) + '%' + mergeI64(ident2))); + case 'add': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]))); + case 'sub': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]))); + case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(idents[0]) + '/' + mergeI64(idents[1]), bits, op[0] === 's'))); + case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '*' + mergeI64(idents[1]))); + case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '%' + mergeI64(idents[1]))); case 'bitcast': { // Pointers are not 64-bit, so there is really only one possible type of bitcast here, int to float or vice versa assert(USE_TYPED_ARRAYS == 2, 'Can only bitcast ints <-> floats with typed arrays mode 2'); - var inType = item.param1.type; + var inType = item.params[0].type; var outType = item.type; if (inType in Runtime.INT_TYPES && outType in Runtime.FLOAT_TYPES) { if (legalizedI64s) { - return '(tempDoubleI32[0]=' + ident1 + '$0, tempDoubleI32[1]=' + ident1 + '$1, tempDoubleF64[0])'; + return '(tempDoubleI32[0]=' + idents[0] + '$0, tempDoubleI32[1]=' + idents[0] + '$1, tempDoubleF64[0])'; } else { - return makeInlineCalculation('tempDoubleI32[0]=VALUE[0],tempDoubleI32[1]=VALUE[1],tempDoubleF64[0]', ident1, 'tempI64'); + return makeInlineCalculation('tempDoubleI32[0]=VALUE[0],tempDoubleI32[1]=VALUE[1],tempDoubleF64[0]', idents[0], 'tempI64'); } } else if (inType in Runtime.FLOAT_TYPES && outType in Runtime.INT_TYPES) { if (legalizedI64s) { - return 'tempDoubleF64[0]=' + ident1 + '; ' + finish(['tempDoubleI32[0]','tempDoubleI32[1]']); + return 'tempDoubleF64[0]=' + idents[0] + '; ' + finish(['tempDoubleI32[0]','tempDoubleI32[1]']); } else { - return '(tempDoubleF64[0]=' + ident1 + ',[tempDoubleI32[0],tempDoubleI32[1]])'; + return '(tempDoubleF64[0]=' + idents[0] + ',[tempDoubleI32[0],tempDoubleI32[1]])'; } } else { - throw 'Invalid I64_MODE1 bitcast: ' + dump(item) + ' : ' + item.param1.type; + throw 'Invalid I64_MODE1 bitcast: ' + dump(item) + ' : ' + item.params[0].type; } } default: throw 'Unsupported i64 mode 1 op: ' + item.op + ' : ' + dump(item); @@ -1727,73 +1720,73 @@ function processMathop(item) { switch (op) { // basic integer ops - case 'add': return handleOverflow(getFastValue(ident1, '+', ident2, item.type), bits); - case 'sub': return handleOverflow(getFastValue(ident1, '-', ident2, item.type), bits); - case 'sdiv': case 'udiv': return makeRounding(getFastValue(ident1, '/', ident2, item.type), bits, op[0] === 's'); - case 'mul': return handleOverflow(getFastValue(ident1, '*', ident2, item.type), bits); - case 'urem': case 'srem': return getFastValue(ident1, '%', ident2, item.type); + case 'add': return handleOverflow(getFastValue(idents[0], '+', idents[1], item.type), bits); + case 'sub': return handleOverflow(getFastValue(idents[0], '-', idents[1], item.type), bits); + case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, op[0] === 's'); + case 'mul': return handleOverflow(getFastValue(idents[0], '*', idents[1], item.type), bits); + case 'urem': case 'srem': return getFastValue(idents[0], '%', idents[1], item.type); case 'or': { if (bits > 32) { assert(bits === 64, 'Too many bits for or: ' + bits); dprint('Warning: 64 bit OR - precision limit may be hit on llvm line ' + item.lineNum); - return 'Runtime.or64(' + ident1 + ', ' + ident2 + ')'; + return 'Runtime.or64(' + idents[0] + ', ' + idents[1] + ')'; } - return ident1 + ' | ' + ident2; + return idents[0] + ' | ' + idents[1]; } case 'and': { if (bits > 32) { assert(bits === 64, 'Too many bits for and: ' + bits); dprint('Warning: 64 bit AND - precision limit may be hit on llvm line ' + item.lineNum); - return 'Runtime.and64(' + ident1 + ', ' + ident2 + ')'; + return 'Runtime.and64(' + idents[0] + ', ' + idents[1] + ')'; } - return ident1 + ' & ' + ident2; + return idents[0] + ' & ' + idents[1]; } case 'xor': { if (bits > 32) { assert(bits === 64, 'Too many bits for xor: ' + bits); dprint('Warning: 64 bit XOR - precision limit may be hit on llvm line ' + item.lineNum); - return 'Runtime.xor64(' + ident1 + ', ' + ident2 + ')'; + return 'Runtime.xor64(' + idents[0] + ', ' + idents[1] + ')'; } - return ident1 + ' ^ ' + ident2; + return idents[0] + ' ^ ' + idents[1]; } case 'shl': { - if (bits > 32) return ident1 + '*' + getFastValue(2, 'pow', ident2); - return ident1 + ' << ' + ident2; + if (bits > 32) return idents[0] + '*' + getFastValue(2, 'pow', idents[1]); + return idents[0] + ' << ' + idents[1]; } case 'ashr': { - if (bits > 32) return integerizeBignum(ident1 + '/' + getFastValue(2, 'pow', ident2)); - if (bits === 32) return originalIdent1 + ' >> ' + ident2; // No need to reSign in this case - return ident1 + ' >> ' + ident2; + if (bits > 32) return integerizeBignum(idents[0] + '/' + getFastValue(2, 'pow', idents[1])); + if (bits === 32) return originalIdents[0] + ' >> ' + idents[1]; // No need to reSign in this case + return idents[0] + ' >> ' + idents[1]; } case 'lshr': { - if (bits > 32) return integerizeBignum(ident1 + '/' + getFastValue(2, 'pow', ident2)); - if (bits === 32) return originalIdent1 + ' >>> ' + ident2; // No need to unSign in this case - return ident1 + ' >>> ' + ident2; + if (bits > 32) return integerizeBignum(idents[0] + '/' + getFastValue(2, 'pow', idents[1])); + if (bits === 32) return originalIdents[0] + ' >>> ' + idents[1]; // No need to unSign in this case + return idents[0] + ' >>> ' + idents[1]; } // basic float ops - case 'fadd': return getFastValue(ident1, '+', ident2, item.type); - case 'fsub': return getFastValue(ident1, '-', ident2, item.type); - case 'fdiv': return getFastValue(ident1, '/', ident2, item.type); - case 'fmul': return getFastValue(ident1, '*', ident2, item.type); - case 'uitofp': case 'sitofp': return ident1; - case 'fptoui': case 'fptosi': return makeRounding(ident1, bitsLeft, op === 'fptosi', true); + case 'fadd': return getFastValue(idents[0], '+', idents[1], item.type); + case 'fsub': return getFastValue(idents[0], '-', idents[1], item.type); + case 'fdiv': return getFastValue(idents[0], '/', idents[1], item.type); + case 'fmul': return getFastValue(idents[0], '*', idents[1], item.type); + case 'uitofp': case 'sitofp': return idents[0]; + case 'fptoui': case 'fptosi': return makeRounding(idents[0], bitsLeft, op === 'fptosi', true); // TODO: We sometimes generate false instead of 0, etc., in the *cmps. It seemed slightly faster before, but worth rechecking // Note that with typed arrays, these become 0 when written. So that is a potential difference with non-typed array runs. case 'icmp': { switch (variant) { - case 'uge': case 'sge': return ident1 + ' >= ' + ident2; - case 'ule': case 'sle': return ident1 + ' <= ' + ident2; - case 'ugt': case 'sgt': return ident1 + ' > ' + ident2; - case 'ult': case 'slt': return ident1 + ' < ' + ident2; + case 'uge': case 'sge': return idents[0] + ' >= ' + idents[1]; + case 'ule': case 'sle': return idents[0] + ' <= ' + idents[1]; + case 'ugt': case 'sgt': return idents[0] + ' > ' + idents[1]; + case 'ult': case 'slt': return idents[0] + ' < ' + idents[1]; // We use loose comparisons, which allows false == 0 to be true, etc. Ditto in fcmp case 'ne': case 'eq': { // We must sign them, so we do not compare -1 to 255 (could have unsigned them both too) // since LLVM tells us if <=, >= etc. comparisons are signed, but not == and !=. assert(paramTypes[0] == paramTypes[1]); - ident1 = makeSignOp(ident1, paramTypes[0], 're'); - ident2 = makeSignOp(ident2, paramTypes[1], 're'); - return ident1 + (variant === 'eq' ? '==' : '!=') + ident2; + idents[0] = makeSignOp(idents[0], paramTypes[0], 're'); + idents[1] = makeSignOp(idents[1], paramTypes[1], 're'); + return idents[0] + (variant === 'eq' ? '==' : '!=') + idents[1]; } default: throw 'Unknown icmp variant: ' + variant; } @@ -1802,23 +1795,23 @@ function processMathop(item) { switch (variant) { // TODO 'o' ones should be 'ordered (no NaN) and', // 'u' ones should be 'unordered or'. - case 'uge': case 'oge': return ident1 + ' >= ' + ident2; - case 'ule': case 'ole': return ident1 + ' <= ' + ident2; - case 'ugt': case 'ogt': return ident1 + ' > ' + ident2; - case 'ult': case 'olt': return ident1 + ' < ' + ident2; - case 'une': case 'one': return ident1 + ' != ' + ident2; - case 'ueq': case 'oeq': return ident1 + ' == ' + ident2; - case 'ord': return '!isNaN(' + ident1 + ') && !isNaN(' + ident2 + ')'; - case 'uno': return 'isNaN(' + ident1 + ') || isNaN(' + ident2 + ')'; + case 'uge': case 'oge': return idents[0] + ' >= ' + idents[1]; + case 'ule': case 'ole': return idents[0] + ' <= ' + idents[1]; + case 'ugt': case 'ogt': return idents[0] + ' > ' + idents[1]; + case 'ult': case 'olt': return idents[0] + ' < ' + idents[1]; + case 'une': case 'one': return idents[0] + ' != ' + idents[1]; + case 'ueq': case 'oeq': return idents[0] + ' == ' + idents[1]; + case 'ord': return '!isNaN(' + idents[0] + ') && !isNaN(' + idents[1] + ')'; + case 'uno': return 'isNaN(' + idents[0] + ') || isNaN(' + idents[1] + ')'; case 'true': return '1'; default: throw 'Unknown fcmp variant: ' + variant; } } // Note that zext has sign checking, see above. We must guard against -33 in i8 turning into -33 in i32 // then unsigning that i32... which would give something huge. - case 'zext': case 'fpext': case 'sext': return ident1; - case 'fptrunc': return ident1; - case 'select': return ident1 + ' ? ' + ident2 + ' : ' + ident3; + case 'zext': case 'fpext': case 'sext': return idents[0]; + case 'fptrunc': return idents[0]; + case 'select': return idents[0] + ' ? ' + idents[1] + ' : ' + idents[2]; case 'ptrtoint': case 'inttoptr': { var ret = ''; if (QUANTUM_SIZE == 1) { @@ -1826,9 +1819,9 @@ function processMathop(item) { 'The safest thing is to investigate every appearance, and modify the source code to avoid this. ' + 'Emscripten will print a list of the .ll lines, and also annotate the .js.'); dprint(' ' + op + ' on .ll line ' + item.lineNum); - ident1 += ' /* Warning: ' + op + ', .ll line ' + item.lineNum + ' */'; + idents[0] += ' /* Warning: ' + op + ', .ll line ' + item.lineNum + ' */'; } - if (op == 'inttoptr' || bitsLeft >= 32) return ident1; + if (op == 'inttoptr' || bitsLeft >= 32) return idents[0]; // For ptrtoint and <32 bits, fall through into trunc since we need to truncate here } case 'trunc': { @@ -1836,23 +1829,23 @@ function processMathop(item) { // truncating can change the number, e.g. by truncating to an i1 // in order to get the first bit assert(bitsLeft <= 32, 'Cannot truncate to more than 32 bits, since we use a native & op'); - return '((' + ident1 + ') & ' + (Math.pow(2, bitsLeft)-1) + ')'; + return '((' + idents[0] + ') & ' + (Math.pow(2, bitsLeft)-1) + ')'; } case 'bitcast': { // Most bitcasts are no-ops for us. However, the exception is int to float and float to int - var inType = item.param1.type; + var inType = item.params[0].type; var outType = item.type; if ((inType in Runtime.INT_TYPES && outType in Runtime.FLOAT_TYPES) || (inType in Runtime.FLOAT_TYPES && outType in Runtime.INT_TYPES)) { assert(USE_TYPED_ARRAYS == 2, 'Can only bitcast ints <-> floats with typed arrays mode 2'); assert(inType == 'i32' || inType == 'float', 'Can only bitcast ints <-> floats with 32 bits (try I64_MODE=1)'); if (inType in Runtime.INT_TYPES) { - return '(tempDoubleI32[0] = ' + ident1 + ',tempDoubleF32[0])'; + return '(tempDoubleI32[0] = ' + idents[0] + ',tempDoubleF32[0])'; } else { - return '(tempDoubleF32[0] = ' + ident1 + ',tempDoubleI32[0])'; + return '(tempDoubleF32[0] = ' + idents[0] + ',tempDoubleI32[0])'; } } - return ident1; + return idents[0]; } default: throw 'Unknown mathcmp op: ' + item.op; } @@ -1870,9 +1863,6 @@ function walkInterdata(item, pre, post, obj) { // TODO if (item.pointer && walkInterdata(item.pointer, pre, post, obj)) return true; if (item.dependent && walkInterdata(item.dependent, pre, post, obj)) return true; var i; - for (i = 1; i <= 4; i++) { - if (item['param'+i] && walkInterdata(item['param'+i], pre, post, obj)) return true; - } if (item.params) { for (i = 0; i <= item.params.length; i++) { if (walkInterdata(item.params[i], pre, post, obj)) return true; @@ -1899,12 +1889,8 @@ function walkAndModifyInterdata(item, pre) { if (item.value && (repl = walkAndModifyInterdata(item.value, pre))) item.value = repl; if (item.pointer && (repl = walkAndModifyInterdata(item.pointer, pre))) item.pointer = repl; if (item.dependent && (repl = walkAndModifyInterdata(item.dependent, pre))) item.dependent = repl; - var i; - for (i = 1; i <= 4; i++) { - if (item['param'+i] && (repl = walkAndModifyInterdata(item['param'+i], pre))) item['param'+i] = repl; - } if (item.params) { - for (i = 0; i <= item.params.length; i++) { + for (var i = 0; i <= item.params.length; i++) { if (repl = walkAndModifyInterdata(item.params[i], pre)) item.params[i] = repl; } } |