diff options
-rw-r--r-- | src/analyzer.js | 26 | ||||
-rw-r--r-- | src/parseTools.js | 2 | ||||
-rw-r--r-- | src/runtime.js | 20 |
3 files changed, 29 insertions, 19 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index d0229612..14677edc 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -387,13 +387,6 @@ function analyzer(data, sidePass) { case 'mathop': { var toAdd = []; var sourceBits = getBits(value.param1.type); - var sourceElements; - if (sourceBits <= 32) { - // The input is a legal type - sourceElements = [{ ident: value.param1.ident, bits: sourceBits }]; - } else { - sourceElements = getLegalVars(value.param1.ident, sourceBits); - } // All mathops can be parametrized by how many shifts we do, and how big the source is var shifts = 0; var targetBits = sourceBits; @@ -428,6 +421,7 @@ 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); processor = function(result, j) { @@ -464,7 +458,23 @@ function analyzer(data, sidePass) { default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)]; } // Do the legalization - assert(isNumber(shifts), 'TODO: handle nonconstant shifts'); + var sourceElements; + if (sourceBits <= 32) { + // The input is a legal type + sourceElements = [{ ident: value.param1.ident, bits: sourceBits }]; + } else { + sourceElements = getLegalVars(value.param1.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);' + + 'var ' + value.assignTo + '$0 = ' + value.assignTo + '[0], ' + value.assignTo + '$1 = ' + value.assignTo + '[1];'; + i++; + continue; + } var targetElements = getLegalVars(item.assignTo, targetBits); var sign = shifts >= 0 ? 1 : -1; var shiftOp = shifts >= 0 ? 'shl' : 'lshr'; diff --git a/src/parseTools.js b/src/parseTools.js index e1072308..70a6ba5a 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1600,7 +1600,7 @@ function processMathop(item) { case 'ashr': case 'lshr': { if (!isNumber(ident2)) { - return 'Runtime.bitshift64(' + ident1 + ',"' + op + '",' + stripCorrections(ident2) + '[0]|0)'; + return 'Runtime.bitshift64(' + ident1 + '[0], ' + ident1 + '[1],"' + op + '",' + stripCorrections(ident2) + '[0]|0)'; } bits = parseInt(ident2); var ander = Math.pow(2, bits)-1; diff --git a/src/runtime.js b/src/runtime.js index 803407c6..852d08d8 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -123,34 +123,34 @@ var Runtime = { FLOAT_TYPES: set('float', 'double'), // Mirrors processMathop's treatment of constants (which we optimize directly) - bitshift64: function(value, op, bits) { + bitshift64: function(low, high, op, bits) { var ander = Math.pow(2, bits)-1; if (bits < 32) { switch (op) { case 'shl': - return [value[0] << bits, (value[1] << bits) | ((value[0]&(ander << (32 - bits))) >>> (32 - bits))]; + return [low << bits, (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))]; case 'ashr': - return [(((value[0] >>> bits ) | ((value[1]&ander) << (32 - bits))) >> 0) >>> 0, (value[1] >> bits) >>> 0]; + return [(((low >>> bits ) | ((high&ander) << (32 - bits))) >> 0) >>> 0, (high >> bits) >>> 0]; case 'lshr': - return [((value[0] >>> bits) | ((value[1]&ander) << (32 - bits))) >>> 0, value[1] >>> bits]; + return [((low >>> bits) | ((high&ander) << (32 - bits))) >>> 0, high >>> bits]; } } else if (bits == 32) { switch (op) { case 'shl': - return [0, value[0]]; + return [0, low]; case 'ashr': - return [value[1], (value[1]|0) < 0 ? ander : 0]; + return [high, (high|0) < 0 ? ander : 0]; case 'lshr': - return [value[1], 0]; + return [high, 0]; } } else { // bits > 32 switch (op) { case 'shl': - return [0, value[0] << (bits - 32)]; + return [0, low << (bits - 32)]; case 'ashr': - return [(value[1] >> (bits - 32)) >>> 0, (value[1]|0) < 0 ? ander : 0]; + return [(high >> (bits - 32)) >>> 0, (high|0) < 0 ? ander : 0]; case 'lshr': - return [value[1] >>> (bits - 32) , 0]; + return [high >>> (bits - 32) , 0]; } } abort('unknown bitshift64 op: ' + [value, op, bits]); |