aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
parent4971364806bea54262ea5169e2af6c6222983964 (diff)
re-enable support for non-fixed i64 bitshifts
Diffstat (limited to 'src')
-rw-r--r--src/parseTools.js37
-rw-r--r--src/runtime.js35
2 files changed, 60 insertions, 12 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;