aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js56
-rw-r--r--tools/js_optimizer.py1
-rw-r--r--tools/shared.py6
-rw-r--r--tools/test-js-optimizer-asm-last-output.js35
-rw-r--r--tools/test-js-optimizer-asm-last.js35
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js44
-rw-r--r--tools/test-js-optimizer-asm-pre.js46
-rw-r--r--tools/test-js-optimizer-asm-regs-output.js7
-rw-r--r--tools/test-js-optimizer-asm-regs.js9
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"]