summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library.js4
-rw-r--r--tests/cases/longjmp_tiny_invoke.ll2
-rw-r--r--tests/cases/longjmp_tiny_phi.ll2
-rw-r--r--tests/cases/longjmp_tiny_phi2.ll2
-rw-r--r--tests/test_core.py69
-rw-r--r--tests/utf32.cpp20
-rw-r--r--tools/js-optimizer.js1
-rw-r--r--tools/test-js-optimizer-asm-regs-min-output.js5
-rw-r--r--tools/test-js-optimizer-asm-regs-min.js5
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" } }