aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js1
-rw-r--r--src/library.js8
-rw-r--r--src/long.js53
-rw-r--r--src/parseTools.js48
-rw-r--r--src/settings.js3
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.