diff options
-rw-r--r-- | src/parseTools.js | 15 | ||||
-rw-r--r-- | src/preamble.js | 3 | ||||
-rw-r--r-- | tests/runner.py | 21 |
3 files changed, 35 insertions, 4 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index da4c4352..bdb5c533 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -540,10 +540,15 @@ function makeI64(low, high) { } } -// Splits a number (an integer in a double, possibly > 32 bits) into an I64_MODE 1 i64 value +// Splits a number (an integer in a double, possibly > 32 bits) into an I64_MODE 1 i64 value. +// Will suffer from rounding. margeI64 does the opposite. function splitI64(value) { assert(I64_MODE == 1); - return makeI64(value + '|0', 'Math.floor(' + value + '/4294967296)'); + return '(tempInt=' + value + ',' + makeI64('tempInt|0', 'Math.floor(tempInt/4294967296)') + ')'; +} +function mergeI64(value) { + assert(I64_MODE == 1); + return '(tempI64=' + value + ',tempI64[0]+tempI64[1]*4294967296)'; } function makeCopyI64(value) { @@ -1469,6 +1474,12 @@ function processMathop(item) { with(item) { } case 'select': return ident1 + ' ? ' + makeCopyI64(ident2) + ' : ' + makeCopyI64(ident3); case 'ptrtoint': case 'inttoptr': throw 'Pointers cannot be 64-bit!'; + // Dangerous, rounded operations. TODO: Fully emulate + case 'add': return handleOverflow(splitI64(mergeI64(ident1) + '+' + mergeI64(ident2)), bits); + case 'sub': return handleOverflow(splitI64(mergeI64(ident1) + '-' + mergeI64(ident2)), bits); + case 'sdiv': case 'udiv': return splitI64(makeRounding(mergeI64(ident1) + '/' + mergeI64(ident2), bits, op[0] === 's')); + case 'mul': return handleOverflow(splitI64(mergeI64(ident1) + '*' + mergeI64(ident2)), bits); + case 'urem': return splitI64(mergeI64(ident1) + '%' + mergeI64(ident2)); default: throw 'Unsupported i64 mode 1 op: ' + item.op; } } diff --git a/src/preamble.js b/src/preamble.js index 51d100e1..45513942 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -382,6 +382,9 @@ var ABORT = false; var undef = 0; var tempValue, tempInt, tempBigInt; +#if I64_MODE == 1 +var tempI64, tempI64b; +#endif function abort(text) { print(text + ':\n' + (new Error).stack); diff --git a/tests/runner.py b/tests/runner.py index 0efea69b..de70f707 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -397,6 +397,7 @@ if 'benchmark' not in str(sys.argv): Settings.I64_MODE = 1 src = r''' + #include <time.h> #include <stdio.h> #include <stdint.h> @@ -414,6 +415,15 @@ if 'benchmark' not in str(sys.argv): t |= 12; } + int truthy() { + int x = time(0); + while (x > 10) { + x |= 7; + x /= 2; + } + return x < 3; + } + int main() { int64_t x1 = 0x1234def123450789ULL; @@ -434,13 +444,20 @@ if 'benchmark' not in str(sys.argv): modifier2(t); printf("*%Ld*\n", t); - // + // Basic (rounded, for now) math + int64_t a = 0x1234def123450789ULL; + a--; if (truthy()) a--; // confuse optimizer + int64_t b = 0x1234000000450789ULL; + b++; if (truthy()) b--; // confuse optimizer + printf("*%Ld,%Ld,%Ld*\n", a+b, a-b, a*3, a/5); + return 0; } ''' self.do_run(src, '*1311918518731868200\n0,0,0,1,1\n1,0,1,0,1*\n*245127260211081*\n*245127260209443*\n' + '*18446744073709552000*\n*576460752303423500*\n' + - 'm1: 127\n*123*\n*127*\n') + 'm1: 127\n*123*\n*127*\n' + + '*2623591910208049000,245127255687168,3935755556195604500*\n') def test_unsigned(self): |