diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jsifier.js | 1 | ||||
-rw-r--r-- | src/library.js | 8 | ||||
-rw-r--r-- | src/long.js | 53 | ||||
-rw-r--r-- | src/parseTools.js | 48 | ||||
-rw-r--r-- | src/settings.js | 3 |
5 files changed, 105 insertions, 8 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 99176fd2..8b9948be 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -38,6 +38,7 @@ function JSify(data, functionsOnly, givenFunctions) { var preFile = BUILD_AS_SHARED_LIB ? 'preamble_sharedlib.js' : 'preamble.js'; var pre = processMacros(preprocess(read(preFile).replace('{{RUNTIME}}', getRuntime()))); print(pre); + if (PRECISE_I64_MATH) print(read('long.js')); Functions.implementedFunctions = set(data.unparsedFunctions.map(function(func) { return func.ident })); } diff --git a/src/library.js b/src/library.js index 78dd629b..6ccd398f 100644 --- a/src/library.js +++ b/src/library.js @@ -2487,9 +2487,13 @@ LibraryManager.library = { var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0); argSize = argSize || 4; var currArg = getNextArg('i' + (argSize * 8)); + var argText = null; #if USE_TYPED_ARRAYS == 2 // Flatten i64-1 [low, high] into a (slightly rounded) double if (argSize == 8) { +#if PRECISE_I64_MATH == 1 + argText = i64Math.stringify(currArg[0], currArg[1]); +#endif currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 'u'.charCodeAt(0)); } #endif @@ -2500,8 +2504,10 @@ LibraryManager.library = { } // Format the number. var currAbsArg = Math.abs(currArg); - var argText; var prefix = ''; +#if PRECISE_I64_MATH == 1 + if (argText !== null) {} else +#endif if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) { argText = reSign(currArg, 8 * argSize, 1).toString(10); } else if (next == 'u'.charCodeAt(0)) { diff --git a/src/long.js b/src/long.js index f03e5fa5..af908322 100644 --- a/src/long.js +++ b/src/long.js @@ -1,3 +1,5 @@ +//======= begin closure i64 code ======= + // Copyright 2009 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,8 +21,8 @@ * */ -goog.provide('goog.math.Long'); - +var i64Math = (function() { // Emscripten wrapper +var goog = { math: {} }; /** @@ -799,3 +801,50 @@ goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { } } }; + +// End Emscripten wrapper +return { + result: [0, 0], // return result stored here + add: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.add(y); + this.result[0] = ret.low_; + this.result[1] = ret.high_; + }, + subtract: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.subtract(y); + this.result[0] = ret.low_; + this.result[1] = ret.high_; + }, + multiply: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.multiply(y); + this.result[0] = ret.low_; + this.result[1] = ret.high_; + }, + divide: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.div(y); + this.result[0] = ret.low_; + this.result[1] = ret.high_; + }, + modulo: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.modulo(y); + this.result[0] = ret.low_; + this.result[1] = ret.high_; + }, + stringify: function(l, h) { + return new goog.math.Long(l, h).toString(); + } +}; +})(); + +//======= end closure i64 code ======= + diff --git a/src/parseTools.js b/src/parseTools.js index 0e6ddee8..436b496e 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1618,6 +1618,9 @@ function processMathop(item) { return result; } } + function i64PreciseOp(type) { + return finish(['(i64Math.' + type + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + '),i64Math.result[0])', 'i64Math.result[1]']); + } switch (op) { // basic integer ops case 'or': { @@ -1703,11 +1706,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'); + } 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'); + } 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'); diff --git a/src/settings.js b/src/settings.js index 66b53218..ede00dd5 100644 --- a/src/settings.js +++ b/src/settings.js @@ -67,6 +67,9 @@ var DOUBLE_MODE = 1; // How to load and store 64-bit doubles. Without typed arra // then load it aligned, and that load-store will make JS engines alter it if it is being // stored to a typed array for security reasons. That will 'fix' the number from being a // NaN or an infinite number. +var PRECISE_I64_MATH = 0; // If enabled, i64 addition etc. is emulated - which is slow but precise. If disabled, + // we use the 'double trick' which is fast but incurs rounding at high values. + // Note that precise math currently only handles *signed* values, not unsigned var CLOSURE_ANNOTATIONS = 0; // If set, the generated code will be annotated for the closure // compiler. This potentially lets closure optimize the code better. |