aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-02-01 16:54:44 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-02-01 16:54:44 -0800
commitf42fd56f4d3451a9ef0cb83248258749e33d22e3 (patch)
tree99b246e4ee893dcd0c835b9744fe498fe231ebda
parent4971364806bea54262ea5169e2af6c6222983964 (diff)
re-enable support for non-fixed i64 bitshifts
-rw-r--r--src/parseTools.js37
-rw-r--r--src/runtime.js35
-rwxr-xr-xtests/runner.py18
3 files changed, 77 insertions, 13 deletions
diff --git a/src/parseTools.js b/src/parseTools.js
index a53ff1c0..815d1a1b 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1616,7 +1616,9 @@ function processMathop(item) {
case 'shl':
case 'ashr':
case 'lshr': {
- assert(isNumber(ident2));
+ if (!isNumber(ident2)) {
+ return 'Runtime.bitshift64(' + ident1 + ',"' + op + '",' + stripCorrections(ident2) + '[0]|0)';
+ }
bits = parseInt(ident2);
var ander = Math.pow(2, bits)-1;
if (bits < 32) {
@@ -1892,17 +1894,28 @@ function finalizeBlockAddress(param) {
function stripCorrections(param) {
var m;
- if (m = /^\((.*)\)$/.exec(param)) {
- param = m[1];
- }
- if (m = /^\((\w+)\)&\d+$/.exec(param)) {
- param = m[1];
- }
- if (m = /^\((\w+)\)\|0$/.exec(param)) {
- param = m[1];
- }
- if (m = /CHECK_OVERFLOW\(([^,)]*),.*/.exec(param)) {
- param = m[1];
+ while (true) {
+ if (m = /^\((.*)\)$/.exec(param)) {
+ param = m[1];
+ continue;
+ }
+ if (m = /^\(([$_\w]+)\)&\d+$/.exec(param)) {
+ param = m[1];
+ continue;
+ }
+ if (m = /^\(([$_\w()]+)\)\|0$/.exec(param)) {
+ param = m[1];
+ continue;
+ }
+ if (m = /^\(([$_\w()]+)\)\>>>0$/.exec(param)) {
+ param = m[1];
+ continue;
+ }
+ if (m = /CHECK_OVERFLOW\(([^,)]*),.*/.exec(param)) {
+ param = m[1];
+ continue;
+ }
+ break;
}
return param;
}
diff --git a/src/runtime.js b/src/runtime.js
index 8e5238da..39aed12c 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -118,6 +118,41 @@ var Runtime = {
INT_TYPES: set('i1', 'i8', 'i16', 'i32', 'i64'),
FLOAT_TYPES: set('float', 'double'),
+ // Mirrors processMathop's treatment of constants (which we optimize directly)
+ bitshift64: function(value, op, bits) {
+ var ander = Math.pow(2, bits)-1;
+ if (bits < 32) {
+ switch (op) {
+ case 'shl':
+ return [value[0] << bits, (value[1] << bits) | ((value[0]&(ander << (32 - bits))) >>> (32 - bits))];
+ case 'ashr':
+ return [(((value[0] >>> bits ) | ((value[1]&ander) << (32 - bits))) >> 0) >>> 0, (value[1] >> bits) >>> 0];
+ case 'lshr':
+ return [((value[0] >>> bits) | ((value[1]&ander) << (32 - bits))) >>> 0, value[1] >>> bits];
+ }
+ } else if (bits == 32) {
+ switch (op) {
+ case 'shl':
+ return [0, value[0]];
+ case 'ashr':
+ return [value[1], (value[1]|0) < 0 ? ander : 0];
+ case 'lshr':
+ return [value[1], 0];
+ }
+ } else { // bits > 32
+ switch (op) {
+ case 'shl':
+ return [0, value[0] << (bits - 32)];
+ case 'ashr':
+ return [(value[1] >> (bits - 32)) >>> 0, (value[1]|0) < 0 ? ander : 0];
+ case 'lshr':
+ return [value[1] >>> (bits - 32) , 0];
+ }
+ }
+ abort('unknown bitshift64 op: ' + [value, op, bits]);
+ },
+
+ // Imprecise bitops utilities
or64: function(x, y) {
var l = (x | 0) | (y | 0);
var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
diff --git a/tests/runner.py b/tests/runner.py
index 2a0307e9..55d0bd0b 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -496,7 +496,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
{ 122, 25769803837 },
};
- int main()
+ int main(int argc, char **argv)
{
int64_t x1 = 0x1234def123450789ULL;
int64_t x2 = 0x1234def123450788ULL;
@@ -533,6 +533,20 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
printf("*%Ld,%Ld,%Ld,%Ld*\n", ua, ub, uc, ud);
}
+ // Nonconstant bitshifts
+ {
+ int64_t a = -1;
+ int64_t b = a >> (29 - argc + 1);
+ int64_t c = a >> (32 - argc + 1);
+ int64_t d = a >> (34 - argc + 1);
+ printf("*%Ld,%Ld,%Ld,%Ld*\n", a, b, c, d);
+ uint64_t ua = -1;
+ int64_t ub = ua >> (29 - argc + 1);
+ int64_t uc = ua >> (32 - argc + 1);
+ int64_t ud = ua >> (34 - argc + 1);
+ printf("*%Ld,%Ld,%Ld,%Ld*\n", ua, ub, uc, ud);
+ }
+
// Math mixtures with doubles
{
uint64_t a = 5;
@@ -565,6 +579,8 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
'*122,25769803837*\n' +
'*-1,-1,-1,-1*\n' +
'*-1,34359738367,4294967295,1073741823*\n' +
+ '*-1,-1,-1,-1*\n' +
+ '*-1,34359738367,4294967295,1073741823*\n' +
'*prod:34*')
Settings.CORRECT_SIGNS = 1