From 025dea98e497bc2c3e9167850c4ecae9a65785cf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 10:10:49 -0800 Subject: turn fastcomp on by default, disabling can be done with EMCC_FAST_COMPILER=0 in the env --- emcc | 2 +- emscripten.py | 2 +- tests/runner.py | 2 +- tests/test_benchmark.py | 1 - tests/test_browser.py | 12 +++++------- tests/test_core.py | 49 +++++++++++++++++++------------------------------ tests/test_other.py | 16 ++++++++-------- tests/test_sanity.py | 2 +- tools/shared.py | 8 ++++---- 9 files changed, 40 insertions(+), 54 deletions(-) diff --git a/emcc b/emcc index 2c3033aa..906ccb3a 100755 --- a/emcc +++ b/emcc @@ -1200,7 +1200,7 @@ try: logging.warning('disabling asm.js since embind is not ready for it yet') shared.Settings.ASM_JS = 0 - fastcomp = os.environ.get('EMCC_FAST_COMPILER') == '1' + fastcomp = os.environ.get('EMCC_FAST_COMPILER') != '0' if fastcomp: shared.Settings.ASM_JS = 1 if opt_level > 0 else 2 diff --git a/emscripten.py b/emscripten.py index 59a0666c..6b49a3cc 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1257,7 +1257,7 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; if DEBUG: logging.debug(' emscript: final python processing took %s seconds' % (time.time() - t)) -if os.environ.get('EMCC_FAST_COMPILER') == '1': +if os.environ.get('EMCC_FAST_COMPILER') != '0': emscript = emscript_fast def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBUG_CACHE): diff --git a/tests/runner.py b/tests/runner.py index 501299c7..989d4ae6 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -36,7 +36,7 @@ except: # Core test runner class, shared between normal tests and benchmarks checked_sanity = False -if os.environ.get('EMCC_FAST_COMPILER') == '1': +if os.environ.get('EMCC_FAST_COMPILER') != '0': test_modes = ['default', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g'] else: test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g', 'asm2x86', 's_0_0', 's_0_1'] diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index 023ac1e2..2bc34c60 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -134,7 +134,6 @@ try: #JSBenchmarker('sm-f32-3.2', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_2 }), #JSBenchmarker('sm-f32-3.3', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_3 }), #JSBenchmarker('sm-f32-3.4', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_4 }), - #JSBenchmarker('sm-fc', SPIDERMONKEY_ENGINE, env={ 'EMCC_FAST_COMPILER': '1' }), #JSBenchmarker('sm-noasm', SPIDERMONKEY_ENGINE + ['--no-asmjs']), #JSBenchmarker('sm-noasm-f32', SPIDERMONKEY_ENGINE + ['--no-asmjs'], ['-s', 'PRECISE_F32=2']), #JSBenchmarker('v8', V8_ENGINE) diff --git a/tests/test_browser.py b/tests/test_browser.py index c2dbf49b..1eddc846 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -120,8 +120,6 @@ If manually bisecting: ''' def test_emscripten_log(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp uses asm, where call stacks are sometimes less clear') - src = os.path.join(self.get_dir(), 'src.cpp') open(src, 'w').write(self.with_report_result(open(path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp')).read())) @@ -143,7 +141,7 @@ If manually bisecting: os.chdir(cwd) def test_split(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('no --split in fastcomp, deprecated') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('no --split in fastcomp, deprecated') # test HTML generation. self.reftest(path_from_root('tests', 'htmltest.png')) @@ -237,7 +235,7 @@ If manually bisecting: self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') def test_split_in_source_filenames(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('no --split in fastcomp, deprecated') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('no --split in fastcomp, deprecated') self.reftest(path_from_root('tests', 'htmltest.png')) output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '-g', '--split', '100', '--pre-js', 'reftest.js']).communicate() @@ -1493,7 +1491,7 @@ keydown(100);keyup(100); // trigger the end self.btest('sdl_resize.c', '1') def test_gc(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('flaky in fastcomp and also non-fastcomp -O1, timing issues') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('flaky in fastcomp and also non-fastcomp -O1, timing issues') self.btest('browser_gc.cpp', '1') @@ -1703,7 +1701,7 @@ void *getBindBuffer() { self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1']) def test_aniso(self): - if SPIDERMONKEY_ENGINE in JS_ENGINES and os.environ.get('EMCC_FAST_COMPILER') != '1': + if SPIDERMONKEY_ENGINE in JS_ENGINES: # asm.js-ification check Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1']).communicate() Settings.ASM_JS = 1 @@ -1763,7 +1761,7 @@ void *getBindBuffer() { self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')]) def test_module(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate() self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8') diff --git a/tests/test_core.py b/tests/test_core.py index b96cbc36..f155d446 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -529,17 +529,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co finally: os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size - assert 'asm1' in test_modes - if self.run_name == 'asm1' and not os.environ.get('EMCC_FAST_COMPILER'): - assert Settings.RELOOP - generated = open('src.cpp.o.js').read() - main = generated[generated.find('function _main'):] - main = main[:main.find('\n}')] - num_vars = 0 - for v in re.findall('var [^;]+;', main): - num_vars += v.count(',') + 1 - assert num_vars == 10, 'no variable elimination should have been run, but seeing %d' % num_vars - def test_unaligned(self): if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1') @@ -951,7 +940,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co for named in (0, 1): print named - if os.environ.get('EMCC_FAST_COMPILER') == '1' and named: continue # no named globals in fastcomp + if os.environ.get('EMCC_FAST_COMPILER') != '0' and named: continue # no named globals in fastcomp Settings.NAMED_GLOBALS = named self.do_run_from_file(src, output, ['wowie', 'too', '74']) @@ -1138,7 +1127,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_longjmp_repeat(self): - if os.environ.get('EMCC_FAST_COMPILER') != '1': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too + if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too test_path = path_from_root('tests', 'core', 'test_longjmp_repeat') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) @@ -1162,7 +1151,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_setjmp_many(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect') src = r''' #include @@ -1930,7 +1919,7 @@ def process(filename): def test_inlinejs(self): if not self.is_le32(): return self.skip('le32 needed for inline js') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp only supports EM_ASM') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp only supports EM_ASM') test_path = path_from_root('tests', 'core', 'test_inlinejs') src, output = (test_path + s for s in ('.in', '.out')) @@ -1943,7 +1932,7 @@ def process(filename): def test_inlinejs2(self): if not self.is_le32(): return self.skip('le32 needed for inline js') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp only supports EM_ASM') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp only supports EM_ASM') test_path = path_from_root('tests', 'core', 'test_inlinejs2') src, output = (test_path + s for s in ('.in', '.out')) @@ -2749,7 +2738,7 @@ The current type of b is: 9 self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.') def can_dlfcn(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': + if os.environ.get('EMCC_FAST_COMPILER') != '0': self.skip('todo in fastcomp') return False @@ -3171,7 +3160,7 @@ def process(filename): def test_dlfcn_self(self): if Settings.USE_TYPED_ARRAYS == 1: return self.skip('Does not work with USE_TYPED_ARRAYS=1') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') Settings.DLOPEN_SUPPORT = 1 def post(filename): @@ -4673,7 +4662,7 @@ return malloc(size); main = main[:main.find('\n}')] assert main.count('\n') <= 7, ('must not emit too many postSets: %d' % main.count('\n')) + ' : ' + main - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp always aliases pointers') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp always aliases pointers') assert 'asm2g' in test_modes if self.run_name == 'asm2g': @@ -4721,7 +4710,7 @@ return malloc(size); self.do_run_from_file(src, output) def test_gcc_unmangler(self): - if os.environ.get('EMCC_FAST_COMPILER') != '1': Settings.NAMED_GLOBALS = 1 # test coverage for this; fastcomp never names globals + if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.NAMED_GLOBALS = 1 # test coverage for this; fastcomp never names globals Building.COMPILER_TEST_OPTS += ['-I' + path_from_root('third_party'), '-Wno-warn-absolute-paths'] @@ -4892,7 +4881,7 @@ def process(filename): test() assert 'asm2g' in test_modes - if self.run_name == 'asm2g' and not use_cmake and os.environ.get('EMCC_FAST_COMPILER') != '1': + if self.run_name == 'asm2g' and not use_cmake and os.environ.get('EMCC_FAST_COMPILER') == '0': # Test forced alignment print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY' old = open('src.cpp.o.js').read() @@ -5125,7 +5114,7 @@ def process(filename): for name in glob.glob(path_from_root('tests', 'cases', '*.ll')): shortname = name.replace('.ll', '') if '' not in shortname: continue - if os.environ.get('EMCC_FAST_COMPILER') == '1' and os.path.basename(shortname) in [ + if os.environ.get('EMCC_FAST_COMPILER') != '0' and os.path.basename(shortname) in [ 'structparam', 'extendedprecision', 'issue_39', 'emptystruct', 'phinonexist', 'quotedlabel', 'oob_ta2', 'phientryimplicit', 'phiself', 'invokebitcast', 'funcptr', # invalid ir 'structphiparam', 'callwithstructural_ta2', 'callwithstructural64_ta2', 'structinparam', # pnacl limitations in ExpandStructRegs '2xi40', # pnacl limitations in ExpandGetElementPtr @@ -5141,7 +5130,7 @@ def process(filename): if '_le32' in shortname and not self.is_le32(): print self.skip('case "%s" not relevant for non-le32 target' % shortname) continue - if '_fastcomp' in shortname and not os.environ.get('EMCC_FAST_COMPILER') == '1': + if '_fastcomp' in shortname and not os.environ.get('EMCC_FAST_COMPILER') != '0': print self.skip('case "%s" not relevant for non-fastcomp' % shortname) continue self.emcc_args = emcc_args @@ -5180,7 +5169,7 @@ def process(filename): for name in glob.glob(path_from_root('tests', 'fuzz', '*.c')) + glob.glob(path_from_root('tests', 'fuzz', '*.cpp')): #if os.path.basename(name) != '4.c': continue if 'newfail' in name: continue - if os.path.basename(name) == '18.cpp' and not os.environ.get('EMCC_FAST_COMPILER') == '1': continue # works only in fastcomp + if os.path.basename(name) == '18.cpp' and not os.environ.get('EMCC_FAST_COMPILER') != '0': continue # works only in fastcomp print name self.do_run(open(path_from_root('tests', 'fuzz', name)).read(), @@ -5420,7 +5409,7 @@ def process(filename): def test_asm_pgo(self): if not Settings.ASM_JS: return self.skip('this is a test for PGO for asm (NB: not *in* asm)') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') src = open(path_from_root('tests', 'hello_libcxx.cpp')).read() output = 'hello, world!' @@ -5540,7 +5529,7 @@ def process(filename): def test_embind(self): if self.emcc_args is None: return self.skip('requires emcc') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') Building.COMPILER_TEST_OPTS += ['--bind'] src = r''' @@ -5563,7 +5552,7 @@ def process(filename): def test_embind_2(self): if self.emcc_args is None: return self.skip('requires emcc') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') Building.COMPILER_TEST_OPTS += ['--bind', '--post-js', 'post.js'] open('post.js', 'w').write(''' Module.print('lerp ' + Module.lerp(1, 2, 0.66) + '.'); @@ -6397,7 +6386,7 @@ def process(filename): def test_minmax(self): if self.emcc_args == None: return self.skip('needs emcc') - if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('this test will not pass in the old compiler') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('this test will not pass in the old compiler') self.do_run(open(path_from_root('tests', 'test_minmax.c')).read(), 'NAN != NAN\nSuccess!') def test_locale(self): @@ -6488,7 +6477,7 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, return TT # Make one run with the defaults -default = make_run("default", compiler=CLANG, emcc_args=[] if os.environ.get('EMCC_FAST_COMPILER') != '1' else ['-s', 'ASM_JS=1']) +default = make_run("default", compiler=CLANG, emcc_args=[] if os.environ.get('EMCC_FAST_COMPILER') == '0' else ['-s', 'ASM_JS=1']) # Make one run with -O1, with safe heap o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=0", "-s", "SAFE_HEAP=1"]) @@ -6501,7 +6490,7 @@ asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1"]) asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"]) asm3 = make_run("asm3", compiler=CLANG, emcc_args=["-O3"]) asm2f = make_run("asm2f", compiler=CLANG, emcc_args=["-O2", "-s", "PRECISE_F32=1"]) -if os.environ.get('EMCC_FAST_COMPILER') == '1': +if os.environ.get('EMCC_FAST_COMPILER') != '0': asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "SAFE_HEAP=1"]) else: asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "CHECK_HEAP_ALIGN=1"]) diff --git a/tests/test_other.py b/tests/test_other.py index b4abf275..c3054247 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -207,7 +207,7 @@ Options that are modified or new in %s include: ]: print params, text self.clear() - if os.environ.get('EMCC_FAST_COMPILER') == '1' and ['disable typed arrays', 'typed arrays 1 selected']: continue + if os.environ.get('EMCC_FAST_COMPILER') != '0' and ['disable typed arrays', 'typed arrays 1 selected']: continue output = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('a.out.js'), '\n'.join(output) @@ -451,7 +451,7 @@ f.close() self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_unaligned_memory(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' #include @@ -477,7 +477,7 @@ f.close() self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_unaligned_memory_2(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' #include @@ -542,7 +542,7 @@ f.close() self.assertContained(expected, run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True)) return open(self.in_dir('a.out.js')).read() - if os.environ.get('EMCC_FAST_COMPILER') != '1': + if os.environ.get('EMCC_FAST_COMPILER') == '0': test([], 'my func') # no asm, so casting func works test(['-O2'], 'abort', ['Casting potentially incompatible function pointer i32 ()* to void (...)*, for my_func', 'Incompatible function pointer casts are very dangerous with ASM_JS=1, you should investigate and correct these']) # asm, so failure @@ -590,7 +590,7 @@ This pointer might make sense in another type signature: i: _my_func assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs' def test_static_link(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') def test(name, header, main, side, expected, args=[], suffix='cpp', first=True): print name @@ -1817,7 +1817,7 @@ This pointer might make sense in another type signature: i: _my_func assert 'error' not in err, 'Unexpected stderr: ' + err def test_chunking(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('not relevant for fastcomp, only checks js compiler chunking') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('not relevant for fastcomp, only checks js compiler chunking') if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') if os.environ.get('EMCC_CORES'): return self.skip('cannot run if cores are altered') if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores') @@ -1868,7 +1868,7 @@ This pointer might make sense in another type signature: i: _my_func assert 'If you see this - the world is all right!' in output def test_embind(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') for args, fail in [ ([], True), # without --bind, we fail (['--bind'], False), @@ -2362,7 +2362,7 @@ int main() { assert '*** PCH/Modules Loaded:\nModule: header.h.gch' not in err[1], err[1] def test_warn_unaligned(self): - if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('need fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('need fastcomp') open('src.cpp', 'w').write(r''' #include static const double grid[4][2] = {{-3 / 3., -1 / 3.}, diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 894f2192..4e01add8 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -196,7 +196,7 @@ class sanity(RunnerCore): del os.environ['EM_IGNORE_SANITY'] def test_llvm_fastcomp(self): - if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('not using fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('not using fastcomp') WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target' diff --git a/tools/shared.py b/tools/shared.py index 1a1026f3..28a3ff10 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -379,7 +379,7 @@ def check_sanity(force=False): # some warning, mostly not fatal checks - do them even if EM_IGNORE_SANITY is on check_llvm_version() check_node_version() - if os.environ.get('EMCC_FAST_COMPILER') == '1': + if os.environ.get('EMCC_FAST_COMPILER') != '0': fastcomp_ok = check_fastcomp() if os.environ.get('EM_IGNORE_SANITY'): @@ -402,7 +402,7 @@ def check_sanity(force=False): logging.critical('Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG)) sys.exit(1) - if os.environ.get('EMCC_FAST_COMPILER') == '1': + if os.environ.get('EMCC_FAST_COMPILER') != '0': if not fastcomp_ok: logging.critical('failing sanity checks due to previous fastcomp failure') sys.exit(1) @@ -1467,7 +1467,7 @@ class Building: @staticmethod def ensure_relooper(relooper): if os.path.exists(relooper): return - if os.environ.get('EMCC_FAST_COMPILER') == '1': + if os.environ.get('EMCC_FAST_COMPILER') != '0': logging.debug('not building relooper to js, using it in c++ backend') return @@ -1542,7 +1542,7 @@ class Building: text = m.groups(0)[0] assert text.count('(') == 1 and text.count(')') == 1, 'must have simple expressions in emscripten_jcache_printf calls, no parens' assert text.count('"') == 2, 'must have simple expressions in emscripten_jcache_printf calls, no strings as varargs parameters' - if os.environ.get('EMCC_FAST_COMPILER') == '1': # fake it in fastcomp + if os.environ.get('EMCC_FAST_COMPILER') != '0': # fake it in fastcomp return text.replace('emscripten_jcache_printf', 'printf') start = text.index('(') end = text.rindex(')') -- cgit v1.2.3-18-g5258 From 4d715bca8971203dd5a68b15129ef1feaaff5356 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 10:52:02 -0800 Subject: adjust main test modes for fastcomp: remove asm2x86 except for one test, and add two modes for legacy non-fastcomp -O2 with and without asm --- tests/runner.py | 5 +-- tests/test_core.py | 100 +++++++++++++++++++++++++---------------------------- 2 files changed, 49 insertions(+), 56 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 989d4ae6..7b99ae18 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -36,10 +36,7 @@ except: # Core test runner class, shared between normal tests and benchmarks checked_sanity = False -if os.environ.get('EMCC_FAST_COMPILER') != '0': - test_modes = ['default', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g'] -else: - test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g', 'asm2x86', 's_0_0', 's_0_1'] +test_modes = ['default', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g', 'slow2', 'slow2asm', 's_0_0', 's_0_1'] test_index = 0 class RunnerCore(unittest.TestCase): diff --git a/tests/test_core.py b/tests/test_core.py index f155d446..75ecec84 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -512,22 +512,45 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read()) def test_cube2hash(self): - try: - old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or '' - os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here) - - # A good test of i64 math - if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing') - self.do_run('', 'Usage: hashstring ', - libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None), - includes=[path_from_root('tests', 'cube2hash')]) - - for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'), - ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'), - ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]: - self.do_run('', 'hash value: ' + output, [text], no_build=True) - finally: - os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size + # extra testing for various codegen modes + for x86 in [0, 1] if self.run_name == 'asm2' else [0]: + print 'x86', x86 + try: + old_x86 = os.environ.get('EMCC_LLVM_TARGET') or '' + if x86: + os.environ['EMCC_LLVM_TARGET'] = "i386-pc-linux-gnu" + try: + old_fastcomp = os.environ.get('EMCC_FAST_COMPILER') or '' + if x86: + os.environ['EMCC_FAST_COMPILER'] = "0" + try: + old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or '' + os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here) + + # A good test of i64 math + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing') + self.do_run('', 'Usage: hashstring ', + libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None, cache_name_extra=str(x86)), + includes=[path_from_root('tests', 'cube2hash')]) + + for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'), + ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'), + ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]: + self.do_run('', 'hash value: ' + output, [text], no_build=True) + finally: + os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size + finally: + if x86: + if old_fastcomp: + os.environ['EMCC_FAST_COMPILER'] = old_fastcomp + else: + del os.environ['EMCC_FAST_COMPILER'] + finally: + if x86: + if old_x86: + os.environ['EMCC_LLVM_TARGET'] = old_x86 + else: + del os.environ['EMCC_LLVM_TARGET'] def test_unaligned(self): if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1') @@ -4662,25 +4685,6 @@ return malloc(size); main = main[:main.find('\n}')] assert main.count('\n') <= 7, ('must not emit too many postSets: %d' % main.count('\n')) + ' : ' + main - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp always aliases pointers') - - assert 'asm2g' in test_modes - if self.run_name == 'asm2g': - results = {} - original = open('src.cpp.o.js').read() - results[Settings.ALIASING_FUNCTION_POINTERS] = len(original) - Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS - self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp') - final = open('src.cpp.o.js').read() - results[Settings.ALIASING_FUNCTION_POINTERS] = len(final) - open('original.js', 'w').write(original) - print results - assert results[1] < 0.99*results[0] - assert ' & 3]()' in original, 'small function table exists' - assert ' & 3]()' not in final, 'small function table does not exist' - assert ' & 255]()' not in original, 'big function table does not exist' - assert ' & 255]()' in final, 'big function table exists' - def test_simd(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate @@ -6476,27 +6480,19 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, return TT -# Make one run with the defaults -default = make_run("default", compiler=CLANG, emcc_args=[] if os.environ.get('EMCC_FAST_COMPILER') == '0' else ['-s', 'ASM_JS=1']) - -# Make one run with -O1, with safe heap -o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=0", "-s", "SAFE_HEAP=1"]) - -# Make one run with -O2, but without closure (we enable closure in specific tests, otherwise on everything it is too slow) -o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"]) - -# asm.js +# Main test modes +default = make_run("default", compiler=CLANG, emcc_args=[]) asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1"]) asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"]) asm3 = make_run("asm3", compiler=CLANG, emcc_args=["-O3"]) asm2f = make_run("asm2f", compiler=CLANG, emcc_args=["-O2", "-s", "PRECISE_F32=1"]) -if os.environ.get('EMCC_FAST_COMPILER') != '0': - asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "SAFE_HEAP=1"]) -else: - asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "CHECK_HEAP_ALIGN=1"]) -asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env={"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}) +asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "SAFE_HEAP=1"]) + +# Legacy test modes - +slow2 = make_run("slow2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0"], env={"EMCC_FAST_COMPILER": "0"}) +slow2asm = make_run("slow2asm", compiler=CLANG, emcc_args=["-O2"], env={"EMCC_FAST_COMPILER": "0"}) -# Make custom runs with various options +# Legacy test modes - very old for compiler, quantum, embetter, typed_arrays in [ (CLANG, 4, 0, 0), (CLANG, 4, 1, 1), @@ -6504,6 +6500,6 @@ for compiler, quantum, embetter, typed_arrays in [ fullname = 's_0_%d%s%s' % ( embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays) ) - locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays) + locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays, env={"EMCC_FAST_COMPILER": "0"}) del T # T is just a shape for the specific subclasses, we don't test it itself -- cgit v1.2.3-18-g5258 From d484101045f135b226bc3c1d3b4948baa356b124 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 10:58:18 -0800 Subject: avoid warning about aliasing function pointers in fastcomp, it has good debug info on assertions 1 and especially 2 anyhow --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index 906ccb3a..7743c9a8 100755 --- a/emcc +++ b/emcc @@ -1284,7 +1284,7 @@ try: shared.Settings.LINKABLE = 1 # TODO: add FORCE_DCE option for the brave people that do want to dce here and in side modules debug_level = max(debug_level, 2) - if shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS: + if not fastcomp and shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS: logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types') if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES: -- cgit v1.2.3-18-g5258 From 91745dd0c857bfe52100ea2876325af85fb7b016 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 11:57:30 -0800 Subject: add message pointing people to the fastcomp wiki page that explains how to disable it, when a compiler setting is not fastcomp-compatible --- emcc | 33 +++++++++++++++++++-------------- tests/test_sanity.py | 4 ++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/emcc b/emcc index 7743c9a8..36532d16 100755 --- a/emcc +++ b/emcc @@ -1204,20 +1204,25 @@ try: if fastcomp: shared.Settings.ASM_JS = 1 if opt_level > 0 else 2 - assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp' - assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet' - assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp' - assert shared.Settings.ASM_HEAP_LOG == 0, 'asm heap log not supported in fastcomp' - assert shared.Settings.LABEL_DEBUG == 0, 'label debug not supported in fastcomp' - assert shared.Settings.EXECUTION_TIMEOUT == -1, 'execution timeout not supported in fastcomp' - assert shared.Settings.NAMED_GLOBALS == 0, 'named globals not supported in fastcomp' - assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp' - assert shared.Settings.TARGET_LE32 == 1, 'fastcomp requires le32' - assert shared.Settings.USE_TYPED_ARRAYS == 2, 'fastcomp assumes ta2' - assert not split_js_file, '--split-js is deprecated and not supported in fastcomp' - assert not bind, 'embind not supported in fastcomp yet' - assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet' - assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)' + try: + assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp' + assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet' + assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp' + assert shared.Settings.ASM_HEAP_LOG == 0, 'asm heap log not supported in fastcomp' + assert shared.Settings.LABEL_DEBUG == 0, 'label debug not supported in fastcomp' + assert shared.Settings.EXECUTION_TIMEOUT == -1, 'execution timeout not supported in fastcomp' + assert shared.Settings.NAMED_GLOBALS == 0, 'named globals not supported in fastcomp' + assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp' + assert shared.Settings.TARGET_LE32 == 1, 'fastcomp requires le32' + assert shared.Settings.USE_TYPED_ARRAYS == 2, 'fastcomp assumes ta2' + assert not split_js_file, '--split-js is deprecated and not supported in fastcomp' + assert not bind, 'embind not supported in fastcomp yet' + assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet' + assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)' + except Exception, e: + logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') + raise e + if jcache: logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling') jcache = False diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 4e01add8..34f98fde 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -223,6 +223,10 @@ class sanity(RunnerCore): os.chmod(path_from_root('tests', 'fake', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) output = self.check_working(EMCC, WARNING) + restore() + + self.check_working([EMCC, 'tests/hello_world.cpp', '-s', 'INIT_HEAP=1'], '''Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend''') + def test_node(self): NODE_WARNING = 'node version appears too old' NODE_WARNING_2 = 'cannot check node version' -- cgit v1.2.3-18-g5258 From 306fa23df2d683a4c6a95c603bd57b440139c092 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:01:24 -0800 Subject: assume fastcomp in fastcomp sanity test --- tests/test_sanity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 34f98fde..123c25a2 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -196,7 +196,7 @@ class sanity(RunnerCore): del os.environ['EM_IGNORE_SANITY'] def test_llvm_fastcomp(self): - if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('not using fastcomp') + assert os.environ.get('EMCC_FAST_COMPILER') != '0', 'must be using fastcomp to test fastcomp' WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target' -- cgit v1.2.3-18-g5258 From ef2608dc9701395be413819d56514fab410afd4f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:07:52 -0800 Subject: point to wiki page on fastcomp when using fastcomp but backend is not present --- tests/test_sanity.py | 3 +++ tools/shared.py | 1 + 2 files changed, 4 insertions(+) diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 123c25a2..38da3988 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -199,6 +199,7 @@ class sanity(RunnerCore): assert os.environ.get('EMCC_FAST_COMPILER') != '0', 'must be using fastcomp to test fastcomp' WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target' + WARNING2 = 'you can fall back to the older (pre-fastcomp) compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend' restore() @@ -206,6 +207,7 @@ class sanity(RunnerCore): assert check_fastcomp() output = self.check_working(EMCC) assert WARNING not in output, output + assert WARNING2 not in output, output # Fake incorrect llc output, no mention of js backend restore() @@ -222,6 +224,7 @@ class sanity(RunnerCore): f.close() os.chmod(path_from_root('tests', 'fake', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) output = self.check_working(EMCC, WARNING) + output = self.check_working(EMCC, WARNING2) restore() diff --git a/tools/shared.py b/tools/shared.py index 28a3ff10..79542926 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -303,6 +303,7 @@ def check_fastcomp(): print >> sys.stderr, '===========================================================================' print >> sys.stderr, llc_version_info, print >> sys.stderr, '===========================================================================' + logging.critical('you can fall back to the older (pre-fastcomp) compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') return False return True except Exception, e: -- cgit v1.2.3-18-g5258 From ce030db1c879ba62fe8ebfde97373febea9988b2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:14:10 -0800 Subject: fix sanity.test_relooper --- tests/test_sanity.py | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 38da3988..54a0e99d 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -453,27 +453,34 @@ fi try_delete(CANONICAL_TEMP_DIR) def test_relooper(self): - RELOOPER = Cache.get_path('relooper.js') + assert os.environ.get('EMCC_FAST_COMPILER') is None - restore() - for phase in range(2): # 0: we wipe the relooper dir. 1: we have it, so should just update - if phase == 0: Cache.erase() - try_delete(RELOOPER) + try: + os.environ['EMCC_FAST_COMPILER'] = '0' - for i in range(4): - print >> sys.stderr, phase, i - opt = min(i, 2) - try_delete('a.out.js') - output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt), '-g'], - stdout=PIPE, stderr=PIPE).communicate() - self.assertContained('hello, world!', run_js('a.out.js')) - output = '\n'.join(output) - assert ('bootstrapping relooper succeeded' in output) == (i == 1), 'only bootstrap on first O2: ' + output - assert os.path.exists(RELOOPER) == (i >= 1), 'have relooper on O2: ' + output - src = open('a.out.js').read() - main = src.split('function _main()')[1].split('\n}\n')[0] - assert ('while (1) {' in main or 'while(1){' in main or 'while(1) {' in main or '} while ($' in main or '}while($' in main) == (i >= 1), 'reloop code on O2: ' + main - assert ('switch' not in main) == (i >= 1), 'reloop code on O2: ' + main + RELOOPER = Cache.get_path('relooper.js') + + restore() + for phase in range(2): # 0: we wipe the relooper dir. 1: we have it, so should just update + if phase == 0: Cache.erase() + try_delete(RELOOPER) + + for i in range(4): + print >> sys.stderr, phase, i + opt = min(i, 2) + try_delete('a.out.js') + output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt), '-g'], + stdout=PIPE, stderr=PIPE).communicate() + self.assertContained('hello, world!', run_js('a.out.js')) + output = '\n'.join(output) + assert ('bootstrapping relooper succeeded' in output) == (i == 1), 'only bootstrap on first O2: ' + output + assert os.path.exists(RELOOPER) == (i >= 1), 'have relooper on O2: ' + output + src = open('a.out.js').read() + main = src.split('function _main()')[1].split('\n}\n')[0] + assert ('while (1) {' in main or 'while(1){' in main or 'while(1) {' in main or '} while ($' in main or '}while($' in main) == (i >= 1), 'reloop code on O2: ' + main + assert ('switch' not in main) == (i >= 1), 'reloop code on O2: ' + main + finally: + del os.environ['EMCC_FAST_COMPILER'] def test_jcache(self): PRE_LOAD_MSG = 'loading pre from jcache' -- cgit v1.2.3-18-g5258 From f220d76a838b0c92abdc24ebad6961122ba3ffc1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:18:13 -0800 Subject: bump expected llvm version to 3.3, which is what fastcomp uses --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 79542926..31dc64b1 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -270,7 +270,7 @@ if EM_POPEN_WORKAROUND and os.name == 'nt': # Expectations -EXPECTED_LLVM_VERSION = (3,2) +EXPECTED_LLVM_VERSION = (3,3) actual_clang_version = None -- cgit v1.2.3-18-g5258 From 9b61c432ec25cb55314b5cf0f45047aabee606b1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:32:52 -0800 Subject: make non-fastcomp tests in other run in non-fastcomp mode --- tests/runner.py | 13 + tests/test_other.py | 666 ++++++++++++++++++++++++++-------------------------- 2 files changed, 349 insertions(+), 330 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 7b99ae18..32575a1a 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -27,6 +27,19 @@ sys.path += [path_from_root(''), path_from_root('third_party/websockify')] import tools.shared from tools.shared import * +# Utils + +def nonfastcomp(test): + try: + old_fastcomp = os.environ.get('EMCC_FAST_COMPILER') + os.environ['EMCC_FAST_COMPILER'] = '0' + test() + finally: + if old_fastcomp is None: + del os.environ['EMCC_FAST_COMPILER'] + else: + os.environ['EMCC_FAST_COMPILER'] = old_fastcomp + # Sanity check for config try: diff --git a/tests/test_other.py b/tests/test_other.py index c3054247..b307b888 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1,7 +1,7 @@ import multiprocessing, os, re, shutil, subprocess, sys import tools.shared from tools.shared import * -from runner import RunnerCore, path_from_root, get_bullet_library +from runner import RunnerCore, path_from_root, get_bullet_library, nonfastcomp class other(RunnerCore): def get_zlib_library(self): @@ -451,48 +451,48 @@ f.close() self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_unaligned_memory(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') - - open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' - #include - #include + def test(): + open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' + #include + #include - typedef unsigned char Bit8u; - typedef unsigned short Bit16u; - typedef unsigned int Bit32u; + typedef unsigned char Bit8u; + typedef unsigned short Bit16u; + typedef unsigned int Bit32u; - int main() - { - va_list argp; - va_arg(argp, char *); // check for compilation error, #1705 + int main() + { + va_list argp; + va_arg(argp, char *); // check for compilation error, #1705 - Bit8u data[4] = {0x01,0x23,0x45,0x67}; + Bit8u data[4] = {0x01,0x23,0x45,0x67}; - printf("data: %x\n", *(Bit32u*)data); - printf("data[0,1] 16bit: %x\n", *(Bit16u*)data); - printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1)); - } - ''') - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() - self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + printf("data: %x\n", *(Bit32u*)data); + printf("data[0,1] 16bit: %x\n", *(Bit16u*)data); + printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1)); + } + ''') + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() + self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + nonfastcomp(test) def test_unaligned_memory_2(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') - - open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' - #include - #include + def test(): + open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' + #include + #include - int main( int argc, char ** argv ) - { - std::string testString( "Hello, World!" ); + int main( int argc, char ** argv ) + { + std::string testString( "Hello, World!" ); - printf( "testString = %s\n", testString.c_str() ); - return 0; - } - ''') - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() - self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + printf( "testString = %s\n", testString.c_str() ); + return 0; + } + ''') + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() + self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + nonfastcomp(test) def test_asm_minify(self): def test(args): @@ -590,283 +590,285 @@ This pointer might make sense in another type signature: i: _my_func assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs' def test_static_link(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') - - def test(name, header, main, side, expected, args=[], suffix='cpp', first=True): - print name - #t = main ; main = side ; side = t - original_main = main - original_side = side - if header: open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header) - if type(main) == str: - open(os.path.join(self.get_dir(), 'main.' + suffix), 'w').write(main) - main = ['main.' + suffix] - if type(side) == str: - open(os.path.join(self.get_dir(), 'side.' + suffix), 'w').write(side) - side = ['side.' + suffix] - Popen([PYTHON, EMCC] + side + ['-o', 'side.js', '-s', 'SIDE_MODULE=1', '-O2'] + args).communicate() - # TODO: test with and without DISABLE_GL_EMULATION, check that file sizes change - Popen([PYTHON, EMCC] + main + ['-o', 'main.js', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'DISABLE_GL_EMULATION=1'] + args).communicate() - Popen([PYTHON, EMLINK, 'main.js', 'side.js', 'together.js'], stdout=PIPE).communicate() - assert os.path.exists('together.js') - for engine in JS_ENGINES: - out = run_js('together.js', engine=engine, stderr=PIPE, full_output=True) - self.assertContained(expected, out) - if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out) - if first: - shutil.copyfile('together.js', 'first.js') - test(name + ' (reverse)', header, original_side, original_main, expected, args, suffix, False) # test reverse order - - # test a simple call from one module to another. only one has a string (and constant memory initialization for it) - test('basics', '', ''' - #include - extern int sidey(); - int main() { - printf("other says %d.", sidey()); - return 0; - } - ''', ''' - int sidey() { return 11; } - ''', 'other says 11.') - - # finalization of float variables should pass asm.js validation - test('floats', '', ''' - #include - extern float sidey(); - int main() { - printf("other says %.2f.", sidey()+1); - return 0; - } - ''', ''' - float sidey() { return 11.5; } - ''', 'other says 12.50') + def nonfc(): + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') + + def test(name, header, main, side, expected, args=[], suffix='cpp', first=True): + print name + #t = main ; main = side ; side = t + original_main = main + original_side = side + if header: open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header) + if type(main) == str: + open(os.path.join(self.get_dir(), 'main.' + suffix), 'w').write(main) + main = ['main.' + suffix] + if type(side) == str: + open(os.path.join(self.get_dir(), 'side.' + suffix), 'w').write(side) + side = ['side.' + suffix] + Popen([PYTHON, EMCC] + side + ['-o', 'side.js', '-s', 'SIDE_MODULE=1', '-O2'] + args).communicate() + # TODO: test with and without DISABLE_GL_EMULATION, check that file sizes change + Popen([PYTHON, EMCC] + main + ['-o', 'main.js', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'DISABLE_GL_EMULATION=1'] + args).communicate() + Popen([PYTHON, EMLINK, 'main.js', 'side.js', 'together.js'], stdout=PIPE).communicate() + assert os.path.exists('together.js') + for engine in JS_ENGINES: + out = run_js('together.js', engine=engine, stderr=PIPE, full_output=True) + self.assertContained(expected, out) + if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out) + if first: + shutil.copyfile('together.js', 'first.js') + test(name + ' (reverse)', header, original_side, original_main, expected, args, suffix, False) # test reverse order + + # test a simple call from one module to another. only one has a string (and constant memory initialization for it) + test('basics', '', ''' + #include + extern int sidey(); + int main() { + printf("other says %d.", sidey()); + return 0; + } + ''', ''' + int sidey() { return 11; } + ''', 'other says 11.') - # memory initialization in both - test('multiple memory inits', '', r''' - #include - extern void sidey(); - int main() { - printf("hello from main\n"); - sidey(); - return 0; - } - ''', r''' - #include - void sidey() { printf("hello from side\n"); } - ''', 'hello from main\nhello from side\n') + # finalization of float variables should pass asm.js validation + test('floats', '', ''' + #include + extern float sidey(); + int main() { + printf("other says %.2f.", sidey()+1); + return 0; + } + ''', ''' + float sidey() { return 11.5; } + ''', 'other says 12.50') - # function pointers - test('fp1', 'typedef void (*voidfunc)();', r''' - #include - #include "header.h" - voidfunc sidey(voidfunc f); - void a() { printf("hello from funcptr\n"); } - int main() { - sidey(a)(); - return 0; - } - ''', ''' - #include "header.h" - voidfunc sidey(voidfunc f) { return f; } - ''', 'hello from funcptr\n') + # memory initialization in both + test('multiple memory inits', '', r''' + #include + extern void sidey(); + int main() { + printf("hello from main\n"); + sidey(); + return 0; + } + ''', r''' + #include + void sidey() { printf("hello from side\n"); } + ''', 'hello from main\nhello from side\n') - # function pointers with 'return' in the name - test('fp2', 'typedef void (*voidfunc)();', r''' - #include - #include "header.h" - int sidey(voidfunc f); - void areturn0() { printf("hello 0\n"); } - void areturn1() { printf("hello 1\n"); } - void areturn2() { printf("hello 2\n"); } - int main(int argc, char **argv) { - voidfunc table[3] = { areturn0, areturn1, areturn2 }; - table[sidey(NULL)](); - return 0; - } - ''', ''' - #include "header.h" - int sidey(voidfunc f) { if (f) f(); return 1; } - ''', 'hello 1\n') + # function pointers + test('fp1', 'typedef void (*voidfunc)();', r''' + #include + #include "header.h" + voidfunc sidey(voidfunc f); + void a() { printf("hello from funcptr\n"); } + int main() { + sidey(a)(); + return 0; + } + ''', ''' + #include "header.h" + voidfunc sidey(voidfunc f) { return f; } + ''', 'hello from funcptr\n') - # Global initializer - test('global init', '', r''' - #include - struct Class { - Class() { printf("a new Class\n"); } - }; - static Class c; - int main() { - return 0; - } - ''', r''' - void nothing() {} - ''', 'a new Class\n') + # function pointers with 'return' in the name + test('fp2', 'typedef void (*voidfunc)();', r''' + #include + #include "header.h" + int sidey(voidfunc f); + void areturn0() { printf("hello 0\n"); } + void areturn1() { printf("hello 1\n"); } + void areturn2() { printf("hello 2\n"); } + int main(int argc, char **argv) { + voidfunc table[3] = { areturn0, areturn1, areturn2 }; + table[sidey(NULL)](); + return 0; + } + ''', ''' + #include "header.h" + int sidey(voidfunc f) { if (f) f(); return 1; } + ''', 'hello 1\n') - # Multiple global initializers (LLVM generates overlapping names for them) - test('global inits', r''' - #include - struct Class { - Class(const char *name) { printf("new %s\n", name); } - }; - ''', r''' - #include "header.h" - static Class c("main"); - int main() { - return 0; - } - ''', r''' - #include "header.h" - static Class c("side"); - ''', ['new main\nnew side\n', 'new side\nnew main\n']) + # Global initializer + test('global init', '', r''' + #include + struct Class { + Class() { printf("a new Class\n"); } + }; + static Class c; + int main() { + return 0; + } + ''', r''' + void nothing() {} + ''', 'a new Class\n') - # Class code used across modules - test('codecall', r''' - #include - struct Class { - Class(const char *name); - }; - ''', r''' - #include "header.h" - int main() { - Class c("main"); - return 0; - } - ''', r''' - #include "header.h" - Class::Class(const char *name) { printf("new %s\n", name); } - ''', ['new main\n']) - - # malloc usage in both modules - test('malloc', r''' - #include - #include - char *side(const char *data); - ''', r''' - #include - #include "header.h" - int main() { - char *temp = side("hello through side\n"); - char *ret = (char*)malloc(strlen(temp)+1); - strcpy(ret, temp); - temp[1] = 'x'; - puts(ret); - return 0; - } - ''', r''' - #include "header.h" - char *side(const char *data) { - char *ret = (char*)malloc(strlen(data)+1); - strcpy(ret, data); - return ret; - } - ''', ['hello through side\n']) + # Multiple global initializers (LLVM generates overlapping names for them) + test('global inits', r''' + #include + struct Class { + Class(const char *name) { printf("new %s\n", name); } + }; + ''', r''' + #include "header.h" + static Class c("main"); + int main() { + return 0; + } + ''', r''' + #include "header.h" + static Class c("side"); + ''', ['new main\nnew side\n', 'new side\nnew main\n']) - # js library call - open('lib.js', 'w').write(r''' - mergeInto(LibraryManager.library, { - test_lib_func: function(x) { - return x + 17.2; + # Class code used across modules + test('codecall', r''' + #include + struct Class { + Class(const char *name); + }; + ''', r''' + #include "header.h" + int main() { + Class c("main"); + return 0; } - }); - ''') - test('js-lib', 'extern "C" { extern double test_lib_func(int input); }', r''' - #include - #include "header.h" - extern double sidey(); - int main2() { return 11; } - int main() { - int input = sidey(); - double temp = test_lib_func(input); - printf("other says %.2f\n", temp); - printf("more: %.5f, %d\n", temp, input); - return 0; - } - ''', r''' - #include - #include "header.h" - extern int main2(); - double sidey() { - int temp = main2(); - printf("main2 sed: %d\n", temp); - printf("main2 sed: %u, %c\n", temp, temp/2); - return test_lib_func(temp); - } - ''', 'other says 45.2', ['--js-library', 'lib.js']) + ''', r''' + #include "header.h" + Class::Class(const char *name) { printf("new %s\n", name); } + ''', ['new main\n']) - # libc usage in one modules. must force libc inclusion in the main module if that isn't the one using mallinfo() - try: - os.environ['EMCC_FORCE_STDLIBS'] = 'libc' - test('malloc-1', r''' + # malloc usage in both modules + test('malloc', r''' + #include #include - int side(); + char *side(const char *data); ''', r''' #include #include "header.h" int main() { - printf("|%d|\n", side()); + char *temp = side("hello through side\n"); + char *ret = (char*)malloc(strlen(temp)+1); + strcpy(ret, temp); + temp[1] = 'x'; + puts(ret); return 0; } ''', r''' - #include - #include #include "header.h" - int side() { - struct mallinfo m = mallinfo(); - return m.arena > 1; + char *side(const char *data) { + char *ret = (char*)malloc(strlen(data)+1); + strcpy(ret, data); + return ret; } - ''', ['|1|\n']) - finally: - del os.environ['EMCC_FORCE_STDLIBS'] - - # iostream usage in one and std::string in both - test('iostream', r''' - #include - #include - std::string side(); - ''', r''' - #include "header.h" - int main() { - std::cout << "hello from main " << side() << std::endl; - return 0; - } - ''', r''' - #include "header.h" - std::string side() { return "and hello from side"; } - ''', ['hello from main and hello from side\n']) - - # followup to iostream test: a second linking - print 'second linking of a linking output' - open('moar.cpp', 'w').write(r''' - #include - struct Moar { - Moar() { std::cout << "moar!" << std::endl; } - }; - Moar m; - ''') - Popen([PYTHON, EMCC, 'moar.cpp', '-o', 'moar.js', '-s', 'SIDE_MODULE=1', '-O2']).communicate() - Popen([PYTHON, EMLINK, 'together.js', 'moar.js', 'triple.js'], stdout=PIPE).communicate() - assert os.path.exists('triple.js') - for engine in JS_ENGINES: - out = run_js('triple.js', engine=engine, stderr=PIPE, full_output=True) - self.assertContained('moar!\nhello from main and hello from side\n', out) - if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out) - - # zlib compression library. tests function pointers in initializers and many other things - test('zlib', '', open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(), - self.get_zlib_library(), - open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(), - args=['-I' + path_from_root('tests', 'zlib')], suffix='c') - - use_cmake = WINDOWS - bullet_library = get_bullet_library(self, use_cmake) - - # bullet physics engine. tests all the things - test('bullet', '', open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(), - bullet_library, - [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings - open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(), - open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()], - args=['-I' + path_from_root('tests', 'bullet', 'src')]) + ''', ['hello through side\n']) + + # js library call + open('lib.js', 'w').write(r''' + mergeInto(LibraryManager.library, { + test_lib_func: function(x) { + return x + 17.2; + } + }); + ''') + test('js-lib', 'extern "C" { extern double test_lib_func(int input); }', r''' + #include + #include "header.h" + extern double sidey(); + int main2() { return 11; } + int main() { + int input = sidey(); + double temp = test_lib_func(input); + printf("other says %.2f\n", temp); + printf("more: %.5f, %d\n", temp, input); + return 0; + } + ''', r''' + #include + #include "header.h" + extern int main2(); + double sidey() { + int temp = main2(); + printf("main2 sed: %d\n", temp); + printf("main2 sed: %u, %c\n", temp, temp/2); + return test_lib_func(temp); + } + ''', 'other says 45.2', ['--js-library', 'lib.js']) + + # libc usage in one modules. must force libc inclusion in the main module if that isn't the one using mallinfo() + try: + os.environ['EMCC_FORCE_STDLIBS'] = 'libc' + test('malloc-1', r''' + #include + int side(); + ''', r''' + #include + #include "header.h" + int main() { + printf("|%d|\n", side()); + return 0; + } + ''', r''' + #include + #include + #include "header.h" + int side() { + struct mallinfo m = mallinfo(); + return m.arena > 1; + } + ''', ['|1|\n']) + finally: + del os.environ['EMCC_FORCE_STDLIBS'] + + # iostream usage in one and std::string in both + test('iostream', r''' + #include + #include + std::string side(); + ''', r''' + #include "header.h" + int main() { + std::cout << "hello from main " << side() << std::endl; + return 0; + } + ''', r''' + #include "header.h" + std::string side() { return "and hello from side"; } + ''', ['hello from main and hello from side\n']) + + # followup to iostream test: a second linking + print 'second linking of a linking output' + open('moar.cpp', 'w').write(r''' + #include + struct Moar { + Moar() { std::cout << "moar!" << std::endl; } + }; + Moar m; + ''') + Popen([PYTHON, EMCC, 'moar.cpp', '-o', 'moar.js', '-s', 'SIDE_MODULE=1', '-O2']).communicate() + Popen([PYTHON, EMLINK, 'together.js', 'moar.js', 'triple.js'], stdout=PIPE).communicate() + assert os.path.exists('triple.js') + for engine in JS_ENGINES: + out = run_js('triple.js', engine=engine, stderr=PIPE, full_output=True) + self.assertContained('moar!\nhello from main and hello from side\n', out) + if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out) + + # zlib compression library. tests function pointers in initializers and many other things + test('zlib', '', open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(), + self.get_zlib_library(), + open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(), + args=['-I' + path_from_root('tests', 'zlib')], suffix='c') + + use_cmake = WINDOWS + bullet_library = get_bullet_library(self, use_cmake) + + # bullet physics engine. tests all the things + test('bullet', '', open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(), + bullet_library, + [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings + open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(), + open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()], + args=['-I' + path_from_root('tests', 'bullet', 'src')]) + nonfastcomp(nonfc) def test_outline(self): def test(name, src, libs, expected, expected_ranges, args=[], suffix='cpp'): @@ -1817,26 +1819,28 @@ This pointer might make sense in another type signature: i: _my_func assert 'error' not in err, 'Unexpected stderr: ' + err def test_chunking(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('not relevant for fastcomp, only checks js compiler chunking') - if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') - if os.environ.get('EMCC_CORES'): return self.skip('cannot run if cores are altered') - if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores') - try: - os.environ['EMCC_DEBUG'] = '1' - os.environ['EMCC_CORES'] = '2' # standardize over machines - for asm, linkable, chunks in [ - (0, 0, 2), (0, 1, 2), - (1, 0, 2), (1, 1, 2) - ]: - print asm, linkable, chunks - output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() - ok = False - for c in range(chunks, chunks+2): - ok = ok or ('phase 2 working on %d chunks' % c in err) - assert ok, err - finally: - del os.environ['EMCC_DEBUG'] - del os.environ['EMCC_CORES'] + def nonfc(): + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('not relevant for fastcomp, only checks js compiler chunking') + if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') + if os.environ.get('EMCC_CORES'): return self.skip('cannot run if cores are altered') + if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores') + try: + os.environ['EMCC_DEBUG'] = '1' + os.environ['EMCC_CORES'] = '2' # standardize over machines + for asm, linkable, chunks in [ + (0, 0, 2), (0, 1, 2), + (1, 0, 2), (1, 1, 2) + ]: + print asm, linkable, chunks + output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() + ok = False + for c in range(chunks, chunks+2): + ok = ok or ('phase 2 working on %d chunks' % c in err) + assert ok, err + finally: + del os.environ['EMCC_DEBUG'] + del os.environ['EMCC_CORES'] + nonfastcomp(nonfc) def test_debuginfo(self): if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') @@ -1868,23 +1872,25 @@ This pointer might make sense in another type signature: i: _my_func assert 'If you see this - the world is all right!' in output def test_embind(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') - for args, fail in [ - ([], True), # without --bind, we fail - (['--bind'], False), - (['--bind', '-O1'], False), - (['--bind', '-O2'], False), - (['--bind', '-O1', '-s', 'ASM_JS=0'], False), - (['--bind', '-O2', '-s', 'ASM_JS=0'], False) - ]: - print args, fail - self.clear() - try_delete(self.in_dir('a.out.js')) - Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate() - assert os.path.exists(self.in_dir('a.out.js')) == (not fail) - if not fail: - output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True) - assert "FAIL" not in output, output + def nonfc(): + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') + for args, fail in [ + ([], True), # without --bind, we fail + (['--bind'], False), + (['--bind', '-O1'], False), + (['--bind', '-O2'], False), + (['--bind', '-O1', '-s', 'ASM_JS=0'], False), + (['--bind', '-O2', '-s', 'ASM_JS=0'], False) + ]: + print args, fail + self.clear() + try_delete(self.in_dir('a.out.js')) + Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate() + assert os.path.exists(self.in_dir('a.out.js')) == (not fail) + if not fail: + output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True) + assert "FAIL" not in output, output + nonfastcomp(nonfc) def test_llvm_nativizer(self): try: -- cgit v1.2.3-18-g5258 From c7e19b82f3cb7a9be1bd9a4eeaa72e31253ecee7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:34:55 -0800 Subject: deprecate toy gc impl --- src/library_gc.js | 2 ++ system/include/gc.h | 2 ++ tests/test_browser.py | 5 ----- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/library_gc.js b/src/library_gc.js index b3dae0e9..d86f2d15 100644 --- a/src/library_gc.js +++ b/src/library_gc.js @@ -1,4 +1,6 @@ +// WARNING: this is deprecated. You should just build Boehm from source, it is much faster than the toy version written in emscripten + if (GC_SUPPORT) { EXPORTED_FUNCTIONS['_calloc'] = 1; EXPORTED_FUNCTIONS['_realloc'] = 1; diff --git a/system/include/gc.h b/system/include/gc.h index a21fd410..affa615f 100644 --- a/system/include/gc.h +++ b/system/include/gc.h @@ -1,5 +1,7 @@ /* * Boehm-compatible GC API + * + * WARNING: this is deprecated. You should just build Boehm from source, it is much faster than the toy version written in emscripten */ #ifndef _GC_H_INCLUDED #define _GC_H_INCLUDED diff --git a/tests/test_browser.py b/tests/test_browser.py index 1eddc846..608aed05 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1490,11 +1490,6 @@ keydown(100);keyup(100); // trigger the end def test_sdl_resize(self): self.btest('sdl_resize.c', '1') - def test_gc(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('flaky in fastcomp and also non-fastcomp -O1, timing issues') - - self.btest('browser_gc.cpp', '1') - def test_glshaderinfo(self): self.btest('glshaderinfo.cpp', '1') -- cgit v1.2.3-18-g5258 From cee68d01cd298c8c71e62190f2e88f8f8fe72698 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:37:21 -0800 Subject: make non-fastcomp tests in browser run in non-fastcomp mode --- tests/test_browser.py | 368 +++++++++++++++++++++++++------------------------- 1 file changed, 185 insertions(+), 183 deletions(-) diff --git a/tests/test_browser.py b/tests/test_browser.py index 608aed05..911e3269 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1,5 +1,5 @@ import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest, zlib, webbrowser, time, shlex -from runner import BrowserCore, path_from_root +from runner import BrowserCore, path_from_root, nonfastcomp from tools.shared import * # User can specify an environment variable EMSCRIPTEN_BROWSER to force the browser test suite to @@ -141,191 +141,193 @@ If manually bisecting: os.chdir(cwd) def test_split(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('no --split in fastcomp, deprecated') + def nfc(): + # test HTML generation. + self.reftest(path_from_root('tests', 'htmltest.png')) + output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '--split', '100', '--pre-js', 'reftest.js']).communicate() + assert os.path.exists(os.path.join(self.get_dir(), 'something.js')), 'must be main js file' + assert os.path.exists(os.path.join(self.get_dir(), 'something_functions.js')), 'must be functions js file' + assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file' - # test HTML generation. - self.reftest(path_from_root('tests', 'htmltest.png')) - output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '--split', '100', '--pre-js', 'reftest.js']).communicate() - assert os.path.exists(os.path.join(self.get_dir(), 'something.js')), 'must be main js file' - assert os.path.exists(os.path.join(self.get_dir(), 'something_functions.js')), 'must be functions js file' - assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file' - - open(os.path.join(self.get_dir(), 'something.html'), 'w').write(''' - - - - - - - Emscripten-Generated Code - - - -
-
Downloading...
-
- -
- -
-
-
- -
- ''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + ''' - - - ''') + }; + Module.setStatus('Downloading...'); + ''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + ''' + + + ''') - self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') + self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') + + nonfastcomp(nfc) def test_split_in_source_filenames(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('no --split in fastcomp, deprecated') - - self.reftest(path_from_root('tests', 'htmltest.png')) - output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '-g', '--split', '100', '--pre-js', 'reftest.js']).communicate() - assert os.path.exists(os.path.join(self.get_dir(), 'something.js')), 'must be main js file' - assert os.path.exists(os.path.join(self.get_dir(), 'something', 'hello_world_sdl.cpp.js')), 'must be functions js file' - assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file' - - open(os.path.join(self.get_dir(), 'something.html'), 'w').write(''' - - - - - - - Emscripten-Generated Code - - - -
-
Downloading...
-
- -
- -
-
-
- -
- ''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + ''' - - - ''') + }; + Module.setStatus('Downloading...'); + ''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + ''' + + + ''') - self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') + self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') + + nonfastcomp(nfc) def test_compression(self): open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' @@ -1756,10 +1758,10 @@ void *getBindBuffer() { self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')]) def test_module(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp') - - Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate() - self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8') + def nfc(): + Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate() + self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8') + nonfastcomp(nfc) def test_mmap_file(self): open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000)) -- cgit v1.2.3-18-g5258 From d2ae502d4cb827d81f1257f088ab7dbf43cb8d1d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 12:45:01 -0800 Subject: add non-fastcomp other.test_emcc run --- tests/test_other.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_other.py b/tests/test_other.py index b307b888..b09f6dea 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -277,6 +277,9 @@ f.close() # TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link! # TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py. + def test_emcc_nonfastcomp(self): + nonfastcomp(self.test_emcc) + def test_cmake(self): # Test all supported generators. if WINDOWS: -- cgit v1.2.3-18-g5258 From 989d49f884cf7b72a14881e6040e43185cbfbd5b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 14:21:12 -0800 Subject: reflect that asm is on by default in fastcomp, even in -O0, in the settings --- src/settings.js | 2 +- tools/shared.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/settings.js b/src/settings.js index c8114059..1c6b998e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -446,7 +446,7 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not // print out anything at all whatsoever. This is useful for benchmarking. -var ASM_JS = 0; // If 1, generate code in asm.js format. If 2, emits the same code except +var ASM_JS = 1; // If 1, generate code in asm.js format. If 2, emits the same code except // for omitting 'use asm' var PGO = 0; // Enables profile-guided optimization in the form of runtime checks for diff --git a/tools/shared.py b/tools/shared.py index 31dc64b1..6d4636cf 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -804,6 +804,8 @@ class Settings2(type): @classmethod def apply_opt_level(self, opt_level, noisy=False): + if opt_level == 0 and os.environ.get('EMCC_FAST_COMPILER') == '0': + self.attrs['ASM_JS'] = 0 # non-fastcomp has asm off in -O1 if opt_level >= 1: self.attrs['ASM_JS'] = 1 self.attrs['ASSERTIONS'] = 0 -- cgit v1.2.3-18-g5258 From 15f6d2d20bafaffe5eb559f42ff05fa296a10dcb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 14:44:32 -0800 Subject: fix llvm nativizer tool for fastcomp --- tools/nativize_llvm.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/nativize_llvm.py b/tools/nativize_llvm.py index b327bdfc..52dfdea1 100755 --- a/tools/nativize_llvm.py +++ b/tools/nativize_llvm.py @@ -25,9 +25,11 @@ Popen([LLVM_OPT, filename, '-strip-debug', '-o', filename + '.clean.bc']).commun print 'bc => s' for params in [['-march=x86'], ['-march=x86-64']]: # try x86, then x86-64 FIXME print 'params', params - Popen([LLVM_COMPILER] + params + [filename + '.clean.bc', '-o', filename + '.s']).communicate()[0] - print 's => o' - Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0] + for triple in [['-mtriple=i386-pc-linux-gnu'], []]: + Popen([LLVM_COMPILER] + params + triple + [filename + '.clean.bc', '-o', filename + '.s']).communicate()[0] + print 's => o' + Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0] + if os.path.exists(filename + '.o'): break if os.path.exists(filename + '.o'): break print 'o => runnable' Popen(['g++', path_from_root('system', 'lib', 'debugging.cpp'), filename + '.o', '-o', filename + '.run'] + ['-l' + lib for lib in libs]).communicate()[0] -- cgit v1.2.3-18-g5258 From 005950752c6e0c42e847b080f6d81a05e1bcb38c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 15:13:03 -0800 Subject: RUNTIME_TYPE_INFO is not supported in fastcomp --- emcc | 1 + tests/test_core.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/emcc b/emcc index 36532d16..47c29465 100755 --- a/emcc +++ b/emcc @@ -1219,6 +1219,7 @@ try: assert not bind, 'embind not supported in fastcomp yet' assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet' assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)' + assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp' except Exception, e: logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') raise e diff --git a/tests/test_core.py b/tests/test_core.py index 75ecec84..2d389fbc 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5872,6 +5872,8 @@ def process(filename): self.do_run(src, '|hello|43|world|41|', post_build=post) def test_typeinfo(self): + if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp does not support RUNTIME_TYPE_INFO') + if self.emcc_args is not None and self.emcc_args != []: return self.skip('full LLVM opts optimize out all the code that uses the type') Settings.RUNTIME_TYPE_INFO = 1 -- cgit v1.2.3-18-g5258 From 77241ebeec90e1ef51306c79d3a5c77dba4f2ab3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 15:14:35 -0800 Subject: fix s_x_x tests --- tests/test_core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_core.py b/tests/test_core.py index 2d389fbc..ef2a3979 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6455,6 +6455,7 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, return # TODO: Move much of these to a init() function in shared.py, and reuse that + Settings.ASM_JS = 0 Settings.USE_TYPED_ARRAYS = typed_arrays Settings.INVOKE_RUN = 1 Settings.RELOOP = 0 # we only do them in the "o2" pass -- cgit v1.2.3-18-g5258 From bc0a257c9864357fea3f678303401841306b7ff7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 17:00:24 -0800 Subject: error on CORRUPTION_CHECK in fastcomp --- emcc | 1 + 1 file changed, 1 insertion(+) diff --git a/emcc b/emcc index 47c29465..b213ab39 100755 --- a/emcc +++ b/emcc @@ -1220,6 +1220,7 @@ try: assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet' assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)' assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp' + assert not shared.Settings.CORRUPTION_CHECK, 'CORRUPTION_CHECK is not supported in asm.js mode, which is what fastcomp can emit (you can use non-asm.js mode in non-fastcomp)' except Exception, e: logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') raise e -- cgit v1.2.3-18-g5258 From bf7b435983d2e891297e76ce3dd80ef635b7e2c1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 17:02:09 -0800 Subject: fix test_scriptaclass --- tests/test_core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index ef2a3979..9898cb50 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5630,8 +5630,6 @@ def process(filename): # Way 2: use CppHeaderParser - Settings.RUNTIME_TYPE_INFO = 1 - header = ''' #include -- cgit v1.2.3-18-g5258 From b8c670c705279fae14ca7742531950b4f84c849d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 18:42:06 -0800 Subject: do not outline the entire stack prelude, including STACKTOP = .. --- tools/js-optimizer.js | 11 +++++- tools/test-js-optimizer-asm-outline1-output.js | 48 ++++++++++++++++++++++++++ tools/test-js-optimizer-asm-outline1.js | 37 ++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index fc195e03..21fce2c2 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -4775,7 +4775,16 @@ function outline(ast) { for (var i = minIndex; i < stats.length; i++) { var stat = stats[i]; if (stat[0] == 'stat') stat = stat[1]; - if (stat[0] == 'assign' && stat[2][0] == 'name' && stat[2][1] == 'sp') minIndex = i+1; // cannot outline |sp = | + if (stat[0] == 'assign' && stat[2][0] == 'name' && stat[2][1] == 'sp') { + // cannot outline |sp = | + minIndex = i+1; + // When followed by a STACKTOP bump, preserve that too (we may need to replace it later) + stat = stats[i+1]; + if (stat[0] == 'stat') stat = stat[1]; + if (stat && stat[0] == 'assign' && stat[2][0] == 'name' && stat[2][1] == 'STACKTOP') { + minIndex = i+2; + } + } } } } diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js index 27f93d8a..c4792c51 100644 --- a/tools/test-js-optimizer-asm-outline1-output.js +++ b/tools/test-js-optimizer-asm-outline1-output.js @@ -423,6 +423,32 @@ function switchh2() { } STACKTOP = sp; } +function stackSet(x1, x2, x3, x4, x5) { + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + x4 = x4 | 0; + x5 = x5 | 0; + var sp = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 282 | 0; + c(1); + c(2); + c(3); + c(4); + c(5); + c(6); + c(7); + c(8); + c(9); + c(10); + HEAP32[sp + 66 >> 2] = 0; + HEAP32[sp + 70 >> 2] = 0; + stackSet$1(sp); + HEAP32[sp + 58 >> 2] = 0; + HEAP32[sp + 62 >> 2] = 0; + stackSet$0(sp); +} function lin$0(sp) { sp = sp | 0; c(14); @@ -926,4 +952,26 @@ function switchh2$2(sp) { } while (0); HEAP32[sp + 8 >> 2] = helper$0; } +function stackSet$0(sp) { + sp = sp | 0; + c(7); + c(8); + c(9); + c(10); + c(11); + c(12); + c(13); +} +function stackSet$1(sp) { + sp = sp | 0; + c(11); + c(12); + c(13); + c(1); + c(2); + c(3); + c(4); + c(5); + c(6); +} diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js index b7ec9011..f640d11d 100644 --- a/tools/test-js-optimizer-asm-outline1.js +++ b/tools/test-js-optimizer-asm-outline1.js @@ -347,5 +347,42 @@ function switchh2() { print(9); } } +function stackSet(x1, x2, x3, x4, x5) { + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + x4 = x4 | 0; + x5 = x5 | 0; + var sp = 0, a = 0, b = 0, cc = 0, d = 0, e = 0, f = 0, g = 0; + var sp1 = 0, a1 = 0, b1 = 0, c1 = 0, d1 = 0, e1 = 0, f1 = 0, g1 = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 10 | 0; + c(1); + c(2); + c(3); + c(4); + c(5); + c(6); + c(7); + c(8); + c(9); + c(10); + c(11); + c(12); + c(13); + c(1); + c(2); + c(3); + c(4); + c(5); + c(6); + c(7); + c(8); + c(9); + c(10); + c(11); + c(12); + c(13); +} // EMSCRIPTEN_GENERATED_FUNCTIONS // EXTRA_INFO: { "sizeToOutline": 30, "allowCostlyOutlines": 1 } -- cgit v1.2.3-18-g5258 From bc4dbe116101b2424ed6a318037711218e86279a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 21 Feb 2014 18:44:55 -0800 Subject: make test_outline limits a little more flexible --- tests/test_other.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_other.py b/tests/test_other.py index b09f6dea..8bc056e6 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -923,7 +923,7 @@ This pointer might make sense in another type signature: i: _my_func 500: (250, 500), 1000: (230, 1000), 2000: (380, 2000), - 5000: (800, 5000), + 5000: (500, 5000), 0: (1500, 5000) }), (['-O2'], { -- cgit v1.2.3-18-g5258 From a08da7bd41166a40bb5d63396540e37d8caa7fd7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 22 Feb 2014 11:58:20 -0800 Subject: add EM_ASM_ which allows sending values without returning anything --- system/include/emscripten/emscripten.h | 14 ++++++++++---- tests/core/test_inlinejs3.in | 1 + tests/core/test_inlinejs3.out | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index b92d920c..852a8e0d 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -40,10 +40,15 @@ extern "C" { #define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__) /* - * Input-output versions of EM_ASM. EM_ASM_INT receives arguments of - * either int or double type and returns an int; EM_ASM_DOUBLE - * receives similar arguments (int or double) but returns a double. - * Arguments arrive as $0, $1 etc; output value should be returned: + * Input-output versions of EM_ASM. + * + * EM_ASM_ (an extra _ is added) allows sending values (ints + * or doubles) into the code. If you also want a return value, + * EM_ASM_INT receives arguments (of int or double type) + * and returns an int; EM_ASM_DOUBLE does the same and returns + * a double. + * + * Arguments arrive as $0, $1 etc. The output value should be returned: * * int x = EM_ASM_INT({ * console.log('I received: ' + [$0, $1]); @@ -54,6 +59,7 @@ extern "C" { * (int or double) but *not* to pass any values, you can use * EM_ASM_INT_V and EM_ASM_DOUBLE_V respectively. */ +#define EM_ASM_(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__) #define EM_ASM_INT_V(code) emscripten_asm_const_int(#code) diff --git a/tests/core/test_inlinejs3.in b/tests/core/test_inlinejs3.in index 9ddd5907..12e31007 100644 --- a/tests/core/test_inlinejs3.in +++ b/tests/core/test_inlinejs3.in @@ -7,6 +7,7 @@ int main(int argc, char **argv) { for (int i = 0; i < 3; i++) { EM_ASM(Module.print('hello dere3'); Module.print('hello dere' + 4);); } + EM_ASM_({ Module.print('hello input ' + $0) }, 123); int sum = 0; for (int i = 0; i < argc * 3; i++) { sum += EM_ASM_INT({ diff --git a/tests/core/test_inlinejs3.out b/tests/core/test_inlinejs3.out index c293e80b..1f64a89a 100644 --- a/tests/core/test_inlinejs3.out +++ b/tests/core/test_inlinejs3.out @@ -6,6 +6,7 @@ hello dere3 hello dere4 hello dere3 hello dere4 +hello input 123 i: 0,0.00 i: 1,0.08 i: 2,0.17 -- cgit v1.2.3-18-g5258 From fd554f90a78d03af31fcc19c22e2ac5f80998fab Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 23 Feb 2014 14:14:43 -0800 Subject: emit value in safe heap load logging --- src/preamble.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preamble.js b/src/preamble.js index 27a98422..28a1dcbc 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -194,9 +194,6 @@ function SAFE_HEAP_STORE(dest, value, bytes, isFloat) { } function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned) { -#if SAFE_HEAP_LOG - Module.print('SAFE_HEAP load: ' + [dest, bytes, isFloat, unsigned]); -#endif assert(dest > 0, 'segmentation fault'); assert(dest % bytes === 0); assert(dest < Math.max(DYNAMICTOP, STATICTOP)); @@ -204,6 +201,9 @@ function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned) { var type = getSafeHeapType(bytes, isFloat); var ret = getValue(dest, type, 1); if (unsigned) ret = unSign(ret, parseInt(type.substr(1)), 1); +#if SAFE_HEAP_LOG + Module.print('SAFE_HEAP load: ' + [dest, ret, bytes, isFloat, unsigned]); +#endif return ret; } -- cgit v1.2.3-18-g5258 From a18bd727401a8495275c78149dbaae5a0adae0d2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 23 Feb 2014 14:21:09 -0800 Subject: add stack bump if only sp is defined but no bump is present, when outlining --- tools/js-optimizer.js | 22 +++++++++++++++++++++- tools/test-js-optimizer-asm-outline2-output.js | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 21fce2c2..d393b159 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -4935,7 +4935,27 @@ function outline(ast) { if ('sp' in asmData.vars) { // find stack bump (STACKTOP = STACKTOP + X | 0) and add the extra space var stackBumpNode = getStackBumpNode(stats); - if (stackBumpNode) stackBumpNode[3][2][3][1] = asmData.totalStackSize; + if (stackBumpNode) { + stackBumpNode[3][2][3][1] = asmData.totalStackSize; + } else { + // sp exists, but no stack bump, so we need to add it + var found = false; + for (var i = 0; i < stats.length; i++) { + var stat = stats[i]; + if (stat[0] === 'stat') stat = stat[1]; + if (stat[0] === 'assign' && stat[2][0] === 'name' && stat[2][1] === 'sp') { + var newNode = ['stat', makeAssign(['name', 'STACKTOP'], ['binary', '|', ['binary', '+', ['name', 'STACKTOP'], ['num', asmData.totalStackSize]], ['num', 0]])]; + if (i+1 < stats.length) { + stats.splice(i+1, 0, newNode); + } else { + stats.push(newNode); + } + found = true; + break; + } + } + assert(found); + } } else if (!('sp' in asmData.params)) { // if sp is a param, then we are an outlined function, no need to add stack support for us // add sp variable and stack bump var index = getFirstIndexInNormalized(func, asmData); diff --git a/tools/test-js-optimizer-asm-outline2-output.js b/tools/test-js-optimizer-asm-outline2-output.js index 2658fda0..923cd7df 100644 --- a/tools/test-js-optimizer-asm-outline2-output.js +++ b/tools/test-js-optimizer-asm-outline2-output.js @@ -25,6 +25,7 @@ function _free($mem) { $mem = $mem | 0; var $5 = 0, $10 = 0, $16 = 0, $21 = 0, $25 = 0, $26 = 0, $psize_0 = 0, $p_0 = 0, $189 = 0, $194 = 0, sp = 0, helper$0 = 0; sp = STACKTOP; + STACKTOP = STACKTOP + 864 | 0; if (($mem | 0) == 0) { STACKTOP = sp; return; -- cgit v1.2.3-18-g5258 From fb9deefc5ac7caaa1b5d2c680a86d9b35238e004 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 23 Feb 2014 19:44:24 -0800 Subject: disable some outlining logging --- tools/js-optimizer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d393b159..240ee2bd 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -4525,10 +4525,10 @@ function outline(ast) { var size = measureSize(func); if (size <= extraInfo.sizeToOutline) { sizeToOutline = Infinity; - printErr(' no point in trying to reduce the size of ' + func[1] + ' which is ' + size + ' <= ' + extraInfo.sizeToOutline); + //printErr(' no point in trying to reduce the size of ' + func[1] + ' which is ' + size + ' <= ' + extraInfo.sizeToOutline); } else { sizeToOutline = Math.round(size/Math.max(2, asmData.intendedPieces--)); - printErr('trying to reduce the size of ' + func[1] + ' which is ' + size + ' (>=? ' + extraInfo.sizeToOutline + '), aim for ' + sizeToOutline); + //printErr('trying to reduce the size of ' + func[1] + ' which is ' + size + ' (>=? ' + extraInfo.sizeToOutline + '), aim for ' + sizeToOutline); } } @@ -4753,7 +4753,7 @@ function outline(ast) { } } outliningParents[newIdent] = func[1]; - printErr('performed outline ' + [func[1], newIdent, 'pre size', originalCodeSize, 'resulting size', measureSize(code), 'overhead (w/r):', setSize(setSub(codeInfo.writes, owned)), setSize(setSub(codeInfo.reads, owned)), ' owned: ', setSize(owned), ' left: ', setSize(asmData.vars), setSize(asmData.params), ' loopsDepth: ', loops]); + //printErr('performed outline ' + [func[1], newIdent, 'pre size', originalCodeSize, 'resulting size', measureSize(code), 'overhead (w/r):', setSize(setSub(codeInfo.writes, owned)), setSize(setSub(codeInfo.reads, owned)), ' owned: ', setSize(owned), ' left: ', setSize(asmData.vars), setSize(asmData.params), ' loopsDepth: ', loops]); calculateThreshold(func, asmData); return [newFunc]; } @@ -4908,7 +4908,7 @@ function outline(ast) { var maxTotalFunctions = Infinity; // debugging tool - printErr('\n'); + //printErr('\n'); var more = true; while (more) { @@ -4990,7 +4990,7 @@ function outline(ast) { } if (ret) { ret.push(func); - printErr('... resulting sizes of ' + func[1] + ' is ' + ret.map(measureSize) + '\n'); + //printErr('... resulting sizes of ' + func[1] + ' is ' + ret.map(measureSize) + '\n'); } } denormalizeAsm(func, asmData); -- cgit v1.2.3-18-g5258 From ae764ac73f78fe23813cc1f07bc7b3d7fed65e8b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 24 Feb 2014 12:36:55 -0800 Subject: deprecate jcache --- emcc | 56 ++--------------------------------- tests/test_sanity.py | 84 ---------------------------------------------------- 2 files changed, 2 insertions(+), 138 deletions(-) diff --git a/emcc b/emcc index b213ab39..4194d0fb 100755 --- a/emcc +++ b/emcc @@ -425,59 +425,6 @@ Options that are modified or new in %s include: -v to Clang, and also enable EMCC_DEBUG to details emcc's operations - --jcache Use a JavaScript cache. This is disabled by - default. When enabled, emcc will store the - results of compilation in a cache and check - the cache when compiling later, something - like what ccache does. This allows incremental - builds - where you are compiling a large - program but only modified a small part of it - - to be much faster (at the cost of more disk - IO for cache accesses). Note that you need - to enable --jcache for both loading and saving - of data, so you must enable it on a full build - for a later incremental build (where you also - enable it) to be sped up. - - Caching works separately on 4 parts of compilation: - 'pre' which is types and global variables; that - information is then fed into 'funcs' which are - the functions (which we parallelize), and then - 'post' which adds final information based on - the functions (e.g., do we need long64 support - code). Finally, 'jsfuncs' are JavaScript-level - optimizations. Each of the 4 parts can be cached - separately, but note that they can affect each - other: If you recompile a single C++ file that - changes a global variable - e.g., adds, removes - or modifies a global variable, say by adding - a printf or by adding a compile-time timestamp, - then 'pre' cannot be loaded from the cache. And - since 'pre's output is sent to 'funcs' and 'post', - they will get invalidated as well, and only - 'jsfuncs' will be cached. So avoid modifying - globals to let caching work fully. - - To work around the problem mentioned in the - previous paragraph, you can use - - emscripten_jcache_printf - - when adding debug printfs to your code. That - function is specially preprocessed so that it - does not create a constant string global for - its first argument. See emscripten.h for more - details. Note in particular that you need to - already have a call to that function in your - code *before* you add one and do an incremental - build, so that adding an external reference - (also a global property) does not invalidate - everything. - - Note that you should use -g during the linking - stage (bitcode to JS), for jcache to work - (otherwise, JS minification can confuse it). - --clear-cache Manually clears the cache of compiled emscripten system libraries (libc++, libc++abi, libc). This is normally @@ -986,6 +933,7 @@ try: logging.warning ('--remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase') newargs[i] = '' elif newargs[i] == '--jcache': + logging.warning('jcache is deprecated') jcache = True newargs[i] = '' elif newargs[i] == '--clear-cache': @@ -1226,7 +1174,7 @@ try: raise e if jcache: - logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling') + logging.warning('jcache is deprecated and not supported in fastcomp (you should not need it anyhow), disabling') jcache = False fastcomp_opts = ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'] diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 54a0e99d..5713c99c 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -482,90 +482,6 @@ fi finally: del os.environ['EMCC_FAST_COMPILER'] - def test_jcache(self): - PRE_LOAD_MSG = 'loading pre from jcache' - PRE_SAVE_MSG = 'saving pre to jcache' - FUNC_CHUNKS_LOAD_MSG = ' funcchunks from jcache' - FUNC_CHUNKS_SAVE_MSG = ' funcchunks to jcache' - JSFUNC_CHUNKS_LOAD_MSG = 'jsfuncchunks from jcache' - JSFUNC_CHUNKS_SAVE_MSG = 'jsfuncchunks to jcache' - - restore() - Cache.erase() - - try: - os.environ['EMCC_DEBUG'] = '1' - os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE'] = str(1024*512) - - self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp') - if not os.path.exists(self.working_dir): os.makedirs(self.working_dir) - - assert not os.path.exists(JCache.get_cachename('emscript_files')) - - srcs = {} - used_jcache = False - - for args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected in [ - ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []), - (['--jcache'], 'hello_world_loop.cpp', True, False, True, False, True, False, []), - (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []), - ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []), - # new - ([], 'hello_world.cpp', False, False, False, False, False, False, []), - (['--jcache'], 'hello_world.cpp', True, False, True, False, True, False, []), - (['--jcache'], 'hello_world.cpp', False, True, False, True, False, True, []), - ([], 'hello_world.cpp', False, False, False, False, False, False, []), - # go back to old file, experience caching - (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []), - # new, large file - ([], 'hello_malloc.cpp', False, False, False, False, False, False, []), - (['--jcache'], 'hello_malloc.cpp', True, False, True, False, True, False, []), - (['--jcache'], 'hello_malloc.cpp', False, True, False, True, False, True, []), - ([], 'hello_malloc.cpp', False, False, False, False, False, False, []), - # new, huge file - ([], 'hello_libcxx.cpp', False, False, False, False, False, False, ('4 chunks',)), - (['--jcache'], 'hello_libcxx.cpp', True, False, True, False, True, False, []), - (['--jcache'], 'hello_libcxx.cpp', False, True, False, True, False, True, []), - ([], 'hello_libcxx.cpp', False, False, False, False, False, False, []), - # finally, build a file close to the previous, to see that some chunks are found in the cache and some not - (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, True, True, True, True, []), # win on pre, mix on funcs, mix on jsfuncs - (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, False, True, False, True, []), - (None, None, None, None, None, None, None, None, None), # clear - (['--jcache'], 'hello_libcxx_mod2.cpp', True, False, True, False, True, False, []), # load into cache - (['--jcache'], 'hello_libcxx_mod2a.cpp', False, True, True, True, True, True, []) # add a printf, do not lose everything - ]: - self.clear() - if args is None: - Cache.erase() - continue - - print >> sys.stderr, args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected - - out, err = Popen([PYTHON, EMCC, '-O2', '-g', path_from_root('tests', input_file)] + args, stdout=PIPE, stderr=PIPE).communicate() - errtail = err.split('emcc invocation')[-1] - self.assertContained('hello, world!', run_js('a.out.js'), errtail) - assert (PRE_SAVE_MSG in err) == expect_pre_save, errtail - assert (PRE_LOAD_MSG in err) == expect_pre_load, errtail - assert (FUNC_CHUNKS_SAVE_MSG in err) == expect_funcs_save, errtail - assert (FUNC_CHUNKS_LOAD_MSG in err) == expect_funcs_load, errtail - assert (JSFUNC_CHUNKS_SAVE_MSG in err) == expect_jsfuncs_save, errtail - assert (JSFUNC_CHUNKS_LOAD_MSG in err) == expect_jsfuncs_load, errtail - for expect in expected: assert expect in err, expect + ' ? ' + errtail - curr = open('a.out.js').read() - if input_file not in srcs: - srcs[input_file] = curr - else: - #open('/home/alon/Dev/emscripten/a', 'w').write(srcs[input_file]) - #open('/home/alon/Dev/emscripten/b', 'w').write(curr) - assert abs(len(curr)/float(len(srcs[input_file]))-1)<0.01, 'contents may shift in order, but must remain the same size %d vs %d' % (len(curr), len(srcs[input_file])) + '\n' + errtail - used_jcache = used_jcache or ('--jcache' in args) - assert used_jcache == os.path.exists(JCache.get_cachename('emscript_files')) - #print >> sys.stderr, errtail - - finally: - del os.environ['EMCC_DEBUG'] - del os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE'] - def test_nostdincxx(self): restore() Cache.erase() -- cgit v1.2.3-18-g5258 From cd3e0b2ceef728c27745d1e7f5d6b95671bcaf04 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 24 Feb 2014 14:31:47 -0800 Subject: add _ZNSt9exceptionD0Ev; fixes fastcomp issue 20 --- src/library.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library.js b/src/library.js index 91d5f925..7c74ddbb 100644 --- a/src/library.js +++ b/src/library.js @@ -4584,6 +4584,7 @@ LibraryManager.library = { // Destructors for std::exception since we don't have them implemented in libcxx as we aren't using libcxxabi. // These are also needed for the dlmalloc tests. + _ZNSt9exceptionD0Ev: function() {}, _ZNSt9exceptionD1Ev: function() {}, _ZNSt9exceptionD2Ev: function() {}, -- cgit v1.2.3-18-g5258