aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-04-01 12:33:37 -0700
committerAlon Zakai <alonzakai@gmail.com>2012-04-01 12:33:37 -0700
commitb215efb7c115aa0c62daf081dc9098042fe2ffda (patch)
tree0d0a55e3908ca1a78d1cc30d2c88cc331e46d7f4
parente1a210f81387d60b3bd75954e76f243bce33068b (diff)
support for precise i64 signed math
-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
-rw-r--r--tests/i64_precise.txt64
-rwxr-xr-xtests/runner.py32
7 files changed, 201 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.
diff --git a/tests/i64_precise.txt b/tests/i64_precise.txt
new file mode 100644
index 00000000..94db160e
--- /dev/null
+++ b/tests/i64_precise.txt
@@ -0,0 +1,64 @@
+signed 0: 0,5,5,-5,0,0,0,0,0
+signed 1: 0,-35,-35,35,0,0,0,0,0
+signed 2: -1,-155,-156,154,155,0,155,-1,0
+signed 3: -2,740,738,-742,-1480,0,-370,-2,0
+signed 4: -4,3770,3766,-3774,-15080,0,-942,-4,2
+signed 5: -9,-18990,-18999,18981,170910,0,2110,-9,0
+signed 6: -18,-94675,-94693,94657,1704150,0,5259,-18,-13
+signed 7: 36,472825,472861,-472789,17021700,0,13134,36,1
+signed 8: -97,2365585,2365488,-2365682,-229461745,0,-24387,-97,46
+signed 9: -138,-11830000,-11830138,11829862,1632540000,0,85724,-138,-88
+signed 10: -295,-59145570,-59145865,59145275,17447943150,0,200493,-295,-135
+signed 11: -584,295719085,295718501,-295719669,-172699945640,0,-506368,-584,173
+signed 12: -1170,1478612985,1478611815,-1478614155,-1729977192450,0,-1263771,-1170,915
+signed 13: -2340,-7393100035,-7393102375,7393097695,17299854081900,0,3159444,-2340,-1075
+signed 14: 4681,-36965429955,-36965425274,36965434636,-173035177619355,0,-7896908,4681,-3607
+signed 15: -12483,184826962530,184826950047,-184826975013,-2307194973261990,0,-14806293,-12483,7011
+signed 16: -17684,924135077915,924135060231,-924135095599,-16342404717848860,0,-52258260,-17684,8075
+signed 17: -37796,-4620675956515,-4620675994311,4620675918719,174643068452440940,0,122253041,-37796,-18879
+signed 18: -74782,-23103378660835,-23103378735617,23103378586053,1727716863014562970,0,308943043,-74782,-19209
+signed 19: -149835,115516891056645,115516890906810,-115516891206480,1138270702237148041,0,-770960663,-149835,116040
+signed 20: -299580,577584459776930,577584459477350,-577584460076510,-7012055796586724856,0,-1927980705,-299580,173030
+signed 21: 599190,-2887922307872510,-2887922307273320,2887922308471700,3579775274568585004,0,-4819710455,599190,-341060
+signed 22: -1597831,-14439611515395080,-14439611516992911,14439611513797249,-4817928955413000136,0,9037007991,-1597831,-127559
+signed 23: -2263592,72198057543021515,72198057540757923,-72198057545285107,-7239720930239415736,0,-31895349313,-2263592,909219
+signed 24: -4837874,360990287787675695,360990287782837821,-360990287792513569,1520893864324420754,0,-74617546423,-4837874,4050993
+signed 25: -9572186,-1804951439081961265,-1804951439091533451,1804951439072389079,-284040605827480006,0,188562094288,-9572186,-7687697
+signed 26: -19178892,-9024757195122122935,-9024757195141301827,9024757195102944043,3158545232664844052,0,470556755579,-19178892,-2084467
+signed 27: -38346278,8230297827616317263,8230297827577970985,-8230297827654663541,-2447170876606408634,0,-214630943519,-38346278,34444981
+signed 28: 76696392,4258000991812928973,4258000991889625365,-4258000991736232581,-4010249384068861784,0,55517617984,76696392,5815245
+signed 29: -204522434,-2843260888422929769,-2843260888627452203,2843260888218407335,-3330061828535700334,0,13901951159,-204522434,-35128763
+signed 30: -289739796,4230439635940999721,4230439635651259925,-4230439636230739517,-8819265314490703668,0,-14600823547,-289739796,1223309
+signed 31: -619247950,-2705454115284166249,-2705454115903414199,2705454114664918299,4237355741738226942,0,4368935117,-619247950,-398906099
+signed 32: -1225239782,4919473515667317101,4919473514442077319,-4919473516892556883,8469738706080185362,0,-4015110828,-1225239782,62757605
+signed 33: -2454898270,-6150623541450507939,-6150623543905406209,6150623538995609669,-6720592984569904678,0,2505449458,-2454898270,-1433870279
+signed 34: -4908323638,6140370513791418107,6140370508883094469,-6140370518699741745,-2321546656369961458,0,-1251011743,-4908323638,4208937073
+signed 35: 9817138243,6191635431204939047,6191635441022077290,-6191635421387800804,1329921992230270261,0,630696571,9817138243,4311874294
+signed 36: -26178871659,-5935310598711333102,-5935310624890204761,5935310572532461443,-1523401759741279878,0,226721406,-26178871659,-8689300548
+signed 37: -37086693937,-7216935710162846787,-7216935747249540724,7216935673076152850,4375670093386346195,0,194596361,-37086693937,-28501883530
+signed 38: -79263737669,808810785560934332,808810706297196663,-808810864824672001,1308775974572414548,0,-10204045,-79263737669,39518263227
+signed 39: -156830692073,-4044056280265052755,-4044056437095744828,4044056123434360682,3200853909245289355,0,25786127,-156830692073,-136972781484
+signed 40: -314226978567,-1773532614211033644,-1773532928438012211,1773532299984055077,149458714710412084,0,5644113,-314226978567,-39530307573
+signed 41: -628265425661,8867653647073783295,8867653018808357634,-8867654275339208956,1335113139221865725,0,-14114502,-628265425661,40050747473
+signed 42: 1256593695147,7444798936855240458,7444800193448935605,-7444797680261545311,194995390784062894,0,5924587,1256593695147,266305361169
+signed 43: -3350895572451,-330556800290685833,-330560151186258284,330553449395113382,-3084978225808244869,0,98647,-3350895572451,-1004755112036
+signed 44: -4747096823988,-1652712795001069340,-1652717542097893328,1652708047904245352,888305014260137904,0,348152,-4747096823988,-1541535999164
+signed 45: -10145758421614,8263411788629022480,8263401642870600866,-8263421934387444094,1433933448381331232,0,-814469,-10145758421614,6072735489514
+signed 46: -20074328585350,4423871910654789418,4423851836326204068,-4423891984983374768,1087756533121529860,0,-220374,-20074328585350,11822986868518
+signed 47: -40221053256659,-3673218795363245364,-3673259016416502023,3673178574309988705,-3788250272949359140,0,91325,-40221053256659,-31106698862189
+signed 48: -80417974484665,81856366510594781,81775948536110116,-81936784485079446,3556652555309224011,0,-1017,-80417974484665,71286459690476
+signed 49: 160843992978882,-411694492447657140,-411533648454678258,411855336440636022,8646015829301599128,0,-2559,160843992978882,-94714414698102
+signed 50: -428914633273835,-2052038742739178170,-2052467657372452005,2051609828105904335,4194688249318378174,0,4784,-428914633273835,-111137157151530
+signed 51: -607628393470471,-8195664785915717831,-8196272414309188302,8195057157522247360,245300141642486641,0,13487,-607628393470471,-580643179475454
+signed 52: -1298657077966675,-4065355925989985798,-4066654583067952473,4064057268912019123,1136007313742779890,0,3130,-1298657077966675,-559271954293048
+signed 53: -2569514058924772,1841492845356505789,1838923331297581017,-1844062359415430561,6068344375485822380,0,-716,-2569514058924772,1720779166369037
+signed 54: -5148294816852404,-9162055424674236611,-9167203719491089015,9156907129857384207,-6087205165210098660,0,1779,-5148294816852404,-3238945493809895
+signed 55: -10293500734037188,8762386464941522003,8752092964207484815,-8772679965675559191,8399093139116719220,0,-851,-10293500734037188,2617340275875015
+signed 56: 20588031101296916,7227264643807960523,7247852674909257439,-7206676612706663607,-3352533841896882468,0,351,20588031101296916,865727252743007
+signed 57: -54901073059050929,-66351167506463323,-121252240565514252,11450094447412394,1896642381847523307,0,1,-54901073059050929,-11450094447412394
+signed 58: -77776434364220271,834890677930987460,757114243566767189,-912667112295207731,-3500275542106939900,0,-10,-77776434364220271,57126334288784750
+signed 59: -166228105979734405,-6667874979350953385,-6834103085330687790,6501646873371218980,-4513011972483376691,0,40,-166228105979734405,-18750740161577185
+signed 60: -328897799542370857,8487580243799899162,8158682444257528305,-8816478043342270019,-905439778191045674,0,-25,-328897799542370857,265135255240627737
+signed 61: -658981736557107698,3017604953772543563,2358623217215435865,-3676586690329651261,-378165734266082790,0,-4,-658981736557107698,381678007544112771
+signed 62: -1317568093956760068,-2041941969204984387,-3359510063161744455,724373875248224319,-7186442770938425588,0,1,-1317568093956760068,-724373875248224319
+signed 63: 2635267980966005246,7574178278953946467,-8237297813789599903,-4938910297987941221,1110862422097806138,0,2,2635267980966005246,2303642317021935975
diff --git a/tests/runner.py b/tests/runner.py
index 3fbe113b..1bd8a165 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -830,6 +830,37 @@ m_divisor is 1091269979
'''
self.do_run(src, 'testu64a is 14746250828952703000\n')
+ def test_i64_precise(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+ Settings.PRECISE_I64_MATH = 1
+
+ src = r'''
+ #include <inttypes.h>
+ #include <stdio.h>
+
+ int main() {
+ /*uint64_t x = 0, y = 0;
+ for (int i = 0; i < 64; i++) {
+ x += 1ULL << i;
+ y += x;
+ x /= 3;
+ y *= 5;
+ printf("unsigned %d: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", i, x, y, x+y, x-y, x*y, y ? x/y : 0, x ? y/x : 0, y ? x%y : 0, x ? y%x : 0);
+return 0;
+ }*/
+ int64_t x2 = 0, y2 = 0;
+ for (int i = 0; i < 64; i++) {
+ x2 += 1LL << i;
+ y2 += x2;
+ x2 /= 3 * (i % 7 ? -1 : 1);
+ y2 *= 5 * (i % 2 ? -1 : 1);
+ printf("signed %d: %lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld\n", i, x2, y2, x2+y2, x2-y2, x2*y2, y2 ? x2/y2 : 0, x2 ? y2/x2 : 0, y2 ? x2%y2 : 0, x2 ? y2%x2 : 0);
+ }
+ return 0;
+ }
+ '''
+ self.do_run(src, open(path_from_root('tests', 'i64_precise.txt')).read())
+
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
@@ -5963,6 +5994,7 @@ class %s(T):
Settings.CATCH_EXIT_CODE = 0
Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2)
Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0
+ Settings.PRECISE_I64_MATH = 0
Building.pick_llvm_opts(3)