diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 56 | ||||
-rw-r--r-- | tools/js_optimizer.py | 1 | ||||
-rw-r--r-- | tools/shared.py | 6 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last-output.js | 35 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last.js | 35 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 44 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 46 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-output.js | 7 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs.js | 9 |
9 files changed, 223 insertions, 16 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d26d902f..12754bb2 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -428,12 +428,13 @@ function simplifyExpressionsPre(ast) { if (stack[i] == 1) { // we will replace ourselves with the non-zero side. Recursively process that node. var result = jsonCompare(node[2], ZERO) ? node[3] : node[2], other; - // Great, we can eliminate - rerun = true; - while (other = process(result, result[0], stack)) { - result = other; + // replace node in-place + node.length = result.length; + for (var j = 0; j < result.length; j++) { + node[j] = result[j]; } - return result; + rerun = true; + return process(result, result[0], stack); } else if (stack[i] == -1) { break; // Too bad, we can't } else if (asm) { @@ -1415,7 +1416,7 @@ function registerize(ast) { // We also mark local variables - i.e., having a var definition var localVars = {}; var hasSwitch = false; // we cannot optimize variables if there is a switch - var hasReturnValue = false; + var returnType = null; // for asm traverse(fun, function(node, type) { if (type == 'var') { node[1].forEach(function(defined) { localVars[defined[0]] = 1 }); @@ -1428,7 +1429,7 @@ function registerize(ast) { } else if (type == 'switch') { hasSwitch = true; } else if (asm && type == 'return' && node[1]) { - hasReturnValue = true; + returnType = detectAsmCoercion(node[1]); } }); vacuum(fun); @@ -1607,11 +1608,13 @@ function registerize(ast) { denormalizeAsm(fun, finalAsmData); // Add a final return if one is missing. This is not strictly a register operation, but // this pass traverses the entire AST anyhow so adding it here is efficient. - if (hasReturnValue) { + if (returnType !== null) { var stats = getStatements(fun); var last = stats[stats.length-1]; if (last[0] != 'return') { - stats.push(['return', ['num', 0]]); + var returnValue = ['num', 0]; + if (returnType == ASM_DOUBLE) returnValue = ['unary-prefix', '+', returnValue]; + stats.push(['return', returnValue]); } } } @@ -2148,6 +2151,32 @@ function eliminateMemSafe(ast) { eliminate(ast, true); } +// Change +5 to DOT$ZERO(5). We then textually change 5 to 5.0 (uglify's ast cannot differentiate between 5 and 5.0 directly) +function prepDotZero(ast) { + traverse(ast, function(node, type) { + if (type == 'unary-prefix' && node[1] == '+') { + if (node[2][0] == 'num') { + return ['call', ['name', 'DOT$ZERO'], [node[2]]]; + } else if (node[2][0] == 'unary-prefix' && node[2][1] == '-' && node[2][2][0] == 'num') { + node[2][2][1] = -node[2][2][1]; + return ['call', ['name', 'DOT$ZERO'], [node[2][2]]]; + } + } + }); +} +function fixDotZero(js) { + return js.replace(/DOT\$ZERO\(((0x)?[-+]?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)\)/g, function(m, num) { + if (num.substr(0, 2) == '0x') { + if (num[2] == '-') num = '-0x' + num.substr(3); // uglify generates 0x-8000 for some reason + return eval(num) + '.0'; + } + if (num.indexOf('.') >= 0) return num; + var e = num.indexOf('e'); + if (e < 0) return num + '.0'; + return num.substr(0, e) + '.0' + num.substr(e); + }); +} + // Passes table var compress = false, printMetadata = true, asm = false, last = false; @@ -2185,15 +2214,18 @@ if (metadata) setGeneratedFunctions(metadata); arguments_.slice(1).forEach(function(arg) { passes[arg](ast); }); +if (asm && last) { + prepDotZero(ast); +} var js = astToSrc(ast, compress), old; +if (asm && last) { + js = fixDotZero(js); +} // remove unneeded newlines+spaces, and print do { old = js; js = js.replace(/\n *\n/g, '\n'); - if (asm && last) { - js = js.replace(/ = \+0([,;])/g, function(m, end) { return ' = 0.0' + end }); // asm requires 0.0 in var definitions, not +0 - } } while (js != old); print(js); print('\n'); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b72a2084..f2e610d0 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -18,6 +18,7 @@ DEBUG = os.environ.get('EMCC_DEBUG') def run_on_chunk(command): filename = command[2] # XXX hackish + #print >> sys.stderr, 'running js optimizer command', ' '.join(command), '""""', open(filename).read() output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0] assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output filename = temp_files.get(os.path.basename(filename) + '.jo.js').name diff --git a/tools/shared.py b/tools/shared.py index a78db8e0..f94bb263 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -344,10 +344,12 @@ try: except: COMPILER_OPTS = [] # Force a simple, standard target as much as possible: target 32-bit linux, and disable various flags that hint at other platforms +# -fno-ms-compatibility is passed, since on Windows, Clang enables a 'MS compatibility mode' by default, that disables char16_t and char32_t +# to be MSVC header -compatible. This would cause build errors in libcxx file __config. COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-Ui386', '-Ux86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__', '-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87', '-DEMSCRIPTEN', '-U__STRICT_ANSI__', '-U__CYGWIN__', - '-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno'] - + '-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno', + '-fno-ms-compatibility'] USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK') diff --git a/tools/test-js-optimizer-asm-last-output.js b/tools/test-js-optimizer-asm-last-output.js new file mode 100644 index 00000000..c10cc6b0 --- /dev/null +++ b/tools/test-js-optimizer-asm-last-output.js @@ -0,0 +1,35 @@ +function finall(x) { + x = +x; + var a = 5.0; + a = +x; + a = 17; + a = 44.0; + a = 44.0; + a = 44.9; + a = 1278.0e3; + a = 12.0e10; + a = -x; + a = -17; + a = -44; + a = -44; + a = -44.9; + a = -1278e3; + a = -12e10; + a = +-x; + a = -17.0; + a = -44.0; + a = -44.0; + a = -44.9; + a = -1278.0e3; + a = -12.0e10; + a = 9223372036854776000.0; + a = -9223372036854776000.0; + a = -9223372036854776000.0; + a = -0x8000000000000000; + a = 999999984306749400.0; + a = -999999984306749400.0; + a = -999999984306749400.0; + a = -0xde0b6b000000000; + return 12.0e10; +} + diff --git a/tools/test-js-optimizer-asm-last.js b/tools/test-js-optimizer-asm-last.js new file mode 100644 index 00000000..6e97b687 --- /dev/null +++ b/tools/test-js-optimizer-asm-last.js @@ -0,0 +1,35 @@ +function finall(x) { + x = +x; + var a = +5; + a = +x; + a = 17; + a = +44; + a = +44.0; + a = +44.9; + a = +12.78e5; + a = +12e10; + a = -x; + a = -17; + a = -44; + a = -44.0; + a = -44.9; + a = -12.78e5; + a = -12e10; + a = +-x; + a = +-17; + a = +-44; + a = +-44.0; + a = +-44.9; + a = +-12.78e5; + a = +-12e10; + a = +0x8000000000000000; + a = +-0x8000000000000000; + a = -+0x8000000000000000; + a = -0x8000000000000000; + a = +0xde0b6b000000000; + a = +-0xde0b6b000000000; + a = -+0xde0b6b000000000; + a = -0xde0b6b000000000; + return +12e10; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["finall"] diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index afd43893..84c95360 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -5,4 +5,48 @@ function a() { f(351); f(8); } +function b($this, $__n) { + $this = $this | 0; + $__n = $__n | 0; + var $4 = 0, $5 = 0, $10 = 0, $13 = 0, $14 = 0, $15 = 0, $23 = 0, $30 = 0, $38 = 0, $40 = 0; + if (($__n | 0) == 0) { + return; + } + $4 = $this; + $5 = HEAP8[$4 & 16777215] | 0; + if (($5 & 1) << 24 >> 24 == 0) { + $14 = 10; + $13 = $5; + } else { + $10 = HEAP32[($this & 16777215) >> 2] | 0; + $14 = ($10 & -2) - 1 | 0; + $13 = $10 & 255; + } + $15 = $13 & 255; + if (($15 & 1 | 0) == 0) { + $23 = $15 >>> 1; + } else { + $23 = HEAP32[($this + 4 & 16777215) >> 2] | 0; + } + if (($14 - $23 | 0) >>> 0 < $__n >>> 0) { + __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEjjjjjj($this, $14, ($__n - $14 | 0) + $23 | 0, $23, $23); + $30 = HEAP8[$4 & 16777215] | 0; + } else { + $30 = $13; + } + if (($30 & 1) << 24 >> 24 == 0) { + $38 = $this + 1 | 0; + } else { + $38 = HEAP32[($this + 8 & 16777215) >> 2] | 0; + } + _memset($38 + $23 | 0, 0, $__n | 0, 1, 1213141516); + $40 = $23 + $__n | 0; + if ((HEAP8[$4 & 16777215] & 1) << 24 >> 24 == 0) { + HEAP8[$4 & 16777215] = $40 << 1 & 255; + } else { + HEAP32[($this + 4 & 16777215) >> 2] = $40; + } + HEAP8[$38 + $40 & 16777215] = 0; + return; +} diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 6c9e64c1..3042ef66 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -5,4 +5,48 @@ function a() { f(347 | 12); f(347 & 12); } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a"] +function b($this, $__n) { + $this = $this | 0; + $__n = $__n | 0; + var $4 = 0, $5 = 0, $10 = 0, $13 = 0, $14 = 0, $15 = 0, $23 = 0, $30 = 0, $38 = 0, $40 = 0; + if (($__n | 0) == 0) { + return; + } + $4 = $this; + $5 = HEAP8[$4 & 16777215] | 0; + if (($5 & 1) << 24 >> 24 == 0) { + $14 = 10; + $13 = $5; + } else { + $10 = HEAP32[(($this | 0) & 16777215) >> 2] | 0; + $14 = ($10 & -2) - 1 | 0; + $13 = $10 & 255; + } + $15 = $13 & 255; + if (($15 & 1 | 0) == 0) { + $23 = $15 >>> 1; + } else { + $23 = HEAP32[(($this + 4 | 0) & 16777215) >> 2] | 0; + } + if (($14 - $23 | 0) >>> 0 < $__n >>> 0) { + __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEjjjjjj($this, $14, ($__n - $14 | 0) + $23 | 0, $23, $23); + $30 = HEAP8[$4 & 16777215] | 0; + } else { + $30 = $13; + } + if (($30 & 1) << 24 >> 24 == 0) { + $38 = $this + 1 | 0; + } else { + $38 = HEAP32[(($this + 8 | 0) & 16777215) >> 2] | 0; + } + _memset($38 + $23 | 0 | 0 | 0, 0 | 0 | 0, $__n | 0 | 0, 1 | 0 | 0, 1213141516); + $40 = $23 + $__n | 0; + if (((HEAP8[$4 & 16777215] | 0) & 1) << 24 >> 24 == 0) { + HEAP8[$4 & 16777215] = $40 << 1 & 255; + } else { + HEAP32[(($this + 4 | 0) & 16777215) >> 2] = $40; + } + HEAP8[($38 + $40 | 0) & 16777215] = 0; + return; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b"] diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js index 26d1d134..99bccd2e 100644 --- a/tools/test-js-optimizer-asm-regs-output.js +++ b/tools/test-js-optimizer-asm-regs-output.js @@ -31,4 +31,11 @@ function ret2t() { return; } } +function retf() { + if (f()) { + g(); + return +h(); + } + return +0; +} diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js index 9192f32e..0afced29 100644 --- a/tools/test-js-optimizer-asm-regs.js +++ b/tools/test-js-optimizer-asm-regs.js @@ -34,5 +34,12 @@ function ret2t() { } // missing final return, but no need } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t"] +function retf() { + if (f()) { + g(); + return +h(); + } + // missing final return, need it as a float +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t", "retf"] |