diff options
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 520d278e..5ec3b4ed 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -683,16 +683,14 @@ function parseArbitraryInt(str, bits) { return ret; } -function parseI64Constant(str) { - assert(USE_TYPED_ARRAYS == 2); - +function parseI64Constant(str, legalized) { if (!isNumber(str)) { // This is a variable. Copy it, so we do not modify the original return legalizedI64s ? str : makeCopyI64(str); } var parsed = parseArbitraryInt(str, 64); - if (legalizedI64s) return parsed; + if (legalizedI64s || legalized) return parsed; return '[' + parsed[0] + ',' + parsed[1] + ']'; } @@ -1537,7 +1535,8 @@ function makeRounding(value, bits, signed, floatConversion) { // TODO: handle roundings of i64s assert(bits); // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that. - if (bits <= 32 && signed) return '((' + value + ')|0)'; // This is fast and even correct, for all cases + if (bits <= 32 && signed) return '((' + value + ')&-1)'; // This is fast and even correct, for all cases. Note that it is the same + // as |0, but &-1 hints to the js optimizer that this is a rounding correction // Do Math.floor, which is reasonably fast, if we either don't care, or if we can be sure // the value is non-negative if (!correctRoundings() || (!signed && !floatConversion)) return 'Math.floor(' + value + ')'; @@ -1617,6 +1616,10 @@ function processMathop(item) { return result; } } + function i64PreciseOp(type, lastArg) { + return finish(['(i64Math.' + type + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + + (lastArg ? ',' + lastArg : '') + '),i64Math.result[0])', 'i64Math.result[1]']); + } switch (op) { // basic integer ops case 'or': { @@ -1702,11 +1705,46 @@ function processMathop(item) { 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(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], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's'))); - case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u'))); - case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u'))); + case 'add': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('add'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]))); + } + } + case 'sub': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('subtract'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]))); + } + } + case 'sdiv': case 'udiv': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('divide', op[0] === 'u'); + } else { + warnI64_1(); + return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's'))); + } + } + case 'mul': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('multiply'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u'))); + } + } + case 'urem': case 'srem': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('modulo', op[0] === 'u'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u'))); + } + } 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'); |