aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc2
-rw-r--r--src/jsifier.js13
-rw-r--r--tests/cases/legalizer_ta2.ll1
-rwxr-xr-xtests/runner.py4
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js15
-rw-r--r--tools/eliminator/asm-eliminator-test.js15
-rw-r--r--tools/js-optimizer.js13
7 files changed, 52 insertions, 11 deletions
diff --git a/emcc b/emcc
index 7edc71e4..e25d9d91 100755
--- a/emcc
+++ b/emcc
@@ -1002,7 +1002,7 @@ try:
# Apply effects from settings
if shared.Settings.ASM_JS:
- assert opt_level == 2, 'asm.js requires -O2'
+ assert opt_level >= 1, 'asm.js requires -O1 or above'
if closure:
print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation'
diff --git a/src/jsifier.js b/src/jsifier.js
index 926be71a..a4dd797b 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1210,6 +1210,12 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
makeFuncLineActor('landingpad', function(item) {
+ if (DISABLE_EXCEPTION_CATCHING && USE_TYPED_ARRAYS == 2) {
+ ret = makeVarDef(item.assignTo) + '$0 = 0; ' + item.assignTo + '$1 = 0;';
+ item.assignTo = null;
+ if (ASSERTIONS) warnOnce('landingpad, but exceptions are disabled!');
+ return ret;
+ }
var catchTypeArray = item.catchables.map(finalizeLLVMParameter).map(function(element) { return asmCoercion(element, 'i32') }).join(',');
var ret = asmCoercion('___cxa_find_matching_catch(-1, -1' + (catchTypeArray.length > 0 ? ',' + catchTypeArray : '') +')', 'i32');
if (USE_TYPED_ARRAYS == 2) {
@@ -1458,11 +1464,12 @@ function JSify(data, functionsOnly, givenFunctions) {
});
makeFuncLineActor('unreachable', function(item) {
+ var ret = '';
+ if (ASM_JS && item.funcData.returnType != 'void') ret = 'return ' + asmCoercion('0', item.funcData.returnType) + ';';
if (ASSERTIONS) {
- return ASM_JS ? 'abort()' : 'throw "Reached an unreachable!"';
- } else {
- return ';';
+ ret = (ASM_JS ? 'abort()' : 'throw "Reached an unreachable!"') + ';' + ret;
}
+ return ret || ';';
});
// Final combiner
diff --git a/tests/cases/legalizer_ta2.ll b/tests/cases/legalizer_ta2.ll
index 7e17c707..89ebcef6 100644
--- a/tests/cases/legalizer_ta2.ll
+++ b/tests/cases/legalizer_ta2.ll
@@ -188,4 +188,5 @@ done:
declare i32 @puts(i8*)
declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_throw(i32, i32, i32) ; for asm1, where exceptions are enabled but this test needs a throw to bring in lib stuff
diff --git a/tests/runner.py b/tests/runner.py
index bda17fe7..507e5041 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -455,7 +455,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]:
ignore, test = sys.argv[1].split('.')
print 'Running all test modes on test "%s"' % test
- sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 'asm2g.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test]
+ sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test]
class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline
## Does a complete test - builds, runs, checks output, etc.
@@ -3709,6 +3709,7 @@ def process(filename):
def test_bigswitch(self):
if Settings.RELOOP: return self.skip('TODO: switch in relooper, issue #781')
+ if Settings.ASM_JS: return self.skip('TODO: switch too large for asm')
src = open(path_from_root('tests', 'bigswitch.cpp')).read()
self.do_run(src, '''34962: GL_ARRAY_BUFFER (0x8892)
@@ -9001,6 +9002,7 @@ TT = %s
exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "JS_CHUNK_SIZE=1024"])')
# asm.js
+ exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=1"])')
exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1"])')
exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])')
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index 4cf15c62..e477c320 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -108,4 +108,19 @@ function label() {
i();
}
}
+function switchy() {
+ var no = 0, yes = 0;
+ while (1) switch (label | 0) {
+ case x:
+ no = 100;
+ break;
+ case y:
+ yes = 111;
+ yes = yes * 2;
+ print(yes);
+ yes--;
+ print(yes / 2);
+ continue;
+ }
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index d2c0507c..acc07edb 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -141,5 +141,20 @@ function label() {
i();
}
}
+function switchy() {
+ var no = 0, yes = 0;
+ while (1) switch (label | 0) {
+ case x:
+ no = 100; // eliminatable in theory, but eliminator does not look into switch. must leave def above as well.
+ break;
+ case y:
+ yes = 111;
+ yes = yes*2;
+ print(yes);
+ yes--;
+ print(yes/2);
+ continue;
+ }
+}
// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label"]
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 5ede0ce8..598287db 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1765,6 +1765,7 @@ function eliminate(ast, memSafe) {
var values = {};
var locals = {};
var varsToRemove = {}; // variables being removed, that we can eliminate all 'var x;' of (this refers to 'var' nodes we should remove)
+ // 1 means we should remove it, 2 means we successfully removed it
var varsToTryToRemove = {}; // variables that have 0 uses, but have side effects - when we scan we can try to remove them
// add arguments as locals
if (func[2]) {
@@ -1822,7 +1823,7 @@ function eliminate(ast, memSafe) {
});
}
if (!hasSideEffects) {
- varsToRemove[name] = 1; // remove it normally
+ varsToRemove[name] = !definitions[name] ? 2 : 1; // remove it normally
sideEffectFree[name] = true;
} else {
varsToTryToRemove[name] = 1; // try to remove it later during scanning
@@ -1979,7 +1980,7 @@ function eliminate(ast, memSafe) {
for (var i = 0; i < value.length; i++) {
node[i] = value[i];
}
- varsToRemove[name] = 1;
+ varsToRemove[name] = 2;
}
} else {
if (allowTracking) track(name, node[3], node);
@@ -2019,7 +2020,7 @@ function eliminate(ast, memSafe) {
for (var i = 0; i < value.length; i++) {
node[i] = value[i];
}
- varsToRemove[name] = 1;
+ varsToRemove[name] = 2;
}
}
}
@@ -2123,7 +2124,7 @@ function eliminate(ast, memSafe) {
function doEliminate(name, node) {
//printErr('elim!!!!! ' + name);
// yes, eliminate!
- varsToRemove[name] = 1; // both assign and var definitions can have other vars we must clean up
+ varsToRemove[name] = 2; // both assign and var definitions can have other vars we must clean up
var info = tracked[name];
delete tracked[name];
var defNode = info.defNode;
@@ -2181,7 +2182,7 @@ function eliminate(ast, memSafe) {
//printErr('cleaning up ' + JSON.stringify(varsToRemove));
traverse(func, function(node, type) {
if (type === 'var') {
- node[1] = node[1].filter(function(pair) { return !(pair[0] in varsToRemove) });
+ node[1] = node[1].filter(function(pair) { return !varsToRemove[pair[0]] });
if (node[1].length == 0) {
// wipe out an empty |var;|
node[0] = 'toplevel';
@@ -2192,7 +2193,7 @@ function eliminate(ast, memSafe) {
if (asm) {
for (var v in varsToRemove) {
- delete asmData.vars[v];
+ if (varsToRemove[v] == 2) delete asmData.vars[v];
}
denormalizeAsm(func, asmData);
}