From 84c58ecc4abb7af1c88cce1af3d86ffa106f22d2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 14 Apr 2013 16:17:56 -0700 Subject: [PATCH] use compiled compiler-rt code for i64 multiplication --- emscripten.py | 17 +- src/fastLong.js | 263 ++++++++++++++++++++++++++++++ src/jsifier.js | 24 ++- src/library.js | 8 +- src/long.js | 7 - src/modules.js | 2 +- src/parseTools.js | 9 +- system/lib/compiler-rt/readme.txt | 1 + 8 files changed, 304 insertions(+), 27 deletions(-) create mode 100644 src/fastLong.js diff --git a/emscripten.py b/emscripten.py index cec28faac..bae6d8cd0 100755 --- a/emscripten.py +++ b/emscripten.py @@ -347,14 +347,15 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, if settings.get('ASM_JS'): post_funcs, post_rest = post.split('// EMSCRIPTEN_END_FUNCS\n') post = post_rest - funcs_js += ['\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n'] # Move preAsms to their right place def move_preasm(m): contents = m.groups(0)[0] outfile.write(contents + '\n') return '' - post = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), post) + post_funcs = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), post_funcs) + + funcs_js += ['\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n'] simple = os.environ.get('EMCC_SIMPLE_ASM') class Counter: @@ -392,17 +393,15 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT'] basic_float_vars = ['NaN', 'Infinity'] if forwarded_json['Types']['preciseI64MathUsed']: - basic_funcs += ['i64Math_' + op for op in ['multiply', 'divide', 'modulo']] + basic_funcs += ['i64Math_' + op for op in ['divide', 'modulo']] asm_setup += ''' -var i64Math_multiply = function(a, b, c, d) { i64Math.multiply(a, b, c, d) }; var i64Math_divide = function(a, b, c, d, e) { i64Math.divide(a, b, c, d, e) }; var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) }; ''' - if forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i32') or \ - forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i32') or \ - forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i64') or \ - forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i64'): + if forwarded_json['Types']['preciseI64MathUsed'] or \ + forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i32') or \ + forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i32'): basic_vars += ['cttz_i8', 'ctlz_i8'] asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)] @@ -454,7 +453,7 @@ function invoke_%s(%s) { pass # If no named globals, only need externals global_vars = map(lambda g: g['name'], filter(lambda g: settings['NAMED_GLOBALS'] or g.get('external') or g.get('unIndexable'), forwarded_json['Variables']['globals'].values())) - global_funcs = ['_' + x for x in forwarded_json['Functions']['libraryFunctions'].keys()] + global_funcs = ['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2] def math_fix(g): return g if not g.startswith('Math_') else g.split('_')[1]; asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \ diff --git a/src/fastLong.js b/src/fastLong.js new file mode 100644 index 000000000..b4bdece00 --- /dev/null +++ b/src/fastLong.js @@ -0,0 +1,263 @@ +// ======== compiled code from system/lib/compiler-rt , see readme therein +function ___muldsi3($a, $b) { + $a = $a | 0; + $b = $b | 0; + var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0; + $1 = $a & 65535; + $2 = $b & 65535; + $3 = Math.imul($2, $1); + $6 = $a >>> 16; + $8 = ($3 >>> 16) + Math.imul($2, $6) | 0; + $11 = $b >>> 16; + $12 = Math.imul($11, $1); + return (tempRet0 = (($8 >>> 16) + Math.imul($11, $6) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0; +} +function ___divdi3($a$0, $a$1, $b$0, $b$1) { + $a$0 = $a$0 | 0; + $a$1 = $a$1 | 0; + $b$0 = $b$0 | 0; + $b$1 = $b$1 | 0; + var $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $7$0 = 0, $7$1 = 0, $8$0 = 0, $10$0 = 0; + $1$0 = $a$1 >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; + $1$1 = (($a$1 | 0) < 0 ? -1 : 0) >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; + $2$0 = $b$1 >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; + $2$1 = (($b$1 | 0) < 0 ? -1 : 0) >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; + $4$0 = _i64Subtract($1$0 ^ $a$0, $1$1 ^ $a$1, $1$0, $1$1); + $4$1 = tempRet0; + $6$0 = _i64Subtract($2$0 ^ $b$0, $2$1 ^ $b$1, $2$0, $2$1); + $7$0 = $2$0 ^ $1$0; + $7$1 = $2$1 ^ $1$1; + $8$0 = ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, 0) | 0; + $10$0 = _i64Subtract($8$0 ^ $7$0, tempRet0 ^ $7$1, $7$0, $7$1); + return (tempRet0 = tempRet0, $10$0) | 0; +} +function ___muldi3($a$0, $a$1, $b$0, $b$1) { + $a$0 = $a$0 | 0; + $a$1 = $a$1 | 0; + $b$0 = $b$0 | 0; + $b$1 = $b$1 | 0; + var $x_sroa_0_0_extract_trunc = 0, $y_sroa_0_0_extract_trunc = 0, $1$0 = 0, $1$1 = 0, $2 = 0; + $x_sroa_0_0_extract_trunc = $a$0; + $y_sroa_0_0_extract_trunc = $b$0; + $1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0; + $1$1 = tempRet0; + $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc); + return (tempRet0 = (Math.imul($b$1, $x_sroa_0_0_extract_trunc) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0; +} +function ___udivdi3($a$0, $a$1, $b$0, $b$1) { + $a$0 = $a$0 | 0; + $a$1 = $a$1 | 0; + $b$0 = $b$0 | 0; + $b$1 = $b$1 | 0; + var $1$0 = 0; + $1$0 = ___udivmoddi4($a$0, $a$1, $b$0, $b$1, 0) | 0; + return (tempRet0 = tempRet0, $1$0) | 0; +} +function ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) { + $a$0 = $a$0 | 0; + $a$1 = $a$1 | 0; + $b$0 = $b$0 | 0; + $b$1 = $b$1 | 0; + $rem = $rem | 0; + var $n_sroa_0_0_extract_trunc = 0, $n_sroa_1_4_extract_shift$0 = 0, $n_sroa_1_4_extract_trunc = 0, $d_sroa_0_0_extract_trunc = 0, $d_sroa_1_4_extract_shift$0 = 0, $d_sroa_1_4_extract_trunc = 0, $4 = 0, $17 = 0, $37 = 0, $49 = 0, $51 = 0, $57 = 0, $58 = 0, $66 = 0, $78 = 0, $86 = 0, $88 = 0, $89 = 0, $91 = 0, $92 = 0, $95 = 0, $105 = 0, $117 = 0, $119 = 0, $125 = 0, $126 = 0, $130 = 0, $q_sroa_1_1_ph = 0, $q_sroa_0_1_ph = 0, $r_sroa_1_1_ph = 0, $r_sroa_0_1_ph = 0, $sr_1_ph = 0, $d_sroa_0_0_insert_insert99$0 = 0, $d_sroa_0_0_insert_insert99$1 = 0, $137$0 = 0, $137$1 = 0, $carry_0203 = 0, $sr_1202 = 0, $r_sroa_0_1201 = 0, $r_sroa_1_1200 = 0, $q_sroa_0_1199 = 0, $q_sroa_1_1198 = 0, $147 = 0, $149 = 0, $r_sroa_0_0_insert_insert42$0 = 0, $r_sroa_0_0_insert_insert42$1 = 0, $150$1 = 0, $151$0 = 0, $152 = 0, $154$0 = 0, $r_sroa_0_0_extract_trunc = 0, $r_sroa_1_4_extract_trunc = 0, $155 = 0, $carry_0_lcssa$0 = 0, $carry_0_lcssa$1 = 0, $r_sroa_0_1_lcssa = 0, $r_sroa_1_1_lcssa = 0, $q_sroa_0_1_lcssa = 0, $q_sroa_1_1_lcssa = 0, $q_sroa_0_0_insert_ext75$0 = 0, $q_sroa_0_0_insert_ext75$1 = 0, $q_sroa_0_0_insert_insert77$1 = 0, $_0$0 = 0, $_0$1 = 0; + $n_sroa_0_0_extract_trunc = $a$0; + $n_sroa_1_4_extract_shift$0 = $a$1; + $n_sroa_1_4_extract_trunc = $n_sroa_1_4_extract_shift$0; + $d_sroa_0_0_extract_trunc = $b$0; + $d_sroa_1_4_extract_shift$0 = $b$1; + $d_sroa_1_4_extract_trunc = $d_sroa_1_4_extract_shift$0; + if (($n_sroa_1_4_extract_trunc | 0) == 0) { + $4 = ($rem | 0) != 0; + if (($d_sroa_1_4_extract_trunc | 0) == 0) { + if ($4) { + HEAP32[$rem >> 2] = ($n_sroa_0_0_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0); + HEAP32[$rem + 4 >> 2] = 0; + } + $_0$1 = 0; + $_0$0 = ($n_sroa_0_0_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } else { + if (!$4) { + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + HEAP32[$rem >> 2] = $a$0 & -1; + HEAP32[$rem + 4 >> 2] = $a$1 & 0; + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + } + $17 = ($d_sroa_1_4_extract_trunc | 0) == 0; + do { + if (($d_sroa_0_0_extract_trunc | 0) == 0) { + if ($17) { + if (($rem | 0) != 0) { + HEAP32[$rem >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0); + HEAP32[$rem + 4 >> 2] = 0; + } + $_0$1 = 0; + $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + if (($n_sroa_0_0_extract_trunc | 0) == 0) { + if (($rem | 0) != 0) { + HEAP32[$rem >> 2] = 0; + HEAP32[$rem + 4 >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_1_4_extract_trunc >>> 0); + } + $_0$1 = 0; + $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_1_4_extract_trunc >>> 0) >>> 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + $37 = $d_sroa_1_4_extract_trunc - 1 | 0; + if (($37 & $d_sroa_1_4_extract_trunc | 0) == 0) { + if (($rem | 0) != 0) { + HEAP32[$rem >> 2] = 0 | $a$0 & -1; + HEAP32[$rem + 4 >> 2] = $37 & $n_sroa_1_4_extract_trunc | $a$1 & 0; + } + $_0$1 = 0; + $_0$0 = $n_sroa_1_4_extract_trunc >>> ((_llvm_cttz_i32($d_sroa_1_4_extract_trunc) | 0) >>> 0); + return (tempRet0 = $_0$1, $_0$0) | 0; + } + $49 = _llvm_ctlz_i32($d_sroa_1_4_extract_trunc) | 0; + $51 = $49 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc) | 0) | 0; + if ($51 >>> 0 <= 30) { + $57 = $51 + 1 | 0; + $58 = 31 - $51 | 0; + $sr_1_ph = $57; + $r_sroa_0_1_ph = $n_sroa_1_4_extract_trunc << $58 | $n_sroa_0_0_extract_trunc >>> ($57 >>> 0); + $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($57 >>> 0); + $q_sroa_0_1_ph = 0; + $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $58; + break; + } + if (($rem | 0) == 0) { + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + HEAP32[$rem >> 2] = 0 | $a$0 & -1; + HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } else { + if (!$17) { + $117 = _llvm_ctlz_i32($d_sroa_1_4_extract_trunc) | 0; + $119 = $117 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc) | 0) | 0; + if ($119 >>> 0 <= 31) { + $125 = $119 + 1 | 0; + $126 = 31 - $119 | 0; + $130 = $119 - 31 >> 31; + $sr_1_ph = $125; + $r_sroa_0_1_ph = $n_sroa_0_0_extract_trunc >>> ($125 >>> 0) & $130 | $n_sroa_1_4_extract_trunc << $126; + $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($125 >>> 0) & $130; + $q_sroa_0_1_ph = 0; + $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $126; + break; + } + if (($rem | 0) == 0) { + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + HEAP32[$rem >> 2] = 0 | $a$0 & -1; + HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; + $_0$1 = 0; + $_0$0 = 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + $66 = $d_sroa_0_0_extract_trunc - 1 | 0; + if (($66 & $d_sroa_0_0_extract_trunc | 0) != 0) { + $86 = (_llvm_ctlz_i32($d_sroa_0_0_extract_trunc) | 0) + 33 | 0; + $88 = $86 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc) | 0) | 0; + $89 = 64 - $88 | 0; + $91 = 32 - $88 | 0; + $92 = $91 >> 31; + $95 = $88 - 32 | 0; + $105 = $95 >> 31; + $sr_1_ph = $88; + $r_sroa_0_1_ph = $91 - 1 >> 31 & $n_sroa_1_4_extract_trunc >>> ($95 >>> 0) | ($n_sroa_1_4_extract_trunc << $91 | $n_sroa_0_0_extract_trunc >>> ($88 >>> 0)) & $105; + $r_sroa_1_1_ph = $105 & $n_sroa_1_4_extract_trunc >>> ($88 >>> 0); + $q_sroa_0_1_ph = $n_sroa_0_0_extract_trunc << $89 & $92; + $q_sroa_1_1_ph = ($n_sroa_1_4_extract_trunc << $89 | $n_sroa_0_0_extract_trunc >>> ($95 >>> 0)) & $92 | $n_sroa_0_0_extract_trunc << $91 & $88 - 33 >> 31; + break; + } + if (($rem | 0) != 0) { + HEAP32[$rem >> 2] = $66 & $n_sroa_0_0_extract_trunc; + HEAP32[$rem + 4 >> 2] = 0; + } + if (($d_sroa_0_0_extract_trunc | 0) == 1) { + $_0$1 = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; + $_0$0 = 0 | $a$0 & -1; + return (tempRet0 = $_0$1, $_0$0) | 0; + } else { + $78 = _llvm_cttz_i32($d_sroa_0_0_extract_trunc) | 0; + $_0$1 = 0 | $n_sroa_1_4_extract_trunc >>> ($78 >>> 0); + $_0$0 = $n_sroa_1_4_extract_trunc << 32 - $78 | $n_sroa_0_0_extract_trunc >>> ($78 >>> 0) | 0; + return (tempRet0 = $_0$1, $_0$0) | 0; + } + } + } while (0); + if (($sr_1_ph | 0) == 0) { + $q_sroa_1_1_lcssa = $q_sroa_1_1_ph; + $q_sroa_0_1_lcssa = $q_sroa_0_1_ph; + $r_sroa_1_1_lcssa = $r_sroa_1_1_ph; + $r_sroa_0_1_lcssa = $r_sroa_0_1_ph; + $carry_0_lcssa$1 = 0; + $carry_0_lcssa$0 = 0; + } else { + $d_sroa_0_0_insert_insert99$0 = 0 | $b$0 & -1; + $d_sroa_0_0_insert_insert99$1 = $d_sroa_1_4_extract_shift$0 | $b$1 & 0; + $137$0 = _i64Add($d_sroa_0_0_insert_insert99$0, $d_sroa_0_0_insert_insert99$1, -1, -1); + $137$1 = tempRet0; + $q_sroa_1_1198 = $q_sroa_1_1_ph; + $q_sroa_0_1199 = $q_sroa_0_1_ph; + $r_sroa_1_1200 = $r_sroa_1_1_ph; + $r_sroa_0_1201 = $r_sroa_0_1_ph; + $sr_1202 = $sr_1_ph; + $carry_0203 = 0; + while (1) { + $147 = $q_sroa_0_1199 >>> 31 | $q_sroa_1_1198 << 1; + $149 = $carry_0203 | $q_sroa_0_1199 << 1; + $r_sroa_0_0_insert_insert42$0 = 0 | ($r_sroa_0_1201 << 1 | $q_sroa_1_1198 >>> 31); + $r_sroa_0_0_insert_insert42$1 = $r_sroa_0_1201 >>> 31 | $r_sroa_1_1200 << 1 | 0; + _i64Subtract($137$0, $137$1, $r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1); + $150$1 = tempRet0; + $151$0 = $150$1 >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1; + $152 = $151$0 & 1; + $154$0 = _i64Subtract($r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1, $151$0 & $d_sroa_0_0_insert_insert99$0, ((($150$1 | 0) < 0 ? -1 : 0) >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1) & $d_sroa_0_0_insert_insert99$1); + $r_sroa_0_0_extract_trunc = $154$0; + $r_sroa_1_4_extract_trunc = tempRet0; + $155 = $sr_1202 - 1 | 0; + if (($155 | 0) == 0) { + break; + } else { + $q_sroa_1_1198 = $147; + $q_sroa_0_1199 = $149; + $r_sroa_1_1200 = $r_sroa_1_4_extract_trunc; + $r_sroa_0_1201 = $r_sroa_0_0_extract_trunc; + $sr_1202 = $155; + $carry_0203 = $152; + } + } + $q_sroa_1_1_lcssa = $147; + $q_sroa_0_1_lcssa = $149; + $r_sroa_1_1_lcssa = $r_sroa_1_4_extract_trunc; + $r_sroa_0_1_lcssa = $r_sroa_0_0_extract_trunc; + $carry_0_lcssa$1 = 0; + $carry_0_lcssa$0 = $152; + } + $q_sroa_0_0_insert_ext75$0 = $q_sroa_0_1_lcssa; + $q_sroa_0_0_insert_ext75$1 = 0; + $q_sroa_0_0_insert_insert77$1 = $q_sroa_1_1_lcssa | $q_sroa_0_0_insert_ext75$1; + if (($rem | 0) != 0) { + HEAP32[$rem >> 2] = 0 | $r_sroa_0_1_lcssa; + HEAP32[$rem + 4 >> 2] = $r_sroa_1_1_lcssa | 0; + } + $_0$1 = (0 | $q_sroa_0_0_insert_ext75$0) >>> 31 | $q_sroa_0_0_insert_insert77$1 << 1 | ($q_sroa_0_0_insert_ext75$1 << 1 | $q_sroa_0_0_insert_ext75$0 >>> 31) & 0 | $carry_0_lcssa$1; + $_0$0 = ($q_sroa_0_0_insert_ext75$0 << 1 | 0 >>> 31) & -2 | $carry_0_lcssa$0; + return (tempRet0 = $_0$1, $_0$0) | 0; +} +// ======================================================================= diff --git a/src/jsifier.js b/src/jsifier.js index 2cf94a0df..926be71aa 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -468,7 +468,7 @@ function JSify(data, functionsOnly, givenFunctions) { asmLibraryFunctions.push(contentText); contentText = ' '; EXPORTED_FUNCTIONS[ident] = 1; - delete Functions.libraryFunctions[ident.substr(1)]; + Functions.libraryFunctions[ident.substr(1)] = 2; } } if ((!ASM_JS || phase == 'pre') && @@ -1606,10 +1606,26 @@ function JSify(data, functionsOnly, givenFunctions) { // "Final shape that will be created"). if (PRECISE_I64_MATH && Types.preciseI64MathUsed) { if (!INCLUDE_FULL_LIBRARY) { - ['i64Add', 'i64Subtract', 'bitshift64Shl', 'bitshift64Lshr', 'bitshift64Ashr'].forEach(function(func) { - print(processLibraryFunction(LibraryManager.library[func], func)); // must be first to be close to generated code - Functions.implementedFunctions['_' + func] = LibraryManager.library[func + '__sig']; + // first row are utilities called from generated code, second are needed from fastLong + ['i64Add', 'i64Subtract', 'bitshift64Shl', 'bitshift64Lshr', 'bitshift64Ashr', + 'llvm_ctlz_i32', 'llvm_cttz_i32'].forEach(function(func) { + if (!Functions.libraryFunctions[func]) { + print(processLibraryFunction(LibraryManager.library[func], func)); // must be first to be close to generated code + Functions.implementedFunctions['_' + func] = LibraryManager.library[func + '__sig']; + Functions.libraryFunctions[func] = 1; + // limited dependency handling + var deps = LibraryManager.library[func + '__deps']; + if (deps) { + deps.forEach(function(dep) { + assert(typeof dep == 'function'); + var text = dep(); + assert(text.indexOf('\n') < 0); + print('/* PRE_ASM */ ' + text + '\n'); + }); + } + } }); + print(read('fastLong.js')); } print('// EMSCRIPTEN_END_FUNCS\n'); print(read('long.js')); diff --git a/src/library.js b/src/library.js index c9f161f2d..11f30a1cd 100644 --- a/src/library.js +++ b/src/library.js @@ -5304,9 +5304,11 @@ LibraryManager.library = { llvm_umul_with_overflow_i64__deps: [function() { Types.preciseI64MathUsed = 1 }], llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) { - i64Math.multiply(xl, xh, yl, yh); - {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32'), '0']) }}}; - // XXX Need to hack support for second param in long.js +#if ASSERTIONS + Runtime.warnOnce('no overflow support in llvm_umul_with_overflow_i64'); +#endif + var low = ___muldi3(xl, xh, yl, yh); + {{{ makeStructuralReturn(['low', 'tempRet0', '0']) }}}; }, llvm_stacksave: function() { diff --git a/src/long.js b/src/long.js index b3d19bd34..9550a48a3 100644 --- a/src/long.js +++ b/src/long.js @@ -1530,13 +1530,6 @@ var i64Math = (function() { // Emscripten wrapper // Emscripten wrapper var Wrapper = { - multiply: function(xl, xh, yl, yh) { - var x = new goog.math.Long(xl, xh); - var y = new goog.math.Long(yl, yh); - var ret = x.multiply(y); - HEAP32[tempDoublePtr>>2] = ret.low_; - HEAP32[tempDoublePtr+4>>2] = ret.high_; - }, abs: function(l, h) { var x = new goog.math.Long(l, h); var ret; diff --git a/src/modules.js b/src/modules.js index f2994adae..5b5f79477 100644 --- a/src/modules.js +++ b/src/modules.js @@ -230,7 +230,7 @@ var Types = { var Functions = { // All functions that will be implemented in this file. Maps id to signature implementedFunctions: {}, - libraryFunctions: {}, // functions added from the library + libraryFunctions: {}, // functions added from the library. value 2 means asmLibraryFunction unimplementedFunctions: {}, // library etc. functions that we need to index, maps id to signature indexedFunctions: {}, diff --git a/src/parseTools.js b/src/parseTools.js index a568b7183..8a6daaf3b 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1998,9 +1998,12 @@ function processMathop(item) { 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')]); } - function i64PreciseLib(type) { + function preciseCall(name) { Types.preciseI64MathUsed = true; - return finish(['_i64' + type[0].toUpperCase() + type.substr(1) + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + ')', 'tempRet0']); + return finish([name + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + ')', 'tempRet0']); + } + function i64PreciseLib(type) { + return preciseCall('_i64' + type[0].toUpperCase() + type.substr(1)); } switch (op) { // basic integer ops @@ -2078,7 +2081,7 @@ function processMathop(item) { } case 'mul': { if (PRECISE_I64_MATH) { - return i64PreciseOp('multiply'); + return preciseCall('___muldi3'); } else { warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u'), true)); diff --git a/system/lib/compiler-rt/readme.txt b/system/lib/compiler-rt/readme.txt index 1fc97635f..d32e4600d 100644 --- a/system/lib/compiler-rt/readme.txt +++ b/system/lib/compiler-rt/readme.txt @@ -13,4 +13,5 @@ Compile with something like ./emcc system/lib/compiler-rt/*.c -Isystem/lib/compiler-rt/ -o rt.bc ./emcc -O2 -s ASM_JS=1 -g rt.bc -s LINKABLE=1 +manually replace Math_imul with Math.imul