summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rwxr-xr-xemcc23
-rwxr-xr-xemscripten.py56
-rw-r--r--src/analyzer.js9
-rw-r--r--src/compiler.js1
-rw-r--r--src/fastLong.js298
-rw-r--r--src/jsifier.js65
-rw-r--r--src/library.js84
-rw-r--r--src/long.js56
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js17
-rw-r--r--src/settings.js2
-rw-r--r--system/lib/compiler-rt/LICENSE.TXT97
-rw-r--r--system/lib/compiler-rt/divdi3.c47
-rw-r--r--system/lib/compiler-rt/int_endianness.h116
-rw-r--r--system/lib/compiler-rt/int_lib.h46
-rw-r--r--system/lib/compiler-rt/int_math.h67
-rw-r--r--system/lib/compiler-rt/int_types.h140
-rw-r--r--system/lib/compiler-rt/int_util.h29
-rw-r--r--system/lib/compiler-rt/muldi3.c56
-rw-r--r--system/lib/compiler-rt/readme.txt20
-rw-r--r--system/lib/compiler-rt/udivdi3.c36
-rw-r--r--system/lib/compiler-rt/udivmoddi4.c251
-rw-r--r--tests/cases/call_i64_noret.ll17
-rw-r--r--tests/cases/uadd_overflow_64_ta2.ll30
-rw-r--r--tests/cases/uadd_overflow_64_ta2.txt2
-rw-r--r--tests/cases/uadd_overflow_ta2.ll6
-rw-r--r--tests/cases/uadd_overflow_ta2.txt1
-rwxr-xr-xtests/runner.py66
-rw-r--r--tests/unistd/misc.out2
30 files changed, 1490 insertions, 153 deletions
diff --git a/AUTHORS b/AUTHORS
index 35aa74a7..87a656d6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -61,4 +61,5 @@ a license to everyone to use it as detailed in LICENSE.)
* Alexander Gladysh <ag@logiceditor.com>
* Arlo Breault <arlolra@gmail.com>
* Jacob Lee <artdent@gmail.com> (copyright owned by Google, Inc.)
+* Joe Lee <jlee@imvu.com> (copyright owned by IMVU)
diff --git a/emcc b/emcc
index adca1266..6c7ed2f5 100755
--- a/emcc
+++ b/emcc
@@ -473,7 +473,7 @@ Options that are modified or new in %s include:
--memory-init-file <on> If on, we generate a separate memory initialization
file. This is more efficient than storing the
memory initialization data embedded inside
- JavaScript as text. (default is on)
+ JavaScript as text. (default is off)
The target file, if specified (-o <target>), defines what will
be generated:
@@ -483,8 +483,8 @@ be generated:
<name>.bc LLVM bitcode (default)
<name>.o LLVM bitcode (same as .bc)
-Note that if --memory-init-file is used, then in addition to a
-.js or .html file that is generated, a .mem file will also appear.
+(Note that if --memory-init-file is used, then in addition to a
+.js or .html file that is generated, a .mem file will also appear.)
The -c option (which tells gcc not to run the linker) will
cause LLVM bitcode to be generated, as %s only generates
@@ -519,7 +519,7 @@ CONFIGURE_CONFIG = (os.environ.get('EMMAKEN_JUST_CONFIGURE') or 'conftest.c' in
CMAKE_CONFIG = 'CMakeFiles/cmTryCompileExec.dir' in ' '.join(sys.argv)# or 'CMakeCCompilerId' in ' '.join(sys.argv)
if CONFIGURE_CONFIG or CMAKE_CONFIG:
debug_configure = 0 # XXX use this to debug configure stuff. ./configure's generally hide our normal output including stderr so we write to a file
- use_clang = 1 # whether we fake configure tests using clang - the local, native compiler - or not. if not we generate JS and use node with a shebang
+ use_js = os.environ.get('EMCONFIGURE_JS') # whether we fake configure tests using clang - the local, native compiler - or not. if not we generate JS and use node with a shebang
# neither approach is perfect, you can try both, but may need to edit configure scripts in some cases
# XXX False is not fully tested yet
@@ -536,13 +536,16 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
if debug_configure: open(tempout, 'a').write('============= ' + sys.argv[i] + '\n' + src + '\n=============\n\n')
except:
pass
+ if sys.argv[i].endswith('.s'):
+ if debug_configure: open(tempout, 'a').write('(compiling .s assembly, must use clang\n')
+ use_js = 0
if src:
if 'fopen' in src and '"w"' in src:
- use_clang = True # we cannot write to files from js!
+ use_js = 0 # we cannot write to files from js!
if debug_configure: open(tempout, 'a').write('Forcing clang since uses fopen to write\n')
- compiler = os.environ.get('CONFIGURE_CC') or (shared.CLANG if use_clang else shared.EMCC) # if CONFIGURE_CC is defined, use that. let's you use local gcc etc. if you need that
+ compiler = os.environ.get('CONFIGURE_CC') or (shared.CLANG if not use_js else shared.EMCC) # if CONFIGURE_CC is defined, use that. let's you use local gcc etc. if you need that
if not ('CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX')):
compiler = shared.to_cc(compiler)
@@ -561,12 +564,12 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
idx += 1
cmd = [compiler] + list(filter_emscripten_options(sys.argv[1:]))
- if use_clang: cmd += shared.EMSDK_OPTS + ['-DEMSCRIPTEN']
+ if not use_js: cmd += shared.EMSDK_OPTS + ['-DEMSCRIPTEN']
if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', ' '.join(cmd)
if debug_configure: open(tempout, 'a').write('emcc, just configuring: ' + ' '.join(cmd) + '\n\n')
- if use_clang:
+ if not use_js:
exit(subprocess.call(cmd))
else:
only_object = '-c' in cmd
@@ -589,7 +592,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
shutil.copyfile(target, target[:-3])
target = target[:-3]
src = open(target).read()
- full_node = shared.NODE_JS
+ full_node = ' '.join(shared.listify(shared.NODE_JS))
if os.path.sep not in full_node:
full_node = '/usr/bin/' + full_node # TODO: use whereis etc. And how about non-*NIX?
open(target, 'w').write('#!' + full_node + '\n' + src) # add shebang
@@ -724,7 +727,7 @@ try:
bind = False
jcache = False
save_bc = False
- memory_init_file = True
+ memory_init_file = False
if use_cxx:
default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
diff --git a/emscripten.py b/emscripten.py
index 19c74531..b49008cd 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -98,19 +98,22 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if DEBUG: t = time.time()
in_func = False
ll_lines = open(infile).readlines()
+ curr_func = None
for line in ll_lines:
if in_func:
- funcs[-1][1].append(line)
+ curr_func.append(line)
if line.startswith('}'):
in_func = False
- funcs[-1] = (funcs[-1][0], ''.join(funcs[-1][1]))
- pre.append(line) # pre needs it to, so we know about all implemented functions
+ funcs.append((curr_func[0], ''.join(curr_func))) # use the entire line as the identifier
+ # pre needs to know about all implemented functions, even for non-pre func
+ pre.append(curr_func[0])
+ pre.append(line)
+ curr_func = None
else:
if line.startswith(';'): continue
if line.startswith('define '):
in_func = True
- funcs.append((line, [line])) # use the entire line as the identifier
- pre.append(line) # pre needs it to, so we know about all implemented functions
+ curr_func = [line]
elif line.find(' = type { ') > 0:
pre.append(line) # type
elif line.startswith('!'):
@@ -222,10 +225,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
# TODO: minimize size of forwarded data from funcs to what we actually need
- if cores == 1 and total_ll_size < MAX_CHUNK_SIZE:
- assert len(chunks) == 1, 'no point in splitting up without multiple cores'
-
if len(chunks) > 0:
+ if cores == 1 and total_ll_size < MAX_CHUNK_SIZE:
+ assert len(chunks) == 1, 'no point in splitting up without multiple cores'
+
if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.))
commands = [
@@ -344,6 +347,14 @@ 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
+
+ # Move preAsms to their right place
+ def move_preasm(m):
+ contents = m.groups(0)[0]
+ outfile.write(contents + '\n')
+ return ''
+ 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')
@@ -381,15 +392,12 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
basic_float_vars = ['NaN', 'Infinity']
- if forwarded_json['Types']['preciseI64MathUsed']:
- basic_funcs += ['i64Math_' + op for op in ['add', 'subtract', 'multiply', 'divide', 'modulo']]
- asm_setup += '''
-var i64Math_add = function(a, b, c, d) { i64Math.add(a, b, c, d) };
-var i64Math_subtract = function(a, b, c, d) { i64Math.subtract(a, b, c, d) };
-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['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)]
# function tables
def asm_coerce(value, sig):
@@ -410,6 +418,18 @@ var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) };
%s;
}
''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
+ args = ','.join(['a' + str(i) for i in range(1, len(sig))])
+ args = 'index' + (',' if args else '') + args
+ asm_setup += '''
+function invoke_%s(%s) {
+ try {
+ %sModule.dynCall_%s(%s);
+ } catch(e) {
+ asm.setThrew(1);
+ }
+}
+''' % (sig, args, 'return ' if sig[0] != 'v' else '', sig, args)
+ basic_funcs.append('invoke_%s' % sig)
# calculate exports
exported_implemented_functions = list(exported_implemented_functions)
@@ -427,7 +447,7 @@ var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) };
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/analyzer.js b/src/analyzer.js
index c10f18cc..df5a435e 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -124,6 +124,10 @@ function analyzer(data, sidePass) {
bits = bits || 32; // things like pointers are all i32, but show up as 0 bits from getBits
if (allowLegal && bits <= 32) return [{ ident: base + ('i' + bits in Runtime.INT_TYPES ? '' : '$0'), bits: bits }];
if (isNumber(base)) return getLegalLiterals(base, bits);
+ if (base[0] == '{') {
+ warnOnce('seeing source of illegal data ' + base + ', likely an inline struct - assuming zeroinit');
+ return getLegalLiterals('0', bits);
+ }
var ret = new Array(Math.ceil(bits/32));
var i = 0;
if (base == 'zeroinitializer' || base == 'undef') base = 0;
@@ -320,12 +324,13 @@ function analyzer(data, sidePass) {
}
// call, return: Return the first 32 bits, the rest are in temp
case 'call': {
- bits = getBits(value.type);
- var elements = getLegalVars(item.assignTo, bits);
var toAdd = [value];
// legalize parameters
legalizeFunctionParameters(value.params);
+ // legalize return value, if any
if (value.assignTo && isIllegalType(item.type)) {
+ bits = getBits(value.type);
+ var elements = getLegalVars(item.assignTo, bits);
// legalize return value
value.assignTo = elements[0].ident;
for (var j = 1; j < elements.length; j++) {
diff --git a/src/compiler.js b/src/compiler.js
index 7cf43f09..9c19aeb0 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -178,7 +178,6 @@ assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS ==
if (ASM_JS) {
assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap');
assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2');
- assert(DISABLE_EXCEPTION_CATCHING == 1, 'asm.js does not support C++ exceptions yet, you must compile with -s DISABLE_EXCEPTION_CATCHING=1');
}
assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals
diff --git a/src/fastLong.js b/src/fastLong.js
new file mode 100644
index 00000000..95f398db
--- /dev/null
+++ b/src/fastLong.js
@@ -0,0 +1,298 @@
+// ======== 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 ___remdi3($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 $rem = 0, $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $10$0 = 0, $10$1 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $rem = __stackBase__ | 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);
+ ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, $rem);
+ $10$0 = _i64Subtract(HEAP32[$rem >> 2] ^ $1$0, HEAP32[$rem + 4 >> 2] ^ $1$1, $1$0, $1$1);
+ $10$1 = tempRet0;
+ STACKTOP = __stackBase__;
+ return (tempRet0 = $10$1, $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 ___uremdi3($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 $rem = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $rem = __stackBase__ | 0;
+ ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem);
+ STACKTOP = __stackBase__;
+ return (tempRet0 = HEAP32[$rem + 4 >> 2] | 0, HEAP32[$rem >> 2] | 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) >>> 0);
+ return (tempRet0 = $_0$1, $_0$0) | 0;
+ }
+ $49 = _llvm_ctlz_i32($d_sroa_1_4_extract_trunc | 0) | 0;
+ $51 = $49 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc | 0) | 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) | 0;
+ $119 = $117 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc | 0) | 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) | 0) + 33 | 0;
+ $88 = $86 - (_llvm_ctlz_i32($n_sroa_1_4_extract_trunc | 0) | 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;
+ $_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 23fbb4c5..926be71a 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -108,7 +108,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
- if (phase == 'funcs') { // pre has function shells, just to defined implementedFunctions
+ if (phase == 'funcs') { // || phase == 'pre') { // pre has function shells, just to defined implementedFunctions
var MAX_BATCH_FUNC_LINES = 1000;
while (data.unparsedFunctions.length > 0) {
var currFuncLines = [];
@@ -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') &&
@@ -1149,20 +1149,21 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// If there is no current exception, set this one as it (during a resume, the current exception can be wiped out)
var ptr = makeStructuralAccess(item.ident, 0);
- return (EXCEPTION_DEBUG ? 'Module.print("Resuming exception");' : '') +
- 'if (' + makeGetValue('_llvm_eh_exception.buf', 0, 'void*') + ' == 0) { ' + makeSetValue('_llvm_eh_exception.buf', 0, ptr, 'void*') + ' } ' +
- makeThrow(ptr) + ';';
+ return '___resumeException(' + asmCoercion(ptr, 'i32') + ')';
});
makeFuncLineActor('invoke', function(item) {
// Wrapping in a function lets us easily return values if we are
// in an assignment
+ var disabled = DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST);
var phiSets = calcPhiSets(item);
- var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type);
-
+ var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type, ASM_JS && !disabled);
+
var ret;
- if (DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST)) {
+ if (disabled) {
ret = call_ + ';';
+ } else if (ASM_JS) {
+ ret = '(__THREW__ = 0,' + call_ + ');';
} else {
ret = '(function() { try { __THREW__ = 0; return '
+ call_ + ' '
@@ -1173,7 +1174,6 @@ function JSify(data, functionsOnly, givenFunctions) {
+ 'return null } })();';
}
-
if (item.assignTo) {
ret = 'var ' + item.assignTo + ' = ' + ret;
if (USE_TYPED_ARRAYS == 2 && isIllegalType(item.type)) {
@@ -1210,8 +1210,8 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
makeFuncLineActor('landingpad', function(item) {
- var catchTypeArray = item.catchables.map(finalizeLLVMParameter).join(',');
- var ret = '___cxa_find_matching_catch('+ makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +',' + makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') + ',[' + catchTypeArray +'])';
+ var catchTypeArray = item.catchables.map(finalizeLLVMParameter).map(function(element) { return asmCoercion(element, 'i32') }).join(',');
+ var ret = asmCoercion('___cxa_find_matching_catch(-1, -1' + (catchTypeArray.length > 0 ? ',' + catchTypeArray : '') +')', 'i32');
if (USE_TYPED_ARRAYS == 2) {
ret = makeVarDef(item.assignTo) + '$0 = ' + ret + '; ' + item.assignTo + '$1 = tempRet0;';
item.assignTo = null;
@@ -1291,7 +1291,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret;
});
- function makeFunctionCall(ident, params, funcData, type) {
+ function makeFunctionCall(ident, params, funcData, type, forceByPointer) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
@@ -1319,6 +1319,11 @@ function JSify(data, functionsOnly, givenFunctions) {
var hasVarArgs = isVarArgsFunctionType(type);
var normalArgs = (hasVarArgs && !useJSArgs) ? countNormalArgs(type) : -1;
var byPointer = getVarData(funcData, ident);
+ var byPointerForced = false;
+
+ if (forceByPointer && !byPointer) {
+ byPointer = byPointerForced = true;
+ }
params.forEach(function(param, i) {
var val = finalizeParam(param);
@@ -1343,7 +1348,7 @@ function JSify(data, functionsOnly, givenFunctions) {
args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) });
if (ASM_JS) {
- if (shortident in Functions.libraryFunctions || simpleIdent in Functions.libraryFunctions) {
+ if (shortident in Functions.libraryFunctions || simpleIdent in Functions.libraryFunctions || byPointerForced) {
args = args.map(function(arg, i) { return asmCoercion(arg, argsTypes[i]) });
} else {
args = args.map(function(arg, i) { return asmEnsureFloat(arg, argsTypes[i]) });
@@ -1421,12 +1426,20 @@ function JSify(data, functionsOnly, givenFunctions) {
var sig = Functions.getSignature(returnType, argsTypes, hasVarArgs);
if (ASM_JS) {
assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out)
- callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py
+ if (!byPointerForced) {
+ callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py
+ } else {
+ // This is a forced call, through an invoke_*.
+ // note: no need to update argsTypes at this point
+ Functions.unimplementedFunctions[callIdent] = sig;
+ args.unshift(byPointerForced ? Functions.getIndex(callIdent) : callIdent);
+ callIdent = 'invoke_' + sig;
+ }
} else if (SAFE_DYNCALLS) {
assert(!ASM_JS, 'cannot emit safe dyncalls in asm');
callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 || !FUNCTION_TABLE[tempInt] ? abort("dyncall error: ' + sig + ' " + FUNCTION_TABLE_NAMES[tempInt]) : tempInt)';
}
- callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
+ if (!byPointerForced) callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
}
var ret = callIdent + '(' + args.join(', ') + ')';
@@ -1593,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', '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 01c0a3f3..11f30a1c 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4913,16 +4913,20 @@ LibraryManager.library = {
}
return 8;
}
- return 'var ctlz_i8 = [' + range(256).map(function(x) { return ctlz(x) }).join(',') + '];';
+ return 'var ctlz_i8 = allocate([' + range(256).map(function(x) { return ctlz(x) }).join(',') + '], "i8", ALLOC_STACK);';
}],
+ llvm_ctlz_i32__asm: true,
+ llvm_ctlz_i32__sig: 'ii',
llvm_ctlz_i32: function(x) {
- var ret = ctlz_i8[x >>> 24];
- if (ret < 8) return ret;
- var ret = ctlz_i8[(x >> 16)&0xff];
- if (ret < 8) return ret + 8;
- var ret = ctlz_i8[(x >> 8)&0xff];
- if (ret < 8) return ret + 16;
- return ctlz_i8[x&0xff] + 24;
+ x = x|0;
+ var ret = 0;
+ ret = {{{ makeGetValueAsm('ctlz_i8', 'x >>> 24', 'i8') }}};
+ if ((ret|0) < 8) return ret|0;
+ var ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 16)&0xff', 'i8') }}};
+ if ((ret|0) < 8) return (ret + 8)|0;
+ var ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 8)&0xff', 'i8') }}};
+ if ((ret|0) < 8) return (ret + 16)|0;
+ return ({{{ makeGetValueAsm('ctlz_i8', 'x&0xff', 'i8') }}} + 24)|0;
},
llvm_ctlz_i64__deps: ['llvm_ctlz_i32'],
@@ -4945,16 +4949,20 @@ LibraryManager.library = {
}
return 8;
}
- return 'var cttz_i8 = [' + range(256).map(function(x) { return cttz(x) }).join(',') + '];';
+ return 'var cttz_i8 = allocate([' + range(256).map(function(x) { return cttz(x) }).join(',') + '], "i8", ALLOC_STACK);';
}],
+ llvm_cttz_i32__asm: true,
+ llvm_cttz_i32__sig: 'ii',
llvm_cttz_i32: function(x) {
- var ret = cttz_i8[x & 0xff];
- if (ret < 8) return ret;
- var ret = cttz_i8[(x >> 8)&0xff];
- if (ret < 8) return ret + 8;
- var ret = cttz_i8[(x >> 16)&0xff];
- if (ret < 8) return ret + 16;
- return cttz_i8[x >>> 24] + 24;
+ x = x|0;
+ var ret = 0;
+ ret = {{{ makeGetValueAsm('cttz_i8', 'x & 0xff', 'i8') }}};
+ if ((ret|0) < 8) return ret|0;
+ var ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 8)&0xff', 'i8') }}};
+ if ((ret|0) < 8) return (ret + 8)|0;
+ var ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 16)&0xff', 'i8') }}};
+ if ((ret|0) < 8) return (ret + 16)|0;
+ return ({{{ makeGetValueAsm('cttz_i8', 'x >>> 24', 'i8') }}} + 24)|0;
},
llvm_cttz_i64__deps: ['llvm_cttz_i32'],
@@ -5016,6 +5024,7 @@ LibraryManager.library = {
__cxa_free_exception: function(ptr) {
return _free(ptr);
},
+ __cxa_throw__sig: 'viii',
__cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'],
__cxa_throw: function(ptr, type, destructor) {
if (!___cxa_throw.initialized) {
@@ -5155,8 +5164,12 @@ LibraryManager.library = {
// functionality boils down to picking a suitable 'catch' block.
// We'll do that here, instead, to keep things simpler.
- __cxa_find_matching_catch__deps: ['__cxa_does_inherit', '__cxa_is_number_type'],
- __cxa_find_matching_catch: function(thrown, throwntype, typeArray) {
+ __cxa_find_matching_catch__deps: ['__cxa_does_inherit', '__cxa_is_number_type', '__resumeException'],
+ __cxa_find_matching_catch: function(thrown, throwntype) {
+ if (thrown == -1) thrown = {{{ makeGetValue('_llvm_eh_exception.buf', '0', 'void*') }}};
+ if (throwntype == -1) throwntype = {{{ makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') }}};
+ var typeArray = Array.prototype.slice.call(arguments, 2);
+
// If throwntype is a pointer, this means a pointer has been
// thrown. When a pointer is thrown, actually what's thrown
// is a pointer to the pointer. We'll dereference it.
@@ -5180,6 +5193,15 @@ LibraryManager.library = {
{{{ makeStructuralReturn(['thrown', 'throwntype']) }}};
},
+ __resumeException__deps: [function() { Functions.libraryFunctions['__resumeException'] = 1 }], // will be called directly from compiled code
+ __resumeException: function(ptr) {
+#if EXCEPTION_DEBUG
+ Module.print("Resuming exception");
+#endif
+ if ({{{ makeGetValue('_llvm_eh_exception.buf', 0, 'void*') }}} == 0) {{{ makeSetValue('_llvm_eh_exception.buf', 0, 'ptr', 'void*') }}};
+ {{{ makeThrow('ptr') }}};
+ },
+
// Recursively walks up the base types of 'possibilityType'
// to see if any of them match 'definiteType'.
__cxa_does_inherit__deps: ['__cxa_is_number_type'],
@@ -5282,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() {
@@ -7468,13 +7492,27 @@ LibraryManager.library = {
var l = 0, h = 0, overflow = 0;
l = (a + c)>>>0;
h = (b + d)>>>0;
- if ((l>>>0) < (a>>>0)) { // iff we overflowed
+ if ((h>>>0) < (b>>>0)) overflow = 1;
+ if ((l>>>0) < (a>>>0)) {
h = (h+1)>>>0;
- overflow = 1;
+ if ((h>>>0) == 0) overflow = 1; // two possibilities to overflow here
}
{{{ makeStructuralReturn(['l|0', 'h', 'overflow'], true) }}};
},
+ i64Subtract__asm: true,
+ i64Subtract__sig: 'iiiii',
+ i64Subtract: function(a, b, c, d) {
+ a = a|0; b = b|0; c = c|0; d = d|0;
+ var l = 0, h = 0;
+ l = (a - c)>>>0;
+ h = (b - d)>>>0;
+ if ((l>>>0) > (a>>>0)) { // iff we overflowed
+ h = (h-1)>>>0;
+ }
+ {{{ makeStructuralReturn(['l|0', 'h'], true) }}};
+ },
+
bitshift64Shl__asm: true,
bitshift64Shl__sig: 'iiii',
bitshift64Shl: function(low, high, bits) {
diff --git a/src/long.js b/src/long.js
index 6d0e873d..42c86c23 100644
--- a/src/long.js
+++ b/src/long.js
@@ -1530,20 +1530,6 @@ var i64Math = (function() { // Emscripten wrapper
// Emscripten wrapper
var Wrapper = {
- subtract: function(xl, xh, yl, yh) {
- var x = new goog.math.Long(xl, xh);
- var y = new goog.math.Long(yl, yh);
- var ret = x.subtract(y);
- HEAP32[tempDoublePtr>>2] = ret.low_;
- HEAP32[tempDoublePtr+4>>2] = ret.high_;
- },
- 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;
@@ -1576,48 +1562,6 @@ var i64Math = (function() { // Emscripten wrapper
c.addTo(b, d);
return d;
},
- divide: function(xl, xh, yl, yh, unsigned) {
- Wrapper.ensureTemps();
- if (!unsigned) {
- var x = new goog.math.Long(xl, xh);
- var y = new goog.math.Long(yl, yh);
- var ret = x.div(y);
- HEAP32[tempDoublePtr>>2] = ret.low_;
- HEAP32[tempDoublePtr+4>>2] = ret.high_;
- } else {
- // slow precise bignum division
- var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0);
- var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0);
- var z = new BigInteger();
- x.divRemTo(y, z, null);
- var l = new BigInteger();
- var h = new BigInteger();
- z.divRemTo(Wrapper.two32, h, l);
- HEAP32[tempDoublePtr>>2] = parseInt(l.toString()) | 0;
- HEAP32[tempDoublePtr+4>>2] = parseInt(h.toString()) | 0;
- }
- },
- modulo: function(xl, xh, yl, yh, unsigned) {
- Wrapper.ensureTemps();
- if (!unsigned) {
- var x = new goog.math.Long(xl, xh);
- var y = new goog.math.Long(yl, yh);
- var ret = x.modulo(y);
- HEAP32[tempDoublePtr>>2] = ret.low_;
- HEAP32[tempDoublePtr+4>>2] = ret.high_;
- } else {
- // slow precise bignum division
- var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0);
- var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0);
- var z = new BigInteger();
- x.divRemTo(y, null, z);
- var l = new BigInteger();
- var h = new BigInteger();
- z.divRemTo(Wrapper.two32, h, l);
- HEAP32[tempDoublePtr>>2] = parseInt(l.toString()) | 0;
- HEAP32[tempDoublePtr+4>>2] = parseInt(h.toString()) | 0;
- }
- },
stringify: function(l, h, unsigned) {
var ret = new goog.math.Long(l, h).toString();
if (unsigned && ret[0] == '-') {
diff --git a/src/modules.js b/src/modules.js
index f2994ada..5b5f7947 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 7dafbebe..2eb456f1 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1756,7 +1756,7 @@ function makeStructuralReturn(values, inAsm) {
return 'return ' + asmCoercion(values.slice(1).map(function(value) {
i++;
return ASM_JS ? (inAsm ? 'tempRet' + i + ' = ' + value : 'asm.setTempRet' + i + '(' + value + ')')
- : 'tempRet' + (i++) + ' = ' + value;
+ : 'tempRet' + i + ' = ' + value;
}).concat([values[0]]).join(','), 'i32');
} else {
var i = 0;
@@ -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
@@ -2062,7 +2065,7 @@ function processMathop(item) {
}
case 'sub': {
if (PRECISE_I64_MATH) {
- return i64PreciseOp('subtract');
+ return i64PreciseLib('subtract');
} else {
warnI64_1();
return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]), true));
@@ -2070,7 +2073,7 @@ function processMathop(item) {
}
case 'sdiv': case 'udiv': {
if (PRECISE_I64_MATH) {
- return i64PreciseOp('divide', op[0] === 'u');
+ return preciseCall(op[0] === 'u' ? '___udivdi3' : '___divdi3');
} else {
warnI64_1();
return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's'), true));
@@ -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));
@@ -2086,7 +2089,7 @@ function processMathop(item) {
}
case 'urem': case 'srem': {
if (PRECISE_I64_MATH) {
- return i64PreciseOp('modulo', op[0] === 'u');
+ return preciseCall(op[0] === 'u' ? '___uremdi3' : '___remdi3');
} else {
warnI64_1();
return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u'), true));
diff --git a/src/settings.js b/src/settings.js
index 08dad7f7..8f31c2d8 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -150,7 +150,7 @@ var LABEL_FUNCTION_FILTERS = []; // Filters for function label debug.
// labels of functions that is equaled to
// one of the filters are printed out
// When the array is empty, the filter is disabled.
-var EXCEPTION_DEBUG = 0; // Print out exceptions in emscriptened code
+var EXCEPTION_DEBUG = 0; // Print out exceptions in emscriptened code. Does not work in asm.js mode
var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js). You can also unset
// Runtime.debug at runtime for logging to cease, and can set it when you
diff --git a/system/lib/compiler-rt/LICENSE.TXT b/system/lib/compiler-rt/LICENSE.TXT
new file mode 100644
index 00000000..6aab1f69
--- /dev/null
+++ b/system/lib/compiler-rt/LICENSE.TXT
@@ -0,0 +1,97 @@
+==============================================================================
+compiler_rt License
+==============================================================================
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties. Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program Directory
+------- ---------
+mach_override lib/interception/mach_override
diff --git a/system/lib/compiler-rt/divdi3.c b/system/lib/compiler-rt/divdi3.c
new file mode 100644
index 00000000..09f4a04e
--- /dev/null
+++ b/system/lib/compiler-rt/divdi3.c
@@ -0,0 +1,47 @@
+/* ===-- divdi3.c - Implement __divdi3 -------------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __divdi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
+
+/* Returns: a / b */
+
+COMPILER_RT_ABI di_int
+__divdi3(di_int a, di_int b)
+{
+ const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+ di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */
+ di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */
+ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */
+ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
+ s_a ^= s_b; /*sign of quotient */
+ return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
+}
+
+/* XXX EMSCRIPTEN */
+
+COMPILER_RT_ABI di_int
+__remdi3(di_int a, di_int b)
+{
+ const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+ di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */
+ di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */
+ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */
+ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
+ du_int rem;
+ __udivmoddi4(a, b, &rem);
+ return (rem ^ s_a) - s_a; /* negate if s_a == -1 */
+}
+
diff --git a/system/lib/compiler-rt/int_endianness.h b/system/lib/compiler-rt/int_endianness.h
new file mode 100644
index 00000000..17905355
--- /dev/null
+++ b/system/lib/compiler-rt/int_endianness.h
@@ -0,0 +1,116 @@
+/* ===-- int_endianness.h - configuration header for compiler-rt ------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is a configuration header for compiler-rt.
+ * This file is not part of the interface of this library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_ENDIANNESS_H
+#define INT_ENDIANNESS_H
+
+#if defined(__SVR4) && defined(__sun)
+#include <sys/byteorder.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* Solaris and AuroraUX. */
+
+/* .. */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__minix)
+#include <sys/endian.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* *BSD */
+
+#if defined(__OpenBSD__) || defined(__Bitrig__)
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* OpenBSD and Bitrig. */
+
+/* .. */
+
+/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the compiler (at least with GCC) */
+#if defined(__APPLE__) && defined(__MACH__) || defined(__ellcc__ )
+
+#ifdef __BIG_ENDIAN__
+#if __BIG_ENDIAN__
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#endif
+#endif /* __BIG_ENDIAN__ */
+
+#ifdef __LITTLE_ENDIAN__
+#if __LITTLE_ENDIAN__
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif
+#endif /* __LITTLE_ENDIAN__ */
+
+#endif /* Mac OSX */
+
+/* .. */
+
+#if defined(__linux__)
+#include <endian.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* __BYTE_ORDER */
+
+#endif /* GNU/Linux */
+
+#if defined(_WIN32)
+
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+
+#endif /* Windows */
+
+#if defined(EMSCRIPTEN)
+
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+
+#endif /* emscripten */
+
+/* . */
+
+#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN)
+#error Unable to determine endian
+#endif /* Check we found an endianness correctly. */
+
+#endif /* INT_ENDIANNESS_H */
diff --git a/system/lib/compiler-rt/int_lib.h b/system/lib/compiler-rt/int_lib.h
new file mode 100644
index 00000000..a87426c5
--- /dev/null
+++ b/system/lib/compiler-rt/int_lib.h
@@ -0,0 +1,46 @@
+/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is a configuration header for compiler-rt.
+ * This file is not part of the interface of this library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_LIB_H
+#define INT_LIB_H
+
+/* Assumption: Signed integral is 2's complement. */
+/* Assumption: Right shift of signed negative is arithmetic shift. */
+/* Assumption: Endianness is little or big (not mixed). */
+
+/* ABI macro definitions */
+
+#if __ARM_EABI__
+# define ARM_EABI_FNALIAS(aeabi_name, name) \
+ void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
+# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+#else
+# define ARM_EABI_FNALIAS(aeabi_name, name)
+# define COMPILER_RT_ABI
+#endif
+
+/* Include the standard compiler builtin headers we use functionality from. */
+#include <limits.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <float.h>
+
+/* Include the commonly used internal type definitions. */
+#include "int_types.h"
+
+/* Include internal utility function declarations. */
+#include "int_util.h"
+
+#endif /* INT_LIB_H */
diff --git a/system/lib/compiler-rt/int_math.h b/system/lib/compiler-rt/int_math.h
new file mode 100644
index 00000000..d6b4bdae
--- /dev/null
+++ b/system/lib/compiler-rt/int_math.h
@@ -0,0 +1,67 @@
+/* ===-- int_math.h - internal math inlines ---------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===-----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines substitutes for the libm functions used in some of the
+ * compiler-rt implementations, defined in such a way that there is not a direct
+ * dependency on libm or math.h. Instead, we use the compiler builtin versions
+ * where available. This reduces our dependencies on the system SDK by foisting
+ * the responsibility onto the compiler.
+ *
+ * ===-----------------------------------------------------------------------===
+ */
+
+#ifndef INT_MATH_H
+#define INT_MATH_H
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+#define CRT_INFINITY __builtin_huge_valf()
+
+#define crt_isinf(x) __builtin_isinf((x))
+#define crt_isnan(x) __builtin_isnan((x))
+
+/* Define crt_isfinite in terms of the builtin if available, otherwise provide
+ * an alternate version in terms of our other functions. This supports some
+ * versions of GCC which didn't have __builtin_isfinite.
+ */
+#if __has_builtin(__builtin_isfinite)
+# define crt_isfinite(x) __builtin_isfinite((x))
+#else
+# define crt_isfinite(x) \
+ __extension__(({ \
+ __typeof((x)) x_ = (x); \
+ !crt_isinf(x_) && !crt_isnan(x_); \
+ }))
+#endif
+
+#define crt_copysign(x, y) __builtin_copysign((x), (y))
+#define crt_copysignf(x, y) __builtin_copysignf((x), (y))
+#define crt_copysignl(x, y) __builtin_copysignl((x), (y))
+
+#define crt_fabs(x) __builtin_fabs((x))
+#define crt_fabsf(x) __builtin_fabsf((x))
+#define crt_fabsl(x) __builtin_fabsl((x))
+
+#define crt_fmax(x, y) __builtin_fmax((x), (y))
+#define crt_fmaxf(x, y) __builtin_fmaxf((x), (y))
+#define crt_fmaxl(x, y) __builtin_fmaxl((x), (y))
+
+#define crt_logb(x) __builtin_logb((x))
+#define crt_logbf(x) __builtin_logbf((x))
+#define crt_logbl(x) __builtin_logbl((x))
+
+#define crt_scalbn(x, y) __builtin_scalbn((x), (y))
+#define crt_scalbnf(x, y) __builtin_scalbnf((x), (y))
+#define crt_scalbnl(x, y) __builtin_scalbnl((x), (y))
+
+#endif /* INT_MATH_H */
diff --git a/system/lib/compiler-rt/int_types.h b/system/lib/compiler-rt/int_types.h
new file mode 100644
index 00000000..fcce390f
--- /dev/null
+++ b/system/lib/compiler-rt/int_types.h
@@ -0,0 +1,140 @@
+/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines various standard types, most importantly a number of unions
+ * used to access parts of larger types.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_TYPES_H
+#define INT_TYPES_H
+
+#include "int_endianness.h"
+
+typedef int si_int;
+typedef unsigned su_int;
+
+typedef long long di_int;
+typedef unsigned long long du_int;
+
+typedef union
+{
+ di_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ su_int low;
+ si_int high;
+#else
+ si_int high;
+ su_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} dwords;
+
+typedef union
+{
+ du_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ su_int low;
+ su_int high;
+#else
+ su_int high;
+ su_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} udwords;
+
+#if __x86_64
+
+typedef int ti_int __attribute__ ((mode (TI)));
+typedef unsigned tu_int __attribute__ ((mode (TI)));
+
+typedef union
+{
+ ti_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ du_int low;
+ di_int high;
+#else
+ di_int high;
+ du_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} twords;
+
+typedef union
+{
+ tu_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ du_int low;
+ du_int high;
+#else
+ du_int high;
+ du_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} utwords;
+
+static inline ti_int make_ti(di_int h, di_int l) {
+ twords r;
+ r.s.high = h;
+ r.s.low = l;
+ return r.all;
+}
+
+static inline tu_int make_tu(du_int h, du_int l) {
+ utwords r;
+ r.s.high = h;
+ r.s.low = l;
+ return r.all;
+}
+
+#endif /* __x86_64 */
+
+typedef union
+{
+ su_int u;
+ float f;
+} float_bits;
+
+typedef union
+{
+ udwords u;
+ double f;
+} double_bits;
+
+typedef struct
+{
+#if _YUGA_LITTLE_ENDIAN
+ udwords low;
+ udwords high;
+#else
+ udwords high;
+ udwords low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+} uqwords;
+
+typedef union
+{
+ uqwords u;
+ long double f;
+} long_double_bits;
+
+#endif /* INT_TYPES_H */
+
diff --git a/system/lib/compiler-rt/int_util.h b/system/lib/compiler-rt/int_util.h
new file mode 100644
index 00000000..1348b85e
--- /dev/null
+++ b/system/lib/compiler-rt/int_util.h
@@ -0,0 +1,29 @@
+/* ===-- int_util.h - internal utility functions ----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===-----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines non-inline utilities which are available for use in the
+ * library. The function definitions themselves are all contained in int_util.c
+ * which will always be compiled into any compiler-rt library.
+ *
+ * ===-----------------------------------------------------------------------===
+ */
+
+#ifndef INT_UTIL_H
+#define INT_UTIL_H
+
+/** \brief Trigger a program abort (or panic for kernel code). */
+#define compilerrt_abort() compilerrt_abort_impl(__FILE__, __LINE__, \
+ __FUNCTION__)
+
+void compilerrt_abort_impl(const char *file, int line,
+ const char *function) __attribute__((noreturn));
+
+#endif /* INT_UTIL_H */
diff --git a/system/lib/compiler-rt/muldi3.c b/system/lib/compiler-rt/muldi3.c
new file mode 100644
index 00000000..2dae44c1
--- /dev/null
+++ b/system/lib/compiler-rt/muldi3.c
@@ -0,0 +1,56 @@
+/* ===-- muldi3.c - Implement __muldi3 -------------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __muldi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Returns: a * b */
+
+static
+di_int
+__muldsi3(su_int a, su_int b)
+{
+ dwords r;
+ const int bits_in_word_2 = (int)(sizeof(si_int) * CHAR_BIT) / 2;
+ const su_int lower_mask = (su_int)~0 >> bits_in_word_2;
+ r.s.low = (a & lower_mask) * (b & lower_mask);
+ su_int t = r.s.low >> bits_in_word_2;
+ r.s.low &= lower_mask;
+ t += (a >> bits_in_word_2) * (b & lower_mask);
+ r.s.low += (t & lower_mask) << bits_in_word_2;
+ r.s.high = t >> bits_in_word_2;
+ t = r.s.low >> bits_in_word_2;
+ r.s.low &= lower_mask;
+ t += (b >> bits_in_word_2) * (a & lower_mask);
+ r.s.low += (t & lower_mask) << bits_in_word_2;
+ r.s.high += t >> bits_in_word_2;
+ r.s.high += (a >> bits_in_word_2) * (b >> bits_in_word_2);
+ return r.all;
+}
+
+/* Returns: a * b */
+
+ARM_EABI_FNALIAS(lmul, muldi3)
+
+COMPILER_RT_ABI di_int
+__muldi3(di_int a, di_int b)
+{
+ dwords x;
+ x.all = a;
+ dwords y;
+ y.all = b;
+ dwords r;
+ r.all = __muldsi3(x.s.low, y.s.low);
+ r.s.high += x.s.high * y.s.low + x.s.low * y.s.high;
+ return r.all;
+}
diff --git a/system/lib/compiler-rt/readme.txt b/system/lib/compiler-rt/readme.txt
new file mode 100644
index 00000000..d10f53e4
--- /dev/null
+++ b/system/lib/compiler-rt/readme.txt
@@ -0,0 +1,20 @@
+These files are from compiler-rt,
+
+Last Changed Rev: 179380
+Last Changed Date: 2013-04-12 07:57:03 -0700 (Fri, 12 Apr 2013)
+
+===========================================================================
+
+Changes:
+
+ * add emscripten endianness to int_endianness.h
+ * add rem functions
+
+===========================================================================
+
+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
+
diff --git a/system/lib/compiler-rt/udivdi3.c b/system/lib/compiler-rt/udivdi3.c
new file mode 100644
index 00000000..3d55785c
--- /dev/null
+++ b/system/lib/compiler-rt/udivdi3.c
@@ -0,0 +1,36 @@
+/* ===-- udivdi3.c - Implement __udivdi3 -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __udivdi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
+
+/* Returns: a / b */
+
+COMPILER_RT_ABI du_int
+__udivdi3(du_int a, du_int b)
+{
+ return __udivmoddi4(a, b, 0);
+}
+
+/* XXX EMSCRIPTEN */
+
+COMPILER_RT_ABI du_int
+__uremdi3(du_int a, du_int b)
+{
+ du_int rem;
+ __udivmoddi4(a, b, &rem);
+ return rem;
+}
+
diff --git a/system/lib/compiler-rt/udivmoddi4.c b/system/lib/compiler-rt/udivmoddi4.c
new file mode 100644
index 00000000..57282d5b
--- /dev/null
+++ b/system/lib/compiler-rt/udivmoddi4.c
@@ -0,0 +1,251 @@
+/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __udivmoddi4 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Effects: if rem != 0, *rem = a % b
+ * Returns: a / b
+ */
+
+/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
+
+COMPILER_RT_ABI du_int
+__udivmoddi4(du_int a, du_int b, du_int* rem)
+{
+ const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
+ const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
+ udwords n;
+ n.all = a;
+ udwords d;
+ d.all = b;
+ udwords q;
+ udwords r;
+ unsigned sr;
+ /* special cases, X is unknown, K != 0 */
+ if (n.s.high == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* 0 X
+ * ---
+ * 0 X
+ */
+ if (rem)
+ *rem = n.s.low % d.s.low;
+ return n.s.low / d.s.low;
+ }
+ /* 0 X
+ * ---
+ * K X
+ */
+ if (rem)
+ *rem = n.s.low;
+ return 0;
+ }
+ /* n.s.high != 0 */
+ if (d.s.low == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 0
+ */
+ if (rem)
+ *rem = n.s.high % d.s.low;
+ return n.s.high / d.s.low;
+ }
+ /* d.s.high != 0 */
+ if (n.s.low == 0)
+ {
+ /* K 0
+ * ---
+ * K 0
+ */
+ if (rem)
+ {
+ r.s.high = n.s.high % d.s.high;
+ r.s.low = 0;
+ *rem = r.all;
+ }
+ return n.s.high / d.s.high;
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ {
+ r.s.low = n.s.low;
+ r.s.high = n.s.high & (d.s.high - 1);
+ *rem = r.all;
+ }
+ return n.s.high >> __builtin_ctz(d.s.high);
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+ /* 0 <= sr <= n_uword_bits - 2 or sr large */
+ if (sr > n_uword_bits - 2)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_uword_bits - 1 */
+ /* q.all = n.all << (n_udword_bits - sr); */
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_uword_bits - sr);
+ /* r.all = n.all >> sr; */
+ r.s.high = n.s.high >> sr;
+ r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ }
+ else /* d.s.low != 0 */
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 K
+ */
+ if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ *rem = n.s.low & (d.s.low - 1);
+ if (d.s.low == 1)
+ return n.all;
+ sr = __builtin_ctz(d.s.low);
+ q.s.high = n.s.high >> sr;
+ q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ return q.all;
+ }
+ /* K X
+ * ---
+ *0 K
+ */
+ sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
+ /* 2 <= sr <= n_udword_bits - 1
+ * q.all = n.all << (n_udword_bits - sr);
+ * r.all = n.all >> sr;
+ * if (sr == n_uword_bits)
+ * {
+ * q.s.low = 0;
+ * q.s.high = n.s.low;
+ * r.s.high = 0;
+ * r.s.low = n.s.high;
+ * }
+ * else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1
+ * {
+ * q.s.low = 0;
+ * q.s.high = n.s.low << (n_uword_bits - sr);
+ * r.s.high = n.s.high >> sr;
+ * r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ * }
+ * else // n_uword_bits + 1 <= sr <= n_udword_bits - 1
+ * {
+ * q.s.low = n.s.low << (n_udword_bits - sr);
+ * q.s.high = (n.s.high << (n_udword_bits - sr)) |
+ * (n.s.low >> (sr - n_uword_bits));
+ * r.s.high = 0;
+ * r.s.low = n.s.high >> (sr - n_uword_bits);
+ * }
+ */
+ q.s.low = (n.s.low << (n_udword_bits - sr)) &
+ ((si_int)(n_uword_bits - sr) >> (n_uword_bits-1));
+ q.s.high = ((n.s.low << ( n_uword_bits - sr)) &
+ ((si_int)(sr - n_uword_bits - 1) >> (n_uword_bits-1))) |
+ (((n.s.high << (n_udword_bits - sr)) |
+ (n.s.low >> (sr - n_uword_bits))) &
+ ((si_int)(n_uword_bits - sr) >> (n_uword_bits-1)));
+ r.s.high = (n.s.high >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1));
+ r.s.low = ((n.s.high >> (sr - n_uword_bits)) &
+ ((si_int)(n_uword_bits - sr - 1) >> (n_uword_bits-1))) |
+ (((n.s.high << (n_uword_bits - sr)) |
+ (n.s.low >> sr)) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1)));
+ }
+ else
+ {
+ /* K X
+ * ---
+ * K K
+ */
+ sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+ /* 0 <= sr <= n_uword_bits - 1 or sr large */
+ if (sr > n_uword_bits - 1)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_uword_bits */
+ /* q.all = n.all << (n_udword_bits - sr); */
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_uword_bits - sr);
+ /* r.all = n.all >> sr;
+ * if (sr < n_uword_bits)
+ * {
+ * r.s.high = n.s.high >> sr;
+ * r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ * }
+ * else
+ * {
+ * r.s.high = 0;
+ * r.s.low = n.s.high;
+ * }
+ */
+ r.s.high = (n.s.high >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1));
+ r.s.low = (n.s.high << (n_uword_bits - sr)) |
+ ((n.s.low >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1)));
+ }
+ }
+ /* Not a special case
+ * q and r are initialized with:
+ * q.all = n.all << (n_udword_bits - sr);
+ * r.all = n.all >> sr;
+ * 1 <= sr <= n_udword_bits - 1
+ */
+ su_int carry = 0;
+ for (; sr > 0; --sr)
+ {
+ /* r:q = ((r:q) << 1) | carry */
+ r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1));
+ r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1));
+ q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1));
+ q.s.low = (q.s.low << 1) | carry;
+ /* carry = 0;
+ * if (r.all >= d.all)
+ * {
+ * r.all -= d.all;
+ * carry = 1;
+ * }
+ */
+ const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
+ carry = s & 1;
+ r.all -= d.all & s;
+ }
+ q.all = (q.all << 1) | carry;
+ if (rem)
+ *rem = r.all;
+ return q.all;
+}
diff --git a/tests/cases/call_i64_noret.ll b/tests/cases/call_i64_noret.ll
new file mode 100644
index 00000000..a8a30fc0
--- /dev/null
+++ b/tests/cases/call_i64_noret.ll
@@ -0,0 +1,17 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i64 0) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/uadd_overflow_64_ta2.ll b/tests/cases/uadd_overflow_64_ta2.ll
new file mode 100644
index 00000000..a4f3e40b
--- /dev/null
+++ b/tests/cases/uadd_overflow_64_ta2.ll
@@ -0,0 +1,30 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str2 = private constant [11 x i8] c"*%llx,%d*\0A\00", align 1 ; [#uses=1]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %uadd1 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 18446744073709551606, i64 9999)
+ %a0 = extractvalue { i64, i1 } %uadd1, 0
+ %a1 = extractvalue { i64, i1 } %uadd1, 1
+ %a2 = zext i1 %a1 to i32
+ call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str2, i32 0, i32 0), i64 %a0, i32 %a2) ; [#uses=0]
+
+ %uadd2 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 18446744073709, i64 9999)
+ %b0 = extractvalue { i64, i1 } %uadd2, 0
+ %b1 = extractvalue { i64, i1 } %uadd2, 1
+ %b2 = zext i1 %b1 to i32
+ call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str2, i32 0, i32 0), i64 %b0, i32 %b2) ; [#uses=0]
+
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+
+declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
+declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
+
diff --git a/tests/cases/uadd_overflow_64_ta2.txt b/tests/cases/uadd_overflow_64_ta2.txt
new file mode 100644
index 00000000..f5711309
--- /dev/null
+++ b/tests/cases/uadd_overflow_64_ta2.txt
@@ -0,0 +1,2 @@
+*2705,1*
+*10c6f7a0dcfc,0*
diff --git a/tests/cases/uadd_overflow_ta2.ll b/tests/cases/uadd_overflow_ta2.ll
index 81a76bcd..feac60e3 100644
--- a/tests/cases/uadd_overflow_ta2.ll
+++ b/tests/cases/uadd_overflow_ta2.ll
@@ -33,6 +33,12 @@ entry:
%64ba2 = zext i1 %64ba1 to i32
call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %64ba0, i32 %64ba2) ; [#uses=0]
+ %zbuadd1 = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 10, 0 ; undef and explicit
+ %zba0 = extractvalue { i32, i1 } %zbuadd1, 0
+ %zba1 = extractvalue { i32, i1 } %zbuadd1, 1
+ %zba2 = zext i1 %ba1 to i32
+ call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %zba0, i32 %zba2) ; [#uses=0]
+
ret i32 1
}
diff --git a/tests/cases/uadd_overflow_ta2.txt b/tests/cases/uadd_overflow_ta2.txt
index bcd04599..81513080 100644
--- a/tests/cases/uadd_overflow_ta2.txt
+++ b/tests/cases/uadd_overflow_ta2.txt
@@ -1,3 +1,4 @@
*3319578,1*
*5177,0*
*9875,1*
+*10,0*
diff --git a/tests/runner.py b/tests/runner.py
index 2865679b..77b156a0 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -266,11 +266,11 @@ process(sys.argv[1])
if output_processor is not None:
output_processor(open(filename + '.o.js').read())
- if self.emcc_args is not None:
+ if self.emcc_args is not None and 'ASM_JS=1' in self.emcc_args:
if '--memory-init-file' in self.emcc_args:
memory_init_file = int(self.emcc_args[self.emcc_args.index('--memory-init-file')+1])
else:
- memory_init_file = 1
+ memory_init_file = 0
if memory_init_file:
assert '/* memory initializer */' not in open(filename + '.o.js').read()
else:
@@ -735,7 +735,8 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
uint64_t a = 5;
double b = 6.8;
uint64_t c = a * b;
- printf("*prod:%llu*\n*%d,%d,%d*\n", c, (int)&a, (int)&b, (int)&c); // printing addresses prevents optimizations
+ if (truthy()) printf("*%d,%d,%d*\n", (int)&a, (int)&b, (int)&c); // printing addresses prevents optimizations
+ printf("*prod:%llu*\n", c);
}
// Basic (rounded, for now) math. Just check compilation.
@@ -745,6 +746,14 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
b++; if (truthy()) b--; // confuse optimizer
printf("*%Ld,%Ld,%Ld,%Ld*\n", (a+b)/5000, (a-b)/5000, (a*3)/5000, (a/5)/5000);
+ a -= 17; if (truthy()) a += 5; // confuse optimizer
+ b -= 17; if (truthy()) b += 121; // confuse optimizer
+ printf("*%Lx,%Lx,%Lx,%Lx*\n", b - a, b - a/2, b/2 - a, b - 20);
+
+ if (truthy()) a += 5/b; // confuse optimizer
+ if (truthy()) b += 121*(3+a/b); // confuse optimizer
+ printf("*%Lx,%Lx,%Lx,%Lx*\n", a - b, a - b/2, a/2 - b, a - 20);
+
return 0;
}
'''
@@ -764,7 +773,10 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
'*-1,34359738367,4294967295,1073741823*\n' +
'*-1,-1,-1,-1*\n' +
'*-1,34359738367,4294967295,1073741823*\n' +
- '*prod:34*')
+ '*prod:34*\n' +
+ '*524718382041609,49025451137,787151111239120,52476740749274*\n' +
+ '*ffff210edd000002,91990876ea283be,f6e5210edcdd7c45,1234000000450765*\n' +
+ '*def122fffffe,91adef1232283bb,f6e66f78915d7c42,1234def123450763*\n')
src = r'''
#include <stdio.h>
@@ -2486,7 +2498,6 @@ Exception execution path of first function! 1
''')
def test_exceptions(self):
- if Settings.ASM_JS: return self.skip('no exceptions support in asm')
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly')
@@ -2576,7 +2587,6 @@ Exception execution path of first function! 1
self.do_run(src, 'Throw...Construct...Catched...Destruct...Throw...Construct...Copy...Catched...Destruct...Destruct...')
def test_white_list_exception(self):
- if Settings.ASM_JS: return self.skip('no exceptions support in asm')
Settings.DISABLE_EXCEPTION_CATCHING = 2
Settings.EXCEPTION_CATCHING_WHITELIST = ["__Z12somefunctionv"]
Settings.INLINING_LIMIT = 50 # otherwise it is inlined and not identified
@@ -2608,9 +2618,7 @@ Exception execution path of first function! 1
Settings.DISABLE_EXCEPTION_CATCHING = 0
Settings.EXCEPTION_CATCHING_WHITELIST = []
-
def test_uncaught_exception(self):
- if Settings.ASM_JS: return self.skip('no exceptions support in asm')
if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc')
Settings.DISABLE_EXCEPTION_CATCHING = 0
@@ -2650,7 +2658,6 @@ Exception execution path of first function! 1
self.do_run(src, 'success')
def test_typed_exceptions(self):
- if Settings.ASM_JS: return self.skip('no exceptions support in asm')
Settings.DISABLE_EXCEPTION_CATCHING = 0
Settings.SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access.
src = open(path_from_root('tests', 'exceptions', 'typed.cpp'), 'r').read()
@@ -2658,7 +2665,6 @@ Exception execution path of first function! 1
self.do_run(src, expected)
def test_multiexception(self):
- if Settings.ASM_JS: return self.skip('no exceptions support in asm')
Settings.DISABLE_EXCEPTION_CATCHING = 0
src = r'''
#include <stdio.h>
@@ -8100,6 +8106,35 @@ def process(filename):
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed2.js'))
assert open('pgoed.js').read() == open('pgoed2.js').read()
+ def test_add_function(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ if Settings.ASM_JS: return self.skip('needs a singleton function table')
+
+ Settings.INVOKE_RUN = 0
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main(int argc, char **argv) {
+ int fp = atoi(argv[1]);
+ printf("fp: %d\n", fp);
+ void (*f)() = reinterpret_cast<void (*)()>(fp);
+ f();
+ return 0;
+ }
+ '''
+
+ open(os.path.join(self.get_dir(), 'post.js'), 'w').write('''
+ var newFuncPtr = Runtime.addFunction(function() {
+ Module.print('Hello from JS!');
+ });
+ Module.callMain([newFuncPtr.toString()]);
+ ''')
+
+ self.emcc_args += ['--post-js', 'post.js']
+ self.do_run(src, '''Hello from JS!''')
+
def test_scriptaclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8967,7 +9002,7 @@ TT = %s
# asm.js
exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1"])')
- exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "0"])')
+ exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])')
# Make custom runs with various options
for compiler, quantum, embetter, typed_arrays, llvm_opts in [
@@ -10996,12 +11031,13 @@ elif 'browser' in str(sys.argv):
self.run_browser('page.html', '', '/report_result?1')
def test_sdl_image(self):
- # load an image file, get pixel data. Also O2 coverage for --preload-file
+ # load an image file, get pixel data. Also O2 coverage for --preload-file, and memory-init
shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpg'))
open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read()))
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-O2', '--preload-file', 'screenshot.jpg', '-o', 'page.html']).communicate()
- self.run_browser('page.html', '', '/report_result?600')
+ for mem in [0, 1]:
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-O2', '--preload-file', 'screenshot.jpg', '-o', 'page.html', '--memory-init-file', str(mem)]).communicate()
+ self.run_browser('page.html', '', '/report_result?600')
def test_sdl_image_jpeg(self):
shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpeg'))
@@ -12107,7 +12143,7 @@ elif 'benchmark' in str(sys.argv):
try_delete(final_filename)
output = Popen([PYTHON, EMCC, filename, #'-O3',
'-O2', '-s', 'INLINING_LIMIT=0', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0',# '-s', 'EXPLICIT_ZEXT=1',
- '-s', 'ASM_JS=1', '-s', 'USE_MATH_IMUL=1', '--llvm-lto', '1',
+ '-s', 'ASM_JS=1', '-s', 'USE_MATH_IMUL=1', '--llvm-lto', '1', '--memory-init-file', '0',
'-s', 'TOTAL_MEMORY=128*1024*1024', '-s', 'FAST_MEMORY=10*1024*1024',
'-o', final_filename] + shared_args + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate()
assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0]
diff --git a/tests/unistd/misc.out b/tests/unistd/misc.out
index 810da215..a872a258 100644
--- a/tests/unistd/misc.out
+++ b/tests/unistd/misc.out
@@ -29,7 +29,7 @@ alarm: 0, errno: 0
ualarm: 0, errno: 0
fork: -1, errno: 11
vfork: -1, errno: 11
-crypt: 0, errno: 38
+crypt: (null), errno: 38
encrypt, errno: 38
getgid: 0, errno: 0
getegid: 0, errno: 0