diff options
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index ca9ad40a..6e0d6e32 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -103,6 +103,11 @@ function isNiceIdent(ident, loose) { } } +function isJSVar(ident) { + return /^\(?[$_]?[\w$_\d ]*\)+$/.test(ident); + +} + function isStructPointerType(type) { // This test is necessary for clang - in llvm-gcc, we // could check for %struct. The downside is that %1 can @@ -988,7 +993,8 @@ function getHeapOffset(offset, type, forceAsm) { if (shifts != 0) { return '(' + offset + '>>' + shifts + ')'; } else { - return offset; + // we need to guard against overflows here, HEAP[U]8 expects a guaranteed int + return isJSVar(offset) ? offset : '(' + offset + '|0)'; } } } @@ -1038,20 +1044,6 @@ function asmCoercion(value, type, signedness) { } } -var TWO_TWENTY = Math.pow(2, 20); - -function asmMultiplyI32(a, b) { - // special-case: there is no integer multiply in asm, because there is no true integer - // multiply in JS. While we wait for Math.imul, do double multiply - if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY)) { - return '(((' + a + ')*(' + b + '))&-1)'; // small enough to emit directly as a multiply - } - if (USE_MATH_IMUL) { - return 'Math.imul(' + a + ',' + b + ')'; - } - return '(~~(+((' + a + ')|0) * +((' + b + ')|0)))'; -} - function asmFloatToInt(x) { return '(~~(' + x + '))'; } @@ -1145,8 +1137,8 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa } } -function makeGetValueAsm(ptr, pos, type) { - return makeGetValue(ptr, pos, type, null, null, null, null, null, true); +function makeGetValueAsm(ptr, pos, type, unsigned) { + return makeGetValue(ptr, pos, type, null, unsigned, null, null, null, true); } function indexizeFunctions(value, type) { @@ -1364,9 +1356,11 @@ function makeHEAPView(which, start, end) { var PLUS_MUL = set('+', '*'); var MUL_DIV = set('*', '/'); var PLUS_MINUS = set('+', '-'); +var TWO_TWENTY = Math.pow(2, 20); // Given two values and an operation, returns the result of that operation. // Tries to do as much as possible at compile time. +// Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul function getFastValue(a, op, b, type) { a = a.toString(); b = b.toString(); @@ -1402,8 +1396,14 @@ function getFastValue(a, op, b, type) { return '(' + a + '<<' + shifts + ')'; } } - if (ASM_JS && !(type in Runtime.FLOAT_TYPES)) { - return asmMultiplyI32(a, b); // unoptimized multiply, do it using asm.js's special multiply operation + if (!(type in Runtime.FLOAT_TYPES)) { + // if guaranteed small enough to not overflow into a double, do a normal multiply + var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes + // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there + if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) { + return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this + } + return 'Math.imul(' + a + ',' + b + ')'; } } else { if (a == '0') { @@ -1548,7 +1548,7 @@ function makePointer(slab, pos, allocator, type, ptr) { var ret = ''; var index = 0; while (index < array.length) { - ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')' : ''); + ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')\n' : ''); index += chunkSize; } return ret; @@ -2130,14 +2130,7 @@ function processMathop(item) { case 'add': return handleOverflow(getFastValue(idents[0], '+', idents[1], item.type), bits); case 'sub': return handleOverflow(getFastValue(idents[0], '-', idents[1], item.type), bits); case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, op[0] === 's'); - case 'mul': { - if (bits == 32 && PRECISE_I32_MUL) { - Types.preciseI64MathUsed = true; - return '(i64Math' + (ASM_JS ? '_' : '.') + 'multiply(' + asmCoercion(idents[0], 'i32') + ',0,' + asmCoercion(idents[1], 'i32') + ',0),' + makeGetValue('tempDoublePtr', 0, 'i32') + ')'; - } else { - return '((' +getFastValue(idents[0], '*', idents[1], item.type) + ')&-1)'; // force a non-eliminatable coercion here, to prevent a double result from leaking - } - } + case 'mul': return getFastValue(idents[0], '*', idents[1], item.type); // overflow handling is already done in getFastValue for '*' case 'urem': case 'srem': return getFastValue(idents[0], '%', idents[1], item.type); case 'or': { if (bits > 32) { |