diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-04-01 12:33:37 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-04-01 12:33:37 -0700 |
commit | b215efb7c115aa0c62daf081dc9098042fe2ffda (patch) | |
tree | 0d0a55e3908ca1a78d1cc30d2c88cc331e46d7f4 | |
parent | e1a210f81387d60b3bd75954e76f243bce33068b (diff) |
support for precise i64 signed math
-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 | ||||
-rw-r--r-- | tests/i64_precise.txt | 64 | ||||
-rwxr-xr-x | tests/runner.py | 32 |
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) |