diff options
-rw-r--r-- | cmake/Platform/Emscripten.cmake | 17 | ||||
-rwxr-xr-x | emscripten.py | 10 | ||||
-rw-r--r-- | src/analyzer.js | 9 | ||||
-rw-r--r-- | src/jsifier.js | 8 | ||||
-rw-r--r-- | src/parseTools.js | 20 | ||||
-rw-r--r-- | src/runtime.js | 21 | ||||
-rw-r--r-- | tools/js-optimizer.js | 8 | ||||
-rw-r--r-- | tools/shared.py | 6 |
8 files changed, 73 insertions, 26 deletions
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake index 532e5d99..4b9c6572 100644 --- a/cmake/Platform/Emscripten.cmake +++ b/cmake/Platform/Emscripten.cmake @@ -42,3 +42,20 @@ set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} -o <TARGET> -emit-llvm <LINK_FLA # Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten. # There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1". set(EMSCRIPTEN 1) + +set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE") +set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO") +set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELEASE") +set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_MINSIZEREL") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELWITHDEBINFO") + +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELEASE") +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_MINSIZEREL") +set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO") +set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELEASE") +set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL") +set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO") +set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELEASE") +set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL") +set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO") diff --git a/emscripten.py b/emscripten.py index 26fe0659..2662e40a 100755 --- a/emscripten.py +++ b/emscripten.py @@ -311,9 +311,9 @@ def emscript(infile, settings, outfile, libraries=[]): maths += ['Math.imul'] asm_setup = '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in maths]) fundamentals = ['buffer', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array'] - basic_funcs = ['abort', 'assert'] + [m.replace('.', '_') for m in maths] + basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in maths] basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT'] - basic_float_vars = ['NaN'] + basic_float_vars = ['NaN', 'Infinity'] if forwarded_json['Types']['preciseI64MathUsed']: basic_funcs += ['i64Math_' + op for op in ['add', 'subtract', 'multiply', 'divide', 'modulo']] asm_setup += ''' @@ -369,6 +369,12 @@ var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) }; # finalize funcs_js = ''' %s +function asmPrintInt(x) { + Module.print('int ' + x);// + ' ' + new Error().stack); +} +function asmPrintFloat(x) { + Module.print('float ' + x);// + ' ' + new Error().stack); +} var asmPre = (function(env, buffer) { 'use asm'; var HEAP8 = new env.Int8Array(buffer); diff --git a/src/analyzer.js b/src/analyzer.js index d91bbe73..229bda9f 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -654,9 +654,12 @@ function analyzer(data, sidePass) { // We can't statically legalize this, do the operation at runtime TODO: optimize assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits'); value.intertype = 'value'; - value.ident = 'Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' + sourceElements[0].ident + ', ' + - sourceElements[1].ident + ',"' + value.op + '",' + value.params[1].ident + '$0);' + - 'var ' + value.assignTo + '$0 = ' + makeGetTempDouble(0, 'i32') + ', ' + value.assignTo + '$1 = ' + makeGetTempDouble(1, 'i32') + ';'; + value.ident = 'Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' + + asmCoercion(sourceElements[0].ident, 'i32') + ',' + + asmCoercion(sourceElements[1].ident, 'i32') + ',' + + Runtime['BITSHIFT64_' + value.op.toUpperCase()] + ',' + + asmCoercion(value.params[1].ident + '$0', 'i32') + ');' + + 'var ' + value.assignTo + '$0 = ' + makeGetTempDouble(0, 'i32') + ', ' + value.assignTo + '$1 = ' + makeGetTempDouble(1, 'i32') + ';'; value.assignTo = null; i++; continue; diff --git a/src/jsifier.js b/src/jsifier.js index 83ddc62e..5fbea5ba 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1313,8 +1313,12 @@ function JSify(data, functionsOnly, givenFunctions) { }); args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) }); - if (ASM_JS && shortident in Functions.libraryFunctions) { - args = args.map(function(arg, i) { return asmCoercion(arg, argsTypes[i]) }); + if (ASM_JS) { + if (shortident in Functions.libraryFunctions) { + args = args.map(function(arg, i) { return asmCoercion(arg, argsTypes[i]) }); + } else { + args = args.map(function(arg, i) { return asmEnsureFloat(arg, argsTypes[i]) }); + } } varargs = varargs.map(function(vararg, i) { diff --git a/src/parseTools.js b/src/parseTools.js index 268d0e24..3ff5e710 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1019,14 +1019,18 @@ function asmCoercion(value, type, signedness) { if (type == 'void') { return value; } else if (type in Runtime.FLOAT_TYPES) { - if (signedness) { - if (signedness == 'u') { - value = '(' + value + ')>>>0'; - } else { - value = '(' + value + ')|0'; + if (isNumber(value)) { + return asmEnsureFloat(value, type); + } else { + if (signedness) { + if (signedness == 'u') { + value = '(' + value + ')>>>0'; + } else { + value = '(' + value + ')|0'; + } } + return '(+(' + value + '))'; } - return '(+(' + value + '))'; } else { return '((' + value + ')|0)'; } @@ -1887,7 +1891,7 @@ function processMathop(item) { function i64PreciseOp(type, lastArg) { Types.preciseI64MathUsed = true; return finish(['(i64Math' + (ASM_JS ? '_' : '.') + type + '(' + asmCoercion(low1, 'i32') + ',' + asmCoercion(high1, 'i32') + ',' + asmCoercion(low2, 'i32') + ',' + asmCoercion(high2, 'i32') + - (lastArg ? ',' + asmCoercion(lastArg, 'i32') : '') + '),' + makeGetValue('tempDoublePtr', 0, 'i32') + ')', makeGetValue('tempDoublePtr', Runtime.getNativeTypeSize('i32'), 'i32')]); + (lastArg ? ',' + asmCoercion(+lastArg, 'i32') : '') + '),' + makeGetValue('tempDoublePtr', 0, 'i32') + ')', makeGetValue('tempDoublePtr', Runtime.getNativeTypeSize('i32'), 'i32')]); } switch (op) { // basic integer ops @@ -1904,7 +1908,7 @@ function processMathop(item) { case 'ashr': case 'lshr': { if (!isNumber(idents[1])) { - return '(Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' + idents[0] + '[0], ' + idents[0] + '[1],"' + op + '",' + stripCorrections(idents[1]) + '[0]|0),' + + return '(Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' + idents[0] + '[0], ' + idents[0] + '[1],' + Runtime['BITSHIFT64_' + op.toUpperCase()] + ',' + stripCorrections(idents[1]) + '[0]|0),' + '[' + makeGetTempDouble(0, 'i32') + ',' + makeGetTempDouble(1, 'i32') + '])'; } bits = parseInt(idents[1]); diff --git a/src/runtime.js b/src/runtime.js index 9d5e5e1f..d1475bd4 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -123,42 +123,45 @@ var Runtime = { FLOAT_TYPES: set('float', 'double'), // Mirrors processMathop's treatment of constants (which we optimize directly) + BITSHIFT64_SHL: 0, + BITSHIFT64_ASHR: 1, + BITSHIFT64_LSHR: 2, bitshift64: function(low, high, op, bits) { var ret; var ander = Math.pow(2, bits)-1; if (bits < 32) { switch (op) { - case 'shl': + case Runtime.BITSHIFT64_SHL: ret = [low << bits, (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))]; break; - case 'ashr': + case Runtime.BITSHIFT64_ASHR: ret = [(((low >>> bits ) | ((high&ander) << (32 - bits))) >> 0) >>> 0, (high >> bits) >>> 0]; break; - case 'lshr': + case Runtime.BITSHIFT64_LSHR: ret = [((low >>> bits) | ((high&ander) << (32 - bits))) >>> 0, high >>> bits]; break; } } else if (bits == 32) { switch (op) { - case 'shl': + case Runtime.BITSHIFT64_SHL: ret = [0, low]; break; - case 'ashr': + case Runtime.BITSHIFT64_ASHR: ret = [high, (high|0) < 0 ? ander : 0]; break; - case 'lshr': + case Runtime.BITSHIFT64_LSHR: ret = [high, 0]; break; } } else { // bits > 32 switch (op) { - case 'shl': + case Runtime.BITSHIFT64_SHL: ret = [0, low << (bits - 32)]; break; - case 'ashr': + case Runtime.BITSHIFT64_ASHR: ret = [(high >> (bits - 32)) >>> 0, (high|0) < 0 ? ander : 0]; break; - case 'lshr': + case Runtime.BITSHIFT64_LSHR: ret = [high >>> (bits - 32) , 0]; break; } diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 49911bb9..d26d902f 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1322,6 +1322,14 @@ function normalizeAsm(func) { while (i < stats.length) { traverse(stats[i], function(node, type) { if (type == 'var') { + for (var j = 0; j < node[1].length; j++) { + var v = node[1][j]; + var name = v[0]; + var value = v[1]; + if (!(name in data.vars)) { + data.vars[name] = detectAsmCoercion(value); + } + } unVarify(node[1], node); } else if (type == 'dot') { if (node[1][0] == 'name' && node[1][1] == 'Math') { 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') |