diff options
-rw-r--r-- | src/library.js | 4 | ||||
-rw-r--r-- | tests/cases/longjmp_tiny_invoke.ll | 2 | ||||
-rw-r--r-- | tests/cases/longjmp_tiny_phi.ll | 2 | ||||
-rw-r--r-- | tests/cases/longjmp_tiny_phi2.ll | 2 | ||||
-rw-r--r-- | tests/test_core.py | 69 | ||||
-rw-r--r-- | tests/utf32.cpp | 20 | ||||
-rw-r--r-- | tools/js-optimizer.js | 1 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-min-output.js | 5 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-min.js | 5 |
9 files changed, 50 insertions, 60 deletions
diff --git a/src/library.js b/src/library.js index 5e53805f..f9af8a96 100644 --- a/src/library.js +++ b/src/library.js @@ -6292,6 +6292,10 @@ LibraryManager.library = { throw { longjmp: true, id: {{{ makeGetValue('env', '0', 'i32') }}}, value: value || 1 }; #endif }, + emscripten_longjmp__deps: ['longjmp'], + emscripten_longjmp: function(env, value) { + _longjmp(env, value); + }, // ========================================================================== // signal.h diff --git a/tests/cases/longjmp_tiny_invoke.ll b/tests/cases/longjmp_tiny_invoke.ll index e1a72e00..5fd35194 100644 --- a/tests/cases/longjmp_tiny_invoke.ll +++ b/tests/cases/longjmp_tiny_invoke.ll @@ -9,7 +9,7 @@ target triple = "i386-pc-linux-gnu" define i32 @main() { %retval = alloca i32, align 4 store i32 0, i32* %retval - %call = invoke i32 @setjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0)) returns_twice, !dbg !20 + %call = invoke i32 @setjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0)) returns_twice to label %allgood unwind label %awful allgood: diff --git a/tests/cases/longjmp_tiny_phi.ll b/tests/cases/longjmp_tiny_phi.ll index cced7cab..21b936dd 100644 --- a/tests/cases/longjmp_tiny_phi.ll +++ b/tests/cases/longjmp_tiny_phi.ll @@ -28,7 +28,7 @@ if.else: ; preds = %entry br label %if.end if.end: ; preds = %if.else, %if.then - %aaa = phi i32 [ -1, %if.then ], [ 0, %if.else ], [ 1, %two ], [ 2, %entry ] + %aaa = phi i32 [ -1, %if.then ], [ 0, %if.else ] %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), i32 %aaa), !dbg !26 ret i32 %aaa, !dbg !28 } diff --git a/tests/cases/longjmp_tiny_phi2.ll b/tests/cases/longjmp_tiny_phi2.ll index 1d7761c3..88312fc6 100644 --- a/tests/cases/longjmp_tiny_phi2.ll +++ b/tests/cases/longjmp_tiny_phi2.ll @@ -24,7 +24,7 @@ if.then: ; preds = %entry br label %if.end, !dbg !25 if.end: ; preds = %if.else, %if.then - %aaa = phi i32 [ -1, %if.then ], [ 1, %two ], [ 2, %entry ] + %aaa = phi i32 [ -1, %if.then ], [ 1, %two ] %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), i32 %aaa), !dbg !26 ret i32 %aaa, !dbg !28 } diff --git a/tests/test_core.py b/tests/test_core.py index b1e1ffe6..7c16f55e 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1117,74 +1117,56 @@ 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(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - - test_path = path_from_root('tests', 'core', 'test_longjmp') - src, output = (test_path + s for s in ('.in', '.out')) - - self.do_run_from_file(src, output) + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 + test_path = path_from_root('tests', 'core', 'test_longjmp') + src, output = (test_path + s for s in ('.in', '.out')) + self.do_run_from_file(src, output) def test_longjmp2(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp2') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_longjmp3(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp3') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_longjmp4(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp4') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_longjmp_funcptr(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp_funcptr') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_longjmp_repeat(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - - Settings.MAX_SETJMPS = 1 - - 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) + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 + Settings.MAX_SETJMPS = 1 + 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) def test_longjmp_stacked(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp_stacked') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) - def test_longjmp_exc(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 test_path = path_from_root('tests', 'core', 'test_longjmp_exc') src, output = (test_path + s for s in ('.in', '.out')) - 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') + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect') src = r''' #include <stdio.h> @@ -1299,7 +1281,6 @@ 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_exceptions_white_list(self): if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') @@ -1364,13 +1345,9 @@ 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_exceptions_multi(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - Settings.DISABLE_EXCEPTION_CATCHING = 0 - test_path = path_from_root('tests', 'core', 'test_exceptions_multi') src, output = (test_path + s for s in ('.in', '.out')) - self.do_run_from_file(src, output) def test_exceptions_std(self): @@ -4095,7 +4072,6 @@ def process(filename): def test_utf32(self): if self.emcc_args is None: return self.skip('need libc for wcslen()') if not self.is_le32(): return self.skip('this test uses inline js, which requires le32') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.') self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.', args=['-fshort-wchar']) @@ -4689,7 +4665,7 @@ return malloc(size); def test_lua(self): if self.emcc_args is None: return self.skip('requires emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 for aggro in ([0, 1] if Settings.ASM_JS and '-O2' in self.emcc_args else [0]): print aggro @@ -4710,7 +4686,7 @@ return malloc(size); def test_freetype(self): if self.emcc_args is None: return self.skip('requires emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 assert 'asm2g' in test_modes if self.run_name == 'asm2g': @@ -4856,7 +4832,7 @@ def process(filename): def test_poppler(self): if self.emcc_args is None: return self.skip('very slow, we only do this in emcc runs') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 Settings.CORRECT_OVERFLOWS = 1 Settings.CORRECT_SIGNS = 1 @@ -5063,6 +5039,7 @@ def process(filename): # to process. def test_cases(self): if Building.LLVM_OPTS: return self.skip("Our code is not exactly 'normal' llvm assembly") + if os.environ.get('EMCC_FAST_COMPILER') == '1': Settings.DISABLE_EXCEPTION_CATCHING = 1 emcc_args = self.emcc_args @@ -5078,7 +5055,7 @@ def process(filename): 'structphiparam', 'callwithstructural_ta2', 'callwithstructural64_ta2', 'structinparam', # pnacl limitations in ExpandStructRegs '2xi40', # pnacl limitations in ExpandGetElementPtr 'legalizer_ta2', '514_ta2', # pnacl limitation in not legalizing i104, i96, etc. - 'longjmp_tiny', 'longjmp_tiny_invoke', 'longjmp_tiny_phi', 'longjmp_tiny_phi2', 'longjmp_tiny_invoke_phi', 'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME + 'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME 'sillyfuncast2', 'sillybitcast', 'atomicrmw_unaligned' # TODO XXX ]: continue if '_ta2' in shortname and not Settings.USE_TYPED_ARRAYS == 2: @@ -6020,7 +5997,6 @@ def process(filename): def test_source_map(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip("doesn't pass without typed arrays") - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') if NODE_JS not in JS_ENGINES: return self.skip('sourcemapper requires Node to run') if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g') @@ -6105,7 +6081,6 @@ def process(filename): if Settings.USE_TYPED_ARRAYS != 2: return self.skip("doesn't pass without typed arrays") if '-g4' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g4') if NODE_JS not in JS_ENGINES: return self.skip('sourcemapper requires Node to run') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') src = ''' #include <stdio.h> @@ -6130,7 +6105,7 @@ def process(filename): tools.shared.NODE_JS, [map_filename])) with open(filename) as f: lines = f.readlines() for m in mappings: - if m['originalLine'] == 5 and '__cxa_throw' in lines[m['generatedLine']]: + if m['originalLine'] == 5 and '__cxa_throw' in lines[m['generatedLine']-1]: # -1 to fix 0-start vs 1-start return assert False, 'Must label throw statements with line numbers' diff --git a/tests/utf32.cpp b/tests/utf32.cpp index 6b75b244..d00338a6 100644 --- a/tests/utf32.cpp +++ b/tests/utf32.cpp @@ -16,11 +16,11 @@ int main() { if (sizeof(wchar_t) == 4) { utf32 *memory = new utf32[wstr.length()+1]; - asm("var str = Module.UTF32ToString(%0);" - "Module.print(str);" - "Module.stringToUTF32(str, %1);" - : - : "r"(wstr.c_str()), "r"(memory)); + EM_ASM_INT({ + var str = Module.UTF32ToString($0); + Module.print(str); + Module.stringToUTF32(str, $1); + }, wstr.c_str(), memory); // Compare memory to confirm that the string is intact after taking a route through JS side. const utf32 *srcPtr = reinterpret_cast<const utf32 *>(wstr.c_str()); @@ -33,11 +33,11 @@ int main() { } else { // sizeof(wchar_t) == 2, and we're building with -fshort-wchar. utf16 *memory = new utf16[2*wstr.length()+1]; - asm("var str = Module.UTF16ToString(%0);" - "Module.print(str);" - "Module.stringToUTF16(str, %1);" - : - : "r"(wstr.c_str()), "r"(memory)); + EM_ASM_INT({ + var str = Module.UTF16ToString($0); + Module.print(str); + Module.stringToUTF16(str, $1); + }, wstr.c_str(), memory); // Compare memory to confirm that the string is intact after taking a route through JS side. const utf16 *srcPtr = reinterpret_cast<const utf16 *>(wstr.c_str()); diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 6d65f3e7..d604f546 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1603,6 +1603,7 @@ function normalizeAsm(func) { node = node[1]; var name = node[2][1]; if (func[2] && func[2].indexOf(name) < 0) break; // not an assign into a parameter, but a global + if (name in data.params) break; // already done that param, must be starting function body data.params[name] = detectAsmCoercion(node[3]); stats[i] = emptyNode(); i++; diff --git a/tools/test-js-optimizer-asm-regs-min-output.js b/tools/test-js-optimizer-asm-regs-min-output.js index 3955e48a..748b8e0a 100644 --- a/tools/test-js-optimizer-asm-regs-min-output.js +++ b/tools/test-js-optimizer-asm-regs-min-output.js @@ -33,4 +33,9 @@ function cl(b) { a(c); i1(b); } +function cl(b) { + b = b | 0; + b = b + 4; + a(b); +} diff --git a/tools/test-js-optimizer-asm-regs-min.js b/tools/test-js-optimizer-asm-regs-min.js index a5b9427e..65d8d429 100644 --- a/tools/test-js-optimizer-asm-regs-min.js +++ b/tools/test-js-optimizer-asm-regs-min.js @@ -33,5 +33,10 @@ function collideLocal(i1) { aGlobal(a); // multiple collisions, a and i1 bGlobal(i1); } +function collideLocal(i1) { + i1 = i1 | 0; + i1 = i1 + 4; // statement is of similar shape to a param coercion + aGlobal(i1); +} // EMSCRIPTEN_GENERATED_FUNCTIONS // EXTRA_INFO: { "names": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "i1", "cl"], "globals": { "aGlobal": "a", "bGlobal": "i1", "collideLocal": "cl" } } |