diff --git a/AUTHORS b/AUTHORS index 5c034e835c14d..8865ab5b92b0d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -173,4 +173,4 @@ a license to everyone to use it as detailed in LICENSE.) * Victor Costan * Pepijn Van Eeckhoudt (copyright owned by Luciad NV) * Stevie Trujillo - +* Edward Rudd diff --git a/emcc b/emcc index fd9c2b3e33b58..1bf69f4961996 100755 --- a/emcc +++ b/emcc @@ -1412,7 +1412,7 @@ try: passes += ['symbolMap='+target+'.symbols'] if minify_whitespace and 'last' in passes: passes += ['minifyWhitespace'] - logging.debug('applying js optimization passes: %s', passes) + logging.debug('applying js optimization passes: %s', ' '.join(passes)) final = shared.Building.js_optimizer(final, passes, jcache, debug_level >= 4, js_optimizer_extra_info, just_split=just_split, just_concat=just_concat) js_transform_tempfiles.append(final) if DEBUG: save_intermediate(title, suffix='js' if 'emitJSON' not in passes else 'json') @@ -1555,7 +1555,7 @@ try: try: # move temp js to final position, alongside its mem init file shutil.move(final, js_target) - args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST), json.dumps(shared.Settings.EMTERPRETIFY_WHITELIST)] + args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST), json.dumps(shared.Settings.EMTERPRETIFY_WHITELIST), str(shared.Settings.SWAPPABLE_ASM_MODULE)] if shared.Settings.EMTERPRETIFY_ASYNC: args += ['ASYNC=1'] if profiling: diff --git a/emscripten-version.txt b/emscripten-version.txt index ade2da5da3bb1..fd0e445f26933 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.29.7 +1.29.8 diff --git a/emscripten.py b/emscripten.py index ae8d786a775ce..800045e423798 100755 --- a/emscripten.py +++ b/emscripten.py @@ -985,8 +985,6 @@ def move_preasm(m): return '' funcs_js[1] = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), funcs_js[1]) - funcs_js += ['\n// EMSCRIPTEN_END_FUNCS\n'] - class Counter: i = 0 j = 0 @@ -1088,7 +1086,7 @@ def make_emulated_param(i): infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()] Counter.pre = [] - function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos]) + function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos]) asm_setup = '' maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul', 'min', 'clz32']] @@ -1193,21 +1191,21 @@ def keyfunc(other): coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings) for i in range(1, len(sig))]) ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0], settings) function_tables_impls.append(''' - function dynCall_%s(index%s%s) { - index = index|0; - %s - %s; - } +function dynCall_%s(index%s%s) { + index = index|0; + %s + %s; +} ''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret)) ffi_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings, ffi_arg=True) for i in range(1, len(sig))]) for i in range(settings['RESERVED_FUNCTION_POINTERS']): jsret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('jsCall(%d%s%s)' % (i, ',' if ffi_args else '', ffi_args), sig[0], settings, ffi_result=True) function_tables_impls.append(''' - function jsCall_%s_%s(%s) { - %s - %s; - } +function jsCall_%s_%s(%s) { + %s + %s; +} ''' % (sig, i, args, arg_coercions, jsret)) shared.Settings.copy(settings) @@ -1453,7 +1451,7 @@ def math_fix(g): // EMSCRIPTEN_END_ASM (%s, %s, buffer); %s; -''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, +''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs, exports, 'Module' + access_quote('asmGlobalArg'), 'Module' + access_quote('asmLibraryArg'), receiving)] diff --git a/site/source/docs/getting_started/FAQ.rst b/site/source/docs/getting_started/FAQ.rst index 53e88c79fe06d..6bbb93ced2c1e 100644 --- a/site/source/docs/getting_started/FAQ.rst +++ b/site/source/docs/getting_started/FAQ.rst @@ -330,6 +330,13 @@ Building :ref:`Fastcomp from source ` (and hence The solution is to ensure the system has sufficient memory. On Ubuntu 14.04.1 LTS 64bit, you should use use at least 6Gb. +Why do I get odd rounding errors when using float variables? +============================================================ + +By default Emscripten uses doubles for all floating-point variables, that is, 64-bit floats even when C/C++ code contains 32-bit floats. This is simplest and most efficient to implement in JS as doubles are the only native numeric type. As a result, you may see rounding errors compared to native code using 32-bit floats, just because of the difference in precision between 32-bit and 64-bit floating-point values. + +To check if this is the issue you are seeing, build with ``-s PRECISE_F32=1``. This uses proper 32-bit floating-point values, at the cost of some extra code size overhead. This may be faster in some browsers, if they optimize ``Math.fround``, but can be slower in others. See ``src/settings.js`` for more details on this option. + Why the weird name for the project? =================================== diff --git a/src/compiler.js b/src/compiler.js index af535702739e7..59f6a9abadf25 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -331,12 +331,12 @@ try { } } } catch(err) { - if (err.indexOf('Aborting compilation due to previous errors') != -1) { + if (err.toString().indexOf('Aborting compilation due to previous errors') != -1) { // Compiler failed on user error, print out the error message. printErr(err + ' | ' + err.stack); } else { // Compiler failed on internal compiler error! - printErr('Internal compiler error in src/compiler.js! Please raise a bug report at https://github.com/kripken/emscripten/issues/ with a log of the build and the input files used to run. Exception message: ' + err + ' | ' + err.stack); + printErr('Internal compiler error in src/compiler.js! Please raise a bug report at https://github.com/kripken/emscripten/issues/ with a log of the build and the input files used to run. Exception message: "' + err + '" | ' + err.stack); } if (ENVIRONMENT_IS_NODE) { diff --git a/src/library.js b/src/library.js index 0ba6218075640..334f792244a88 100644 --- a/src/library.js +++ b/src/library.js @@ -150,7 +150,7 @@ LibraryManager.library = { } {{{ makeSetValue('entry', C_STRUCTS.dirent.d_ino, 'id', 'i32') }}}; {{{ makeSetValue('entry', C_STRUCTS.dirent.d_off, 'stream.position', 'i32') }}}; - {{{ makeSetValue('entry', C_STRUCTS.dirent.d_reclen, 'name.length + 1', 'i32') }}}; + {{{ makeSetValue('entry', C_STRUCTS.dirent.d_reclen, C_STRUCTS.dirent.__size__, 'i32') }}}; for (var i = 0; i < name.length; i++) { {{{ makeSetValue('entry + ' + C_STRUCTS.dirent.d_name, 'i', 'name.charCodeAt(i)', 'i8') }}}; } @@ -5748,17 +5748,6 @@ LibraryManager.library = { // ========================================================================== // setjmp.h - // - // Basic support for setjmp/longjmp: enough to run the wikipedia example and - // hopefully handle most normal behavior. We do not support cases where - // longjmp behavior is undefined (for example, if the setjmp function returns - // before longjmp is called). - // - // Note that we need to emulate functions that use setjmp, and also to create - // a new label we can return to. Emulation make such functions slower, this - // can be alleviated by making a new function containing just the setjmp - // related functionality so the slowdown is more limited - you may need - // to prevent inlining to keep this isolated, try __attribute__((noinline)) // ========================================================================== saveSetjmp__asm: true, diff --git a/src/library_gl.js b/src/library_gl.js index ba98c1804b05b..9d26e2ef0c3f9 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1339,7 +1339,7 @@ var LibraryGL = { // Framebuffer objects glBlitFramebuffer__sig: 'viiiiiiiiii', glBlitFramebuffer: function(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) { - GLctx.blitFramebuffer(srcX0, srcY0, srxC1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + GLctx.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); }, glReadBuffer__sig: 'vi', diff --git a/src/preamble.js b/src/preamble.js index c52859cf17439..9c31b019e3fff 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1322,7 +1322,7 @@ while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { totalMemory = Math.max(totalMemory, 16*1024*1024); #endif if (totalMemory !== TOTAL_MEMORY) { - Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be compliant with the asm.js spec'); + Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be compliant with the asm.js spec (and given that TOTAL_STACK=' + TOTAL_STACK + ')'); TOTAL_MEMORY = totalMemory; } #endif diff --git a/src/settings.js b/src/settings.js index d06238955a16b..0a01bc0214e92 100644 --- a/src/settings.js +++ b/src/settings.js @@ -133,7 +133,8 @@ var PRECISE_F32 = 0; // 0: Use JS numbers for floating-point values. These are 6 // polyfill in cases where engine support is not present. In addition, we can // remove the empty polyfill calls themselves on the client when generating html, // which should mean that this gives you the best of both worlds of 0 and 1, and is - // therefore recommended. + // therefore recommended, *unless* you need a guarantee of proper float32 precision + // (in that case, use option 1). // XXX Note: To optimize float32-using code, we use the 'const' keyword in the emitted // code. This allows us to avoid unnecessary calls to Math.fround, which would // slow down engines not yet supporting that function. 'const' is present in diff --git a/system/lib/libc/musl/src/dirent/alphasort.c b/system/lib/libc/musl/src/dirent/alphasort.c new file mode 100644 index 0000000000000..42050fb7cb52e --- /dev/null +++ b/system/lib/libc/musl/src/dirent/alphasort.c @@ -0,0 +1,10 @@ +#include +#include +#include "libc.h" + +int alphasort(const struct dirent **a, const struct dirent **b) +{ + return strcoll((*a)->d_name, (*b)->d_name); +} + +LFS64(alphasort); diff --git a/system/lib/libc/musl/src/dirent/scandir.c b/system/lib/libc/musl/src/dirent/scandir.c new file mode 100644 index 0000000000000..3af2b50f81920 --- /dev/null +++ b/system/lib/libc/musl/src/dirent/scandir.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include "libc.h" + +int scandir(const char *path, struct dirent ***res, + int (*sel)(const struct dirent *), + int (*cmp)(const struct dirent **, const struct dirent **)) +{ + DIR *d = opendir(path); + struct dirent *de, **names=0, **tmp; + size_t cnt=0, len=0; + int old_errno = errno; + + if (!d) return -1; + + while ((errno=0), (de = readdir(d))) { + if (sel && !sel(de)) continue; + if (cnt >= len) { + len = 2*len+1; + if (len > SIZE_MAX/sizeof *names) break; + tmp = realloc(names, len * sizeof *names); + if (!tmp) break; + names = tmp; + } + names[cnt] = malloc(de->d_reclen); + if (!names[cnt]) break; + memcpy(names[cnt++], de, de->d_reclen); + } + + closedir(d); + + if (errno) { + if (names) while (cnt-->0) free(names[cnt]); + free(names); + return -1; + } + errno = old_errno; + + if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp); + *res = names; + return cnt; +} + +LFS64(scandir); diff --git a/system/lib/libcextra.symbols b/system/lib/libcextra.symbols index e08f7f185cff0..e781e835c326d 100644 --- a/system/lib/libcextra.symbols +++ b/system/lib/libcextra.symbols @@ -21,6 +21,7 @@ T __wcscoll_l T __wcsxfrm_l W __wctype_l + T alphasort T asprintf T atoll T bcmp @@ -137,6 +138,7 @@ T regfree T rindex T scalbnf + T scandir D signgam T sscanf T stpcpy diff --git a/tests/dirent/test_readdir.c b/tests/dirent/test_readdir.c index dc14a1471759f..7b6a3c9bdbb50 100644 --- a/tests/dirent/test_readdir.c +++ b/tests/dirent/test_readdir.c @@ -71,12 +71,15 @@ void test() { ent = readdir(dir); assert(!strcmp(ent->d_name, ".")); assert(ent->d_type & DT_DIR); + assert(ent->d_reclen == sizeof(*ent)); ent = readdir(dir); assert(!strcmp(ent->d_name, "..")); assert(ent->d_type & DT_DIR); + assert(ent->d_reclen == sizeof(*ent)); ent = readdir(dir); assert(!strcmp(ent->d_name, "file.txt")); assert(ent->d_type & DT_REG); + assert(ent->d_reclen == sizeof(*ent)); ent = readdir(dir); assert(!ent); @@ -124,11 +127,29 @@ void test() { puts("success"); } +void test_scandir() { + struct dirent **namelist; + int n; + + n = scandir(".", &namelist, NULL, alphasort); + printf("n: %d\n", n); + if (n < 0) + return; + else { + while (n--) { + printf("name: %s\n", namelist[n]->d_name); + free(namelist[n]); + } + free(namelist); + } +} + int main() { printf("SIGILL: %s\n", strsignal(SIGILL)); atexit(cleanup); signal(SIGABRT, cleanup); setup(); test(); + test_scandir(); return EXIT_SUCCESS; } diff --git a/tests/fuzz/csmith_driver.py b/tests/fuzz/csmith_driver.py index dc68e889e2744..a0f1ffb312355 100755 --- a/tests/fuzz/csmith_driver.py +++ b/tests/fuzz/csmith_driver.py @@ -45,10 +45,15 @@ opts = '-Oz' print 'opt level:', opts + llvm_opts = [] + if random.random() < 0.5: + llvm_opts = ['--llvm-opts', str(random.randint(0, 3))] + print 'Tried %d, notes: %s' % (tried, notes) print '1) Generate source' extra_args = [] if random.random() < 0.5: extra_args += ['--no-math64'] + extra_args += ['--no-bitfields'] # due to pnacl bug 4027, "LLVM ERROR: can't convert calls with illegal types" #if random.random() < 0.5: extra_args += ['--float'] # XXX hits undefined behavior on float=>int conversions (too big to fit) suffix = '.c' COMP = shared.CLANG_CC @@ -96,8 +101,9 @@ def try_js(args): shared.try_delete(filename + '.js') - print '(compile)' - shared.check_execute([shared.PYTHON, shared.EMCC, opts, fullname, '-o', filename + '.js', '-s', 'PRECISE_F32=1'] + CSMITH_CFLAGS + args) + js_args = [shared.PYTHON, shared.EMCC, opts] + llvm_opts + [fullname, '-o', filename + '.js'] + CSMITH_CFLAGS + args + print '(compile)', ' '.join(js_args) + shared.check_execute(js_args) assert os.path.exists(filename + '.js') print '(run in %s)' % engine1 js = shared.run_js(filename + '.js', engine=engine1, check_timeout=True, assert_returncode=None, cwd='/tmp/emscripten_temp') @@ -124,7 +130,7 @@ def try_js(args): print "EMSCRIPTEN BUG" notes['embug'] += 1 fails += 1 - shutil.copyfile(fullname, 'newfail%d%s%s' % (fails, opts.replace('-', '_'), suffix)) + shutil.copyfile(fullname, 'newfail%d%s%s%s' % (fails, opts.replace('-', '_'), ' '.join(llvm_opts).replace('-', '_').replace(' ', ''), suffix)) continue #if not ok: # try: # finally, try with safe heap. if that is triggered, this is nonportable code almost certainly diff --git a/tests/test_core.py b/tests/test_core.py index 07ac2031dec25..2cd17c03dfc4f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4477,7 +4477,17 @@ def test_readdir(self): if self.emcc_args is None: return self.skip('requires emcc') self.banned_js_engines = [V8_ENGINE] # stderr printing limitations in v8 src = open(path_from_root('tests', 'dirent', 'test_readdir.c'), 'r').read() - self.do_run(src, 'SIGILL: Illegal instruction\nsuccess', force_c=True) + self.do_run(src, '''SIGILL: Illegal instruction +success +n: 7 +name: tmp +name: nocanread +name: home +name: foobar +name: dev +name: .. +name: . +''', force_c=True) def test_readdir_empty(self): src = open(path_from_root('tests', 'dirent', 'test_readdir_empty.c'), 'r').read() diff --git a/tests/test_other.py b/tests/test_other.py index fc4e5e86a8418..0162eb2391302 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1451,6 +1451,41 @@ def test_dup_o_in_a(self): self.assertContained('a\nb\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_dup_o_in_one_a(self): + open('common.c', 'w').write(r''' + #include + void a(void) { + printf("a\n"); + } + ''') + Popen([PYTHON, EMCC, 'common.c', '-c', '-o', 'common.o']).communicate() + + try: + os.makedirs(os.path.join(self.get_dir(), 'libdir')); + except: + pass + open(os.path.join('libdir', 'common.c'), 'w').write(r''' + #include + void b(void) { + printf("b...\n"); + } + ''') + Popen([PYTHON, EMCC, os.path.join('libdir', 'common.c'), '-c', '-o', os.path.join('libdir', 'common.o')]).communicate() + + Popen([PYTHON, EMAR, 'rc', 'liba.a', 'common.o', os.path.join('libdir', 'common.o')]).communicate() + + open('main.c', 'w').write(r''' + void a(void); + void b(void); + int main() { + a(); + b(); + } + ''') + out, err = Popen([PYTHON, EMCC, 'main.c', '-L.', '-la'], stderr=PIPE).communicate() + assert 'loading from archive /tmp/emscripten_temp/liba.a, which has duplicate entries' in err + assert 'duplicate: common.o' in err + def test_export_in_a(self): export_name = 'this_is_an_entry_point' @@ -3959,7 +3994,7 @@ def test_create_readonly(self): def test_embed_file_large(self): # If such long files are encoded on one line, # they overflow the interpreter's limit - large_size = int(40e6) + large_size = int(1500000) open('large.txt', 'w').write('x' * large_size) open('src.cpp', 'w').write(r''' #include @@ -4675,31 +4710,37 @@ def test_f0(self): assert ' = f0;' in src or ' = f0,' in src def test_merge_pair(self): - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-O1', '-profiling', '-o', 'left.js']).communicate() - src = open('left.js').read() - open('right.js', 'w').write(src.replace('function _main() {', 'function _main() { Module.print("replaced"); ')) - - self.assertContained('hello, world!', run_js('left.js')) - self.assertContained('hello, world!', run_js('right.js')) - self.assertNotContained('replaced', run_js('left.js')) - self.assertContained('replaced', run_js('right.js')) - - n = src.count('function _') - - def has(i): - Popen([PYTHON, path_from_root('tools', 'merge_pair.py'), 'left.js', 'right.js', str(i), 'out.js']).communicate() - return 'replaced' in run_js('out.js') - - assert not has(0), 'same as left' - assert has(n), 'same as right' - assert has(n+5), 'same as right, big number is still ok' - - change = -1 - for i in range(n): - if has(i): - change = i - break - assert change > 0 and change <= n + def test(filename, full): + print '----', filename, full + Popen([PYTHON, EMCC, path_from_root('tests', filename), '-O1', '-profiling', '-o', 'left.js']).communicate() + src = open('left.js').read() + open('right.js', 'w').write(src.replace('function _main() {', 'function _main() { Module.print("replaced"); ')) + + self.assertContained('hello, world!', run_js('left.js')) + self.assertContained('hello, world!', run_js('right.js')) + self.assertNotContained('replaced', run_js('left.js')) + self.assertContained('replaced', run_js('right.js')) + + n = src.count('function _') + + def has(i): + Popen([PYTHON, path_from_root('tools', 'merge_pair.py'), 'left.js', 'right.js', str(i), 'out.js']).communicate() + return 'replaced' in run_js('out.js') + + assert not has(0), 'same as left' + assert has(n), 'same as right' + assert has(n+5), 'same as right, big number is still ok' + + if full: + change = -1 + for i in range(n): + if has(i): + change = i + break + assert change > 0 and change <= n + + test('hello_world.cpp', True) + test('hello_libcxx.cpp', False) def test_emmake_emconfigure(self): def check(what, args, fail=True): diff --git a/tools/asm_module.py b/tools/asm_module.py index 1482d1434cc21..fcf86ae5509d6 100644 --- a/tools/asm_module.py +++ b/tools/asm_module.py @@ -302,6 +302,7 @@ def get_funcs_map(self): def apply_funcs_map(self, funcs_map): # assumes self.funcs is the set of funcs, in the right order jses = [] for f in self.funcs: - jses.append(funcs_map[f]) + if f in funcs_map: # TODO: fix + jses.append(funcs_map[f]) self.funcs_js = '\n'.join(jses) diff --git a/tools/emterpretify.py b/tools/emterpretify.py index 25650f45c21bd..ccb829e514052 100755 --- a/tools/emterpretify.py +++ b/tools/emterpretify.py @@ -21,6 +21,7 @@ ASYNC = False ASSERTIONS = False PROFILING = False +SWAPPABLE = False def handle_arg(arg): global ZERO, ASYNC, ASSERTIONS, PROFILING @@ -33,7 +34,12 @@ def handle_arg(arg): return False return True -if os.environ.get('EMCC_DEBUG'): +DEBUG = os.environ.get('EMCC_DEBUG') + +config = shared.Configuration() +temp_files = config.get_temp_files() + +if DEBUG: print >> sys.stderr, 'running emterpretify on', sys.argv sys.argv = filter(handle_arg, sys.argv) @@ -646,6 +652,7 @@ def process(code): assert temp[1] == '@' temp = open(temp[2:-1]).read() extra_blacklist = json.loads(temp) + if len(sys.argv) >= 6: temp = sys.argv[5] if temp[0] == '"': @@ -654,10 +661,15 @@ def process(code): temp = open(temp[2:-1]).read() WHITELIST = json.loads(temp) + if len(sys.argv) >= 7: + SWAPPABLE = int(sys.argv[6]) + BLACKLIST = set(list(BLACKLIST) + extra_blacklist) - shared.logging.debug('saving original (non-emterpreted) code to ' + infile + '.orig.js') - shutil.copyfile(infile, infile + '.orig.js') + if DEBUG or SWAPPABLE: + orig = infile + '.orig.js' + shared.logging.debug('saving original (non-emterpreted) code to ' + orig) + shutil.copyfile(infile, orig) # final global functions @@ -679,7 +691,7 @@ def process(code): tabled_funcs = asm.get_table_funcs() exported_funcs = [func.split(':')[0] for func in asm.exports] - temp = infile + '.tmp.js' + temp = temp_files.get('.js').name # infile + '.tmp.js' # find emterpreted functions reachable by non-emterpreted ones, we will force a trampoline for them later diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 21c8b7e43d689..1697b6ee69623 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -7112,7 +7112,7 @@ function emterpretify(ast) { function walkStatements(stats) { if (!stats) return []; - if (stats[0] === 'block') stats = stats[1]; + if (stats[0] === 'block') return walkStatements(stats[1]); if (typeof stats[0] === 'string') stats = [stats]; var ret = []; stats.forEach(function(stat) { diff --git a/tools/merge_pair.py b/tools/merge_pair.py index 4782c73b9fc09..4c2311098c6e4 100644 --- a/tools/merge_pair.py +++ b/tools/merge_pair.py @@ -30,7 +30,8 @@ for i in range(n): f = funcs[i] - left_map[f] = right_map[f] + if f in right_map: # TODO: fix + left_map[f] = right_map[f] print 'merging in the first %d from the second file' % n left_asm.apply_funcs_map(left_map) diff --git a/tools/optimizer/parser.h b/tools/optimizer/parser.h index cacf1033c744a..4ade69bc3a2cf 100644 --- a/tools/optimizer/parser.h +++ b/tools/optimizer/parser.h @@ -681,6 +681,14 @@ class Parser { printf("|\n"); } + NodeRef makeBinary(NodeRef left, IString op, NodeRef right) { + if (op == PERIOD) { + return Builder::makeDot(left, right); + } else { + return Builder::makeBinary(left, op ,right); + } + } + NodeRef parseExpression(ExpressionElement initial, char*&src, const char* seps) { //dump("parseExpression", src); ExpressionParts& parts = expressionPartsStack.back(); @@ -727,7 +735,7 @@ class Parser { IString op = parts[i].getOp(); if (!ops.ops.has(op)) continue; if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) { - parts[i] = Builder::makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); + parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); parts.erase(parts.begin() + i + 1); parts.erase(parts.begin() + i - 1); } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size()-1) { @@ -753,7 +761,7 @@ class Parser { IString op = parts[i].getOp(); if (!ops.ops.has(op)) continue; if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) { - parts[i] = Builder::makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); + parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); parts.erase(parts.begin() + i + 1); parts.erase(parts.begin() + i - 1); i--; diff --git a/tools/optimizer/simple_ast.h b/tools/optimizer/simple_ast.h index b769ea5d95165..db8664b489da5 100644 --- a/tools/optimizer/simple_ast.h +++ b/tools/optimizer/simple_ast.h @@ -1340,11 +1340,6 @@ class ValueBuilder { return &makeRawArray()->push_back(makeRawString(SEQ)) .push_back(left) .push_back(right); - } else if (op == PERIOD) { - assert(right[0] == NAME); - return &makeRawArray()->push_back(makeRawString(DOT)) - .push_back(left) - .push_back(makeRawString(right[1]->getIString())); } else { return &makeRawArray()->push_back(makeRawString(BINARY)) .push_back(makeRawString(op)) @@ -1467,6 +1462,11 @@ class ValueBuilder { .push_back(makeRawString(key)); } + static Ref makeDot(Ref obj, Ref key) { + assert(key[0] == NAME); + return makeDot(obj, key[1]->getIString()); + } + static Ref makeNew(Ref call) { return &makeRawArray()->push_back(makeRawString(NEW)) .push_back(call); diff --git a/tools/shared.py b/tools/shared.py index 93bf1773be815..f0915750344e2 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1258,7 +1258,7 @@ def get_archive_contents(f): # will trample each other when we extract them. to help warn of such situations, we warn if there # are duplicate entries in the archive if len(contents) != len(set(contents)): - logging.warning('loading from archive %s, which has duplicate entries (files with identical names). this is dangerous as only the last will be taken into account, and you may see surprising undefined symbols later. run |llvm-ar t archive.a| to see the list of entries' % f) + logging.warning('loading from archive %s, which has duplicate entries (files with identical base names). this is dangerous as only the last will be taken into account, and you may see surprising undefined symbols later. you should rename source files to avoid this problem (or avoid .a archives, and just link bitcode together to form libraries for later linking)' % f) warned = set() for i in range(len(contents)): curr = contents[i] diff --git a/tools/system_libs.py b/tools/system_libs.py index be7ed51c2ea4a..6c8dbad1ef9ee 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -313,6 +313,10 @@ def create_libcextra(): 'wctrans.c', 'wcwidth.c', ]], + ['dirent', [ + 'alphasort.c', + 'scandir.c', + ]], ['legacy', [ 'err.c', ]],