diff options
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 123 |
1 files changed, 77 insertions, 46 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index ad6f2830..49e5b411 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -558,22 +558,13 @@ function makeInlineCalculation(expression, value, tempVar) { return '(' + expression.replace(/VALUE/g, value) + ')'; } -// Given two 32-bit unsigned parts of an emulated 64-bit number, combine them into a JS number (double). -// Rounding is inevitable if the number is large. This is a particular problem for small negative numbers -// (-1 will be rounded!), so handle negatives separately and carefully -function makeBigInt(low, high) { - // here VALUE will be the big part - return '(' + high + ' <= 2147483648 ? (' + makeSignOp(low, 'i32', 'un', 1, 1) + '+(' + makeSignOp(high, 'i32', 'un', 1, 1) + '*4294967296))' + - ' : (' + makeSignOp(low, 'i32', 're', 1, 1) + '+(1+' + makeSignOp(high, 'i32', 're', 1, 1) + ')*4294967296))'; -} - // Makes a proper runtime value for a 64-bit value from low and high i32s. low and high are assumed to be unsigned. function makeI64(low, high) { high = high || '0'; if (I64_MODE == 1) { return '[' + makeSignOp(low, 'i32', 'un', 1, 1) + ',' + makeSignOp(high, 'i32', 'un', 1, 1) + ']'; } else { - if (high) return makeBigInt(low, high); + if (high) return RuntimeGenerator.makeBigInt(low, high); return low; } } @@ -589,7 +580,7 @@ function splitI64(value) { } function mergeI64(value) { assert(I64_MODE == 1); - return makeInlineCalculation(makeBigInt('VALUE[0]', 'VALUE[1]'), value, 'tempI64'); + return makeInlineCalculation(RuntimeGenerator.makeBigInt('VALUE[0]', 'VALUE[1]'), value, 'tempI64'); } // Takes an i64 value and changes it into the [low, high] form used in i64 mode 1. In that @@ -912,23 +903,32 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa 'tempDoubleF64[0])'; } - if (EMULATE_UNALIGNED_ACCESSES && USE_TYPED_ARRAYS == 2 && align && isIntImplemented(type)) { // TODO: support unaligned doubles and floats + if (USE_TYPED_ARRAYS == 2 && align) { // Alignment is important here. May need to split this up var bytes = Runtime.getNativeTypeSize(type); if (bytes > align) { - var ret = '/* unaligned */('; - if (bytes <= 4) { - for (var i = 0; i < bytes; i++) { - ret += 'tempInt' + (i == 0 ? '=' : (i < bytes-1 ? '+=((' : '+((')); - ret += makeSignOp(makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, unsigned, ignore), 'i8', 'un', true); - if (i > 0) ret += ')<<' + (8*i) + ')'; - if (i < bytes-1) ret += ','; + var ret = '('; + if (isIntImplemented(type)) { + if (bytes <= 4) { + for (var i = 0; i < bytes; i++) { + ret += 'tempInt' + (i == 0 ? '=' : '|=(('); + ret += makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, 1, ignore); + if (i > 0) ret += ')<<' + (8*i) + ')'; + ret += ','; + } + ret += makeSignOp('tempInt', type, unsigned ? 'un' : 're', true); + } else { + assert(bytes == 8); + ret += 'tempBigInt=' + makeGetValue(ptr, pos, 'i32', noNeedFirst, true, ignore, align) + ','; + ret += 'tempBigInt2=' + makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, true, ignore, align) + ','; + ret += makeI64('tempBigInt', 'tempBigInt2'); } } else { - assert(bytes == 8); - ret += 'tempBigInt=' + makeGetValue(ptr, pos, 'i32', noNeedFirst, true, ignore, align) + ','; - ret += 'tempBigInt2=' + makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, true, ignore, align) + ','; - ret += makeI64('tempBigInt', 'tempBigInt2'); + if (type == 'float') { + ret += 'copyTempFloat(' + getFastValue(ptr, '+', pos) + '),tempDoubleF32[0]'; + } else { + ret += 'copyTempDouble(' + getFastValue(ptr, '+', pos) + '),tempDoubleF64[0]'; + } } ret += ')'; return ret; @@ -994,22 +994,27 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe) makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align) + ')'; } - if (EMULATE_UNALIGNED_ACCESSES && USE_TYPED_ARRAYS == 2 && align && isIntImplemented(type)) { // TODO: support unaligned doubles and floats + if (USE_TYPED_ARRAYS == 2 && align) { // Alignment is important here. May need to split this up var bytes = Runtime.getNativeTypeSize(type); if (bytes > align) { - var ret = '/* unaligned */'; - if (bytes <= 4) { - ret += 'tempBigInt=' + value + ';'; - for (var i = 0; i < bytes; i++) { - ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore) + ';'; - if (i < bytes-1) ret += 'tempBigInt>>=8;'; + var ret = ''; + if (isIntImplemented(type)) { + if (bytes <= 4) { + ret += 'tempBigInt=' + value + ';'; + for (var i = 0; i < bytes; i++) { + ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore) + ';'; + if (i < bytes-1) ret += 'tempBigInt>>=8;'; + } + } else { + assert(bytes == 8); + ret += 'tempPair=' + ensureI64_1(value) + ';'; + ret += makeSetValue(ptr, pos, 'tempPair[0]', 'i32', noNeedFirst, ignore, align) + ';'; + ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align) + ';'; } } else { - assert(bytes == 8); - ret += 'tempPair=' + ensureI64_1(value) + ';'; - ret += makeSetValue(ptr, pos, 'tempPair[0]', 'i32', noNeedFirst, ignore, align) + ';'; - ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align) + ';'; + ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8) + ';'; + ret += makeCopyValues(getFastValue(ptr, '+', pos), 'tempDoublePtr', Runtime.getNativeTypeSize(type), type, null, align); } return ret; } @@ -1465,7 +1470,7 @@ function makeSignOp(value, type, op, force, ignore) { var bits, full; if (type in Runtime.INT_TYPES) { bits = parseInt(type.substr(1)); - full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(correctSpecificSign() && !PGO) + ( + full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(ignore || (correctSpecificSign() && !PGO)) + ( PGO ? ', "' + (ignore ? '' : Debugging.getIdentifier()) + '"' : '' ) + ')'; // Always sign/unsign constants at compile time, regardless of CHECK/CORRECT @@ -1473,7 +1478,7 @@ function makeSignOp(value, type, op, force, ignore) { return eval(full).toString(); } } - if (!correctSigns() && !CHECK_SIGNS && !force) return value; + if ((ignore || !correctSigns()) && !CHECK_SIGNS && !force) return value; if (type in Runtime.INT_TYPES) { // shortcuts if (!CHECK_SIGNS || ignore) { @@ -1589,17 +1594,43 @@ function processMathop(item) { case 'xor': { return '[' + ident1 + '[0] ^ ' + ident2 + '[0], ' + ident1 + '[1] ^ ' + ident2 + '[1]]'; } - case 'shl': { - return '[' + ident1 + '[0] << ' + ident2 + ', ' + - '('+ident1 + '[1] << ' + ident2 + ') | ((' + ident1 + '[0]&((Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + '))) >>> (32-' + ident2 + '))]'; - } - case 'ashr': { - return '[('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&(Math.pow(2, ' + ident2 + ')-1))<<(32-' + ident2 + ')),' + - ident1 + '[1] >>> ' + ident2 + ']'; - } + case 'shl': + case 'ashr': case 'lshr': { - return '[('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&(Math.pow(2, ' + ident2 + ')-1))<<(32-' + ident2 + ')),' + - ident1 + '[1] >>> ' + ident2 + ']'; + assert(isNumber(ident2)); + bits = parseInt(ident2); + 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 + '))]'; + case 'ashr': + return '[((('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&' + ander + ')<<' + (32 - bits) + ')) >> 0) >>> 0,' + + '(' + ident1 + '[1] >> ' + ident2 + ') >>> 0]'; + case 'lshr': + return '[(('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident1 + '[1]&' + ander + ')<<' + (32 - bits) + ')) >>> 0,' + + ident1 + '[1] >>> ' + ident2 + ']'; + } + } else if (bits == 32) { + switch (op) { + case 'shl': + return '[0, ' + ident1 + '[0]]'; + case 'ashr': + return '[' + ident1 + '[1], (' + ident1 + '[1]|0) < 0 ? ' + ander + ' : 0]'; + case 'lshr': + return '[' + ident1 + '[1], 0]'; + } + } else { // bits > 32 + switch (op) { + case 'shl': + return '[0, ' + ident1 + '[0] << ' + (bits - 32) + ']'; + case 'ashr': + return '[(' + ident1 + '[1] >> ' + (bits - 32) + ') >>> 0, (' + ident1 + '[1]|0) < 0 ? ' + ander + ' : 0]'; + case 'lshr': + return '[' + ident1 + '[1] >>> ' + (bits - 32) + ', 0]'; + } + } } case 'uitofp': case 'sitofp': return ident1 + '[0] + ' + ident1 + '[1]*4294967296'; case 'fptoui': case 'fptosi': return splitI64(ident1); |