aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-05-25 07:16:26 -0700
committerAlon Zakai <alonzakai@gmail.com>2011-05-25 07:16:26 -0700
commitf0b0519c989c4b3a418857ac2d54c09c36966b76 (patch)
tree1e96dd016a63566a625ab1424673b5524bc409fc
parenta33bd79873b6872c7fab3fa4992ef9749f2c0aa5 (diff)
64-bit bitops
-rw-r--r--src/library.js2
-rw-r--r--src/parseTools.js27
-rw-r--r--src/runtime.js16
-rw-r--r--tests/runner.py13
4 files changed, 54 insertions, 4 deletions
diff --git a/src/library.js b/src/library.js
index ff485bc3..471bbc96 100644
--- a/src/library.js
+++ b/src/library.js
@@ -113,7 +113,7 @@ var Library = {
}
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
}
- if (next == 'l'.charCodeAt(0)) {
+ if (next == 'l'.charCodeAt(0) || next == 'L'.charCodeAt(0)) {
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
}
diff --git a/src/parseTools.js b/src/parseTools.js
index bc83e4ea..03b88c0f 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -916,9 +916,30 @@ function processMathop(item) { with(item) {
case 'sdiv': case 'udiv': return makeRounding(ident1 + '/' + ident2, bits, op[0] === 's');
case 'mul': return handleOverflow(ident1 + ' * ' + ident2, bits);
case 'urem': case 'srem': return ident1 + ' % ' + ident2;
- case 'or': return ident1 + ' | ' + ident2; // TODO this forces into a 32-bit int - add overflow-style checks? also other bitops below us
- case 'and': return ident1 + ' & ' + ident2;
- case 'xor': return ident1 + ' ^ ' + ident2;
+ case 'or': {
+ if (bits > 32) {
+ assert(bits === 64, 'Too many bits for or: ' + bits);
+ dprint('Warning: 64 bit OR - precision limit may be hit');
+ return 'Runtime.or64(' + ident1 + ', ' + ident2 + ')';
+ }
+ return ident1 + ' | ' + ident2;
+ }
+ case 'and': {
+ if (bits > 32) {
+ assert(bits === 64, 'Too many bits for and: ' + bits);
+ dprint('Warning: 64 bit AND - precision limit may be hit');
+ return 'Runtime.and64(' + ident1 + ', ' + ident2 + ')';
+ }
+ return ident1 + ' & ' + ident2;
+ }
+ case 'xor': {
+ if (bits > 32) {
+ assert(bits === 64, 'Too many bits for xor: ' + bits);
+ dprint('Warning: 64 bit XOR - precision limit may be hit');
+ return 'Runtime.xor64(' + ident1 + ', ' + ident2 + ')';
+ }
+ return ident1 + ' ^ ' + ident2;
+ }
case 'shl': {
// Note: Increases in size may reach the 32-bit limit... where our sign can flip. But this may be expected by the code...
/*
diff --git a/src/runtime.js b/src/runtime.js
index b0378e08..1aefc135 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -85,6 +85,22 @@ Runtime = {
INT_TYPES: set('i1', 'i8', 'i16', 'i32', 'i64'),
FLOAT_TYPES: set('float', 'double'),
+ or64: function(x, y) {
+ var l = (x | 0) | (y | 0);
+ var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ and64: function(x, y) {
+ var l = (x | 0) & (y | 0);
+ var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ xor64: function(x, y) {
+ var l = (x | 0) ^ (y | 0);
+ var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+
getNativeFieldSize: getNativeFieldSize,
dedup: dedup,
diff --git a/tests/runner.py b/tests/runner.py
index c0814c52..4fb8e2d7 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -422,6 +422,19 @@ if 'benchmark' not in sys.argv:
global CORRECT_OVERFLOWS; CORRECT_OVERFLOWS = 0 # We should not need overflow correction to get this right
self.do_test(src, output, force_c=True)
+ def test_bigint(self):
+ src = '''
+ #include <stdio.h>
+ int main()
+ {
+ long long x = 0x0000def123450789ULL; // any bigger than this, and we
+ long long y = 0x00020ef123456089ULL; // start to run into the double precision limit!
+ printf("*%Ld,%Ld,%Ld,%Ld,%Ld*\\n", x, y, x | y, x & y, x ^ y, x >> 2, y << 2);
+ return 0;
+ }
+ '''
+ self.do_test(src, '*245127260211081,579378795077769,808077213656969,16428841631881,791648372025088*')
+
def test_unsigned(self):
global CORRECT_SIGNS; CORRECT_SIGNS = 1 # We test for exactly this sort of thing here
src = '''