summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS9
-rw-r--r--demos/scons-embind/SConstruct23
-rw-r--r--demos/scons-embind/bar.cpp2
-rw-r--r--demos/scons-embind/foo.cpp11
-rw-r--r--demos/scons-embind/test.js2
-rw-r--r--docs/splashpres.pdfbin0 -> 131072 bytes
-rwxr-xr-xemcc47
-rwxr-xr-xemscons20
-rw-r--r--scons-tools/closure.py28
-rwxr-xr-xscons-tools/emscripten.py359
-rwxr-xr-xscons-tools/llvm.py33
-rw-r--r--src/determinstic.js8
-rw-r--r--src/embind/embind.js99
-rw-r--r--src/embind/emval.js177
-rw-r--r--src/intertyper.js15
-rw-r--r--src/jsifier.js17
-rw-r--r--src/library.js1242
-rw-r--r--src/library_browser.js72
-rw-r--r--src/library_gc.js2
-rw-r--r--src/library_gl.js1492
-rw-r--r--src/library_glut.js10
-rw-r--r--src/library_sdl.js25
-rw-r--r--src/parseTools.js40
-rw-r--r--src/postamble.js2
-rw-r--r--src/preamble.js13
-rw-r--r--src/relooper/Relooper.cpp127
-rw-r--r--src/relooper/Relooper.h7
-rw-r--r--src/relooper/fuzzer.py4
-rw-r--r--src/relooper/test.cpp41
-rw-r--r--src/relooper/test.txt27
-rw-r--r--src/relooper/test4.txt1
-rw-r--r--src/relooper/test_debug.txt76
-rw-r--r--src/relooper/test_fuzz1.txt11
-rw-r--r--src/relooper/test_fuzz5.txt24
-rw-r--r--src/relooper/test_fuzz6.txt1
-rwxr-xr-xsrc/relooper/testit.sh2
-rwxr-xr-xsrc/relooper/updateit.sh2
-rw-r--r--src/settings.js7
-rw-r--r--src/shell.js1
-rw-r--r--src/socket.io.js3870
-rw-r--r--src/wrtcp.js821
-rw-r--r--system/include/emscripten/bind.h62
-rw-r--r--system/include/emscripten/emscripten.h13
-rw-r--r--system/include/emscripten/val.h116
-rw-r--r--system/include/emscripten/wire.h81
-rw-r--r--system/include/libcxx/exception4
-rw-r--r--system/lib/embind/bind.cpp1
-rw-r--r--system/lib/libcxx/symbols1
-rw-r--r--tests/aniso.c16
-rw-r--r--tests/cases/emptystruct.ll2
-rw-r--r--tests/cases/fp80_ta2.ll (renamed from tests/cases/fp80.ll)0
-rw-r--r--tests/cases/muli33_ta2.ll114
-rw-r--r--tests/cases/muli33_ta2.txt1
-rw-r--r--tests/cases/oob_ta2.ll25
-rw-r--r--tests/cases/philoop_ta2.ll305
-rw-r--r--tests/cases/philoop_ta2.txt1
-rw-r--r--tests/embind/build_benchmark2
-rw-r--r--tests/embind/embind.benchmark.js35
-rw-r--r--tests/embind/embind.test.js153
-rw-r--r--tests/embind/embind_benchmark.cpp71
-rw-r--r--tests/embind/embind_test.cpp65
-rw-r--r--tests/files.cpp3
-rw-r--r--tests/full_es2_sdlproc.c727
-rw-r--r--tests/gl_ps.c40
-rw-r--r--tests/gl_ps_workaround.c230
-rw-r--r--tests/gl_ps_workaround2.c230
-rw-r--r--tests/glbegin_points.c44
-rw-r--r--tests/linpack.c1153
-rwxr-xr-xtests/runner.py662
-rw-r--r--tests/s3tc.c16
-rw-r--r--tests/s3tc_crunch.c16
-rw-r--r--tests/sdl_audio.c4
-rw-r--r--tests/sdl_fog_density.c48
-rw-r--r--tests/sdl_fog_exp2.c48
-rw-r--r--tests/sdl_fog_linear.c48
-rw-r--r--tests/sdl_fog_negative.c48
-rw-r--r--tests/sdl_fog_simple.c51
-rw-r--r--tests/sdl_ogl.c48
-rw-r--r--tests/sdl_ogl_defaultMatrixMode.c46
-rw-r--r--tests/sdl_ogl_p.c44
-rw-r--r--tests/time/src.c5
-rw-r--r--tests/unistd/login.out2
-rw-r--r--tests/unistd/misc.out8
-rw-r--r--tests/unistd/unlink.out2
-rw-r--r--tests/websockets.c2
-rw-r--r--tests/websockets_bi.c16
-rw-r--r--tests/websockets_bi_side.c7
-rw-r--r--third_party/lzma.js/lzip/Makefile18
-rw-r--r--tools/cache.py5
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js4605
-rw-r--r--tools/eliminator/asm-eliminator-test.js6087
-rw-r--r--tools/file_packager.py90
-rw-r--r--tools/js-optimizer.js120
-rw-r--r--tools/shared.py10
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js20
-rw-r--r--tools/test-js-optimizer-asm-pre.js14
-rw-r--r--tools/test-js-optimizer-asm-regs-output.js81
-rw-r--r--tools/test-js-optimizer-asm-regs.js84
98 files changed, 22670 insertions, 1850 deletions
diff --git a/AUTHORS b/AUTHORS
index 6b48014f..9e9d5748 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -76,4 +76,13 @@ a license to everyone to use it as detailed in LICENSE.)
* John Allwine <jallwine86@gmail.com>
* Martin Gerhardy <martin.gerhardy@gmail.com>
* James Gregory <jgregory@zynga.com> (copyright owned by Zynga, Inc)
+* Dan Gohman <sunfish@google.com> (copyright owned by Google, Inc.)
+* Jeff Gilbert <jgilbert@mozilla.com> (copyright owned by Mozilla Foundation)
+* Frits Talbot <frits@metapathy.com>
+* Onno Jongbloed <hey@onnoj.net>
+* Jez Ng <me@jezng.com>
+* Marc Feeley <mfeeley@mozilla.com> (copyright owned by Mozilla Foundation)
* Ludovic Perrine <jazzzz@gmail.com>
+
+
+
diff --git a/demos/scons-embind/SConstruct b/demos/scons-embind/SConstruct
new file mode 100644
index 00000000..8afc3e27
--- /dev/null
+++ b/demos/scons-embind/SConstruct
@@ -0,0 +1,23 @@
+env = Environment(
+ toolpath=['../../scons-tools'],
+ tools=['cc', 'c++', 'ar', 'emscripten', 'llvm', 'closure'],
+ LLVM_ROOT='/opt/local/bin',
+ CLANG='clang-mp-3.2',
+ CLANGXX='clang++-mp-3.2',
+ LLVM_LINK='llvm-link-mp-3.2',
+ LLVM_OPT='opt-mp-3.2',
+ LLVM_DIS='llvm-dis-mp-3.2',
+ EMSCRIPTEN_VERSION_FILE=File('build/version_file'),
+ EMSCRIPTEN_SETTINGS={
+ 'ASM_JS': 0,
+ })
+env['BUILDERS']['WrapInModule'] = Builder(
+ action='cp $SOURCE $TARGET',
+)
+
+env.Append()
+a1 = env.Object('build/foo.bc', 'foo.cpp')
+a2 = env.Object('build/bar.bc', 'bar.cpp')
+total = env.LLVMLink('build/thelibrary.bc', [a1, a2])
+
+env.emscripten('build/thelibrary.js', total)
diff --git a/demos/scons-embind/bar.cpp b/demos/scons-embind/bar.cpp
new file mode 100644
index 00000000..a3908014
--- /dev/null
+++ b/demos/scons-embind/bar.cpp
@@ -0,0 +1,2 @@
+void foo() {
+}
diff --git a/demos/scons-embind/foo.cpp b/demos/scons-embind/foo.cpp
new file mode 100644
index 00000000..61be501a
--- /dev/null
+++ b/demos/scons-embind/foo.cpp
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <emscripten/bind.h>
+
+void print_some_stuff(int a, float b, const std::string& s) {
+ printf("print_some_stuff: %d, %f, %s\n", a, b, s.c_str());
+}
+
+EMSCRIPTEN_BINDINGS(foo) {
+ emscripten::function("print_some_stuff", &print_some_stuff);
+}
+
diff --git a/demos/scons-embind/test.js b/demos/scons-embind/test.js
new file mode 100644
index 00000000..a6252fd8
--- /dev/null
+++ b/demos/scons-embind/test.js
@@ -0,0 +1,2 @@
+var thelibrary = require('./build/thelibrary.js');
+thelibrary.Module.print_some_stuff(1, 2, 'hello world');
diff --git a/docs/splashpres.pdf b/docs/splashpres.pdf
new file mode 100644
index 00000000..02fa4ea0
--- /dev/null
+++ b/docs/splashpres.pdf
Binary files differ
diff --git a/emcc b/emcc
index 1ed5fcb6..2a7e10d0 100755
--- a/emcc
+++ b/emcc
@@ -28,34 +28,6 @@ Example uses:
so it should relay everything to gcc/g++. You should not define that when
running make, of course.
- * With CMake, the same command will work (with cmake instead of ./configure). You may also be
- able to do the following in your CMakeLists.txt:
-
- SET(CMAKE_C_COMPILER "PATH/emcc")
- SET(CMAKE_CXX_COMPILER "PATH/em++")
- SET(CMAKE_LINKER "PATH/emcc")
- SET(CMAKE_CXX_LINKER "PATH/emcc")
- SET(CMAKE_C_LINK_EXECUTABLE "PATH/emcc")
- SET(CMAKE_CXX_LINK_EXECUTABLE "PATH/emcc")
- SET(CMAKE_AR "PATH/emar")
- SET(CMAKE_RANLIB "PATH/emranlib")
-
- * For SCons the shared.py can be imported like so:
- __file__ = str(Dir('#/project_path_to_emscripten/dummy/dummy'))
- __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- def path_from_root(*pathelems):
- return os.path.join(__rootpath__, *pathelems)
- sys.path += [path_from_root('')]
- from tools.shared import *
-
- For using the Emscripten compilers/linkers/etc. you can do:
- env = Environment()
- ...
- env.Append(CCFLAGS = COMPILER_OPTS)
- env.Replace(LINK = LLVM_LD)
- env.Replace(LD = LLVM_LD)
- TODO: Document all relevant setup changes
-
After setting that up, run your build system normally.
Note the appearance of em++ instead of emcc
@@ -138,7 +110,7 @@ while response_file:
sys.argv[index:index+1] = extra_args
break
-if len(sys.argv) == 1 or sys.argv[1] == '--help':
+if len(sys.argv) == 1 or '--help' in sys.argv:
this = os.path.basename('em++' if os.environ.get('EMMAKEN_CXX') else 'emcc')
print '''%s [options] file...
@@ -567,7 +539,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
skip_next = False
idx += 1
continue
- if el == '-s' and is_minus_s_for_emcc(argv, idx):
+ if not use_js and el == '-s' and is_minus_s_for_emcc(argv, idx): # skip -s X=Y if not using js for configure
skip_next = True
else:
yield el
@@ -629,7 +601,7 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS)
# ---------------- Utilities ---------------
-SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc')
+SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
STATICLIB_SUFFIXES = ('.a',)
@@ -657,7 +629,7 @@ header = False # pre-compiled headers. We fake that by just copying the file
for i in range(1, len(sys.argv)):
arg = sys.argv[i]
if not arg.startswith('-'):
- if arg.endswith('.c'):
+ if arg.endswith(('.c','.m')):
use_cxx = False
if arg.endswith('.h') and sys.argv[i-1] != '-include':
header = True
@@ -932,6 +904,9 @@ try:
prev = newargs[i-1]
if prev in ['-MT', '-install_name', '-I', '-L']: continue # ignore this gcc-style argument
+ if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
+ arg = os.path.realpath(arg)
+
if not arg.startswith('-') and (arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg)): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
if os.path.exists(arg):
@@ -1019,7 +994,8 @@ try:
for change in settings_changes:
key, value = change.split('=')
if value[0] == '@':
- value = '"' + value + '"'
+ value = '"@' + os.path.abspath(value[1:]) + '"'
+ value = value.replace('\\\\', '/').replace('\\', '/') # Convert backslash paths to forward slashes on Windows as well, since the JS compiler otherwise needs the backslashes escaped (alternative is to escape all input paths passing to JS, which feels clumsier to read)
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
@@ -1027,8 +1003,7 @@ try:
assert opt_level >= 1, 'asm.js requires -O1 or above'
if bind:
- shared.Settings.ASM_JS = 0
- logging.warning('disabling asm.js because it is not compatible with embind yet')
+ shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
if shared.Settings.CORRECT_SIGNS != 1:
logging.warning('setting CORRECT_SIGNS to 1 for asm.js code generation')
shared.Settings.CORRECT_SIGNS = 1
@@ -1047,8 +1022,6 @@ try:
logging.warning('disabling closure because debug info was requested')
closure = False
- if jcache and not keep_js_debug: print >> sys.stderr, 'emcc: warning: it is recommended to run jcache with -g when compiling bitcode to JS'
-
if minify_whitespace is None:
minify_whitespace = opt_level >= 2 and not keep_js_debug
diff --git a/emscons b/emscons
new file mode 100755
index 00000000..2666f18c
--- /dev/null
+++ b/emscons
@@ -0,0 +1,20 @@
+#!/usr/bin/env python2
+
+'''
+Wrapping the scons invocation, EMSCRIPTEN_TOOL_PATH is set in the process
+environment, and can be used to locate the emscripten SCons Tool.
+Example:
+# Load emscripten Tool
+my_env = Environment(tools=['emscripten'], toolpath=[os.environ['EMSCRIPTEN_TOOL_PATH']])
+'''
+
+import os, subprocess, sys
+from tools import shared
+
+tool_path = os.path.join(shared.path_from_root('tools'), 'scons', 'site_scons', 'site_tools', 'emscripten')
+
+env = os.environ.copy()
+env[ 'EMSCRIPTEN_TOOL_PATH' ] = tool_path
+
+exit(subprocess.call(sys.argv[1:], env=env))
+
diff --git a/scons-tools/closure.py b/scons-tools/closure.py
new file mode 100644
index 00000000..8f53e507
--- /dev/null
+++ b/scons-tools/closure.py
@@ -0,0 +1,28 @@
+import os.path
+from SCons.Builder import Builder
+
+def generate(env):
+ def depend_on_closure_compiler(target, source, env):
+ env.Depends(target, env['CLOSURE_COMPILER'])
+ return target, source
+
+ ClosureCompiler = Builder(
+ action='$JAVA $JAVAFLAGS -jar $CLOSURE_COMPILER $CLOSURE_FLAGS --js_output_file $TARGET $SOURCES',
+ emitter=depend_on_closure_compiler
+ )
+
+ closure = os.path.join(
+ os.path.dirname(__file__),
+ '..',
+ 'third_party',
+ 'closure-compiler',
+ 'compiler.jar')
+ closure = env.File(closure)
+
+ env['JAVA'] = 'java'
+ env['CLOSURE_COMPILER'] = closure
+ env.Append(
+ BUILDERS={'ClosureCompiler':ClosureCompiler})
+
+def exists(_env):
+ return True
diff --git a/scons-tools/emscripten.py b/scons-tools/emscripten.py
new file mode 100755
index 00000000..473c51ad
--- /dev/null
+++ b/scons-tools/emscripten.py
@@ -0,0 +1,359 @@
+import hashlib
+import json
+import sys
+import os
+from SCons.Defaults import Delete
+from SCons.Builder import Builder
+from SCons.Scanner import Scanner
+
+def exists(env):
+ return True
+
+def _expand_settings_flags(settings, env):
+ return [
+ ('-s%s=%s' % (KEY, json.dumps(VALUE).replace('"', '\\"')))
+ for KEY, VALUE in settings.items() ]
+
+emscripten_version_files = {}
+
+def build_version_file(env):
+ if not env.subst('$EMSCRIPTEN_VERSION_FILE'):
+ raise AssertionError('Must set EMSCRIPTEN_VERSION_FILE in environment')
+ if not env.subst('$EMSCRIPTEN_TEMP_DIR'):
+ raise AssertionError('Must set EMSCRIPTEN_TEMP_DIR in environment')
+
+ EMSCRIPTEN_DEPENDENCIES = [
+ env.Glob('${EMSCRIPTEN_HOME}/src/*.js'),
+ env.Glob('${EMSCRIPTEN_HOME}/tools/*.py'),
+ '${EMSCRIPTEN_HOME}/emscripten.py',
+ ]
+ if env.subst('$EMSCRIPTEN_SHELL'):
+ EMSCRIPTEN_DEPENDENCIES.append('$EMSCRIPTEN_SHELL')
+
+ def touch_file(target, source, env):
+ m = hashlib.md5()
+ for s in source:
+ m.update(file(s.abspath, 'rb').read())
+ for t in target:
+ file(t.abspath, 'wb').write(m.hexdigest())
+
+ [emscripten_version_file] = env.Command(
+ '$EMSCRIPTEN_VERSION_FILE',
+ EMSCRIPTEN_DEPENDENCIES,
+ touch_file)
+
+ env.AddPostAction(
+ emscripten_version_file,
+ Delete(env.Dir('$EMSCRIPTEN_TEMP_DIR').abspath))
+
+ return emscripten_version_file
+
+def get_emscripten_version_file(env):
+ EMSCRIPTEN_HOME = env.Dir('$EMSCRIPTEN_HOME').abspath
+ try:
+ version_file = emscripten_version_files[EMSCRIPTEN_HOME]
+ except KeyError:
+ version_file = build_version_file(env)
+ emscripten_version_files[EMSCRIPTEN_HOME] = version_file
+ return version_file
+
+def depend_on_emscripten(node, env, path):
+ return [get_emscripten_version_file(env)]
+
+EmscriptenScanner = Scanner(
+ name='emscripten',
+ function=depend_on_emscripten)
+
+def setExtension(filename, extension):
+ return os.path.splitext(filename)[0] + '.' + extension
+
+def emscripten(env, target_js, source_bc):
+ env = env.Clone()
+ def buildName(extension):
+ return setExtension(target_js, extension)
+
+ # for debugging and reading generated code.
+ # not in critical path, uses spare cores.
+ env.LLVMDis(buildName('ll'), source_bc)
+
+ [opt_ll] = env.LLVMOpt(
+ buildName('opt.ll'),
+ source_bc,
+ LLVM_OPT_FLAGS=['-S'])
+
+ [raw_emscripten_js] = env.Emscripten(
+ buildName('raw.js'),
+ [opt_ll])
+
+ [optimized_js] = env.JSOptimizer(
+ buildName('opt.js'),
+ raw_emscripten_js)
+
+ prejs = [
+ env['EMSCRIPTEN_PREJS'],
+ '${EMSCRIPTEN_HOME}/src/embind/emval.js',
+ '${EMSCRIPTEN_HOME}/src/embind/embind.js' ]
+
+ [concatenated_js] = env.Concatenate(
+ buildName('concat.js'),
+ [ prejs,
+ optimized_js,
+ env['EMSCRIPTEN_POSTJS'] ])
+
+ DISABLE_EMSCRIPTEN_WARNINGS = [
+ '--jscomp_error', 'ambiguousFunctionDecl',
+ '--jscomp_error', 'checkDebuggerStatement',
+ '--jscomp_off', 'checkTypes',
+ '--jscomp_off', 'checkVars',
+ '--jscomp_error', 'deprecated',
+ '--jscomp_off', 'duplicate',
+ #'--jscomp_error', 'es5strict',
+ '--jscomp_off', 'missingProperties', # TODO: fix emscripten and turn this one on
+ '--jscomp_error', 'undefinedNames',
+ '--jscomp_off', 'undefinedVars', # TODO: fix emscripten and turn this one on
+ '--jscomp_off', 'uselessCode',
+ '--jscomp_off', 'globalThis',
+ ]
+
+ [iter_global_emscripten_js] = env.Concatenate(
+ buildName('iter.js'),
+ [ prejs,
+ raw_emscripten_js,
+ env['EMSCRIPTEN_POSTJS'] ])
+
+ [global_cc_emscripten_js] = env.ClosureCompiler(
+ buildName('global.closure.js'),
+ concatenated_js,
+ CLOSURE_FLAGS=['--language_in', 'ECMASCRIPT5']+DISABLE_EMSCRIPTEN_WARNINGS+['--formatting', 'PRETTY_PRINT', '--compilation_level', 'SIMPLE_OPTIMIZATIONS'])
+
+ #env.Append(
+ # NODEJSFLAGS=['--max-stack-size=1000000000'],
+ # UGLIFYJSFLAGS=['--stats', '-c', 'warnings=false', '-b'])
+ #env.UglifyJS(
+ # buildName('global.uglify.js'),
+ # concatenated_js)
+
+ [closure_js] = env.ClosureCompiler(
+ buildName('closure.js'),
+ concatenated_js,
+ CLOSURE_FLAGS=['--language_in', 'ECMASCRIPT5']+DISABLE_EMSCRIPTEN_WARNINGS+['--formatting', 'PRETTY_PRINT', '--compilation_level', 'ADVANCED_OPTIMIZATIONS'])
+
+ [global_emscripten_min_js] = env.JSOptimizer(
+ buildName('global.min.js'),
+ closure_js,
+ JS_OPTIMIZER_PASSES=['simplifyExpressionsPost', 'compress', 'last'])
+
+ [emscripten_iteration_js] = env.WrapInModule(
+ buildName('iteration.js'),
+ iter_global_emscripten_js)
+
+ [emscripten_js] = env.WrapInModule(
+ buildName('debug.js'),
+ global_cc_emscripten_js)
+
+ [emscripten_min_js] = env.WrapInModule(
+ buildName('min.js'),
+ global_emscripten_min_js)
+
+ env.InstallAs(buildName('js'), emscripten_js)
+
+ return [emscripten_iteration_js, emscripten_js, emscripten_min_js]
+
+LIBC_SOURCES = [
+ 'system/lib/dlmalloc.c',
+ 'system/lib/libc/musl/src/string/wmemset.c',
+ 'system/lib/libc/musl/src/string/wmemcpy.c',
+]
+
+LIBCXX_SOURCES = [os.path.join('system/lib/libcxx', x) for x in [
+ 'algorithm.cpp',
+ 'bind.cpp',
+ #'chrono.cpp',
+ #'condition_variable.cpp',
+ #'debug.cpp',
+ #'exception.cpp',
+ 'future.cpp',
+ 'hash.cpp',
+ #'ios.cpp',
+ #'iostream.cpp',
+ 'memory.cpp',
+ 'mutex.cpp',
+ 'new.cpp',
+ 'random.cpp',
+ 'regex.cpp',
+ 'stdexcept.cpp',
+ 'string.cpp',
+ 'strstream.cpp',
+ 'system_error.cpp',
+ #'thread.cpp',
+ 'typeinfo.cpp',
+ 'utility.cpp',
+ 'valarray.cpp',
+]]
+
+LIBCXXABI_SOURCES = [os.path.join('system/lib/libcxxabi/src', x) for x in [
+ 'private_typeinfo.cpp'
+]]
+
+# MAJOR HACK ALERT
+# ugh, SCons imports tool .py files multiple times, meaning that global variables aren't really global
+# store our "globals" "privately" on the SCons object :(
+import SCons
+
+def build_libembind(env):
+ emscripten_temp_dir = env.Dir('$EMSCRIPTEN_TEMP_DIR').abspath
+ try:
+ libembind_cache = SCons.__emscripten_libembind_cache
+ except AttributeError:
+ libembind_cache = {}
+ SCons.__emscripten_libembind_cache = libembind_cache
+ try:
+ return libembind_cache[emscripten_temp_dir]
+ except KeyError:
+ pass
+
+ libembind = env.Object(
+ '$EMSCRIPTEN_TEMP_DIR/internal_libs/bind',
+ '$EMSCRIPTEN_HOME/system/lib/embind/bind.cpp')
+ env.Depends(libembind, get_emscripten_version_file(env))
+ libembind_cache[emscripten_temp_dir] = libembind
+ return libembind
+
+def build_libcxx(env):
+ emscripten_temp_dir = env.Dir('$EMSCRIPTEN_TEMP_DIR').abspath
+ try:
+ libcxx_cache = SCons.__emscripten_libcxx_cache
+ except AttributeError:
+ libcxx_cache = {}
+ SCons.__emscripten_libcxx_cache = libcxx_cache
+ try:
+ return libcxx_cache[emscripten_temp_dir]
+ except KeyError:
+ pass
+
+ env = env.Clone()
+ env['CXXFLAGS'] = filter(lambda e: e not in ('-Werror', '-Wall'), env['CXXFLAGS'])
+ env['CCFLAGS'] = filter(lambda e: e not in ('-Werror', '-Wall'), env['CCFLAGS'])
+
+ objs = [
+ env.Object(
+ '${EMSCRIPTEN_TEMP_DIR}/libcxx_objects/' + os.path.splitext(o)[0] + '.bc',
+ '${EMSCRIPTEN_HOME}/' + o)
+ for o in LIBC_SOURCES + LIBCXXABI_SOURCES + LIBCXX_SOURCES]
+ env.Depends(objs, get_emscripten_version_file(env))
+
+ libcxx = env.Library('${EMSCRIPTEN_TEMP_DIR}/internal_libs/libcxx', objs)
+ libcxx_cache[emscripten_temp_dir] = libcxx
+ return libcxx
+
+def generate(env):
+ env.SetDefault(
+ PYTHON=sys.executable,
+ NODEJS='node',
+ JS_ENGINE='$NODEJS',
+ EMSCRIPTEN_FLAGS=['-v', '-j', '--suppressUsageWarning'],
+ EMSCRIPTEN_TEMP_DIR=env.Dir('#/emscripten.tmp'),
+ _expand_settings_flags=_expand_settings_flags,
+ EMSCRIPTEN_PREJS=[],
+ EMSCRIPTEN_POSTJS=[],
+ EMSCRIPTEN_SETTINGS={},
+ _EMSCRIPTEN_SETTINGS_FLAGS='${_expand_settings_flags(EMSCRIPTEN_SETTINGS, __env__)}',
+ JS_OPTIMIZER_PASSES=[],
+ LLVM_OPT_PASSES=['-std-compile-opts', '-std-link-opts'],
+
+ EMSCRIPTEN_HOME=env.Dir(os.path.join(os.path.dirname(__file__), '..')),
+ )
+
+ env.Replace(
+ CC='${LLVM_ROOT}/${CLANG}',
+ CXX='${LLVM_ROOT}/${CLANGXX}',
+ AR='${LLVM_ROOT}/${LLVM_LINK}',
+ ARCOM='$AR -o $TARGET $SOURCES',
+ OBJSUFFIX='.bc',
+ LIBPREFIX='',
+ LIBSUFFIX='.bc',
+ RANLIBCOM='',
+ CCFLAGS=[
+ '-U__STRICT_ANSI__',
+ '-target', 'le32-unknown-nacl',
+ '-nostdinc',
+ '-Wno-#warnings',
+ '-Wno-error=unused-variable',
+ '-Werror',
+ '-Os',
+ '-fno-threadsafe-statics',
+ '-fvisibility=hidden',
+ '-fvisibility-inlines-hidden',
+ '-Xclang', '-nostdinc++',
+ '-Xclang', '-nobuiltininc',
+ '-Xclang', '-nostdsysteminc',
+ '-Xclang', '-isystem$EMSCRIPTEN_HOME/system/include',
+ '-Xclang', '-isystem$EMSCRIPTEN_HOME/system/include/libc',
+ '-Xclang', '-isystem$EMSCRIPTEN_HOME/system/include/libcxx',
+ '-Xclang', '-isystem$EMSCRIPTEN_HOME/system/include/bsd',
+ '-emit-llvm'],
+ CXXFLAGS=['-std=c++11', '-fno-exceptions'],
+ )
+ env.Append(CPPDEFINES=[
+ 'EMSCRIPTEN',
+ '__EMSCRIPTEN__',
+ '__STDC__',
+ '__IEEE_LITTLE_ENDIAN',
+ ])
+
+ env['BUILDERS']['Emscripten'] = Builder(
+ action='$PYTHON ${EMSCRIPTEN_HOME}/emscripten.py $EMSCRIPTEN_FLAGS $_EMSCRIPTEN_SETTINGS_FLAGS --temp-dir=$EMSCRIPTEN_TEMP_DIR --compiler $JS_ENGINE --relooper=third-party/relooper.js $SOURCE > $TARGET',
+ target_scanner=EmscriptenScanner)
+
+ env['BUILDERS']['JSOptimizer'] = Builder(
+ action='$JS_ENGINE ${EMSCRIPTEN_HOME}/tools/js-optimizer.js $SOURCE $JS_OPTIMIZER_PASSES > $TARGET',
+ target_scanner=EmscriptenScanner)
+
+ def depend_on_embedder(target, source, env):
+ env.Depends(target, env['JS_EMBEDDER'])
+ return target, source
+
+ def embed_files_in_js(target, source, env, for_signature):
+ return '$PYTHON $JS_EMBEDDER $SOURCE.srcpath > $TARGET'
+
+ def get_files_in_tree(node, env, path):
+ tree_paths = []
+ for root, dirs, files in os.walk(str(node)):
+ tree_paths += [os.path.join(root, f) for f in files]
+ return [env.File(p) for p in tree_paths]
+
+ env.SetDefault(
+ JS_EMBEDDER=env.File('#/bin/embed_files_in_js.py'))
+
+ FileTreeScanner = Scanner(
+ function=get_files_in_tree,
+ name='FileTreeScanner',
+ recursive=False)
+
+ env['BUILDERS']['EmbedFilesInJS'] = Builder(
+ generator=embed_files_in_js,
+ emitter=depend_on_embedder,
+ source_scanner=FileTreeScanner)
+
+ env.AddMethod(emscripten)
+
+ def ConcatenateAction(target, source, env):
+ [target] = target
+ total = ''.join(file(str(s), 'rb').read() for s in source)
+ file(str(target), 'wb').write(total)
+ env['BUILDERS']['Concatenate'] = Builder(action=ConcatenateAction)
+
+ libembind = build_libembind(env)
+ libcxx = build_libcxx(env)
+
+ # should embind be its own tool?
+ env.Append(
+ CPPPATH=[
+ '${EMSCRIPTEN_HOME}/system/include' ],
+ LIBPATH=['$EMSCRIPTEN_TEMP_DIR/internal_libs'],
+ LIBS=[
+ libembind,
+ libcxx,
+ ],
+ )
+
diff --git a/scons-tools/llvm.py b/scons-tools/llvm.py
new file mode 100755
index 00000000..f272bd16
--- /dev/null
+++ b/scons-tools/llvm.py
@@ -0,0 +1,33 @@
+from SCons.Scanner.Prog import scan
+from SCons.Builder import Builder
+
+def exists(env):
+ return True
+
+def add_libraries(target, source, env):
+ unique = []
+ lib_nodes = set()
+ for x in scan(None, env, tuple(map(env.Dir, env['LIBPATH']))):
+ if x in lib_nodes:
+ continue
+ lib_nodes.add(x)
+ unique.append(x)
+ return (target, source + unique)
+
+def generate(env):
+ env.SetDefault(
+ CLANG='clang',
+ CLANGXX='clang++',
+ LLVM_DIS='llvm-dis',
+ LLVM_OPT='opt',
+ LLVM_LINK='llvm-link')
+
+ env['BUILDERS']['LLVMDis'] = Builder(
+ action='${LLVM_ROOT}/$LLVM_DIS -o=$TARGET $SOURCE')
+
+ env['BUILDERS']['LLVMOpt'] = Builder(
+ action='${LLVM_ROOT}/$LLVM_OPT $LLVM_OPT_FLAGS $LLVM_OPT_PASSES -o=$TARGET $SOURCE')
+
+ env['BUILDERS']['LLVMLink'] = Builder(
+ action='${LLVM_ROOT}/$LLVM_LINK -o=$TARGET $SOURCES',
+ emitter=add_libraries)
diff --git a/src/determinstic.js b/src/determinstic.js
index 91f98ed9..1ec0bbfe 100644
--- a/src/determinstic.js
+++ b/src/determinstic.js
@@ -10,3 +10,11 @@ Date.now = function() {
};
performance.now = Date.now;
+function hashMemory(id) {
+ var ret = 0;
+ for (var i = 0; i < HEAPU8.length; i++) {
+ ret = (ret*17 + HEAPU8[i])|0;
+ }
+ print(id + ':' + ret);
+}
+
diff --git a/src/embind/embind.js b/src/embind/embind.js
index cadee700..91386c69 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -131,6 +131,7 @@ function extendError(baseErrorType, errorName) {
// from https://github.com/imvu/imvujs/blob/master/src/function.js
function createNamedFunction(name, body) {
+ name = makeLegalFunctionName(name);
/*jshint evil:true*/
return new Function(
"body",
@@ -270,6 +271,10 @@ function __embind_register_void(rawType, name) {
'fromWireType': function() {
return undefined;
},
+ 'toWireType': function(destructors, o) {
+ // TODO: assert if anything else is given?
+ return undefined;
+ },
});
}
@@ -306,7 +311,7 @@ function __embind_register_integer(primitiveType, name, minRange, maxRange) {
'toWireType': function(destructors, value) {
// todo: Here we have an opportunity for -O3 level "unsafe" optimizations: we could
// avoid the following two if()s and assume value is of proper type.
- if (typeof value !== "number") {
+ if (typeof value !== "number" && typeof value !== "boolean") {
throw new TypeError('Cannot convert "' + _embind_repr(value) + '" to ' + this.name);
}
if (value < minRange || value > maxRange) {
@@ -328,8 +333,8 @@ function __embind_register_float(rawType, name) {
'toWireType': function(destructors, value) {
// todo: Here we have an opportunity for -O3 level "unsafe" optimizations: we could
// avoid the following if() and assume value is of proper type.
- if (typeof value !== "number") {
- throw new TypeError('Cannot convert "' + _embind_repr(value) + '" to ' +this.name);
+ if (typeof value !== "number" && typeof value !== "boolean") {
+ throw new TypeError('Cannot convert "' + _embind_repr(value) + '" to ' + this.name);
}
return value;
},
@@ -449,6 +454,31 @@ function __embind_register_emval(rawType, name) {
});
}
+function __embind_register_memory_view(rawType, name) {
+ var typeMapping = [
+ Int8Array,
+ Uint8Array,
+ Int16Array,
+ Uint16Array,
+ Int32Array,
+ Uint32Array,
+ Float32Array,
+ Float64Array,
+ ];
+
+ name = readLatin1String(name);
+ registerType(rawType, {
+ name: name,
+ 'fromWireType': function(handle) {
+ var type = HEAPU32[handle >> 2];
+ var size = HEAPU32[(handle >> 2) + 1]; // in elements
+ var data = HEAPU32[(handle >> 2) + 2]; // byte offset into emscripten heap
+ var TA = typeMapping[type];
+ return new TA(HEAP8.buffer, data, size);
+ },
+ });
+}
+
function runDestructors(destructors) {
while (destructors.length) {
var ptr = destructors.pop();
@@ -677,7 +707,7 @@ function __embind_finalize_tuple(rawTupleType) {
},
'toWireType': function(destructors, o) {
if (elementsLength !== o.length) {
- throw new TypeError("Incorrect number of tuple elements");
+ throw new TypeError("Incorrect number of tuple elements for " + reg.name + ": expected=" + elementsLength + ", actual=" + o.length);
}
var ptr = rawConstructor();
for (var i = 0; i < elementsLength; ++i) {
@@ -685,7 +715,7 @@ function __embind_finalize_tuple(rawTupleType) {
}
if (destructors !== null) {
destructors.push(rawDestructor, ptr);
- }
+ }
return ptr;
},
destructorFunction: rawDestructor,
@@ -802,7 +832,9 @@ var genericPointerToWireType = function(destructors, handle) {
if (this.isSmartPointer) {
var ptr = this.rawConstructor();
- destructors.push(this.rawDestructor, ptr);
+ if (destructors !== null) {
+ destructors.push(this.rawDestructor, ptr);
+ }
return ptr;
} else {
return 0;
@@ -854,7 +886,9 @@ var genericPointerToWireType = function(destructors, handle) {
clonedHandle.delete();
})
);
- destructors.push(this.rawDestructor, ptr);
+ if (destructors !== null) {
+ destructors.push(this.rawDestructor, ptr);
+ }
}
break;
@@ -1080,9 +1114,13 @@ ClassHandle.prototype.isAliasOf = function(other) {
return leftClass === rightClass && left === right;
};
+function throwInstanceAlreadyDeleted(obj) {
+ throwBindingError(getInstanceTypeName(obj) + ' instance already deleted');
+}
+
ClassHandle.prototype.clone = function() {
if (!this.$$.ptr) {
- throwBindingError(getInstanceTypeName(this) + ' instance already deleted');
+ throwInstanceAlreadyDeleted(this);
}
var clone = Object.create(Object.getPrototypeOf(this), {
@@ -1104,9 +1142,12 @@ function runDestructor(handle) {
}
}
-ClassHandle.prototype['delete'] = function() {
+ClassHandle.prototype['delete'] = function ClassHandle_delete() {
if (!this.$$.ptr) {
- throwBindingError(getInstanceTypeName(this) + ' instance already deleted');
+ throwInstanceAlreadyDeleted(this);
+ }
+ if (this.$$.deleteScheduled) {
+ throwBindingError('Object already scheduled for deletion');
}
this.$$.count.value -= 1;
@@ -1116,6 +1157,44 @@ ClassHandle.prototype['delete'] = function() {
this.$$.smartPtr = undefined;
this.$$.ptr = undefined;
};
+
+var deletionQueue = [];
+
+ClassHandle.prototype['isDeleted'] = function isDeleted() {
+ return !this.$$.ptr;
+};
+
+ClassHandle.prototype['deleteLater'] = function deleteLater() {
+ if (!this.$$.ptr) {
+ throwInstanceAlreadyDeleted(this);
+ }
+ if (this.$$.deleteScheduled) {
+ throwBindingError('Object already scheduled for deletion');
+ }
+ deletionQueue.push(this);
+ if (deletionQueue.length === 1 && delayFunction) {
+ delayFunction(flushPendingDeletes);
+ }
+ this.$$.deleteScheduled = true;
+ return this;
+};
+
+function flushPendingDeletes() {
+ while (deletionQueue.length) {
+ var obj = deletionQueue.pop();
+ obj.$$.deleteScheduled = false;
+ obj['delete']();
+ }
+}
+Module['flushPendingDeletes'] = flushPendingDeletes;
+
+var delayFunction;
+Module['setDelayFunction'] = function setDelayFunction(fn) {
+ delayFunction = fn;
+ if (deletionQueue.length && delayFunction) {
+ delayFunction(flushPendingDeletes);
+ }
+};
function RegisteredClass(
name,
diff --git a/src/embind/emval.js b/src/embind/emval.js
index c02ffa92..77270597 100644
--- a/src/embind/emval.js
+++ b/src/embind/emval.js
@@ -1,8 +1,12 @@
-/*global Module*/
+/*global Module:true, Runtime*/
/*global HEAP32*/
+/*global new_*/
+/*global createNamedFunction*/
/*global readLatin1String, writeStringToMemory*/
/*global requireRegisteredType, throwBindingError*/
+var Module = Module || {};
+
var _emval_handle_array = [{}]; // reserve zero
var _emval_free_list = [];
@@ -69,14 +73,8 @@ function __emval_incref(handle) {
function __emval_decref(handle) {
if (handle && 0 === --_emval_handle_array[handle].refcount) {
- delete _emval_handle_array[handle];
+ _emval_handle_array[handle] = undefined;
_emval_free_list.push(handle);
-
- var actual_length = _emval_handle_array.length;
- while (actual_length > 0 && _emval_handle_array[actual_length - 1] === undefined) {
- --actual_length;
- }
- _emval_handle_array.length = actual_length;
}
}
@@ -108,44 +106,73 @@ function __emval_take_value(type, v) {
var __newers = {}; // arity -> function
-function __emval_new(handle, argCount, argTypes) {
- requireHandle(handle);
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 3));
+function craftEmvalAllocator(argCount) {
+ /*This function returns a new function that looks like this:
+ function emval_allocator_3(handle, argTypes, arg0Wired, arg1Wired, arg2Wired) {
+ var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0");
+ var arg0 = argType0.fromWireType(arg0Wired);
+ var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1");
+ var arg1 = argType1.fromWireType(arg1Wired);
+ var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2");
+ var arg2 = argType2.fromWireType(arg2Wired);
+ var constructor = _emval_handle_array[handle].value;
+ var emval = new constructor(arg0, arg1, arg2);
+ return emval;
+ } */
+
+ var args1 = ["requireRegisteredType", "HEAP32", "_emval_handle_array", "__emval_register"];
+ var args2 = [requireRegisteredType, HEAP32, _emval_handle_array, __emval_register];
+
+ var argsList = "";
+ var argsListWired = "";
+ for(var i = 0; i < argCount; ++i) {
+ argsList += (i!==0?", ":"")+"arg"+i; // 'arg0, arg1, ..., argn'
+ argsListWired += ", arg"+i+"Wired"; // ', arg0Wired, arg1Wired, ..., argnWired'
+ }
- // Alas, we are forced to use operator new until WebKit enables
- // constructing typed arrays without new.
- // In WebKit, Uint8Array(10) throws an error.
- // In every other browser, it's identical to new Uint8Array(10).
+ var invokerFnBody =
+ "return function emval_allocator_"+argCount+"(handle, argTypes " + argsListWired + ") {\n";
+ for(var i = 0; i < argCount; ++i) {
+ invokerFnBody +=
+ "var argType"+i+" = requireRegisteredType(HEAP32[(argTypes >> 2) + "+i+"], \"parameter "+i+"\");\n" +
+ "var arg"+i+" = argType"+i+".fromWireType(arg"+i+"Wired);\n";
+ }
+ invokerFnBody +=
+ "var constructor = _emval_handle_array[handle].value;\n" +
+ "var obj = new constructor("+argsList+");\n" +
+ "return __emval_register(obj);\n" +
+ "}\n";
+
+ args1.push(invokerFnBody);
+ var invokerFunction = new_(Function, args1).apply(null, args2);
+ return invokerFunction;
+}
+
+function __emval_new(handle, argCount, argTypes) {
+ requireHandle(handle);
+
var newer = __newers[argCount];
if (!newer) {
- var parameters = new Array(argCount);
- for (var i = 0; i < argCount; ++i) {
- parameters[i] = 'a' + i;
- }
- /*jshint evil:true*/
- newer = __newers[argCount] = new Function(
- ['c'].concat(parameters),
- "return new c(" + parameters.join(',') + ");");
+ newer = craftEmvalAllocator(argCount);
+ __newers[argCount] = newer;
}
-
- var constructor = _emval_handle_array[handle].value;
- var obj = newer.apply(undefined, [constructor].concat(args));
-/*
- // implement what amounts to operator new
- function dummy(){}
- dummy.prototype = constructor.prototype;
- var obj = new constructor;
- var rv = constructor.apply(obj, args);
- if (typeof rv === 'object') {
- obj = rv;
+
+ if (argCount === 0) {
+ return newer(handle, argTypes);
+ } else if (argCount === 1) {
+ return newer(handle, argTypes, arguments[3]);
+ } else if (argCount === 2) {
+ return newer(handle, argTypes, arguments[3], arguments[4]);
+ } else if (argCount === 3) {
+ return newer(handle, argTypes, arguments[3], arguments[4], arguments[5]);
+ } else if (argCount === 4) {
+ return newer(handle, argTypes, arguments[3], arguments[4], arguments[5], arguments[6]);
+ } else {
+ // This is a slow path! (.apply and .splice are slow), so a few specializations are present above.
+ return newer.apply(null, arguments.splice(1));
}
-*/
- return __emval_register(obj);
}
// appease jshint (technically this code uses eval)
@@ -192,38 +219,62 @@ function parseParameters(argCount, argTypes, argWireTypes) {
function __emval_call(handle, argCount, argTypes) {
requireHandle(handle);
+ var types = lookupTypes(argCount, argTypes);
+
+ var args = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ args[i] = types[i].fromWireType(arguments[3 + i]);
+ }
+
var fn = _emval_handle_array[handle].value;
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 3));
var rv = fn.apply(undefined, args);
return __emval_register(rv);
}
-function __emval_call_method(handle, name, argCount, argTypes) {
- requireHandle(handle);
- name = getStringOrSymbol(name);
-
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 4));
- var obj = _emval_handle_array[handle].value;
- var rv = obj[name].apply(obj, args);
- return __emval_register(rv);
+function lookupTypes(argCount, argTypes, argWireTypes) {
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ a[i] = requireRegisteredType(
+ HEAP32[(argTypes >> 2) + i],
+ "parameter " + i);
+ }
+ return a;
}
-function __emval_call_void_method(handle, name, argCount, argTypes) {
- requireHandle(handle);
- name = getStringOrSymbol(name);
+function __emval_get_method_caller(argCount, argTypes) {
+ var types = lookupTypes(argCount, argTypes);
+
+ var retType = types[0];
+ var signatureName = retType.name + "_$" + types.slice(1).map(function (t) { return t.name; }).join("_") + "$";
+
+ var args1 = ["Runtime", "createNamedFunction", "requireHandle", "getStringOrSymbol", "_emval_handle_array", "retType"];
+ var args2 = [Runtime, createNamedFunction, requireHandle, getStringOrSymbol, _emval_handle_array, retType];
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 4));
- var obj = _emval_handle_array[handle].value;
- obj[name].apply(obj, args);
+ var argsList = ""; // 'arg0, arg1, arg2, ... , argN'
+ var argsListWired = ""; // 'arg0Wired, ..., argNWired'
+ for (var i = 0; i < argCount - 1; ++i) {
+ argsList += (i !== 0 ? ", " : "") + "arg" + i;
+ argsListWired += ", arg" + i + "Wired";
+ args1.push("argType" + i);
+ args2.push(types[1 + i]);
+ }
+
+ var invokerFnBody =
+ "return Runtime.addFunction(createNamedFunction('" + signatureName + "', function (handle, name" + argsListWired + ") {\n" +
+ "requireHandle(handle);\n" +
+ "name = getStringOrSymbol(name);\n";
+
+ for (var i = 0; i < argCount - 1; ++i) {
+ invokerFnBody += "var arg" + i + " = argType" + i + ".fromWireType(arg" + i + "Wired);\n";
+ }
+ invokerFnBody +=
+ "var obj = _emval_handle_array[handle].value;\n" +
+ "return retType.toWireType(null, obj[name](" + argsList + "));\n" +
+ "}));\n";
+
+ args1.push(invokerFnBody);
+ var invokerFunction = new_(Function, args1).apply(null, args2);
+ return invokerFunction;
}
function __emval_has_function(handle, name) {
diff --git a/src/intertyper.js b/src/intertyper.js
index 445c37f4..6da30ae8 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -537,12 +537,17 @@ function intertyper(data, sidePass, baseLineNums) {
});
}
} else if (!external) {
- if (item.tokens[3].text == 'c')
- item.tokens.splice(3, 1);
- if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
+ if (item.tokens[3] && item.tokens[3].text != ';') {
+ if (item.tokens[3].text == 'c') {
+ item.tokens.splice(3, 1);
+ }
+ if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
+ ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
+ } else {
+ ret.value = scanConst(item.tokens[3], ret.type);
+ }
} else {
- ret.value = scanConst(item.tokens[3], ret.type);
+ ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type };
}
}
return [ret];
diff --git a/src/jsifier.js b/src/jsifier.js
index 3f52337f..156fd65d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -12,6 +12,8 @@ var RELOOP_IGNORED_LASTS = set('return', 'unreachable', 'resume');
var addedLibraryItems = {};
var asmLibraryFunctions = [];
+var SETJMP_LABEL = -1;
+
// JSifier
function JSify(data, functionsOnly, givenFunctions) {
var mainPass = !functionsOnly;
@@ -458,6 +460,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
ident = '_' + ident;
}
+ if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps);
var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';');
if (ASM_JS) {
@@ -730,7 +733,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}).join('\n') + '\n';
if (func.setjmpTable && ASM_JS) {
// emit a label in which we write to the proper local variable, before jumping to the actual label
- ret += ' case -1111: ';
+ ret += ' case ' + SETJMP_LABEL + ': ';
ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
}).join(' else ');
@@ -1030,13 +1033,13 @@ function JSify(data, functionsOnly, givenFunctions) {
}
for (var i = 0; i < idents.length; i++) {
if (keys(deps[idents[i]]).length == 0) {
- pre = 'var ' + idents[i] + ' = ' + valueJSes[idents[i]] + ';' + pre;
+ post = 'var ' + idents[i] + ' = ' + valueJSes[idents[i]] + ';' + post;
remove(idents[i]);
continue mainLoop;
}
}
// If we got here, we have circular dependencies, and must break at least one.
- pre = 'var ' + idents[0] + '$phi = ' + valueJSes[idents[0]] + ';' + pre;
+ pre += 'var ' + idents[0] + '$phi = ' + valueJSes[idents[0]] + ';';
post += 'var ' + idents[0] + ' = ' + idents[0] + '$phi;';
remove(idents[0]);
}
@@ -1160,6 +1163,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret + ';';
});
makeFuncLineActor('resume', function(item) {
+ if (DISABLE_EXCEPTION_CATCHING) return 'abort()';
if (item.ident == 0) {
// No exception to resume, so we can just bail.
// This is related to issue #917 and http://llvm.org/PR15518
@@ -1181,6 +1185,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (disabled) {
ret = call_ + ';';
} else if (ASM_JS) {
+ call_ = call_.replace('; return', ''); // we auto-add returns when aborting, but do not need them here
ret = '(__THREW__ = 0,' + call_ + ');';
} else {
ret = '(function() { try { __THREW__ = 0; return '
@@ -1356,7 +1361,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var ignoreFunctionIndexizing = [];
var useJSArgs = (simpleIdent + '__jsargs') in LibraryManager.library;
var hasVarArgs = isVarArgsFunctionType(type);
- var normalArgs = (hasVarArgs && !useJSArgs) ? countNormalArgs(type) : -1;
+ var normalArgs = (hasVarArgs && !useJSArgs) ? countNormalArgs(type, null, true) : -1;
var byPointer = getVarData(funcData, ident);
var byPointerForced = false;
@@ -1487,9 +1492,9 @@ function JSify(data, functionsOnly, givenFunctions) {
}
if (ASM_JS && funcData.setjmpTable) {
- // check if a longjmp was done. If a setjmp happened, check if ours. If ours, go to -111 to handle it.
+ // check if a longjmp was done. If a setjmp happened, check if ours. If ours, go to a special label to handle it.
// otherwise, just return - the call to us must also have been an invoke, so the setjmp propagates that way
- ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) > 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = -1111; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;\n';
+ ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) != 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = ' + SETJMP_LABEL + '; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;\n';
}
return ret;
diff --git a/src/library.js b/src/library.js
index 344ec8d6..ab27ed35 100644
--- a/src/library.js
+++ b/src/library.js
@@ -63,6 +63,36 @@ LibraryManager.library = {
// This is set to false when the runtime is initialized, allowing you
// to modify the filesystem freely before run() is called.
ignorePermissions: true,
+ createFileHandle: function(stream, fd) {
+ if (typeof stream === 'undefined') {
+ stream = null;
+ }
+ if (!fd) {
+ if (stream && stream.socket) {
+ for (var i = 1; i < 64; i++) {
+ if (!FS.streams[i]) {
+ fd = i;
+ break;
+ }
+ }
+ assert(fd, 'ran out of low fds for sockets');
+ } else {
+ fd = Math.max(FS.streams.length, 64);
+ for (var i = FS.streams.length; i < fd; i++) {
+ FS.streams[i] = null; // Keep dense
+ }
+ }
+ }
+ // Close WebSocket first if we are about to replace the fd (i.e. dup2)
+ if (FS.streams[fd] && FS.streams[fd].socket && FS.streams[fd].socket.close) {
+ FS.streams[fd].socket.close();
+ }
+ FS.streams[fd] = stream;
+ return fd;
+ },
+ removeFileHandle: function(fd) {
+ FS.streams[fd] = null;
+ },
joinPath: function(parts, forceRelative) {
var ret = parts[0];
for (var i = 1; i < parts.length; i++) {
@@ -326,24 +356,25 @@ LibraryManager.library = {
#else
var chunkSize = 1024*1024; // Chunk size in bytes
#endif
+
if (!hasByteServing) chunkSize = datalength;
-
+
// Function to get a range from the remote URL.
var doXHR = (function(from, to) {
if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
-
+
// TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
-
+
// Some hints to the browser that we want binary data.
if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
if (xhr.overrideMimeType) {
xhr.overrideMimeType('text/plain; charset=x-user-defined');
}
-
+
xhr.send(null);
if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
if (xhr.response !== undefined) {
@@ -368,7 +399,7 @@ LibraryManager.library = {
this._chunkSize = chunkSize;
this.lengthKnown = true;
}
-
+
var lazyArray = new LazyUint8Array();
Object.defineProperty(lazyArray, "length", {
get: function() {
@@ -560,6 +591,7 @@ LibraryManager.library = {
var stdout = FS.createDevice(devFolder, 'stdout', null, output);
var stderr = FS.createDevice(devFolder, 'stderr', null, error);
FS.createDevice(devFolder, 'tty', input, output);
+ FS.createDevice(devFolder, 'null', function(){}, function(){});
// Create default streams.
FS.streams[1] = {
@@ -619,7 +651,7 @@ LibraryManager.library = {
#endif
allocate([ allocate(
{{{ Runtime.QUANTUM_SIZE === 4 ? '[0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0]' : '[0, _stdin, _stdout, _stderr]' }}},
- 'void*', ALLOC_DYNAMIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
+ 'void*', ALLOC_NORMAL) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
},
quit: function() {
@@ -675,10 +707,9 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EACCES);
return 0;
}
- var id = FS.streams.length; // Keep dense
var contents = [];
for (var key in target.contents) contents.push(key);
- FS.streams[id] = {
+ var id = FS.createFileHandle({
path: path,
object: target,
// An index into contents. Special values: -2 is ".", -1 is "..".
@@ -695,7 +726,7 @@ LibraryManager.library = {
contents: contents,
// Each stream has its own area for readdir() returns.
currentEntry: _malloc(___dirent_struct_layout.__size__)
- };
+ });
#if ASSERTIONS
FS.checkStreams();
#endif
@@ -1213,7 +1244,7 @@ LibraryManager.library = {
finalPath = path.parentPath + '/' + path.name;
}
// Actually create an open stream.
- var id = FS.streams.length; // Keep dense
+ var id;
if (target.isFolder) {
var entryBuffer = 0;
if (___dirent_struct_layout) {
@@ -1221,7 +1252,7 @@ LibraryManager.library = {
}
var contents = [];
for (var key in target.contents) contents.push(key);
- FS.streams[id] = {
+ id = FS.createFileHandle({
path: finalPath,
object: target,
// An index into contents. Special values: -2 is ".", -1 is "..".
@@ -1238,9 +1269,9 @@ LibraryManager.library = {
contents: contents,
// Each stream has its own area for readdir() returns.
currentEntry: entryBuffer
- };
+ });
} else {
- FS.streams[id] = {
+ id = FS.createFileHandle({
path: finalPath,
object: target,
position: 0,
@@ -1250,7 +1281,7 @@ LibraryManager.library = {
error: false,
eof: false,
ungotten: []
- };
+ });
}
#if ASSERTIONS
FS.checkStreams();
@@ -1293,10 +1324,7 @@ LibraryManager.library = {
newStream[member] = stream[member];
}
arg = dup2 ? arg : Math.max(arg, FS.streams.length); // dup2 wants exactly arg; fcntl wants a free descriptor >= arg
- for (var i = FS.streams.length; i < arg; i++) {
- FS.streams[i] = null; // Keep dense
- }
- FS.streams[arg] = newStream;
+ FS.createFileHandle(newStream, arg);
#if ASSERTIONS
FS.checkStreams();
#endif
@@ -1773,12 +1801,14 @@ LibraryManager.library = {
return bytesRead;
}
},
- read__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'pread'],
+ read__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'recv', 'pread'],
read: function(fildes, buf, nbyte) {
// ssize_t read(int fildes, void *buf, size_t nbyte);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html
var stream = FS.streams[fildes];
- if (!stream) {
+ if (stream && ('socket' in stream)) {
+ return _recv(fildes, buf, nbyte, 0);
+ } else if (!stream) {
___setErrNo(ERRNO_CODES.EBADF);
return -1;
} else if (!stream.isRead) {
@@ -1804,6 +1834,10 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EIO);
return -1;
}
+ if (result === undefined && bytesRead === 0) {
+ ___setErrNo(ERRNO_CODES.EAGAIN);
+ return -1;
+ }
if (result === null || result === undefined) break;
bytesRead++;
{{{ makeSetValue('buf', 'i', 'result', 'i8') }}}
@@ -1969,12 +2003,14 @@ LibraryManager.library = {
return i;
}
},
- write__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'pwrite'],
+ write__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'send', 'pwrite'],
write: function(fildes, buf, nbyte) {
// ssize_t write(int fildes, const void *buf, size_t nbyte);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html
var stream = FS.streams[fildes];
- if (!stream) {
+ if (stream && ('socket' in stream)) {
+ return _send(fildes, buf, nbyte, 0);
+ } else if (!stream) {
___setErrNo(ERRNO_CODES.EBADF);
return -1;
} else if (!stream.isWrite) {
@@ -2572,7 +2608,7 @@ LibraryManager.library = {
if (format[formatIndex] == 'l') {
long_ = true;
formatIndex++;
- if(format[formatIndex] == 'l') {
+ if (format[formatIndex] == 'l') {
longLong = true;
formatIndex++;
}
@@ -2585,7 +2621,8 @@ LibraryManager.library = {
var curr = 0;
var buffer = [];
// Read characters according to the format. floats are trickier, they may be in an unfloat state in the middle, then be a valid float later
- if (type == 'f' || type == 'e' || type == 'g' || type == 'E') {
+ if (type == 'f' || type == 'e' || type == 'g' ||
+ type == 'F' || type == 'E' || type == 'G') {
var last = 0;
next = get();
while (next > 0) {
@@ -2607,7 +2644,7 @@ LibraryManager.library = {
(type == 's' ||
((type === 'd' || type == 'u' || type == 'i') && ((next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}}) ||
(first && next == {{{ charCode('-') }}}))) ||
- (type === 'x' && (next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}} ||
+ ((type === 'x' || type === 'X') && (next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}} ||
next >= {{{ charCode('a') }}} && next <= {{{ charCode('f') }}} ||
next >= {{{ charCode('A') }}} && next <= {{{ charCode('F') }}}))) &&
(formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up
@@ -2631,17 +2668,21 @@ LibraryManager.library = {
case 'd': case 'u': case 'i':
if (half) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
- } else if(longLong) {
+ } else if (longLong) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i64') }}};
} else {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}};
}
break;
+ case 'X':
case 'x':
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}}
break;
+ case 'F':
case 'f':
+ case 'E':
case 'e':
+ case 'G':
case 'g':
case 'E':
// fallthrough intended
@@ -3576,14 +3617,14 @@ LibraryManager.library = {
return -1;
},
fscanf__deps: ['$FS', '__setErrNo', '$ERRNO_CODES',
- '_scanString', 'getc', 'ungetc'],
+ '_scanString', 'fgetc', 'fseek', 'ftell'],
fscanf: function(stream, format, varargs) {
// int fscanf(FILE *restrict stream, const char *restrict format, ... );
// http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
if (FS.streams[stream]) {
- var stack = [];
- var get = function() { var ret = _fgetc(stream); stack.push(ret); return ret };
- var unget = function(c) { return _ungetc(stack.pop(), stream) };
+ var i = _ftell(stream), SEEK_SET = 0;
+ var get = function () { i++; return _fgetc(stream); };
+ var unget = function () { _fseek(stream, --i, SEEK_SET); };
return __scanString(format, get, unget, varargs);
} else {
return -1;
@@ -3726,30 +3767,44 @@ LibraryManager.library = {
* this implementation simply uses malloc underneath the call to
* mmap.
*/
+ var MAP_PRIVATE = 2;
+ var allocated = false;
+
if (!_mmap.mappings) _mmap.mappings = {};
+
if (stream == -1) {
var ptr = _malloc(num);
+ if (!ptr) return -1;
+ _memset(ptr, 0, num);
+ allocated = true;
} else {
var info = FS.streams[stream];
if (!info) return -1;
var contents = info.object.contents;
- contents = Array.prototype.slice.call(contents, offset, offset+num);
- ptr = allocate(contents, 'i8', ALLOC_NORMAL);
- }
- // align to page size
- var ret = ptr;
- if (ptr % PAGE_SIZE != 0) {
- var old = ptr;
- ptr = _malloc(num + PAGE_SIZE);
- ret = alignMemoryPage(ptr);
- _memcpy(ret, old, num);
- _free(old);
- }
- if (stream == -1) {
- _memset(ret, 0, num);
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if (flags & MAP_PRIVATE == 0) {
+ // We can't emulate MAP_SHARED when the file is not backed by HEAP.
+ assert(contents.buffer === HEAPU8.buffer);
+ ptr = contents.byteOffset;
+ allocated = false;
+ } else {
+ // Try to avoid unnecessary slices.
+ if (offset > 0 || offset + num < contents.length) {
+ if (contents.subarray) {
+ contents = contents.subarray(offset, offset+num);
+ } else {
+ contents = Array.prototype.slice.call(contents, offset, offset+num);
+ }
+ }
+ ptr = _malloc(num);
+ if (!ptr) return -1;
+ HEAPU8.set(contents, ptr);
+ allocated = true;
+ }
}
- _mmap.mappings[ret] = { malloc: ptr, num: num };
- return ret;
+
+ _mmap.mappings[ptr] = { malloc: ptr, num: num, allocated: allocated };
+ return ptr;
},
__01mmap64_: 'mmap',
@@ -3760,7 +3815,9 @@ LibraryManager.library = {
if (!info) return 0;
if (num == info.num) {
_mmap.mappings[start] = null;
- _free(info.malloc);
+ if (info.allocated) {
+ _free(info.malloc);
+ }
}
return 0;
},
@@ -3781,14 +3838,14 @@ LibraryManager.library = {
* implementation (replaced by dlmalloc normally) so
* not an issue.
*/
-#if ASSERTIONS
+#if ASSERTIONS == 2
Runtime.warnOnce('using stub malloc (reference it from C to have the real one included)');
#endif
var ptr = Runtime.dynamicAlloc(bytes + 8);
return (ptr+8) & 0xFFFFFFF8;
},
free: function() {
-#if ASSERTIONS
+#if ASSERTIONS == 2
Runtime.warnOnce('using stub free (reference it from C to have the real one included)');
#endif
},
@@ -3902,7 +3959,14 @@ LibraryManager.library = {
str++;
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
// Get digits.
@@ -3953,13 +4017,14 @@ LibraryManager.library = {
#if USE_TYPED_ARRAYS == 2
_parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }],
_parseInt64: function(str, endptr, base, min, max, unsign) {
- var start = str;
+ var isNegative = false;
// Skip space.
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
-
+
// Check for a plus/minus sign.
if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('-') }}}) {
str++;
+ isNegative = true;
} else if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('+') }}}) {
str++;
}
@@ -3975,12 +4040,19 @@ LibraryManager.library = {
str += 2;
} else {
finalBase = 8;
- str++;
ok = true; // we saw an initial zero, perhaps the entire thing is just "0"
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
+ start = str;
// Get digits.
var chr;
@@ -3993,6 +4065,7 @@ LibraryManager.library = {
ok = true;
}
}
+
if (!ok) {
___setErrNo(ERRNO_CODES.EINVAL);
{{{ makeStructuralReturn(['0', '0']) }}};
@@ -4004,7 +4077,8 @@ LibraryManager.library = {
}
try {
- i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign);
+ var numberString = isNegative ? '-'+Pointer_stringify(start, str - start) : Pointer_stringify(start, str - start);
+ i64Math.fromString(numberString, finalBase, min, max, unsign);
} catch(e) {
___setErrNo(ERRNO_CODES.ERANGE); // not quite correct
}
@@ -4451,24 +4525,24 @@ LibraryManager.library = {
}
return pdest|0;
},
-
+
strlwr__deps:['tolower'],
strlwr: function(pstr){
var i = 0;
while(1) {
var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
- if(x == 0) break;
+ if (x == 0) break;
{{{ makeSetValue('pstr', 'i', '_tolower(x)', 'i8') }}};
i++;
}
},
-
+
strupr__deps:['toupper'],
strupr: function(pstr){
var i = 0;
while(1) {
var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
- if(x == 0) break;
+ if (x == 0) break;
{{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}};
i++;
}
@@ -4644,7 +4718,7 @@ LibraryManager.library = {
if (size < 0) {
size = 0;
}
-
+
var newStr = _malloc(size + 1);
{{{ makeCopyValues('newStr', 'ptr', 'size', 'null', null, 1) }}};
{{{ makeSetValue('newStr', 'size', '0', 'i8') }}};
@@ -5072,7 +5146,13 @@ LibraryManager.library = {
return _malloc(size);
},
__cxa_free_exception: function(ptr) {
- return _free(ptr);
+ try {
+ return _free(ptr);
+ } catch(e) { // XXX FIXME
+#if ASSERTIONS
+ Module.printErr('exception during cxa_free_exception: ' + e);
+#endif
+ }
},
__cxa_throw__sig: 'viii',
__cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'],
@@ -5560,10 +5640,15 @@ LibraryManager.library = {
frexp: function(x, exp_addr) {
var sig = 0, exp_ = 0;
if (x !== 0) {
+ var sign = 1;
+ if (x < 0) {
+ x = -x;
+ sign = -1;
+ }
var raw_exp = Math.log(x)/Math.log(2);
exp_ = Math.ceil(raw_exp);
if (exp_ === raw_exp) exp_ += 1;
- sig = x/Math.pow(2, exp_);
+ sig = sign*x/Math.pow(2, exp_);
}
{{{ makeSetValue('exp_addr', 0, 'exp_', 'i32') }}}
return sig;
@@ -6170,8 +6255,9 @@ LibraryManager.library = {
clock_gettime__deps: ['__timespec_struct_layout'],
clock_gettime: function(clk_id, tp) {
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
- {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', '0', 'i32') }}}
- {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}}
+ var now = Date.now();
+ {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', 'Math.floor(now/1000)', 'i32') }}}; // seconds
+ {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}}; // nanoseconds - not supported
return 0;
},
clock_settime: function(clk_id, tp) {
@@ -6631,182 +6717,274 @@ LibraryManager.library = {
// ==========================================================================
$ERRNO_CODES: {
+ EPERM: 1,
+ ENOENT: 2,
+ ESRCH: 3,
+ EINTR: 4,
+ EIO: 5,
+ ENXIO: 6,
E2BIG: 7,
- EACCES: 13,
- EADDRINUSE: 98,
- EADDRNOTAVAIL: 99,
- EAFNOSUPPORT: 97,
- EAGAIN: 11,
- EALREADY: 114,
+ ENOEXEC: 8,
EBADF: 9,
- EBADMSG: 74,
- EBUSY: 16,
- ECANCELED: 125,
ECHILD: 10,
- ECONNABORTED: 103,
- ECONNREFUSED: 111,
- ECONNRESET: 104,
- EDEADLK: 35,
- EDESTADDRREQ: 89,
- EDOM: 33,
- EDQUOT: 122,
- EEXIST: 17,
+ EAGAIN: 11,
+ EWOULDBLOCK: 11,
+ ENOMEM: 12,
+ EACCES: 13,
EFAULT: 14,
- EFBIG: 27,
- EHOSTUNREACH: 113,
- EIDRM: 43,
- EILSEQ: 84,
- EINPROGRESS: 115,
- EINTR: 4,
- EINVAL: 22,
- EIO: 5,
- EISCONN: 106,
- EISDIR: 21,
- ELOOP: 40,
- EMFILE: 24,
- EMLINK: 31,
- EMSGSIZE: 90,
- EMULTIHOP: 72,
- ENAMETOOLONG: 36,
- ENETDOWN: 100,
- ENETRESET: 102,
- ENETUNREACH: 101,
- ENFILE: 23,
- ENOBUFS: 105,
- ENODATA: 61,
+ ENOTBLK: 15,
+ EBUSY: 16,
+ EEXIST: 17,
+ EXDEV: 18,
ENODEV: 19,
- ENOENT: 2,
- ENOEXEC: 8,
- ENOLCK: 37,
- ENOLINK: 67,
- ENOMEM: 12,
- ENOMSG: 42,
- ENOPROTOOPT: 92,
- ENOSPC: 28,
- ENOSR: 63,
- ENOSTR: 60,
- ENOSYS: 38,
- ENOTCONN: 107,
ENOTDIR: 20,
- ENOTEMPTY: 39,
- ENOTRECOVERABLE: 131,
- ENOTSOCK: 88,
- ENOTSUP: 95,
+ EISDIR: 21,
+ EINVAL: 22,
+ ENFILE: 23,
+ EMFILE: 24,
ENOTTY: 25,
- ENXIO: 6,
- EOPNOTSUPP: 45,
- EOVERFLOW: 75,
- EOWNERDEAD: 130,
- EPERM: 1,
+ ETXTBSY: 26,
+ EFBIG: 27,
+ ENOSPC: 28,
+ ESPIPE: 29,
+ EROFS: 30,
+ EMLINK: 31,
EPIPE: 32,
- EPROTO: 71,
- EPROTONOSUPPORT: 93,
- EPROTOTYPE: 91,
+ EDOM: 33,
ERANGE: 34,
- EROFS: 30,
- ESPIPE: 29,
- ESRCH: 3,
- ESTALE: 116,
+ ENOMSG: 35,
+ EIDRM: 36,
+ ECHRNG: 37,
+ EL2NSYNC: 38,
+ EL3HLT: 39,
+ EL3RST: 40,
+ ELNRNG: 41,
+ EUNATCH: 42,
+ ENOCSI: 43,
+ EL2HLT: 44,
+ EDEADLK: 45,
+ ENOLCK: 46,
+ EBADE: 50,
+ EBADR: 51,
+ EXFULL: 52,
+ ENOANO: 53,
+ EBADRQC: 54,
+ EBADSLT: 55,
+ EDEADLOCK: 56,
+ EBFONT: 57,
+ ENOSTR: 60,
+ ENODATA: 61,
ETIME: 62,
- ETIMEDOUT: 110,
- ETXTBSY: 26,
- EWOULDBLOCK: 11,
- EXDEV: 18,
+ ENOSR: 63,
+ ENONET: 64,
+ ENOPKG: 65,
+ EREMOTE: 66,
+ ENOLINK: 67,
+ EADV: 68,
+ ESRMNT: 69,
+ ECOMM: 70,
+ EPROTO: 71,
+ EMULTIHOP: 74,
+ ELBIN: 75,
+ EDOTDOT: 76,
+ EBADMSG: 77,
+ EFTYPE: 79,
+ ENOTUNIQ: 80,
+ EBADFD: 81,
+ EREMCHG: 82,
+ ELIBACC: 83,
+ ELIBBAD: 84,
+ ELIBSCN: 85,
+ ELIBMAX: 86,
+ ELIBEXEC: 87,
+ ENOSYS: 88,
+ ENMFILE: 89,
+ ENOTEMPTY: 90,
+ ENAMETOOLONG: 91,
+ ELOOP: 92,
+ EOPNOTSUPP: 95,
+ EPFNOSUPPORT: 96,
+ ECONNRESET: 104,
+ ENOBUFS: 105,
+ EAFNOSUPPORT: 106,
+ EPROTOTYPE: 107,
+ ENOTSOCK: 108,
+ ENOPROTOOPT: 109,
+ ESHUTDOWN: 110,
+ ECONNREFUSED: 111,
+ EADDRINUSE: 112,
+ ECONNABORTED: 113,
+ ENETUNREACH: 114,
+ ENETDOWN: 115,
+ ETIMEDOUT: 116,
+ EHOSTDOWN: 117,
+ EHOSTUNREACH: 118,
+ EINPROGRESS: 119,
+ EALREADY: 120,
+ EDESTADDRREQ: 121,
+ EMSGSIZE: 122,
+ EPROTONOSUPPORT: 123,
+ ESOCKTNOSUPPORT: 124,
+ EADDRNOTAVAIL: 125,
+ ENETRESET: 126,
+ EISCONN: 127,
+ ENOTCONN: 128,
+ ETOOMANYREFS: 129,
+ EPROCLIM: 130,
+ EUSERS: 131,
+ EDQUOT: 132,
+ ESTALE: 133,
+ ENOTSUP: 134,
+ ENOMEDIUM: 135,
+ ENOSHARE: 136,
+ ECASECLASH: 137,
+ EILSEQ: 138,
+ EOVERFLOW: 139,
+ ECANCELED: 140,
+ ENOTRECOVERABLE: 141,
+ EOWNERDEAD: 142,
+ ESTRPIPE: 143
},
$ERRNO_MESSAGES: {
+ 0: 'Success',
+ 1: 'Not super-user',
2: 'No such file or directory',
+ 3: 'No such process',
+ 4: 'Interrupted system call',
+ 5: 'I/O error',
+ 6: 'No such device or address',
+ 7: 'Arg list too long',
+ 8: 'Exec format error',
+ 9: 'Bad file number',
+ 10: 'No children',
+ 11: 'No more processes',
+ 12: 'Not enough core',
13: 'Permission denied',
- 98: 'Address already in use',
- 99: 'Cannot assign requested address',
- 97: 'Address family not supported by protocol',
- 11: 'Resource temporarily unavailable',
- 114: 'Operation already in progress',
- 9: 'Bad file descriptor',
- 74: 'Bad message',
- 16: 'Device or resource busy',
- 125: 'Operation canceled',
- 10: 'No child processes',
- 103: 'Software caused connection abort',
- 111: 'Connection refused',
- 104: 'Connection reset by peer',
- 35: 'Resource deadlock avoided',
- 89: 'Destination address required',
- 33: 'Numerical argument out of domain',
- 122: 'Disk quota exceeded',
- 17: 'File exists',
14: 'Bad address',
- 27: 'File too large',
- 113: 'No route to host',
- 43: 'Identifier removed',
- 84: 'Invalid or incomplete multibyte or wide character',
- 115: 'Operation now in progress',
- 4: 'Interrupted system call',
- 22: 'Invalid argument',
- 5: 'Input/output error',
- 106: 'Transport endpoint is already connected',
+ 15: 'Block device required',
+ 16: 'Mount device busy',
+ 17: 'File exists',
+ 18: 'Cross-device link',
+ 19: 'No such device',
+ 20: 'Not a directory',
21: 'Is a directory',
- 40: 'Too many levels of symbolic links',
- 24: 'Too many open files',
- 31: 'Too many links',
- 90: 'Message too long',
- 72: 'Multihop attempted',
- 36: 'File name too long',
- 100: 'Network is down',
- 102: 'Network dropped connection on reset',
- 101: 'Network is unreachable',
+ 22: 'Invalid argument',
23: 'Too many open files in system',
- 105: 'No buffer space available',
- 61: 'No data available',
- 19: 'No such device',
- 8: 'Exec format error',
- 37: 'No locks available',
- 67: 'Link has been severed',
- 12: 'Cannot allocate memory',
- 42: 'No message of desired type',
- 92: 'Protocol not available',
+ 24: 'Too many open files',
+ 25: 'Not a typewriter',
+ 26: 'Text file busy',
+ 27: 'File too large',
28: 'No space left on device',
- 63: 'Out of streams resources',
- 60: 'Device not a stream',
- 38: 'Function not implemented',
- 107: 'Transport endpoint is not connected',
- 20: 'Not a directory',
- 39: 'Directory not empty',
- 131: 'State not recoverable',
- 88: 'Socket operation on non-socket',
- 95: 'Operation not supported',
- 25: 'Inappropriate ioctl for device',
- 6: 'No such device or address',
- 45: 'Op not supported on transport endpoint',
- 75: 'Value too large for defined data type',
- 130: 'Owner died',
- 1: 'Operation not permitted',
- 32: 'Broken pipe',
- 71: 'Protocol error',
- 93: 'Protocol not supported',
- 91: 'Protocol wrong type for socket',
- 34: 'Numerical result out of range',
- 30: 'Read-only file system',
29: 'Illegal seek',
- 3: 'No such process',
- 116: 'Stale NFS file handle',
+ 30: 'Read only file system',
+ 31: 'Too many links',
+ 32: 'Broken pipe',
+ 33: 'Math arg out of domain of func',
+ 34: 'Math result not representable',
+ 35: 'No message of desired type',
+ 36: 'Identifier removed',
+ 37: 'Channel number out of range',
+ 38: 'Level 2 not synchronized',
+ 39: 'Level 3 halted',
+ 40: 'Level 3 reset',
+ 41: 'Link number out of range',
+ 42: 'Protocol driver not attached',
+ 43: 'No CSI structure available',
+ 44: 'Level 2 halted',
+ 45: 'Deadlock condition',
+ 46: 'No record locks available',
+ 50: 'Invalid exchange',
+ 51: 'Invalid request descriptor',
+ 52: 'Exchange full',
+ 53: 'No anode',
+ 54: 'Invalid request code',
+ 55: 'Invalid slot',
+ 56: 'File locking deadlock error',
+ 57: 'Bad font file fmt',
+ 60: 'Device not a stream',
+ 61: 'No data (for no delay io)',
62: 'Timer expired',
- 110: 'Connection timed out',
- 26: 'Text file busy',
- 18: 'Invalid cross-device link'
- },
+ 63: 'Out of streams resources',
+ 64: 'Machine is not on the network',
+ 65: 'Package not installed',
+ 66: 'The object is remote',
+ 67: 'The link has been severed',
+ 68: 'Advertise error',
+ 69: 'Srmount error',
+ 70: 'Communication error on send',
+ 71: 'Protocol error',
+ 74: 'Multihop attempted',
+ 75: 'Inode is remote (not really error)',
+ 76: 'Cross mount point (not really error)',
+ 77: 'Trying to read unreadable message',
+ 79: 'Inappropriate file type or format',
+ 80: 'Given log. name not unique',
+ 81: 'f.d. invalid for this operation',
+ 82: 'Remote address changed',
+ 83: 'Can\t access a needed shared lib',
+ 84: 'Accessing a corrupted shared lib',
+ 85: '.lib section in a.out corrupted',
+ 86: 'Attempting to link in too many libs',
+ 87: 'Attempting to exec a shared library',
+ 88: 'Function not implemented',
+ 89: 'No more files',
+ 90: 'Directory not empty',
+ 91: 'File or path name too long',
+ 92: 'Too many symbolic links',
+ 95: 'Operation not supported on transport endpoint',
+ 96: 'Protocol family not supported',
+ 104: 'Connection reset by peer',
+ 105: 'No buffer space available',
+ 106: 'Address family not supported by protocol family',
+ 107: 'Protocol wrong type for socket',
+ 108: 'Socket operation on non-socket',
+ 109: 'Protocol not available',
+ 110: 'Can\'t send after socket shutdown',
+ 111: 'Connection refused',
+ 112: 'Address already in use',
+ 113: 'Connection aborted',
+ 114: 'Network is unreachable',
+ 115: 'Network interface is not configured',
+ 116: 'Connection timed out',
+ 117: 'Host is down',
+ 118: 'Host is unreachable',
+ 119: 'Connection already in progress',
+ 120: 'Socket already connected',
+ 121: 'Destination address required',
+ 122: 'Message too long',
+ 123: 'Unknown protocol',
+ 124: 'Socket type not supported',
+ 125: 'Address not available',
+ 126: 'ENETRESET',
+ 127: 'Socket is already connected',
+ 128: 'Socket is not connected',
+ 129: 'TOOMANYREFS',
+ 130: 'EPROCLIM',
+ 131: 'EUSERS',
+ 132: 'EDQUOT',
+ 133: 'ESTALE',
+ 134: 'Not supported',
+ 135: 'No medium (in tape drive)',
+ 136: 'No such host or network path',
+ 137: 'Filename exists with different case',
+ 138: 'EILSEQ',
+ 139: 'Value too large for defined data type',
+ 140: 'Operation canceled',
+ 141: 'State not recoverable',
+ 142: 'Previous owner died',
+ 143: 'Streams pipe error',
+ },
+ __errno_state: 0,
+ __setErrNo__deps: ['__errno_state'],
+ __setErrNo__postset: '___errno_state = Runtime.staticAlloc(4); {{{ makeSetValue("___errno_state", 0, 0, "i32") }}};',
__setErrNo: function(value) {
// For convenient setting and returning of errno.
- if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
- {{{ makeSetValue('___setErrNo.ret', '0', 'value', 'i32') }}}
+ {{{ makeSetValue('___errno_state', '0', 'value', 'i32') }}}
return value;
},
__errno_location__deps: ['__setErrNo'],
__errno_location: function() {
- if (!___setErrNo.ret) {
- ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
- {{{ makeSetValue('___setErrNo.ret', '0', '0', 'i32') }}}
- }
- return ___setErrNo.ret;
+ return ___errno_state;
},
__errno: '__errno_location',
@@ -7055,6 +7233,7 @@ LibraryManager.library = {
['i32', 'h_length'],
['i8**', 'h_addr_list'],
]),
+
gethostbyname__deps: ['__hostent_struct_layout'],
gethostbyname: function(name) {
name = Pointer_stringify(name);
@@ -7097,17 +7276,28 @@ LibraryManager.library = {
// sockets. Note that the implementation assumes all sockets are always
// nonblocking
// ==========================================================================
-
+#if SOCKET_WEBRTC
+ $Sockets__deps: ['__setErrNo', '$ERRNO_CODES',
+ function() { return 'var SocketIO = ' + read('socket.io.js') + ';\n' },
+ function() { return 'var Peer = ' + read('wrtcp.js') + ';\n' }],
+#else
$Sockets__deps: ['__setErrNo', '$ERRNO_CODES'],
+#endif
$Sockets: {
- BACKEND_WEBSOCKETS: 0,
- BACKEND_WEBRTC: 1,
BUFFER_SIZE: 10*1024, // initial size
MAX_BUFFER_SIZE: 10*1024*1024, // maximum size we will grow the buffer
- backend: 0, // default to websockets
nextFd: 1,
fds: {},
+ nextport: 1,
+ maxport: 65535,
+ peer: null,
+ connections: {},
+ portmap: {},
+ localAddr: 0xfe00000a, // Local address is always 10.0.0.254
+ addrPool: [ 0x0200000a, 0x0300000a, 0x0400000a, 0x0500000a,
+ 0x0600000a, 0x0700000a, 0x0800000a, 0x0900000a, 0x0a00000a,
+ 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a], /* 0x0100000a is reserved */
sockaddr_in_layout: Runtime.generateStructInfo([
['i32', 'sin_family'],
['i16', 'sin_port'],
@@ -7124,135 +7314,404 @@ LibraryManager.library = {
['i32', 'msg_controllen'],
['i32', 'msg_flags'],
]),
+ },
- backends: {
- 0: { // websockets
- connect: function(info) {
- console.log('opening ws://' + info.host + ':' + info.port);
- info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']);
- info.socket.binaryType = 'arraybuffer';
+#if SOCKET_WEBRTC
+ /* WebRTC sockets supports several options on the Module object.
- var i32Temp = new Uint32Array(1);
- var i8Temp = new Uint8Array(i32Temp.buffer);
+ * Module['host']: true if this peer is hosting, false otherwise
+ * Module['webrtc']['broker']: hostname for the p2p broker that this peer should use
+ * Module['webrtc']['session']: p2p session for that this peer will join, or undefined if this peer is hosting
+ * Module['webrtc']['hostOptions']: options to pass into p2p library if this peer is hosting
+ * Module['webrtc']['onpeer']: function(peer, route), invoked when this peer is ready to connect
+ * Module['webrtc']['onconnect']: function(peer), invoked when a new peer connection is ready
+ * Module['webrtc']['ondisconnect']: function(peer), invoked when an existing connection is closed
+ * Module['webrtc']['onerror']: function(error), invoked when an error occurs
+ */
+ socket__deps: ['$Sockets'],
+ socket: function(family, type, protocol) {
+ var fd = FS.createFileHandle({
+ addr: null,
+ port: null,
+ inQueue: new CircularBuffer(INCOMING_QUEUE_LENGTH),
+ header: new Uint16Array(2),
+ bound: false,
+ socket: true
+ };
+ assert(fd < 64); // select() assumes socket fd values are in 0..63
+ var stream = type == {{{ cDefine('SOCK_STREAM') }}};
+ if (protocol) {
+ assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if stream, must be tcp
+ }
- info.inQueue = [];
- info.hasData = function() { return info.inQueue.length > 0 }
- if (!info.stream) {
- var partialBuffer = null; // in datagram mode, inQueue contains full dgram messages; this buffers incomplete data. Must begin with the beginning of a message
+ // Open the peer connection if we don't have it already
+ if (null == Sockets.peer) {
+ var host = Module['host'];
+ var broker = Module['webrtc']['broker'];
+ var session = Module['webrtc']['session'];
+ var peer = new Peer(broker);
+ var listenOptions = Module['webrtc']['hostOptions'] || {};
+ peer.onconnection = function(connection) {
+ console.log('connected');
+ var addr;
+ /* If this peer is connecting to the host, assign 10.0.0.1 to the host so it can be
+ reached at a known address.
+ */
+ // Assign 10.0.0.1 to the host
+ if (session && session === connection['route']) {
+ addr = 0x0100000a; // 10.0.0.1
+ } else {
+ addr = Sockets.addrPool.shift();
+ }
+ connection['addr'] = addr;
+ Sockets.connections[addr] = connection;
+ connection.ondisconnect = function() {
+ console.log('disconnect');
+ // Don't return the host address (10.0.0.1) to the pool
+ if (!(session && session === Sockets.connections[addr]['route'])) {
+ Sockets.addrPool.push(addr);
}
+ delete Sockets.connections[addr];
- info.socket.onmessage = function(event) {
- assert(typeof event.data !== 'string' && event.data.byteLength); // must get binary data!
- var data = new Uint8Array(event.data); // make a typed array view on the array buffer
+ if (Module['webrtc']['ondisconnect'] && 'function' === typeof Module['webrtc']['ondisconnect']) {
+ Module['webrtc']['ondisconnect'](peer);
+ }
+ };
+ connection.onerror = function(error) {
+ if (Module['webrtc']['onerror'] && 'function' === typeof Module['webrtc']['onerror']) {
+ Module['webrtc']['onerror'](error);
+ }
+ };
+ connection.onmessage = function(label, message) {
+ if ('unreliable' === label) {
+ handleMessage(addr, message.data);
+ }
+ }
+
+ if (Module['webrtc']['onconnect'] && 'function' === typeof Module['webrtc']['onconnect']) {
+ Module['webrtc']['onconnect'](peer);
+ }
+ };
+ peer.onpending = function(pending) {
+ console.log('pending from: ', pending['route'], '; initiated by: ', (pending['incoming']) ? 'remote' : 'local');
+ };
+ peer.onerror = function(error) {
+ console.error(error);
+ };
+ peer.onroute = function(route) {
+ if (Module['webrtc']['onpeer'] && 'function' === typeof Module['webrtc']['onpeer']) {
+ Module['webrtc']['onpeer'](peer, route);
+ }
+ };
+ function handleMessage(addr, message) {
#if SOCKET_DEBUG
- Module.print(['onmessage', data.length, '|', Array.prototype.slice.call(data)]);
+ Module.print("received " + message.byteLength + " raw bytes");
#endif
- if (info.stream) {
- info.inQueue.push(data);
- } else {
- // we added headers with message sizes, read those to find discrete messages
- if (partialBuffer) {
- // append to the partial buffer
- var newBuffer = new Uint8Array(partialBuffer.length + data.length);
- newBuffer.set(partialBuffer);
- newBuffer.set(data, partialBuffer.length);
- // forget the partial buffer and work on data
- data = newBuffer;
- partialBuffer = null;
- }
- var currPos = 0;
- while (currPos+4 < data.length) {
- i8Temp.set(data.subarray(currPos, currPos+4));
- var currLen = i32Temp[0];
- assert(currLen > 0);
- if (currPos + 4 + currLen > data.length) {
- break; // not enough data has arrived
- }
- currPos += 4;
+ var header = new Uint16Array(message, 0, 2);
+ if (Sockets.portmap[header[1]]) {
+ Sockets.portmap[header[1]].inQueue.push([addr, message]);
+ } else {
+ console.log("unable to deliver message: ", addr, header[1], message);
+ }
+ }
+ window.onbeforeunload = function() {
+ var ids = Object.keys(Sockets.connections);
+ ids.forEach(function(id) {
+ Sockets.connections[id].close();
+ });
+ }
+ Sockets.peer = peer;
+ }
+
+ var INCOMING_QUEUE_LENGTH = 64;
+
+ function CircularBuffer(max_length) {
+ var buffer = new Array(++ max_length);
+ var head = 0;
+ var tail = 0;
+ var length = 0;
+
+ return {
+ push: function(element) {
+ buffer[tail ++] = element;
+ length = Math.min(++ length, max_length - 1);
+ tail = tail % max_length;
+ if (tail === head) {
+ head = (head + 1) % max_length;
+ }
+ },
+ shift: function(element) {
+ if (length < 1) return undefined;
+
+ var element = buffer[head];
+ -- length;
+ head = (head + 1) % max_length;
+ return element;
+ },
+ length: function() {
+ return length;
+ }
+ };
+ };
+
+ return fd;
+ },
+
+ mkport__deps: ['$Sockets'],
+ mkport: function() {
+ for(var i = 0; i < Sockets.maxport; ++ i) {
+ var port = Sockets.nextport ++;
+ Sockets.nextport = (Sockets.nextport > Sockets.maxport) ? 1 : Sockets.nextport;
+ if (!Sockets.portmap[port]) {
+ return port;
+ }
+ }
+ assert(false, 'all available ports are in use!');
+ },
+
+ connect: function() {
+ // Stub: connection-oriented sockets are not supported yet.
+ },
+
+ bind__deps: ['$Sockets', '_inet_ntop_raw', 'ntohs', 'mkport'],
+ bind: function(fd, addr, addrlen) {
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ if (addr) {
+ info.port = _ntohs(getValue(addr + Sockets.sockaddr_in_layout.sin_port, 'i16'));
+ // info.addr = getValue(addr + Sockets.sockaddr_in_layout.sin_addr, 'i32');
+ }
+ if (!info.port) {
+ info.port = _mkport();
+ }
+ info.addr = Sockets.localAddr; // 10.0.0.254
+ info.host = __inet_ntop_raw(info.addr);
+ info.close = function() {
+ Sockets.portmap[info.port] = undefined;
+ }
+ Sockets.portmap[info.port] = info;
+ console.log("bind: ", info.host, info.port);
+ info.bound = true;
+ },
+
+ sendmsg__deps: ['$Sockets', 'bind', '_inet_ntop_raw', 'ntohs'],
+ sendmsg: function(fd, msg, flags) {
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ // if we are not connected, use the address info in the message
+ if (!info.bound) {
+ _bind(fd);
+ }
+
+ var name = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_name', '*') }}};
+ assert(name, 'sendmsg on non-connected socket, and no name/address in the message');
+ var port = _ntohs(getValue(name + Sockets.sockaddr_in_layout.sin_port, 'i16'));
+ var addr = getValue(name + Sockets.sockaddr_in_layout.sin_addr, 'i32');
+ var connection = Sockets.connections[addr];
+ // var host = __inet_ntop_raw(addr);
+
+ if (!(connection && connection.connected)) {
+ ___setErrNo(ERRNO_CODES.EWOULDBLOCK);
+ return -1;
+ }
+
+ var iov = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}};
+ var num = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}};
#if SOCKET_DEBUG
- Module.print(['onmessage message', currLen, '|', Array.prototype.slice.call(data.subarray(currPos, currPos+currLen))]);
+ Module.print('sendmsg vecs: ' + num);
#endif
- info.inQueue.push(data.subarray(currPos, currPos+currLen));
- currPos += currLen;
- }
- // If data remains, buffer it
- if (currPos < data.length) {
- partialBuffer = data.subarray(currPos);
- }
- }
- }
- function send(data) {
- // TODO: if browser accepts views, can optimize this
+ var totalSize = 0;
+ for (var i = 0; i < num; i++) {
+ totalSize += {{{ makeGetValue('iov', '8*i + 4', 'i32') }}};
+ }
+ var data = new Uint8Array(totalSize);
+ var ret = 0;
+ for (var i = 0; i < num; i++) {
+ var currNum = {{{ makeGetValue('iov', '8*i + 4', 'i32') }}};
#if SOCKET_DEBUG
- Module.print('sender actually sending ' + Array.prototype.slice.call(data));
+ Module.print('sendmsg curr size: ' + currNum);
#endif
- // ok to use the underlying buffer, we created data and know that the buffer starts at the beginning
- info.socket.send(data.buffer);
- }
- var outQueue = [];
- var intervalling = false, interval;
- function trySend() {
- if (info.socket.readyState != info.socket.OPEN) {
- if (!intervalling) {
- intervalling = true;
- console.log('waiting for socket in order to send');
- interval = setInterval(trySend, 100);
- }
- return;
- }
- for (var i = 0; i < outQueue.length; i++) {
- send(outQueue[i]);
- }
- outQueue.length = 0;
- if (intervalling) {
- intervalling = false;
- clearInterval(interval);
- }
+ if (!currNum) continue;
+ var currBuf = {{{ makeGetValue('iov', '8*i', 'i8*') }}};
+ data.set(HEAPU8.subarray(currBuf, currBuf+currNum), ret);
+ ret += currNum;
+ }
+
+ info.header[0] = info.port; // src port
+ info.header[1] = port; // dst port
+#if SOCKET_DEBUG
+ Module.print('sendmsg port: ' + info.header[0] + ' -> ' + info.header[1]);
+ Module.print('sendmsg bytes: ' + data.length + ' | ' + Array.prototype.slice.call(data));
+#endif
+ var buffer = new Uint8Array(info.header.byteLength + data.byteLength);
+ buffer.set(new Uint8Array(info.header.buffer));
+ buffer.set(data, info.header.byteLength);
+
+ connection.send('unreliable', buffer.buffer);
+ },
+
+ recvmsg__deps: ['$Sockets', 'bind', '__setErrNo', '$ERRNO_CODES', 'htons'],
+ recvmsg: function(fd, msg, flags) {
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ // if we are not connected, use the address info in the message
+ if (!info.port) {
+ console.log('recvmsg on unbound socket');
+ assert(false, 'cannot receive on unbound socket');
+ }
+ if (info.inQueue.length() == 0) {
+ ___setErrNo(ERRNO_CODES.EWOULDBLOCK);
+ return -1;
+ }
+
+ var entry = info.inQueue.shift();
+ var addr = entry[0];
+ var message = entry[1];
+ var header = new Uint16Array(message, 0, info.header.length);
+ var buffer = new Uint8Array(message, info.header.byteLength);
+
+ var bytes = buffer.length;
+#if SOCKET_DEBUG
+ Module.print('recvmsg port: ' + header[1] + ' <- ' + header[0]);
+ Module.print('recvmsg bytes: ' + bytes + ' | ' + Array.prototype.slice.call(buffer));
+#endif
+ // write source
+ var name = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_name', '*') }}};
+ {{{ makeSetValue('name', 'Sockets.sockaddr_in_layout.sin_addr', 'addr', 'i32') }}};
+ {{{ makeSetValue('name', 'Sockets.sockaddr_in_layout.sin_port', '_htons(header[0])', 'i16') }}};
+ // write data
+ var ret = bytes;
+ var iov = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}};
+ var num = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}};
+ var bufferPos = 0;
+ for (var i = 0; i < num && bytes > 0; i++) {
+ var currNum = {{{ makeGetValue('iov', '8*i + 4', 'i32') }}};
+#if SOCKET_DEBUG
+ Module.print('recvmsg loop ' + [i, num, bytes, currNum]);
+#endif
+ if (!currNum) continue;
+ currNum = Math.min(currNum, bytes); // XXX what should happen when we partially fill a buffer..?
+ bytes -= currNum;
+ var currBuf = {{{ makeGetValue('iov', '8*i', 'i8*') }}};
+#if SOCKET_DEBUG
+ Module.print('recvmsg call recv ' + currNum);
+#endif
+ HEAPU8.set(buffer.subarray(bufferPos, bufferPos + currNum), currBuf);
+ bufferPos += currNum;
+ }
+ return ret;
+ },
+
+ shutdown: function(fd, how) {
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ info.close();
+ FS.removeFileHandle(fd);
+ },
+
+ ioctl: function(fd, request, varargs) {
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ var bytes = 0;
+ if (info.hasData()) {
+ bytes = info.inQueue[0].length;
+ }
+ var dest = {{{ makeGetValue('varargs', '0', 'i32') }}};
+ {{{ makeSetValue('dest', '0', 'bytes', 'i32') }}};
+ return 0;
+ },
+
+ setsockopt: function(d, level, optname, optval, optlen) {
+ console.log('ignoring setsockopt command');
+ return 0;
+ },
+
+ accept: function(fd, addr, addrlen) {
+ // TODO: webrtc queued incoming connections, etc.
+ // For now, the model is that bind does a connect, and we "accept" that one connection,
+ // which has host:port the same as ours. We also return the same socket fd.
+ var info = FS.streams[fd];
+ if (!info) return -1;
+ if (addr) {
+ setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32');
+ setValue(addr + Sockets.sockaddr_in_layout.sin_port, info.port, 'i32');
+ setValue(addrlen, Sockets.sockaddr_in_layout.__size__, 'i32');
+ }
+ return fd;
+ },
+
+ select: function(nfds, readfds, writefds, exceptfds, timeout) {
+ // readfds are supported,
+ // writefds checks socket open status
+ // exceptfds not supported
+ // timeout is always 0 - fully async
+ assert(!exceptfds);
+
+ var errorCondition = 0;
+
+ function canRead(info) {
+ return info.inQueue.length() > 0;
+ }
+
+ function canWrite(info) {
+ return true;
+ }
+
+ function checkfds(nfds, fds, can) {
+ if (!fds) return 0;
+
+ var bitsSet = 0;
+ var dstLow = 0;
+ var dstHigh = 0;
+ var srcLow = {{{ makeGetValue('fds', 0, 'i32') }}};
+ var srcHigh = {{{ makeGetValue('fds', 4, 'i32') }}};
+ nfds = Math.min(64, nfds); // fd sets have 64 bits
+
+ for (var fd = 0; fd < nfds; fd++) {
+ var mask = 1 << (fd % 32), int = fd < 32 ? srcLow : srcHigh;
+ if (int & mask) {
+ // index is in the set, check if it is ready for read
+ var info = FS.streams[fd];
+ if (info && can(info)) {
+ // set bit
+ fd < 32 ? (dstLow = dstLow | mask) : (dstHigh = dstHigh | mask);
+ bitsSet++;
}
- info.sender = function(data) {
- if (!info.stream) {
- // add a header with the message size
- var header = new Uint8Array(4);
- i32Temp[0] = data.length;
- header.set(i8Temp);
- outQueue.push(header);
- }
- outQueue.push(new Uint8Array(data));
- trySend();
- };
}
- },
- 1: { // webrtc
}
+
+ {{{ makeSetValue('fds', 0, 'dstLow', 'i32') }}};
+ {{{ makeSetValue('fds', 4, 'dstHigh', 'i32') }}};
+ return bitsSet;
}
- },
- emscripten_set_network_backend__deps: ['$Sockets'],
- emscripten_set_network_backend: function(backend) {
- Sockets.backend = backend;
+ var totalHandles = checkfds(nfds, readfds, canRead) + checkfds(nfds, writefds, canWrite);
+ if (errorCondition) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else {
+ return totalHandles;
+ }
},
-
+#else
socket__deps: ['$Sockets'],
socket: function(family, type, protocol) {
- var fd = Sockets.nextFd++;
- assert(fd < 64); // select() assumes socket fd values are in 0..63
var stream = type == {{{ cDefine('SOCK_STREAM') }}};
if (protocol) {
- assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if stream, must be tcp
- }
- if (Sockets.backend == Sockets.BACKEND_WEBRTC) {
- assert(!stream); // If WebRTC, we can only support datagram, not stream
+ assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if SOCK_STREAM, must be tcp
}
- Sockets.fds[fd] = {
+ var fd = FS.createFileHandle({
connected: false,
- stream: stream
- };
+ stream: stream,
+ socket: true
+ });
+ assert(fd < 64); // select() assumes socket fd values are in 0..63
return fd;
},
- connect__deps: ['$Sockets', '_inet_ntop_raw', 'htons', 'gethostbyname'],
+ connect__deps: ['$FS', '$Sockets', '_inet_ntop_raw', 'ntohs', 'gethostbyname'],
connect: function(fd, addr, addrlen) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
info.connected = true;
info.addr = getValue(addr + Sockets.sockaddr_in_layout.sin_addr, 'i32');
@@ -7267,18 +7726,110 @@ LibraryManager.library = {
assert(info.host, 'problem translating fake ip ' + parts);
}
try {
- Sockets.backends[Sockets.backend].connect(info);
+ console.log('opening ws://' + info.host + ':' + info.port);
+ info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']);
+ info.socket.binaryType = 'arraybuffer';
+
+ var i32Temp = new Uint32Array(1);
+ var i8Temp = new Uint8Array(i32Temp.buffer);
+
+ info.inQueue = [];
+ info.hasData = function() { return info.inQueue.length > 0 }
+ if (!info.stream) {
+ var partialBuffer = null; // in datagram mode, inQueue contains full dgram messages; this buffers incomplete data. Must begin with the beginning of a message
+ }
+
+ info.socket.onmessage = function(event) {
+ assert(typeof event.data !== 'string' && event.data.byteLength); // must get binary data!
+ var data = new Uint8Array(event.data); // make a typed array view on the array buffer
+#if SOCKET_DEBUG
+ Module.print(['onmessage', data.length, '|', Array.prototype.slice.call(data)]);
+#endif
+ if (info.stream) {
+ info.inQueue.push(data);
+ } else {
+ // we added headers with message sizes, read those to find discrete messages
+ if (partialBuffer) {
+ // append to the partial buffer
+ var newBuffer = new Uint8Array(partialBuffer.length + data.length);
+ newBuffer.set(partialBuffer);
+ newBuffer.set(data, partialBuffer.length);
+ // forget the partial buffer and work on data
+ data = newBuffer;
+ partialBuffer = null;
+ }
+ var currPos = 0;
+ while (currPos+4 < data.length) {
+ i8Temp.set(data.subarray(currPos, currPos+4));
+ var currLen = i32Temp[0];
+ assert(currLen > 0);
+ if (currPos + 4 + currLen > data.length) {
+ break; // not enough data has arrived
+ }
+ currPos += 4;
+#if SOCKET_DEBUG
+ Module.print(['onmessage message', currLen, '|', Array.prototype.slice.call(data.subarray(currPos, currPos+currLen))]);
+#endif
+ info.inQueue.push(data.subarray(currPos, currPos+currLen));
+ currPos += currLen;
+ }
+ // If data remains, buffer it
+ if (currPos < data.length) {
+ partialBuffer = data.subarray(currPos);
+ }
+ }
+ }
+ function send(data) {
+ // TODO: if browser accepts views, can optimize this
+#if SOCKET_DEBUG
+ Module.print('sender actually sending ' + Array.prototype.slice.call(data));
+#endif
+ // ok to use the underlying buffer, we created data and know that the buffer starts at the beginning
+ info.socket.send(data.buffer);
+ }
+ var outQueue = [];
+ var intervalling = false, interval;
+ function trySend() {
+ if (info.socket.readyState != info.socket.OPEN) {
+ if (!intervalling) {
+ intervalling = true;
+ console.log('waiting for socket in order to send');
+ interval = setInterval(trySend, 100);
+ }
+ return;
+ }
+ for (var i = 0; i < outQueue.length; i++) {
+ send(outQueue[i]);
+ }
+ outQueue.length = 0;
+ if (intervalling) {
+ intervalling = false;
+ clearInterval(interval);
+ }
+ }
+ info.sender = function(data) {
+ if (!info.stream) {
+ // add a header with the message size
+ var header = new Uint8Array(4);
+ i32Temp[0] = data.length;
+ header.set(i8Temp);
+ outQueue.push(header);
+ }
+ outQueue.push(new Uint8Array(data));
+ trySend();
+ };
} catch(e) {
Module.printErr('Error in connect(): ' + e);
___setErrNo(ERRNO_CODES.EACCES);
return -1;
}
+
return 0;
},
- recv__deps: ['$Sockets'],
+ recv__deps: ['$FS'],
recv: function(fd, buf, len, flags) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
if (!info.hasData()) {
___setErrNo(ERRNO_CODES.EAGAIN); // no data, and all sockets are nonblocking, so this is the right behavior
@@ -7302,17 +7853,17 @@ LibraryManager.library = {
return buffer.length;
},
- send__deps: ['$Sockets'],
+ send__deps: ['$FS'],
send: function(fd, buf, len, flags) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
info.sender(HEAPU8.subarray(buf, buf+len));
return len;
},
- sendmsg__deps: ['$Sockets', 'connect'],
+ sendmsg__deps: ['$FS', '$Sockets', 'connect'],
sendmsg: function(fd, msg, flags) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
// if we are not connected, use the address info in the message
if (!info.connected) {
@@ -7323,7 +7874,7 @@ LibraryManager.library = {
var iov = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}};
var num = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}};
#if SOCKET_DEBUG
- Module.print('sendmsg vecs: ' + num);
+ Module.print('sendmsg vecs: ' + num);
#endif
var totalSize = 0;
for (var i = 0; i < num; i++) {
@@ -7345,14 +7896,14 @@ LibraryManager.library = {
return ret;
},
- recvmsg__deps: ['$Sockets', 'connect', 'recv', '__setErrNo', '$ERRNO_CODES', 'htons'],
+ recvmsg__deps: ['$FS', '$Sockets', 'connect', 'recv', '__setErrNo', '$ERRNO_CODES', 'htons'],
recvmsg: function(fd, msg, flags) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
// if we are not connected, use the address info in the message
if (!info.connected) {
#if SOCKET_DEBUG
- Module.print('recvmsg connecting');
+ Module.print('recvmsg connecting');
#endif
var name = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_name', '*') }}};
assert(name, 'sendmsg on non-connected socket, and no name/address in the message');
@@ -7403,9 +7954,9 @@ LibraryManager.library = {
return ret;
},
- recvfrom__deps: ['$Sockets', 'connect', 'recv'],
+ recvfrom__deps: ['$FS', 'connect', 'recv'],
recvfrom: function(fd, buf, len, flags, addr, addrlen) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
// if we are not connected, use the address info in the message
if (!info.connected) {
@@ -7416,14 +7967,14 @@ LibraryManager.library = {
},
shutdown: function(fd, how) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
info.socket.close();
- Sockets.fds[fd] = null;
+ FS.removeFileHandle(fd);
},
ioctl: function(fd, request, varargs) {
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
var bytes = 0;
if (info.hasData()) {
@@ -7448,11 +7999,12 @@ LibraryManager.library = {
return 0;
},
+ accept__deps: ['$FS', '$Sockets'],
accept: function(fd, addr, addrlen) {
// TODO: webrtc queued incoming connections, etc.
// For now, the model is that bind does a connect, and we "accept" that one connection,
// which has host:port the same as ours. We also return the same socket fd.
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (!info) return -1;
if (addr) {
setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32');
@@ -7462,18 +8014,19 @@ LibraryManager.library = {
return fd;
},
+ select__deps: ['$FS'],
select: function(nfds, readfds, writefds, exceptfds, timeout) {
// readfds are supported,
// writefds checks socket open status
// exceptfds not supported
// timeout is always 0 - fully async
assert(!exceptfds);
-
+
var errorCondition = 0;
function canRead(info) {
- // make sure hasData exists.
- // we do create it when the socket is connected,
+ // make sure hasData exists.
+ // we do create it when the socket is connected,
// but other implementations may create it lazily
if ((info.socket.readyState == WebSocket.CLOSING || info.socket.readyState == WebSocket.CLOSED) && info.inQueue.length == 0) {
errorCondition = -1;
@@ -7483,8 +8036,8 @@ LibraryManager.library = {
}
function canWrite(info) {
- // make sure socket exists.
- // we do create it when the socket is connected,
+ // make sure socket exists.
+ // we do create it when the socket is connected,
// but other implementations may create it lazily
if ((info.socket.readyState == WebSocket.CLOSING || info.socket.readyState == WebSocket.CLOSED)) {
errorCondition = -1;
@@ -7507,7 +8060,7 @@ LibraryManager.library = {
var mask = 1 << (fd % 32), int = fd < 32 ? srcLow : srcHigh;
if (int & mask) {
// index is in the set, check if it is ready for read
- var info = Sockets.fds[fd];
+ var info = FS.streams[fd];
if (info && can(info)) {
// set bit
fd < 32 ? (dstLow = dstLow | mask) : (dstHigh = dstHigh | mask);
@@ -7529,6 +8082,7 @@ LibraryManager.library = {
return totalHandles;
}
},
+#endif
socketpair__deps: ['__setErrNo', '$ERRNO_CODES'],
socketpair: function(domain, type, protocol, sv) {
@@ -7563,7 +8117,7 @@ LibraryManager.library = {
},
emscripten_run_script_int: function(ptr) {
- return eval(Pointer_stringify(ptr));
+ return eval(Pointer_stringify(ptr))|0;
},
emscripten_run_script_string: function(ptr) {
diff --git a/src/library_browser.js b/src/library_browser.js
index 5f9c4d06..a690286b 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -6,7 +6,8 @@ mergeInto(LibraryManager.library, {
$Browser__postset: 'Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports
'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' +
'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' +
- 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n',
+ 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n' +
+ 'Module["getUserMedia"] = function() { Browser.getUserMedia() }',
$Browser: {
mainLoop: {
scheduler: null,
@@ -184,7 +185,7 @@ mergeInto(LibraryManager.library, {
};
audio.src = url;
// workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
- setTimeout(function() {
+ Browser.safeSetTimeout(function() {
finish(audio); // try to use it even though it is not necessarily ready to play
}, 10000);
} else {
@@ -201,7 +202,8 @@ mergeInto(LibraryManager.library, {
canvas['webkitRequestPointerLock'];
canvas.exitPointerLock = document['exitPointerLock'] ||
document['mozExitPointerLock'] ||
- document['webkitExitPointerLock'];
+ document['webkitExitPointerLock'] ||
+ function(){}; // no-op if function does not exist
canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
function pointerLockChange() {
@@ -345,7 +347,7 @@ mergeInto(LibraryManager.library, {
canvas.requestFullScreen = canvas['requestFullScreen'] ||
canvas['mozRequestFullScreen'] ||
(canvas['webkitRequestFullScreen'] ? function() { canvas['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
- canvas.requestFullScreen();
+ canvas.requestFullScreen();
},
requestAnimationFrame: function(func) {
@@ -360,6 +362,38 @@ mergeInto(LibraryManager.library, {
window.requestAnimationFrame(func);
},
+ // generic abort-aware wrapper for an async callback
+ safeCallback: function(func) {
+ return function() {
+ if (!ABORT) return func.apply(null, arguments);
+ };
+ },
+
+ // abort-aware versions
+ safeRequestAnimationFrame: function(func) {
+ Browser.requestAnimationFrame(function() {
+ if (!ABORT) func();
+ });
+ },
+ safeSetTimeout: function(func, timeout) {
+ setTimeout(function() {
+ if (!ABORT) func();
+ }, timeout);
+ },
+ safeSetInterval: function(func, timeout) {
+ setInterval(function() {
+ if (!ABORT) func();
+ }, timeout);
+ },
+
+ getUserMedia: function(func) {
+ if(!window.getUserMedia) {
+ window.getUserMedia = navigator['getUserMedia'] ||
+ navigator['mozGetUserMedia'];
+ }
+ window.getUserMedia(func);
+ },
+
getMovementX: function(event) {
return event['movementX'] ||
event['mozMovementX'] ||
@@ -474,7 +508,7 @@ mergeInto(LibraryManager.library, {
{{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}}
Browser.updateResizeListeners();
},
-
+
setWindowedCanvasSize: function() {
var canvas = Module['canvas'];
canvas.width = this.windowedWidth;
@@ -484,7 +518,7 @@ mergeInto(LibraryManager.library, {
{{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}}
Browser.updateResizeListeners();
}
-
+
},
emscripten_async_wget: function(url, file, onload, onerror) {
@@ -521,11 +555,11 @@ mergeInto(LibraryManager.library, {
var _request = Pointer_stringify(request);
var _param = Pointer_stringify(param);
var index = _file.lastIndexOf('/');
-
+
var http = new XMLHttpRequest();
http.open(_request, _url, true);
http.responseType = 'arraybuffer';
-
+
// LOAD
http.onload = function(e) {
if (http.status == 200) {
@@ -535,20 +569,20 @@ mergeInto(LibraryManager.library, {
if (onerror) Runtime.dynCall('vii', onerror, [arg, http.status]);
}
};
-
+
// ERROR
http.onerror = function(e) {
if (onerror) Runtime.dynCall('vii', onerror, [arg, http.status]);
};
-
+
// PROGRESS
http.onprogress = function(e) {
var percentComplete = (e.position / e.totalSize)*100;
if (onprogress) Runtime.dynCall('vii', onprogress, [arg, percentComplete]);
};
-
+
// Useful because the browser can limit the number of redirection
- try {
+ try {
if (http.channel instanceof Ci.nsIHttpChannel)
http.channel.redirectionLimit = 0;
} catch (ex) { /* whatever */ }
@@ -563,7 +597,7 @@ mergeInto(LibraryManager.library, {
http.send(null);
}
},
-
+
emscripten_async_prepare: function(file, onload, onerror) {
var _file = Pointer_stringify(file);
var data = FS.analyzePath(_file);
@@ -611,7 +645,7 @@ mergeInto(LibraryManager.library, {
Module['noExitRuntime'] = true;
// TODO: cache these to avoid generating garbage
- setTimeout(function() {
+ Browser.safeSetTimeout(function() {
_emscripten_run_script(script);
}, millis);
},
@@ -620,6 +654,7 @@ mergeInto(LibraryManager.library, {
Module['noExitRuntime'] = true;
Browser.mainLoop.runner = function() {
+ if (ABORT) return;
if (Browser.mainLoop.queue.length > 0) {
var start = Date.now();
var blocker = Browser.mainLoop.queue.shift();
@@ -722,12 +757,17 @@ mergeInto(LibraryManager.library, {
}
if (millis >= 0) {
- setTimeout(wrapper, millis);
+ Browser.safeSetTimeout(wrapper, millis);
} else {
- Browser.requestAnimationFrame(wrapper);
+ Browser.safeRequestAnimationFrame(wrapper);
}
},
+ emscripten_exit_with_live_runtime: function() {
+ Module['noExitRuntime'] = true;
+ throw 'SimulateInfiniteLoop';
+ },
+
emscripten_hide_mouse: function() {
var styleSheet = document.styleSheets[0];
var rules = styleSheet.cssRules;
diff --git a/src/library_gc.js b/src/library_gc.js
index 2a164250..b3dae0e9 100644
--- a/src/library_gc.js
+++ b/src/library_gc.js
@@ -26,7 +26,7 @@ if (GC_SUPPORT) {
_GC_finalizer_notifier = _malloc(4); setValue(_GC_finalizer_notifier, 0, 'i32');
if (ENVIRONMENT_IS_WEB) {
- setInterval(function() {
+ Browser.safeSetInterval(function() {
GC.maybeCollect();
}, 1000);
} else {
diff --git a/src/library_gl.js b/src/library_gl.js
index ba99eaa8..1fa0cc9c 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -373,7 +373,7 @@ var LibraryGL = {
glGetIntegerv__sig: 'vii',
glGetIntegerv: function(name_, p) {
- switch(name_) { // Handle a few trivial GLES values
+ switch(name_) { // Handle a few trivial GLES values
case 0x8DFA: // GL_SHADER_COMPILER
{{{ makeSetValue('p', '0', '1', 'i32') }}};
return;
@@ -507,7 +507,7 @@ var LibraryGL = {
glGenTextures__sig: 'vii',
glGenTextures: function(n, textures) {
for (var i = 0; i < n; i++) {
- var id = GL.getNewId(GL.textures);
+ var id = GL.getNewId(GL.textures);
GL.textures[id] = Module.ctx.createTexture();
{{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}};
}
@@ -726,7 +726,7 @@ var LibraryGL = {
var ptable = GL.uniformTable[program];
if (!ptable) ptable = GL.uniformTable[program] = {};
var id = ptable[name];
- if (id) return id;
+ if (id) return id;
var loc = Module.ctx.getUniformLocation(GL.programs[program], name);
if (!loc) return -1;
id = GL.getNewId(GL.uniforms);
@@ -989,13 +989,15 @@ var LibraryGL = {
glBindBuffer__sig: 'vii',
glBindBuffer: function(target, buffer) {
+ var bufferObj = buffer ? GL.buffers[buffer] : null;
+
if (target == Module.ctx.ARRAY_BUFFER) {
GL.currArrayBuffer = buffer;
} else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) {
GL.currElementArrayBuffer = buffer;
}
- Module.ctx.bindBuffer(target, buffer ? GL.buffers[buffer] : null);
+ Module.ctx.bindBuffer(target, bufferObj);
},
glVertexAttrib1fv__sig: 'vii',
@@ -1275,7 +1277,22 @@ var LibraryGL = {
currentVao: null,
enabledVertexAttribArrays: {}, // helps with vao cleanups
+ hasRunInit: false,
+
init: function() {
+ // Do not activate immediate/emulation code (e.g. replace glDrawElements) when in FULL_ES2 mode.
+ // We do not need full emulation, we instead emulate client-side arrays etc. in FULL_ES2 code in
+ // a straightforward manner, and avoid not having a bound buffer be ambiguous between es2 emulation
+ // code and legacy gl emulation code.
+#if FULL_ES2
+ return;
+#endif
+
+ if (GLEmulation.hasRunInit) {
+ return;
+ }
+ GLEmulation.hasRunInit = true;
+
GLEmulation.fogColor = new Float32Array(4);
// Add some emulation workarounds
@@ -1297,6 +1314,7 @@ var LibraryGL = {
0x80A0: 1 // GL_SAMPLE_COVERAGE
};
+ var glEnable = _glEnable;
_glEnable = function(cap) {
// Clean up the renderer on any change to the rendering state. The optimization of
// skipping renderer setup is aimed at the case of multiple glDraw* right after each other
@@ -1307,13 +1325,18 @@ var LibraryGL = {
} else if (cap == 0x0de1 /* GL_TEXTURE_2D */) {
// XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support
// it by forwarding to glEnableClientState
+ /* Actually, let's not, for now. (This sounds exceedingly broken)
+ * This is in gl_ps_workaround2.c.
_glEnableClientState(cap);
+ */
return;
} else if (!(cap in validCapabilities)) {
return;
}
- Module.ctx.enable(cap);
+ glEnable(cap);
};
+
+ var glDisable = _glDisable;
_glDisable = function(cap) {
if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup();
if (cap == 0x0B60 /* GL_FOG */) {
@@ -1322,12 +1345,15 @@ var LibraryGL = {
} else if (cap == 0x0de1 /* GL_TEXTURE_2D */) {
// XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support
// it by forwarding to glDisableClientState
+ /* Actually, let's not, for now. (This sounds exceedingly broken)
+ * This is in gl_ps_workaround2.c.
_glDisableClientState(cap);
+ */
return;
} else if (!(cap in validCapabilities)) {
return;
}
- Module.ctx.disable(cap);
+ glDisable(cap);
};
_glIsEnabled = function(cap) {
if (cap == 0x0B60 /* GL_FOG */) {
@@ -1453,6 +1479,7 @@ var LibraryGL = {
_glShaderSource = function(shader, count, string, length) {
var source = GL.getSource(shader, count, string, length);
#if GL_DEBUG
+ console.log("glShaderSource: Input: \n" + source);
GL.shaderOriginalSources[shader] = source;
#endif
// XXX We add attributes and uniforms to shaders. The program can ask for the # of them, and see the
@@ -1510,9 +1537,7 @@ var LibraryGL = {
}
if (source.indexOf('gl_Color') >= 0) {
source = 'attribute vec4 a_color; \n' +
- 'uniform vec4 u_color; \n' +
- 'uniform int u_hasColorAttrib; \n' +
- source.replace(/gl_Color/g, '(u_hasColorAttrib > 0 ? a_color : u_color)');
+ source.replace(/gl_Color/g, 'a_color');
}
if (source.indexOf('gl_Normal') >= 0) {
source = 'attribute vec3 a_normal; \n' +
@@ -1558,6 +1583,7 @@ var LibraryGL = {
}
#if GL_DEBUG
GL.shaderSources[shader] = source;
+ console.log("glShaderSource: Output: \n" + source);
#endif
Module.ctx.shaderSource(GL.shaders[shader], source);
};
@@ -1706,8 +1732,12 @@ var LibraryGL = {
getAttributeFromCapability: function(cap) {
var attrib = null;
switch (cap) {
- case 0x8078: // GL_TEXTURE_COORD_ARRAY
case 0x0de1: // GL_TEXTURE_2D - XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support it
+#if ASSERTIONS
+ abort("GL_TEXTURE_2D is not a spec-defined capability for gl{Enable,Disable}ClientState.");
+#endif
+ // Fall through:
+ case 0x8078: // GL_TEXTURE_COORD_ARRAY
attrib = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; break;
case 0x8074: // GL_VERTEX_ARRAY
attrib = GL.immediate.VERTEX; break;
@@ -1767,19 +1797,19 @@ var LibraryGL = {
case 'glEnableVertexAttribArray': ret = {{{ Functions.getIndex('_glEnableVertexAttribArray', true) }}}; break;
case 'glDisableVertexAttribArray': ret = {{{ Functions.getIndex('_glDisableVertexAttribArray', true) }}}; break;
case 'glVertexAttribPointer': ret = {{{ Functions.getIndex('_glVertexAttribPointer', true) }}}; break;
- case 'glVertexAttrib1f': ret = {{{ Functions.getIndex('_glVertexAttrib1f', true) }}}; break;
- case 'glVertexAttrib2f': ret = {{{ Functions.getIndex('_glVertexAttrib2f', true) }}}; break;
- case 'glVertexAttrib3f': ret = {{{ Functions.getIndex('_glVertexAttrib3f', true) }}}; break;
- case 'glVertexAttrib4f': ret = {{{ Functions.getIndex('_glVertexAttrib4f', true) }}}; break;
- case 'glVertexAttrib1fv': ret = {{{ Functions.getIndex('_glVertexAttrib1fv', true) }}}; break;
- case 'glVertexAttrib2fv': ret = {{{ Functions.getIndex('_glVertexAttrib2fv', true) }}}; break;
- case 'glVertexAttrib3fv': ret = {{{ Functions.getIndex('_glVertexAttrib3fv', true) }}}; break;
- case 'glVertexAttrib4fv': ret = {{{ Functions.getIndex('_glVertexAttrib4fv', true) }}}; break;
- case 'glGetVertexAttribfv': ret = {{{ Functions.getIndex('_glGetVertexAttribfv', true) }}}; break;
- case 'glGetVertexAttribiv': ret = {{{ Functions.getIndex('_glGetVertexAttribiv', true) }}}; break;
- case 'glGetVertexAttribPointerv': ret = {{{ Functions.getIndex('_glGetVertexAttribPointerv', true) }}}; break;
- case 'glGetAttribLocation': ret = {{{ Functions.getIndex('_glGetAttribLocation', true) }}}; break;
- case 'glGetActiveAttrib': ret = {{{ Functions.getIndex('_glGetActiveAttrib', true) }}}; break;
+ case 'glVertexAttrib1f': ret = {{{ Functions.getIndex('_glVertexAttrib1f', true) }}}; break;
+ case 'glVertexAttrib2f': ret = {{{ Functions.getIndex('_glVertexAttrib2f', true) }}}; break;
+ case 'glVertexAttrib3f': ret = {{{ Functions.getIndex('_glVertexAttrib3f', true) }}}; break;
+ case 'glVertexAttrib4f': ret = {{{ Functions.getIndex('_glVertexAttrib4f', true) }}}; break;
+ case 'glVertexAttrib1fv': ret = {{{ Functions.getIndex('_glVertexAttrib1fv', true) }}}; break;
+ case 'glVertexAttrib2fv': ret = {{{ Functions.getIndex('_glVertexAttrib2fv', true) }}}; break;
+ case 'glVertexAttrib3fv': ret = {{{ Functions.getIndex('_glVertexAttrib3fv', true) }}}; break;
+ case 'glVertexAttrib4fv': ret = {{{ Functions.getIndex('_glVertexAttrib4fv', true) }}}; break;
+ case 'glGetVertexAttribfv': ret = {{{ Functions.getIndex('_glGetVertexAttribfv', true) }}}; break;
+ case 'glGetVertexAttribiv': ret = {{{ Functions.getIndex('_glGetVertexAttribiv', true) }}}; break;
+ case 'glGetVertexAttribPointerv': ret = {{{ Functions.getIndex('_glGetVertexAttribPointerv', true) }}}; break;
+ case 'glGetAttribLocation': ret = {{{ Functions.getIndex('_glGetAttribLocation', true) }}}; break;
+ case 'glGetActiveAttrib': ret = {{{ Functions.getIndex('_glGetActiveAttrib', true) }}}; break;
case 'glBindRenderbuffer': ret = {{{ Functions.getIndex('_glBindRenderbuffer', true) }}}; break;
case 'glDeleteRenderbuffers': ret = {{{ Functions.getIndex('_glDeleteRenderbuffers', true) }}}; break;
case 'glGenRenderbuffers': ret = {{{ Functions.getIndex('_glGenRenderbuffers', true) }}}; break;
@@ -1798,86 +1828,86 @@ var LibraryGL = {
case 'glDeleteVertexArrays': ret = {{{ Functions.getIndex('_glDeleteVertexArrays', true) }}}; break;
case 'glBindVertexArray': ret = {{{ Functions.getIndex('_glBindVertexArray', true) }}}; break;
case 'glGetString': ret = {{{ Functions.getIndex('_glGetString', true) }}}; break;
- case 'glBindTexture': ret = {{{ Functions.getIndex('_glBindTexture', true) }}}; break;
- case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break;
- case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break;
- case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break;
+ case 'glBindTexture': ret = {{{ Functions.getIndex('_glBindTexture', true) }}}; break;
+ case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break;
+ case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break;
+ case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break;
case 'glUniformMatrix2fv': ret = {{{ Functions.getIndex('_glUniformMatrix2fv', true) }}}; break;
case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break;
case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break;
- case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break;
- case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break;
- case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break;
- case 'glBlendFuncSeparate': ret = {{{ Functions.getIndex('_glBlendFuncSeparate', true) }}}; break;
- case 'glBlendEquationSeparate': ret = {{{ Functions.getIndex('_glBlendEquationSeparate', true) }}}; break;
- case 'glDepthRangef': ret = {{{ Functions.getIndex('_glDepthRangef', true) }}}; break;
- case 'glClear': ret = {{{ Functions.getIndex('_glClear', true) }}}; break;
- case 'glGenerateMipmap': ret = {{{ Functions.getIndex('_glGenerateMipmap', true) }}}; break;
- case 'glBlendColor': ret = {{{ Functions.getIndex('_glBlendColor', true) }}}; break;
- case 'glClearDepthf': ret = {{{ Functions.getIndex('_glClearDepthf', true) }}}; break;
- case 'glDeleteProgram': ret = {{{ Functions.getIndex('_glDeleteProgram', true) }}}; break;
- case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break;
- case 'glClearColor': ret = {{{ Functions.getIndex('_glClearColor', true) }}}; break;
- case 'glGetRenderbufferParameteriv': ret = {{{ Functions.getIndex('_glGetRenderbufferParameteriv', true) }}}; break;
- case 'glGetShaderInfoLog': ret = {{{ Functions.getIndex('_glGetShaderInfoLog', true) }}}; break;
- case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break;
- case 'glClearStencil': ret = {{{ Functions.getIndex('_glClearStencil', true) }}}; break;
- case 'glGetProgramInfoLog': ret = {{{ Functions.getIndex('_glGetProgramInfoLog', true) }}}; break;
- case 'glGetUniformfv': ret = {{{ Functions.getIndex('_glGetUniformfv', true) }}}; break;
- case 'glStencilFuncSeparate': ret = {{{ Functions.getIndex('_glStencilFuncSeparate', true) }}}; break;
- case 'glSampleCoverage': ret = {{{ Functions.getIndex('_glSampleCoverage', true) }}}; break;
- case 'glColorMask': ret = {{{ Functions.getIndex('_glColorMask', true) }}}; break;
- case 'glGetShaderiv': ret = {{{ Functions.getIndex('_glGetShaderiv', true) }}}; break;
- case 'glGetUniformiv': ret = {{{ Functions.getIndex('_glGetUniformiv', true) }}}; break;
- case 'glCopyTexSubImage2D': ret = {{{ Functions.getIndex('_glCopyTexSubImage2D', true) }}}; break;
- case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break;
- case 'glGetShaderSource': ret = {{{ Functions.getIndex('_glGetShaderSource', true) }}}; break;
- case 'glDeleteTextures': ret = {{{ Functions.getIndex('_glDeleteTextures', true) }}}; break;
- case 'glGetAttachedShaders': ret = {{{ Functions.getIndex('_glGetAttachedShaders', true) }}}; break;
- case 'glValidateProgram': ret = {{{ Functions.getIndex('_glValidateProgram', true) }}}; break;
- case 'glDepthFunc': ret = {{{ Functions.getIndex('_glDepthFunc', true) }}}; break;
- case 'glIsShader': ret = {{{ Functions.getIndex('_glIsShader', true) }}}; break;
- case 'glDepthMask': ret = {{{ Functions.getIndex('_glDepthMask', true) }}}; break;
- case 'glStencilMaskSeparate': ret = {{{ Functions.getIndex('_glStencilMaskSeparate', true) }}}; break;
- case 'glIsProgram': ret = {{{ Functions.getIndex('_glIsProgram', true) }}}; break;
- case 'glDisable': ret = {{{ Functions.getIndex('_glDisable', true) }}}; break;
- case 'glStencilOpSeparate': ret = {{{ Functions.getIndex('_glStencilOpSeparate', true) }}}; break;
- case 'glDrawArrays': ret = {{{ Functions.getIndex('_glDrawArrays', true) }}}; break;
- case 'glDrawElements': ret = {{{ Functions.getIndex('_glDrawElements', true) }}}; break;
- case 'glEnable': ret = {{{ Functions.getIndex('_glEnable', true) }}}; break;
- case 'glFinish': ret = {{{ Functions.getIndex('_glFinish', true) }}}; break;
- case 'glFlush': ret = {{{ Functions.getIndex('_glFlush', true) }}}; break;
- case 'glFrontFace': ret = {{{ Functions.getIndex('_glFrontFace', true) }}}; break;
- case 'glCullFace': ret = {{{ Functions.getIndex('_glCullFace', true) }}}; break;
- case 'glGenTextures': ret = {{{ Functions.getIndex('_glGenTextures', true) }}}; break;
- case 'glGetError': ret = {{{ Functions.getIndex('_glGetError', true) }}}; break;
- case 'glGetIntegerv': ret = {{{ Functions.getIndex('_glGetIntegerv', true) }}}; break;
- case 'glGetBooleanv': ret = {{{ Functions.getIndex('_glGetBooleanv', true) }}}; break;
- case 'glGetFloatv': ret = {{{ Functions.getIndex('_glGetFloatv', true) }}}; break;
- case 'glHint': ret = {{{ Functions.getIndex('_glHint', true) }}}; break;
- case 'glIsTexture': ret = {{{ Functions.getIndex('_glIsTexture', true) }}}; break;
- case 'glPixelStorei': ret = {{{ Functions.getIndex('_glPixelStorei', true) }}}; break;
- case 'glReadPixels': ret = {{{ Functions.getIndex('_glReadPixels', true) }}}; break;
- case 'glScissor': ret = {{{ Functions.getIndex('_glScissor', true) }}}; break;
- case 'glStencilFunc': ret = {{{ Functions.getIndex('_glStencilFunc', true) }}}; break;
- case 'glStencilMask': ret = {{{ Functions.getIndex('_glStencilMask', true) }}}; break;
- case 'glStencilOp': ret = {{{ Functions.getIndex('_glStencilOp', true) }}}; break;
- case 'glTexImage2D': ret = {{{ Functions.getIndex('_glTexImage2D', true) }}}; break;
- case 'glTexParameterf': ret = {{{ Functions.getIndex('_glTexParameterf', true) }}}; break;
- case 'glTexParameterfv': ret = {{{ Functions.getIndex('_glTexParameterfv', true) }}}; break;
- case 'glTexParameteri': ret = {{{ Functions.getIndex('_glTexParameteri', true) }}}; break;
- case 'glTexParameteriv': ret = {{{ Functions.getIndex('_glTexParameteriv', true) }}}; break;
- case 'glGetTexParameterfv': ret = {{{ Functions.getIndex('_glGetTexParameterfv', true) }}}; break;
- case 'glGetTexParameteriv': ret = {{{ Functions.getIndex('_glGetTexParameteriv', true) }}}; break;
- case 'glTexSubImage2D': ret = {{{ Functions.getIndex('_glTexSubImage2D', true) }}}; break;
- case 'glCopyTexImage2D': ret = {{{ Functions.getIndex('_glCopyTexImage2D', true) }}}; break;
- case 'glViewport': ret = {{{ Functions.getIndex('_glViewport', true) }}}; break;
- case 'glIsEnabled': ret = {{{ Functions.getIndex('_glIsEnabled', true) }}}; break;
- case 'glLineWidth': ret = {{{ Functions.getIndex('_glLineWidth', true) }}}; break;
- case 'glPolygonOffset': ret = {{{ Functions.getIndex('_glPolygonOffset', true) }}}; break;
- case 'glReleaseShaderCompiler': ret = {{{ Functions.getIndex('_glReleaseShaderCompiler', true) }}}; break;
- case 'glGetShaderPrecisionFormat': ret = {{{ Functions.getIndex('_glGetShaderPrecisionFormat', true) }}}; break;
- case 'glShaderBinary': ret = {{{ Functions.getIndex('_glShaderBinary', true) }}}; break;
+ case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break;
+ case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break;
+ case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break;
+ case 'glBlendFuncSeparate': ret = {{{ Functions.getIndex('_glBlendFuncSeparate', true) }}}; break;
+ case 'glBlendEquationSeparate': ret = {{{ Functions.getIndex('_glBlendEquationSeparate', true) }}}; break;
+ case 'glDepthRangef': ret = {{{ Functions.getIndex('_glDepthRangef', true) }}}; break;
+ case 'glClear': ret = {{{ Functions.getIndex('_glClear', true) }}}; break;
+ case 'glGenerateMipmap': ret = {{{ Functions.getIndex('_glGenerateMipmap', true) }}}; break;
+ case 'glBlendColor': ret = {{{ Functions.getIndex('_glBlendColor', true) }}}; break;
+ case 'glClearDepthf': ret = {{{ Functions.getIndex('_glClearDepthf', true) }}}; break;
+ case 'glDeleteProgram': ret = {{{ Functions.getIndex('_glDeleteProgram', true) }}}; break;
+ case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break;
+ case 'glClearColor': ret = {{{ Functions.getIndex('_glClearColor', true) }}}; break;
+ case 'glGetRenderbufferParameteriv': ret = {{{ Functions.getIndex('_glGetRenderbufferParameteriv', true) }}}; break;
+ case 'glGetShaderInfoLog': ret = {{{ Functions.getIndex('_glGetShaderInfoLog', true) }}}; break;
+ case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break;
+ case 'glClearStencil': ret = {{{ Functions.getIndex('_glClearStencil', true) }}}; break;
+ case 'glGetProgramInfoLog': ret = {{{ Functions.getIndex('_glGetProgramInfoLog', true) }}}; break;
+ case 'glGetUniformfv': ret = {{{ Functions.getIndex('_glGetUniformfv', true) }}}; break;
+ case 'glStencilFuncSeparate': ret = {{{ Functions.getIndex('_glStencilFuncSeparate', true) }}}; break;
+ case 'glSampleCoverage': ret = {{{ Functions.getIndex('_glSampleCoverage', true) }}}; break;
+ case 'glColorMask': ret = {{{ Functions.getIndex('_glColorMask', true) }}}; break;
+ case 'glGetShaderiv': ret = {{{ Functions.getIndex('_glGetShaderiv', true) }}}; break;
+ case 'glGetUniformiv': ret = {{{ Functions.getIndex('_glGetUniformiv', true) }}}; break;
+ case 'glCopyTexSubImage2D': ret = {{{ Functions.getIndex('_glCopyTexSubImage2D', true) }}}; break;
+ case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break;
+ case 'glGetShaderSource': ret = {{{ Functions.getIndex('_glGetShaderSource', true) }}}; break;
+ case 'glDeleteTextures': ret = {{{ Functions.getIndex('_glDeleteTextures', true) }}}; break;
+ case 'glGetAttachedShaders': ret = {{{ Functions.getIndex('_glGetAttachedShaders', true) }}}; break;
+ case 'glValidateProgram': ret = {{{ Functions.getIndex('_glValidateProgram', true) }}}; break;
+ case 'glDepthFunc': ret = {{{ Functions.getIndex('_glDepthFunc', true) }}}; break;
+ case 'glIsShader': ret = {{{ Functions.getIndex('_glIsShader', true) }}}; break;
+ case 'glDepthMask': ret = {{{ Functions.getIndex('_glDepthMask', true) }}}; break;
+ case 'glStencilMaskSeparate': ret = {{{ Functions.getIndex('_glStencilMaskSeparate', true) }}}; break;
+ case 'glIsProgram': ret = {{{ Functions.getIndex('_glIsProgram', true) }}}; break;
+ case 'glDisable': ret = {{{ Functions.getIndex('_glDisable', true) }}}; break;
+ case 'glStencilOpSeparate': ret = {{{ Functions.getIndex('_glStencilOpSeparate', true) }}}; break;
+ case 'glDrawArrays': ret = {{{ Functions.getIndex('_glDrawArrays', true) }}}; break;
+ case 'glDrawElements': ret = {{{ Functions.getIndex('_glDrawElements', true) }}}; break;
+ case 'glEnable': ret = {{{ Functions.getIndex('_glEnable', true) }}}; break;
+ case 'glFinish': ret = {{{ Functions.getIndex('_glFinish', true) }}}; break;
+ case 'glFlush': ret = {{{ Functions.getIndex('_glFlush', true) }}}; break;
+ case 'glFrontFace': ret = {{{ Functions.getIndex('_glFrontFace', true) }}}; break;
+ case 'glCullFace': ret = {{{ Functions.getIndex('_glCullFace', true) }}}; break;
+ case 'glGenTextures': ret = {{{ Functions.getIndex('_glGenTextures', true) }}}; break;
+ case 'glGetError': ret = {{{ Functions.getIndex('_glGetError', true) }}}; break;
+ case 'glGetIntegerv': ret = {{{ Functions.getIndex('_glGetIntegerv', true) }}}; break;
+ case 'glGetBooleanv': ret = {{{ Functions.getIndex('_glGetBooleanv', true) }}}; break;
+ case 'glGetFloatv': ret = {{{ Functions.getIndex('_glGetFloatv', true) }}}; break;
+ case 'glHint': ret = {{{ Functions.getIndex('_glHint', true) }}}; break;
+ case 'glIsTexture': ret = {{{ Functions.getIndex('_glIsTexture', true) }}}; break;
+ case 'glPixelStorei': ret = {{{ Functions.getIndex('_glPixelStorei', true) }}}; break;
+ case 'glReadPixels': ret = {{{ Functions.getIndex('_glReadPixels', true) }}}; break;
+ case 'glScissor': ret = {{{ Functions.getIndex('_glScissor', true) }}}; break;
+ case 'glStencilFunc': ret = {{{ Functions.getIndex('_glStencilFunc', true) }}}; break;
+ case 'glStencilMask': ret = {{{ Functions.getIndex('_glStencilMask', true) }}}; break;
+ case 'glStencilOp': ret = {{{ Functions.getIndex('_glStencilOp', true) }}}; break;
+ case 'glTexImage2D': ret = {{{ Functions.getIndex('_glTexImage2D', true) }}}; break;
+ case 'glTexParameterf': ret = {{{ Functions.getIndex('_glTexParameterf', true) }}}; break;
+ case 'glTexParameterfv': ret = {{{ Functions.getIndex('_glTexParameterfv', true) }}}; break;
+ case 'glTexParameteri': ret = {{{ Functions.getIndex('_glTexParameteri', true) }}}; break;
+ case 'glTexParameteriv': ret = {{{ Functions.getIndex('_glTexParameteriv', true) }}}; break;
+ case 'glGetTexParameterfv': ret = {{{ Functions.getIndex('_glGetTexParameterfv', true) }}}; break;
+ case 'glGetTexParameteriv': ret = {{{ Functions.getIndex('_glGetTexParameteriv', true) }}}; break;
+ case 'glTexSubImage2D': ret = {{{ Functions.getIndex('_glTexSubImage2D', true) }}}; break;
+ case 'glCopyTexImage2D': ret = {{{ Functions.getIndex('_glCopyTexImage2D', true) }}}; break;
+ case 'glViewport': ret = {{{ Functions.getIndex('_glViewport', true) }}}; break;
+ case 'glIsEnabled': ret = {{{ Functions.getIndex('_glIsEnabled', true) }}}; break;
+ case 'glLineWidth': ret = {{{ Functions.getIndex('_glLineWidth', true) }}}; break;
+ case 'glPolygonOffset': ret = {{{ Functions.getIndex('_glPolygonOffset', true) }}}; break;
+ case 'glReleaseShaderCompiler': ret = {{{ Functions.getIndex('_glReleaseShaderCompiler', true) }}}; break;
+ case 'glGetShaderPrecisionFormat': ret = {{{ Functions.getIndex('_glGetShaderPrecisionFormat', true) }}}; break;
+ case 'glShaderBinary': ret = {{{ Functions.getIndex('_glShaderBinary', true) }}}; break;
}
if (!ret) Module.printErr('WARNING: getProcAddress failed for ' + name);
return ret;
@@ -1960,10 +1990,879 @@ var LibraryGL = {
// GL Immediate mode
+ // See comment in GLEmulation.init()
+#if FULL_ES2 == 0
$GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });',
+#endif
$GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'],
$GLImmediate: {
- MAX_TEXTURES: 7,
+ MapTreeLib: null,
+ spawnMapTreeLib: function() {
+ /* A naive implementation of a map backed by an array, and accessed by
+ * naive iteration along the array. (hashmap with only one bucket)
+ */
+ function CNaiveListMap() {
+ var list = [];
+
+ this.insert = function(key, val) {
+ if (this.contains(key|0)) return false;
+ list.push([key, val]);
+ return true;
+ };
+
+ var __contains_i;
+ this.contains = function(key) {
+ for (__contains_i = 0; __contains_i < list.length; ++__contains_i) {
+ if (list[__contains_i][0] === key) return true;
+ }
+ return false;
+ };
+
+ var __get_i;
+ this.get = function(key) {
+ for (__get_i = 0; __get_i < list.length; ++__get_i) {
+ if (list[__get_i][0] === key) return list[__get_i][1];
+ }
+ return undefined;
+ };
+ };
+
+ /* A tree of map nodes.
+ Uses `KeyView`s to allow descending the tree without garbage.
+ Example: {
+ // Create our map object.
+ var map = new ObjTreeMap();
+
+ // Grab the static keyView for the map.
+ var keyView = map.GetStaticKeyView();
+
+ // Let's make a map for:
+ // root: <undefined>
+ // 1: <undefined>
+ // 2: <undefined>
+ // 5: "Three, sir!"
+ // 3: "Three!"
+
+ // Note how we can chain together `Reset` and `Next` to
+ // easily descend based on multiple key fragments.
+ keyView.Reset().Next(1).Next(2).Next(5).Set("Three, sir!");
+ keyView.Reset().Next(1).Next(2).Next(3).Set("Three!");
+ }
+ */
+ function CMapTree() {
+ function CNLNode() {
+ var map = new CNaiveListMap();
+
+ this.child = function(keyFrag) {
+ if (!map.contains(keyFrag|0)) {
+ map.insert(keyFrag|0, new CNLNode());
+ }
+ return map.get(keyFrag|0);
+ };
+
+ this.value = undefined;
+ this.get = function() {
+ return this.value;
+ };
+
+ this.set = function(val) {
+ this.value = val;
+ };
+ }
+
+ function CKeyView(root) {
+ var cur;
+
+ this.reset = function() {
+ cur = root;
+ return this;
+ };
+ this.reset();
+
+ this.next = function(keyFrag) {
+ cur = cur.child(keyFrag);
+ return this;
+ };
+
+ this.get = function() {
+ return cur.get();
+ };
+
+ this.set = function(val) {
+ cur.set(val);
+ };
+ };
+
+ var root;
+ var staticKeyView;
+
+ this.createKeyView = function() {
+ return new CKeyView(root);
+ }
+
+ this.clear = function() {
+ root = new CNLNode();
+ staticKeyView = this.createKeyView();
+ };
+ this.clear();
+
+ this.getStaticKeyView = function() {
+ staticKeyView.reset();
+ return staticKeyView;
+ };
+ };
+
+ // Exports:
+ return {
+ create: function() {
+ return new CMapTree();
+ },
+ };
+ },
+
+ TexEnvJIT: null,
+ spawnTexEnvJIT: function() {
+ // GL defs:
+ var GL_TEXTURE0 = 0x84C0;
+ var GL_TEXTURE_1D = 0x0DE0;
+ var GL_TEXTURE_2D = 0x0DE1;
+ var GL_TEXTURE_3D = 0x806f;
+ var GL_TEXTURE_CUBE_MAP = 0x8513;
+ var GL_TEXTURE_ENV = 0x2300;
+ var GL_TEXTURE_ENV_MODE = 0x2200;
+ var GL_TEXTURE_ENV_COLOR = 0x2201;
+ var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
+ var GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
+ var GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
+ var GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
+ var GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
+ var GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
+
+ var GL_SRC0_RGB = 0x8580;
+ var GL_SRC1_RGB = 0x8581;
+ var GL_SRC2_RGB = 0x8582;
+
+ var GL_SRC0_ALPHA = 0x8588;
+ var GL_SRC1_ALPHA = 0x8589;
+ var GL_SRC2_ALPHA = 0x858A;
+
+ var GL_OPERAND0_RGB = 0x8590;
+ var GL_OPERAND1_RGB = 0x8591;
+ var GL_OPERAND2_RGB = 0x8592;
+
+ var GL_OPERAND0_ALPHA = 0x8598;
+ var GL_OPERAND1_ALPHA = 0x8599;
+ var GL_OPERAND2_ALPHA = 0x859A;
+
+ var GL_COMBINE_RGB = 0x8571;
+ var GL_COMBINE_ALPHA = 0x8572;
+
+ var GL_RGB_SCALE = 0x8573;
+ var GL_ALPHA_SCALE = 0x0D1C;
+
+ // env.mode
+ var GL_ADD = 0x0104;
+ var GL_BLEND = 0x0BE2;
+ var GL_REPLACE = 0x1E01;
+ var GL_MODULATE = 0x2100;
+ var GL_DECAL = 0x2101;
+ var GL_COMBINE = 0x8570;
+
+ // env.color/alphaCombiner
+ //var GL_ADD = 0x0104;
+ //var GL_REPLACE = 0x1E01;
+ //var GL_MODULATE = 0x2100;
+ var GL_SUBTRACT = 0x84E7;
+ var GL_INTERPOLATE = 0x8575;
+
+ // env.color/alphaSrc
+ var GL_TEXTURE = 0x1702;
+ var GL_CONSTANT = 0x8576;
+ var GL_PRIMARY_COLOR = 0x8577;
+ var GL_PREVIOUS = 0x8578;
+
+ // env.color/alphaOp
+ var GL_SRC_COLOR = 0x0300;
+ var GL_ONE_MINUS_SRC_COLOR = 0x0301;
+ var GL_SRC_ALPHA = 0x0302;
+ var GL_ONE_MINUS_SRC_ALPHA = 0x0303;
+
+ var GL_RGB = 0x1907;
+ var GL_RGBA = 0x1908;
+
+ // Our defs:
+ var TEXENVJIT_NAMESPACE_PREFIX = "tej_";
+ // Not actually constant, as they can be changed between JIT passes:
+ var TEX_UNIT_UNIFORM_PREFIX = "uTexUnit";
+ var TEX_COORD_VARYING_PREFIX = "vTexCoord";
+ var PRIM_COLOR_VARYING = "vPrimColor";
+ var TEX_MATRIX_UNIFORM_PREFIX = "uTexMatrix";
+
+ // Static vars:
+ var s_texUnits = null; //[];
+ var s_activeTexture = 0;
+
+ var s_requiredTexUnitsForPass = [];
+
+ // Static funcs:
+ function abort(info) {
+ assert(false, "[TexEnvJIT] ABORT: " + info);
+ }
+
+ function abort_noSupport(info) {
+ abort("No support: " + info);
+ }
+
+ function abort_sanity(info) {
+ abort("Sanity failure: " + info);
+ }
+
+ function genTexUnitSampleExpr(texUnitID) {
+ var texUnit = s_texUnits[texUnitID];
+ var texType = texUnit.getTexType();
+
+ var func = null;
+ switch (texType) {
+ case GL_TEXTURE_1D:
+ func = "texture2D";
+ break;
+ case GL_TEXTURE_2D:
+ func = "texture2D";
+ break;
+ case GL_TEXTURE_3D:
+ return abort_noSupport("No support for 3D textures.");
+ case GL_TEXTURE_CUBE_MAP:
+ func = "textureCube";
+ break;
+ default:
+ return abort_sanity("Unknown texType: 0x" + texType.toString(16));
+ }
+
+ var texCoordExpr = TEX_COORD_VARYING_PREFIX + texUnitID;
+ if (TEX_MATRIX_UNIFORM_PREFIX != null) {
+ texCoordExpr = "(" + TEX_MATRIX_UNIFORM_PREFIX + texUnitID + " * " + texCoordExpr + ")";
+ }
+ return func + "(" + TEX_UNIT_UNIFORM_PREFIX + texUnitID + ", " + texCoordExpr + ".xy)";
+ }
+
+ function getTypeFromCombineOp(op) {
+ switch (op) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ return "vec3";
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return "float";
+ }
+
+ return Abort_NoSupport("Unsupported combiner op: 0x" + op.toString(16));
+ }
+
+ function getCurTexUnit() {
+ return s_texUnits[s_activeTexture];
+ }
+
+ function genCombinerSourceExpr(texUnitID, constantExpr, previousVar,
+ src, op)
+ {
+ var srcExpr = null;
+ switch (src) {
+ case GL_TEXTURE:
+ srcExpr = genTexUnitSampleExpr(texUnitID);
+ break;
+ case GL_CONSTANT:
+ srcExpr = constantExpr;
+ break;
+ case GL_PRIMARY_COLOR:
+ srcExpr = PRIM_COLOR_VARYING;
+ break;
+ case GL_PREVIOUS:
+ srcExpr = previousVar;
+ break;
+ default:
+ return abort_noSupport("Unsupported combiner src: 0x" + src.toString(16));
+ }
+
+ var expr = null;
+ switch (op) {
+ case GL_SRC_COLOR:
+ expr = srcExpr + ".rgb";
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ expr = "(vec3(1.0) - " + srcExpr + ".rgb)";
+ break;
+ case GL_SRC_ALPHA:
+ expr = srcExpr + ".a";
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ expr = "(1.0 - " + srcExpr + ".a)";
+ break;
+ default:
+ return abort_noSupport("Unsupported combiner op: 0x" + op.toString(16));
+ }
+
+ return expr;
+ }
+
+ function valToFloatLiteral(val) {
+ if (val == Math.round(val)) return val + '.0';
+ return val;
+ }
+
+
+ // Classes:
+ function CTexEnv() {
+ this.mode = GL_MODULATE;
+ this.colorCombiner = GL_MODULATE;
+ this.alphaCombiner = GL_MODULATE;
+ this.colorScale = 1;
+ this.alphaScale = 1;
+ this.envColor = [0, 0, 0, 0];
+
+ this.colorSrc = [
+ GL_TEXTURE,
+ GL_PREVIOUS,
+ GL_CONSTANT
+ ];
+ this.alphaSrc = [
+ GL_TEXTURE,
+ GL_PREVIOUS,
+ GL_CONSTANT
+ ];
+ this.colorOp = [
+ GL_SRC_COLOR,
+ GL_SRC_COLOR,
+ GL_SRC_ALPHA
+ ];
+ this.alphaOp = [
+ GL_SRC_ALPHA,
+ GL_SRC_ALPHA,
+ GL_SRC_ALPHA
+ ];
+
+ this.traverseState = function(keyView) {
+ keyView.next(this.mode);
+ keyView.next(this.colorCombiner);
+ keyView.next(this.alphaCombiner);
+ keyView.next(this.colorCombiner);
+ keyView.next(this.alphaScale);
+ keyView.next(this.envColor[0]);
+ keyView.next(this.envColor[1]);
+ keyView.next(this.envColor[2]);
+ keyView.next(this.envColor[3]);
+
+ keyView.next(this.colorSrc[0]);
+ keyView.next(this.colorSrc[1]);
+ keyView.next(this.colorSrc[2]);
+
+ keyView.next(this.alphaSrc[0]);
+ keyView.next(this.alphaSrc[1]);
+ keyView.next(this.alphaSrc[2]);
+
+ keyView.next(this.colorOp[0]);
+ keyView.next(this.colorOp[1]);
+ keyView.next(this.colorOp[2]);
+
+ keyView.next(this.alphaOp[0]);
+ keyView.next(this.alphaOp[1]);
+ keyView.next(this.alphaOp[2]);
+ };
+ }
+
+ function CTexUnit() {
+ this.env = new CTexEnv();
+ this.enabled_tex1D = false;
+ this.enabled_tex2D = false;
+ this.enabled_tex3D = false;
+ this.enabled_texCube = false;
+
+ this.traverseState = function(keyView) {
+ var texUnitType = this.getTexType();
+ keyView.next(texUnitType);
+ if (!texUnitType) return;
+ this.env.traverseState(keyView);
+ };
+ };
+
+ // Class impls:
+ CTexUnit.prototype.enabled = function() {
+ return this.getTexType() != 0;
+ }
+
+ CTexUnit.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) {
+ if (!this.enabled()) {
+ return ["vec4 " + passOutputVar + " = " + passInputVar + ";"];
+ }
+
+ return this.env.genPassLines(passOutputVar, passInputVar, texUnitID);
+ }
+
+ CTexUnit.prototype.getTexType = function() {
+ if (this.enabled_texCube) {
+ return GL_TEXTURE_CUBE_MAP;
+ } else if (this.enabled_tex3D) {
+ return GL_TEXTURE_3D;
+ } else if (this.enabled_tex2D) {
+ return GL_TEXTURE_2D;
+ } else if (this.enabled_tex1D) {
+ return GL_TEXTURE_1D;
+ }
+ return 0;
+ }
+
+ CTexEnv.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) {
+ switch (this.mode) {
+ case GL_REPLACE: {
+ /* RGB:
+ * Cv = Cs
+ * Av = Ap // Note how this is different, and that we'll
+ * need to track the bound texture internalFormat
+ * to get this right.
+ *
+ * RGBA:
+ * Cv = Cs
+ * Av = As
+ */
+ return [
+ "vec4 " + passOutputVar + " = " + genTexUnitSampleExpr(texUnitID) + ";",
+ ];
+ }
+ case GL_ADD: {
+ /* RGBA:
+ * Cv = Cp + Cs
+ * Av = ApAs
+ */
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_";
+ var texVar = prefix + "tex";
+ var colorVar = prefix + "color";
+ var alphaVar = prefix + "alpha";
+
+ return [
+ "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";",
+ "vec3 " + colorVar + " = " + passInputVar + ".rgb + " + texVar + ".rgb;",
+ "float " + alphaVar + " = " + passInputVar + ".a * " + texVar + ".a;",
+ "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");",
+ ];
+ }
+ case GL_MODULATE: {
+ /* RGBA:
+ * Cv = CpCs
+ * Av = ApAs
+ */
+ var line = [
+ "vec4 " + passOutputVar,
+ " = ",
+ passInputVar,
+ " * ",
+ genTexUnitSampleExpr(texUnitID),
+ ";",
+ ];
+ return [line.join("")];
+ }
+ case GL_DECAL: {
+ /* RGBA:
+ * Cv = Cp(1 - As) + CsAs
+ * Av = Ap
+ */
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_";
+ var texVar = prefix + "tex";
+ var colorVar = prefix + "color";
+ var alphaVar = prefix + "alpha";
+
+ return [
+ "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";",
+ [
+ "vec3 " + colorVar + " = ",
+ passInputVar + ".rgb * (1.0 - " + texVar + ".a)",
+ " + ",
+ texVar + ".rgb * " + texVar + ".a",
+ ";"
+ ].join(""),
+ "float " + alphaVar + " = " + passInputVar + ".a;",
+ "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");",
+ ];
+ }
+ case GL_BLEND: {
+ /* RGBA:
+ * Cv = Cp(1 - Cs) + CcCs
+ * Av = As
+ */
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_";
+ var texVar = prefix + "tex";
+ var colorVar = prefix + "color";
+ var alphaVar = prefix + "alpha";
+
+ return [
+ "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";",
+ [
+ "vec3 " + colorVar + " = ",
+ passInputVar + ".rgb * (1.0 - " + texVar + ".rgb)",
+ " + ",
+ PRIM_COLOR_VARYING + ".rgb * " + texVar + ".rgb",
+ ";"
+ ].join(""),
+ "float " + alphaVar + " = " + texVar + ".a;",
+ "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");",
+ ];
+ }
+ case GL_COMBINE: {
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_";
+ var colorVar = prefix + "color";
+ var alphaVar = prefix + "alpha";
+ var colorLines = this.genCombinerLines(true, colorVar,
+ passInputVar, texUnitID,
+ this.colorCombiner, this.colorSrc, this.colorOp);
+ var alphaLines = this.genCombinerLines(false, alphaVar,
+ passInputVar, texUnitID,
+ this.alphaCombiner, this.alphaSrc, this.alphaOp);
+ var line = [
+ "vec4 " + passOutputVar,
+ " = ",
+ "vec4(",
+ colorVar + " * " + valToFloatLiteral(this.colorScale),
+ ", ",
+ alphaVar + " * " + valToFloatLiteral(this.alphaScale),
+ ")",
+ ";",
+ ].join("");
+ return [].concat(colorLines, alphaLines, [line]);
+ }
+ }
+
+ return Abort_NoSupport("Unsupported TexEnv mode: 0x" + this.mode.toString(16));
+ }
+
+ CTexEnv.prototype.genCombinerLines = function(isColor, outputVar,
+ passInputVar, texUnitID,
+ combiner, srcArr, opArr)
+ {
+ var argsNeeded = null;
+ switch (combiner) {
+ case GL_REPLACE:
+ argsNeeded = 1;
+ break;
+
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_SUBTRACT:
+ argsNeeded = 2;
+ break;
+
+ case GL_INTERPOLATE:
+ argsNeeded = 3;
+ break;
+
+ default:
+ return abort_noSupport("Unsupported combiner: 0x" + combiner.toString(16));
+ }
+
+ var constantExpr = [
+ "vec4(",
+ valToFloatLiteral(this.envColor[0]),
+ ", ",
+ valToFloatLiteral(this.envColor[1]),
+ ", ",
+ valToFloatLiteral(this.envColor[2]),
+ ", ",
+ valToFloatLiteral(this.envColor[3]),
+ ")",
+ ].join("");
+ var src0Expr = (argsNeeded >= 1) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[0], opArr[0])
+ : null;
+ var src1Expr = (argsNeeded >= 2) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[1], opArr[1])
+ : null;
+ var src2Expr = (argsNeeded >= 3) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[2], opArr[2])
+ : null;
+
+ var outputType = isColor ? "vec3" : "float";
+ var lines = null;
+ switch (combiner) {
+ case GL_REPLACE: {
+ var line = [
+ outputType + " " + outputVar,
+ " = ",
+ src0Expr,
+ ";",
+ ];
+ lines = [line.join("")];
+ break;
+ }
+ case GL_MODULATE: {
+ var line = [
+ outputType + " " + outputVar + " = ",
+ src0Expr + " * " + src1Expr,
+ ";",
+ ];
+ lines = [line.join("")];
+ break;
+ }
+ case GL_ADD: {
+ var line = [
+ outputType + " " + outputVar + " = ",
+ src0Expr + " + " + src1Expr,
+ ";",
+ ];
+ lines = [line.join("")];
+ break;
+ }
+ case GL_SUBTRACT: {
+ var line = [
+ outputType + " " + outputVar + " = ",
+ src0Expr + " - " + src1Expr,
+ ";",
+ ];
+ lines = [line.join("")];
+ break;
+ }
+ case GL_INTERPOLATE: {
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_";
+ var arg2Var = prefix + "colorSrc2";
+ var arg2Line = getTypeFromCombineOp(this.colorOp[2]) + " " + arg2Var + " = " + src2Expr + ";";
+
+ var line = [
+ outputType + " " + outputVar,
+ " = ",
+ src0Expr + " * " + arg2Var,
+ " + ",
+ src1Expr + " * (1.0 - " + arg2Var + ")",
+ ";",
+ ];
+ lines = [
+ arg2Line,
+ line.join(""),
+ ];
+ break;
+ }
+
+ default:
+ return abort_sanity("Unmatched TexEnv.colorCombiner?");
+ }
+
+ return lines;
+ }
+
+ return {
+ // Exports:
+ init: function(gl, specifiedMaxTextureImageUnits) {
+ var maxTexUnits = 0;
+ if (specifiedMaxTextureImageUnits) {
+ maxTexUnits = specifiedMaxTextureImageUnits;
+ } else if (gl) {
+ maxTexUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
+ }
+
+ assert(maxTexUnits > 0);
+
+ s_texUnits = [];
+ for (var i = 0; i < maxTexUnits; i++) {
+ s_texUnits.push(new CTexUnit());
+ }
+ },
+
+ setGLSLVars: function(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix) {
+ TEX_UNIT_UNIFORM_PREFIX = uTexUnitPrefix;
+ TEX_COORD_VARYING_PREFIX = vTexCoordPrefix;
+ PRIM_COLOR_VARYING = vPrimColor;
+ TEX_MATRIX_UNIFORM_PREFIX = uTexMatrixPrefix;
+ },
+
+ genAllPassLines: function(resultDest, indentSize) {
+ indentSize = indentSize || 0;
+
+ s_requiredTexUnitsForPass.length = 0; // Clear the list.
+ var lines = [];
+ var lastPassVar = PRIM_COLOR_VARYING;
+ for (var i = 0; i < s_texUnits.length; i++) {
+ if (!s_texUnits[i].enabled()) continue;
+
+ s_requiredTexUnitsForPass.push(i);
+
+ var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + i + "_";
+ var passOutputVar = prefix + "result";
+
+ var newLines = s_texUnits[i].genPassLines(passOutputVar, lastPassVar, i);
+ lines = lines.concat(newLines, [""]);
+
+ lastPassVar = passOutputVar;
+ }
+ lines.push(resultDest + " = " + lastPassVar + ";");
+
+ var indent = "";
+ for (var i = 0; i < indentSize; i++) indent += " ";
+
+ var output = indent + lines.join("\n" + indent);
+
+ return output;
+ },
+
+ getUsedTexUnitList: function() {
+ return s_requiredTexUnitsForPass;
+ },
+
+ traverseState: function(keyView) {
+ for (var i = 0; i < s_texUnits.length; i++) {
+ var texUnit = s_texUnits[i];
+ var enabled = texUnit.enabled();
+ keyView.next(enabled);
+ if (enabled) {
+ texUnit.traverseState(keyView);
+ }
+ }
+ },
+
+ getTexUnitType: function(texUnitID) {
+ assert(texUnitID >= 0 &&
+ texUnitID < s_texUnits.length);
+
+ return s_texUnits[texUnitID].getTexType();
+ },
+
+ // Hooks:
+ hook_activeTexture: function(texture) {
+ s_activeTexture = texture - GL_TEXTURE0;
+ },
+
+ hook_enable: function(cap) {
+ var cur = getCurTexUnit();
+ switch (cap) {
+ case GL_TEXTURE_1D:
+ cur.enabled_tex1D = true;
+ break;
+ case GL_TEXTURE_2D:
+ cur.enabled_tex2D = true;
+ break;
+ case GL_TEXTURE_3D:
+ cur.enabled_tex3D = true;
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ cur.enabled_texCube = true;
+ break;
+ }
+ },
+
+ hook_disable: function(cap) {
+ var cur = getCurTexUnit();
+ switch (cap) {
+ case GL_TEXTURE_1D:
+ cur.enabled_tex1D = false;
+ break;
+ case GL_TEXTURE_2D:
+ cur.enabled_tex2D = false;
+ break;
+ case GL_TEXTURE_3D:
+ cur.enabled_tex3D = false;
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ cur.enabled_texCube = false;
+ break;
+ }
+ },
+
+ hook_texEnvf: function(target, pname, param) {
+ if (target != GL_TEXTURE_ENV)
+ return;
+
+ var env = getCurTexUnit().env;
+ switch (pname) {
+ case GL_RGB_SCALE:
+ env.colorScale = param;
+ break;
+ case GL_ALPHA_SCALE:
+ env.alphaScale = param;
+ break;
+
+ default:
+ Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvf`.');
+ }
+ },
+
+ hook_texEnvi: function(target, pname, param) {
+ if (target != GL_TEXTURE_ENV)
+ return;
+
+ var env = getCurTexUnit().env;
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ env.mode = param;
+ break;
+
+ case GL_COMBINE_RGB:
+ env.colorCombiner = param;
+ break;
+ case GL_COMBINE_ALPHA:
+ env.alphaCombiner = param;
+ break;
+
+ case GL_SRC0_RGB:
+ env.colorSrc[0] = param;
+ break;
+ case GL_SRC1_RGB:
+ env.colorSrc[1] = param;
+ break;
+ case GL_SRC2_RGB:
+ env.colorSrc[2] = param;
+ break;
+
+ case GL_SRC0_ALPHA:
+ env.alphaSrc[0] = param;
+ break;
+ case GL_SRC1_ALPHA:
+ env.alphaSrc[1] = param;
+ break;
+ case GL_SRC2_ALPHA:
+ env.alphaSrc[2] = param;
+ break;
+
+ case GL_OPERAND0_RGB:
+ env.colorOp[0] = param;
+ break;
+ case GL_OPERAND1_RGB:
+ env.colorOp[1] = param;
+ break;
+ case GL_OPERAND2_RGB:
+ env.colorOp[2] = param;
+ break;
+
+ case GL_OPERAND0_ALPHA:
+ env.alphaOp[0] = param;
+ break;
+ case GL_OPERAND1_ALPHA:
+ env.alphaOp[1] = param;
+ break;
+ case GL_OPERAND2_ALPHA:
+ env.alphaOp[2] = param;
+ break;
+
+ case GL_RGB_SCALE:
+ env.colorScale = param;
+ break;
+ case GL_ALPHA_SCALE:
+ env.alphaScale = param;
+ break;
+
+ default:
+ Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvi`.');
+ }
+ },
+
+ hook_texEnvfv: function(target, pname, params) {
+ if (target != GL_TEXTURE_ENV) return;
+
+ var env = getCurTexUnit().env;
+ switch (pname) {
+ case GL_TEXTURE_ENV_COLOR: {
+ for (var i = 0; i < 4; i++) {
+ var param = {{{ makeGetValue('params', 'i*4', 'float') }}};
+ env.envColor[i] = param;
+ }
+ break
+ }
+ default:
+ Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvfv`.');
+ }
+ },
+ };
+ },
// Vertex and index data
vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer). Default view is F32
@@ -1974,7 +2873,6 @@ var LibraryGL = {
mode: -1,
rendererCache: null,
- rendererCacheItemTemplate: [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], // 16 nulls
rendererComponents: [], // small cache for calls inside glBegin/end. counts how many times the element was seen
rendererComponentPointer: 0, // next place to start a glBegin/end component
lastRenderer: null, // used to avoid cleaning up and re-preparing the same renderer
@@ -1988,6 +2886,7 @@ var LibraryGL = {
currentMatrix: 'm', // default is modelview
tempMatrix: null,
matricesModified: false,
+ useTextureMatrix: false,
// Clientside attributes
VERTEX: 0,
@@ -2000,8 +2899,8 @@ var LibraryGL = {
TEXTURE4: 7,
TEXTURE5: 8,
TEXTURE6: 9,
- NUM_ATTRIBUTES: 10,
- NUM_TEXTURES: 7,
+ NUM_ATTRIBUTES: 10, // Overwritten in init().
+ MAX_TEXTURES: 7, // Overwritten in init().
totalEnabledClientAttributes: 0,
enabledClientAttributes: [0, 0],
@@ -2010,6 +2909,8 @@ var LibraryGL = {
modifiedClientAttributes: false,
clientActiveTexture: 0,
clientColor: null,
+ usedTexUnitList: [],
+ fixedFunctionProgram: null,
setClientAttribute: function(name, size, type, stride, pointer) {
var attrib = this.clientAttributes[name];
@@ -2042,7 +2943,9 @@ var LibraryGL = {
if (!this.rendererComponents[name]) {
this.rendererComponents[name] = 1;
#if ASSERTIONS
- assert(!this.enabledClientAttributes[name]); // cannot get mixed up with this, for example we will disable this later
+ if (this.enabledClientAttributes[name]) {
+ console.log("Warning: glTexCoord used after EnableClientState for TEXTURE_COORD_ARRAY for TEXTURE0. Disabling TEXTURE_COORD_ARRAY...");
+ }
#endif
this.enabledClientAttributes[name] = true;
this.setClientAttribute(name, size, type, 0, this.rendererComponentPointer);
@@ -2062,19 +2965,18 @@ var LibraryGL = {
// return a renderer object given the liveClientAttributes
// we maintain a cache of renderers, optimized to not generate garbage
var attributes = GL.immediate.liveClientAttributes;
- var cacheItem = GL.immediate.rendererCache;
+ var cacheMap = GL.immediate.rendererCache;
var temp;
+ var keyView = cacheMap.getStaticKeyView().reset();
+
+ // By attrib state:
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
- temp = cacheItem[attribute.name];
- cacheItem = temp ? temp : (cacheItem[attribute.name] = GL.immediate.rendererCacheItemTemplate.slice());
- temp = cacheItem[attribute.size];
- cacheItem = temp ? temp : (cacheItem[attribute.size] = GL.immediate.rendererCacheItemTemplate.slice());
- var typeIndex = attribute.type - GL.byteSizeByTypeRoot; // ensure it starts at 0 to keep the cache items dense
- temp = cacheItem[typeIndex];
- cacheItem = temp ? temp : (cacheItem[typeIndex] = GL.immediate.rendererCacheItemTemplate.slice());
- }
- var fogParam;
+ keyView.next(attribute.name).next(attribute.size).next(attribute.type);
+ }
+
+ // By fog state:
+ var fogParam = 0;
if (GLEmulation.fogEnabled) {
switch (GLEmulation.fogMode) {
case 0x0801: // GL_EXP2
@@ -2087,33 +2989,40 @@ var LibraryGL = {
fogParam = 3;
break;
}
- } else {
- fogParam = 0;
}
- temp = cacheItem[fogParam];
- cacheItem = temp ? temp : (cacheItem[fogParam] = GL.immediate.rendererCacheItemTemplate.slice());
- if (GL.currProgram) { // Note the order here; this one is last, and optional. Note that we cannot ensure it is dense, sadly
- temp = cacheItem[GL.currProgram];
- cacheItem = temp ? temp : (cacheItem[GL.currProgram] = GL.immediate.rendererCacheItemTemplate.slice());
+ keyView.next(fogParam);
+
+ // By cur program:
+ keyView.next(GL.currProgram);
+ if (!GL.currProgram) {
+ GL.immediate.TexEnvJIT.traverseState(keyView);
}
- if (!cacheItem.renderer) {
+
+ // If we don't already have it, create it.
+ if (!keyView.get()) {
#if GL_DEBUG
Module.printErr('generating renderer for ' + JSON.stringify(attributes));
#endif
- cacheItem.renderer = this.createRenderer();
+ keyView.set(this.createRenderer());
}
- return cacheItem.renderer;
+ return keyView.get();
},
createRenderer: function(renderer) {
var useCurrProgram = !!GL.currProgram;
var hasTextures = false, textureSizes = [], textureTypes = [];
- for (var i = 0; i < GL.immediate.NUM_TEXTURES; i++) {
- if (GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) {
- textureSizes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].size;
- textureTypes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].type;
- hasTextures = true;
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ var texAttribName = GL.immediate.TEXTURE0 + i;
+ if (!GL.immediate.enabledClientAttributes[texAttribName])
+ continue;
+
+ if (!useCurrProgram) {
+ assert(GL.immediate.TexEnvJIT.getTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline.");
}
+
+ textureSizes[i] = GL.immediate.clientAttributes[texAttribName].size;
+ textureTypes[i] = GL.immediate.clientAttributes[texAttribName].type;
+ hasTextures = true;
}
var positionSize = GL.immediate.clientAttributes[GL.immediate.VERTEX].size;
var positionType = GL.immediate.clientAttributes[GL.immediate.VERTEX].type;
@@ -2129,6 +3038,13 @@ var LibraryGL = {
}
var ret = {
init: function() {
+ // For fixed-function shader generation.
+ var uTexUnitPrefix = 'u_texUnit';
+ var aTexCoordPrefix = 'a_texCoord';
+ var vTexCoordPrefix = 'v_texCoord';
+ var vPrimColor = 'v_color';
+ var uTexMatrixPrefix = GL.immediate.useTextureMatrix ? 'u_textureMatrix' : null;
+
if (useCurrProgram) {
if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) {
this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][0]];
@@ -2138,13 +3054,12 @@ var LibraryGL = {
this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][0]];
}
this.program = GL.programs[GL.currProgram];
+ this.usedTexUnitList = [];
} else {
// IMPORTANT NOTE: If you parameterize the shader source based on any runtime values
// in order to create the least expensive shader possible based on the features being
// used, you should also update the code in the beginning of getRenderer to make sure
// that you cache the renderer based on the said parameters.
- this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER);
- var zero = positionSize == 2 ? '0, ' : '';
if (GLEmulation.fogEnabled) {
switch (GLEmulation.fogMode) {
case 0x0801: // GL_EXP2
@@ -2161,47 +3076,95 @@ var LibraryGL = {
break;
}
}
- Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n' +
- 'attribute vec2 a_texCoord0; \n' +
- (hasTextures ? 'varying vec2 v_texCoord; \n' : '') +
- 'varying vec4 v_color; \n' +
- (colorSize ? 'attribute vec4 a_color; \n': 'uniform vec4 u_color; \n') +
- (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord; \n' : '') +
- 'uniform mat4 u_modelView; \n' +
- 'uniform mat4 u_projection; \n' +
- 'void main() \n' +
- '{ \n' +
- ' vec4 ecPosition = (u_modelView * vec4(a_position, ' + zero + '1.0)); \n' + // eye-coordinate position
- ' gl_Position = u_projection * ecPosition; \n' +
- (hasTextures ? 'v_texCoord = a_texCoord0; \n' : '') +
- (colorSize ? 'v_color = a_color; \n' : 'v_color = u_color; \n') +
- (GLEmulation.fogEnabled ? 'v_fogFragCoord = abs(ecPosition.z);\n' : '') +
- '} \n');
+
+ GL.immediate.TexEnvJIT.setGLSLVars(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix);
+ var fsTexEnvPass = GL.immediate.TexEnvJIT.genAllPassLines('gl_FragColor', 2);
+
+ var texUnitAttribList = '';
+ var texUnitVaryingList = '';
+ var texUnitUniformList = '';
+ var vsTexCoordInits = '';
+ this.usedTexUnitList = GL.immediate.TexEnvJIT.getUsedTexUnitList();
+ for (var i = 0; i < this.usedTexUnitList.length; i++) {
+ var texUnit = this.usedTexUnitList[i];
+ texUnitAttribList += 'attribute vec4 ' + aTexCoordPrefix + texUnit + ';\n';
+ texUnitVaryingList += 'varying vec4 ' + vTexCoordPrefix + texUnit + ';\n';
+ texUnitUniformList += 'uniform sampler2D ' + uTexUnitPrefix + texUnit + ';\n';
+ vsTexCoordInits += ' ' + vTexCoordPrefix + texUnit + ' = ' + aTexCoordPrefix + texUnit + ';\n';
+
+ if (GL.immediate.useTextureMatrix) {
+ texUnitUniformList += 'uniform mat4 ' + uTexMatrixPrefix + texUnit + ';\n';
+ }
+ }
+
+ var vsFogVaryingInit = null;
+ if (GLEmulation.fogEnabled) {
+ vsFogVaryingInit = ' v_fogFragCoord = abs(ecPosition.z);\n';
+ }
+
+ var vsSource = [
+ 'attribute vec4 a_position;',
+ 'attribute vec4 a_color;',
+ 'varying vec4 v_color;',
+ texUnitAttribList,
+ texUnitVaryingList,
+ (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord;' : null),
+ 'uniform mat4 u_modelView;',
+ 'uniform mat4 u_projection;',
+ 'void main()',
+ '{',
+ ' vec4 ecPosition = u_modelView * a_position;', // eye-coordinate position
+ ' gl_Position = u_projection * ecPosition;',
+ ' v_color = a_color;',
+ vsTexCoordInits,
+ vsFogVaryingInit,
+ '}',
+ ''
+ ].join('\n').replace(/\n\n+/g, '\n');
+
+ this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER);
+ Module.ctx.shaderSource(this.vertexShader, vsSource);
Module.ctx.compileShader(this.vertexShader);
+ var fogHeaderIfNeeded = null;
+ if (GLEmulation.fogEnabled) {
+ fogHeaderIfNeeded = [
+ '',
+ 'varying float v_fogFragCoord; ',
+ 'uniform vec4 u_fogColor; ',
+ 'uniform float u_fogEnd; ',
+ 'uniform float u_fogScale; ',
+ 'uniform float u_fogDensity; ',
+ 'float ffog(in float ecDistance) { ',
+ fogFormula,
+ ' fog = clamp(fog, 0.0, 1.0); ',
+ ' return fog; ',
+ '}',
+ '',
+ ].join("\n");
+ }
+
+ var fogPass = null;
+ if (GLEmulation.fogEnabled) {
+ fogPass = 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a);\n';
+ }
+
+ var fsSource = [
+ 'precision mediump float;',
+ texUnitVaryingList,
+ texUnitUniformList,
+ 'varying vec4 v_color;',
+ fogHeaderIfNeeded,
+ 'void main()',
+ '{',
+ fsTexEnvPass,
+ fogPass,
+ '}',
+ ''
+ ].join("\n").replace(/\n\n+/g, '\n');
+
this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER);
- Module.ctx.shaderSource(this.fragmentShader, 'precision mediump float; \n' +
- 'varying vec2 v_texCoord; \n' +
- 'uniform sampler2D u_texture; \n' +
- 'varying vec4 v_color; \n' +
- (GLEmulation.fogEnabled ? (
- 'varying float v_fogFragCoord; \n' +
- 'uniform vec4 u_fogColor; \n' +
- 'uniform float u_fogEnd; \n' +
- 'uniform float u_fogScale; \n' +
- 'uniform float u_fogDensity; \n' +
- 'float ffog(in float ecDistance) { \n' +
- fogFormula +
- ' fog = clamp(fog, 0.0, 1.0); \n' +
- ' return fog; \n' +
- '} \n'
- ) : '') +
- 'void main() \n' +
- '{ \n' +
- (hasTextures ? 'gl_FragColor = v_color * texture2D( u_texture, v_texCoord );\n' :
- 'gl_FragColor = v_color;\n') +
- (GLEmulation.fogEnabled ? 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a); \n' : '') +
- '} \n');
+ Module.ctx.shaderSource(this.fragmentShader, fsSource);
Module.ctx.compileShader(this.fragmentShader);
this.program = Module.ctx.createProgram();
@@ -2212,12 +3175,36 @@ var LibraryGL = {
}
this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position');
+
this.texCoordLocations = [];
- for (var i = 0; i < textureSizes.length; i++) {
- if (textureSizes[i]) {
+
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ if (!GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) {
+ this.texCoordLocations[i] = -1;
+ continue;
+ }
+
+ if (useCurrProgram) {
this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, 'a_texCoord' + i);
+ } else {
+ this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, aTexCoordPrefix + i);
+ }
+ }
+
+ if (!useCurrProgram) {
+ // Temporarily switch to the program so we can set our sampler uniforms early.
+ var prevBoundProg = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM);
+ Module.ctx.useProgram(this.program);
+ {
+ for (var i = 0; i < this.usedTexUnitList.length; i++) {
+ var texUnitID = this.usedTexUnitList[i];
+ var texSamplerLoc = Module.ctx.getUniformLocation(this.program, uTexUnitPrefix + texUnitID);
+ Module.ctx.uniform1i(texSamplerLoc, texUnitID);
+ }
}
+ Module.ctx.useProgram(prevBoundProg);
}
+
this.textureMatrixLocations = [];
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i);
@@ -2225,16 +3212,12 @@ var LibraryGL = {
this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color');
this.normalLocation = Module.ctx.getAttribLocation(this.program, 'a_normal');
- this.textureLocation = Module.ctx.getUniformLocation(this.program, 'u_texture'); // only for immediate mode with no shaders, so only one is enough
this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView');
this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection');
- this.hasColorAttribLocation = Module.ctx.getUniformLocation(this.program, 'u_hasColorAttrib');
- this.colorUniformLocation = Module.ctx.getUniformLocation(this.program, 'u_color');
this.hasTextures = hasTextures;
- this.hasColorAttrib = colorSize > 0 && this.colorLocation >= 0;
- this.hasColorUniform = !!this.colorUniformLocation;
this.hasNormal = normalSize > 0 && this.normalLocation >= 0;
+ this.hasColor = (this.colorLocation === 0) || this.colorLocation > 0;
this.floatType = Module.ctx.FLOAT; // minor optimization
@@ -2294,6 +3277,7 @@ var LibraryGL = {
if (!GL.currProgram) {
Module.ctx.useProgram(this.program);
+ GL.immediate.fixedFunctionProgram = this.program;
}
if (this.modelViewLocation) Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']);
@@ -2305,11 +3289,21 @@ var LibraryGL = {
GL.immediate.stride, clientAttributes[GL.immediate.VERTEX].offset);
Module.ctx.enableVertexAttribArray(this.positionLocation);
if (this.hasTextures) {
- for (var i = 0; i < textureSizes.length; i++) {
- if (textureSizes[i] && this.texCoordLocations[i] >= 0) {
- Module.ctx.vertexAttribPointer(this.texCoordLocations[i], textureSizes[i], textureTypes[i], false,
- GL.immediate.stride, clientAttributes[GL.immediate.TEXTURE0 + i].offset);
- Module.ctx.enableVertexAttribArray(this.texCoordLocations[i]);
+ //for (var i = 0; i < this.usedTexUnitList.length; i++) {
+ // var texUnitID = this.usedTexUnitList[i];
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ var texUnitID = i;
+ var attribLoc = this.texCoordLocations[texUnitID];
+ if (attribLoc === undefined || attribLoc < 0) continue;
+
+ if (texUnitID < textureSizes.length && textureSizes[texUnitID]) {
+ Module.ctx.vertexAttribPointer(attribLoc, textureSizes[texUnitID], textureTypes[texUnitID], false,
+ GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + texUnitID].offset);
+ Module.ctx.enableVertexAttribArray(attribLoc);
+ } else {
+ // These two might be dangerous, but let's try them.
+ Module.ctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1);
+ Module.ctx.disableVertexAttribArray(attribLoc);
}
}
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
@@ -2318,26 +3312,19 @@ var LibraryGL = {
}
}
}
- if (this.hasColorAttrib) {
+ if (colorSize) {
Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true,
GL.immediate.stride, clientAttributes[GL.immediate.COLOR].offset);
Module.ctx.enableVertexAttribArray(this.colorLocation);
- Module.ctx.uniform1i(this.hasColorAttribLocation, 1);
- } else if (this.hasColorUniform) {
- Module.ctx.uniform1i(this.hasColorAttribLocation, 0);
- Module.ctx.uniform4fv(this.colorUniformLocation, GL.immediate.clientColor);
+ } else if (this.hasColor) {
+ Module.ctx.disableVertexAttribArray(this.colorLocation);
+ Module.ctx.vertexAttrib4fv(this.colorLocation, GL.immediate.clientColor);
}
if (this.hasNormal) {
Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true,
GL.immediate.stride, clientAttributes[GL.immediate.NORMAL].offset);
Module.ctx.enableVertexAttribArray(this.normalLocation);
}
- if (!useCurrProgram) { // otherwise, the user program will set the sampler2D binding and uniform itself
- var texture = Module.ctx.getParameter(Module.ctx.TEXTURE_BINDING_2D);
- Module.ctx.activeTexture(Module.ctx.TEXTURE0);
- Module.ctx.bindTexture(Module.ctx.TEXTURE_2D, texture);
- Module.ctx.uniform1i(this.textureLocation, 0);
- }
if (this.hasFog) {
if (this.fogColorLocation) Module.ctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor);
if (this.fogEndLocation) Module.ctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd);
@@ -2355,7 +3342,7 @@ var LibraryGL = {
}
}
}
- if (this.hasColorAttrib) {
+ if (this.hasColor) {
Module.ctx.disableVertexAttribArray(this.colorLocation);
}
if (this.hasNormal) {
@@ -2408,6 +3395,9 @@ var LibraryGL = {
if (!GL.currElementArrayBuffer) {
assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now
}
+#if ASSERTIONS
+ console.log("DrawElements doesn't actually prepareClientAttributes properly.");
+#endif
GL.immediate.prepareClientAttributes(count, false);
GL.immediate.mode = mode;
if (!GL.currArrayBuffer) {
@@ -2418,6 +3408,76 @@ var LibraryGL = {
GL.immediate.flush(count, 0, indices);
GL.immediate.mode = -1;
};
+
+ // TexEnv stuff needs to be prepared early, so do it here.
+ // init() is too late for -O2, since it freezes the GL functions
+ // by that point.
+ GL.immediate.MapTreeLib = GL.immediate.spawnMapTreeLib();
+ GL.immediate.spawnMapTreeLib = null;
+
+ GL.immediate.TexEnvJIT = GL.immediate.spawnTexEnvJIT();
+ GL.immediate.spawnTexEnvJIT = null;
+
+ GL.immediate.setupHooks();
+ },
+
+ setupHooks: function() {
+ if (!GLEmulation.hasRunInit) {
+ GLEmulation.init();
+ }
+
+ var glActiveTexture = _glActiveTexture;
+ _glActiveTexture = function(texture) {
+ GL.immediate.TexEnvJIT.hook_activeTexture(texture);
+ glActiveTexture(texture);
+ };
+
+ var glEnable = _glEnable;
+ _glEnable = function(cap) {
+ GL.immediate.TexEnvJIT.hook_enable(cap);
+ glEnable(cap);
+ };
+ var glDisable = _glDisable;
+ _glDisable = function(cap) {
+ GL.immediate.TexEnvJIT.hook_disable(cap);
+ glDisable(cap);
+ };
+
+ var glTexEnvf = (typeof(_glTexEnvf) != 'undefined') ? _glTexEnvf : function(){};
+ _glTexEnvf = function(target, pname, param) {
+ GL.immediate.TexEnvJIT.hook_texEnvf(target, pname, param);
+ // Don't call old func, since we are the implementor.
+ //glTexEnvf(target, pname, param);
+ };
+ var glTexEnvi = (typeof(_glTexEnvi) != 'undefined') ? _glTexEnvi : function(){};
+ _glTexEnvi = function(target, pname, param) {
+ GL.immediate.TexEnvJIT.hook_texEnvi(target, pname, param);
+ // Don't call old func, since we are the implementor.
+ //glTexEnvi(target, pname, param);
+ };
+ var glTexEnvfv = (typeof(_glTexEnvfv) != 'undefined') ? _glTexEnvfv : function(){};
+ _glTexEnvfv = function(target, pname, param) {
+ GL.immediate.TexEnvJIT.hook_texEnvfv(target, pname, param);
+ // Don't call old func, since we are the implementor.
+ //glTexEnvfv(target, pname, param);
+ };
+
+ var glGetIntegerv = _glGetIntegerv;
+ _glGetIntegerv = function(pname, params) {
+ switch (pname) {
+ case 0x8B8D: { // GL_CURRENT_PROGRAM
+ // Just query directly so we're working with WebGL objects.
+ var cur = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM);
+ if (cur == GL.immediate.fixedFunctionProgram) {
+ // Pretend we're not using a program.
+ {{{ makeSetValue('params', '0', '0', 'i32') }}};
+ return;
+ }
+ break;
+ }
+ }
+ glGetIntegerv(pname, params);
+ };
},
// Main functions
@@ -2428,6 +3488,15 @@ var LibraryGL = {
if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case
+ this.TexEnvJIT.init(Module.ctx);
+
+ GL.immediate.MAX_TEXTURES = Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS);
+ GL.immediate.NUM_ATTRIBUTES = GL.immediate.TEXTURE0 + GL.immediate.MAX_TEXTURES;
+ GL.immediate.clientAttributes = [];
+ for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) {
+ GL.immediate.clientAttributes.push({});
+ }
+
this.matrixStack['m'] = [];
this.matrixStack['p'] = [];
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
@@ -2445,7 +3514,7 @@ var LibraryGL = {
}
// Renderer cache
- this.rendererCache = this.rendererCacheItemTemplate.slice();
+ this.rendererCache = this.MapTreeLib.create();
// Buffers for data
this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2);
@@ -2486,6 +3555,7 @@ var LibraryGL = {
if (stride != 0 && stride != attribute.stride) multiStrides = true;
if (attribute.stride) stride = attribute.stride;
}
+
if (multiStrides) stride = 0; // we will need to restride
var bytes = 0; // total size in bytes
if (!stride && !beginEnd) {
@@ -2564,8 +3634,8 @@ var LibraryGL = {
var renderer = this.getRenderer();
// Generate index data in a format suitable for GLES 2.0/WebGL
- var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; // XXX assuming float
- assert(numVertexes % 1 == 0);
+ var numVertexes = 4 * this.vertexCounter / GL.immediate.stride;
+ assert(numVertexes % 1 == 0, "`numVertexes` must be an integer.");
var emulatedElementArrayBuffer = false;
var numIndexes = 0;
@@ -2629,6 +3699,16 @@ var LibraryGL = {
glBegin__deps: ['$GLImmediateSetup'],
glBegin: function(mode) {
+ // Push the old state:
+ GL.immediate.enabledClientAttributes_preBegin = GL.immediate.enabledClientAttributes;
+ GL.immediate.enabledClientAttributes = [];
+
+ GL.immediate.clientAttributes_preBegin = GL.immediate.clientAttributes;
+ GL.immediate.clientAttributes = []
+ for (var i = 0; i < GL.immediate.clientAttributes_preBegin.length; i++) {
+ GL.immediate.clientAttributes.push({});
+ }
+
GL.immediate.mode = mode;
GL.immediate.vertexCounter = 0;
var components = GL.immediate.rendererComponents = [];
@@ -2646,6 +3726,12 @@ var LibraryGL = {
GL.immediate.flush();
GL.immediate.disableBeginEndClientAttributes();
GL.immediate.mode = -1;
+
+ // Pop the old state:
+ GL.immediate.enabledClientAttributes = GL.immediate.enabledClientAttributes_preBegin;
+ GL.immediate.clientAttributes = GL.immediate.clientAttributes_preBegin;
+
+ GL.immediate.modifiedClientAttributes = true;
},
glVertex3f: function(x, y, z) {
@@ -2670,7 +3756,7 @@ var LibraryGL = {
glVertex2fv: function(p) {
_glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, 0);
},
-
+
glVertex3i: 'glVertex3f',
glVertex2i: 'glVertex3f',
@@ -2879,11 +3965,11 @@ var LibraryGL = {
},
// Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos
- glGenVertexArrays__deps: ['$GLEMulation'],
+ glGenVertexArrays__deps: ['$GLEmulation'],
glGenVertexArrays__sig: 'vii',
glGenVertexArrays: function(n, vaos) {
for (var i = 0; i < n; i++) {
- var id = GL.getNewId(GLEmulation.vaos);
+ var id = GL.getNewId(GLEmulation.vaos);
GLEmulation.vaos[id] = {
id: id,
arrayBuffer: 0,
@@ -2944,6 +4030,7 @@ var LibraryGL = {
} else if (mode == 0x1701 /* GL_PROJECTION */) {
GL.immediate.currentMatrix = 'p';
} else if (mode == 0x1702) { // GL_TEXTURE
+ GL.immediate.useTextureMatrix = true;
GL.immediate.currentMatrix = 't' + GL.immediate.clientActiveTexture;
} else {
throw "Wrong mode " + mode + " passed to glMatrixMode";
@@ -3113,7 +4200,7 @@ var LibraryGL = {
return 1 /* GL_TRUE */;
},
-
+
gluOrtho2D: function(left, right, bottom, top) {
_glOrtho(left, right, bottom, top, -1, 1);
},
@@ -3280,9 +4367,10 @@ var LibraryGL = {
glGenVertexArraysOES: 'glGenVertexArrays',
glDeleteVertexArraysOES: 'glDeleteVertexArrays',
glBindVertexArrayOES: 'glBindVertexArray',
- glFramebufferTexture2DOES: 'glFramebufferTexture2D'
+ glFramebufferTexture2DOES: 'glFramebufferTexture2D',
};
+
// Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name
[[0, 'getError* finish flush'],
[1, 'clearDepth clearDepth[f] depthFunc enable disable frontFace cullFace clear lineWidth clearStencil depthMask stencilMask checkFramebufferStatus* generateMipmap activeTexture blendEquation sampleCoverage isEnabled*'],
diff --git a/src/library_glut.js b/src/library_glut.js
index 35348028..38cfe55b 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -322,16 +322,17 @@ var LibraryGLUT = {
var callback = function() {
if (GLUT.idleFunc) {
Runtime.dynCall('v', GLUT.idleFunc);
- window.setTimeout(callback, 0);
+ Browser.safeSetTimeout(callback, 0);
}
}
- if (!GLUT.idleFunc)
- window.setTimeout(callback, 0);
+ if (!GLUT.idleFunc) {
+ Browser.safeSetTimeout(callback, 0);
+ }
GLUT.idleFunc = func;
},
glutTimerFunc: function(msec, func, value) {
- window.setTimeout(function() { Runtime.dynCall('vi', func, [value]); }, msec);
+ Browser.safeSetTimeout(function() { Runtime.dynCall('vi', func, [value]); }, msec);
},
glutDisplayFunc: function(func) {
@@ -419,6 +420,7 @@ var LibraryGLUT = {
glutPostRedisplay: function() {
if (GLUT.displayFunc) {
Browser.requestAnimationFrame(function() {
+ if (ABORT) return;
Runtime.dynCall('v', GLUT.displayFunc);
});
}
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 75544765..aa7ab532 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -694,6 +694,11 @@ var LibrarySDL = {
Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
});
Browser.setCanvasSize(width, height, true);
+ // Free the old surface first.
+ if (SDL.screen) {
+ SDL.freeSurface(SDL.screen);
+ SDL.screen = null;
+ }
SDL.screen = SDL.makeSurface(width, height, flags, true, 'screen');
if (!SDL.addedResizeListener) {
SDL.addedResizeListener = true;
@@ -1155,9 +1160,6 @@ var LibrarySDL = {
SDL_OpenAudio: function(desired, obtained) {
SDL.allocateChannels(32);
- // FIXME: Assumes 16-bit audio
- assert(obtained === 0, 'Cannot return obtained SDL audio params');
-
SDL.audio = {
freq: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.freq', 'i32', 0, 1) }}},
format: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.format', 'i16', 0, 1) }}},
@@ -1169,6 +1171,16 @@ var LibrarySDL = {
timer: null
};
+ if (obtained) {
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.freq', 'SDL.audio.freq', 'i32') }}}; // no good way for us to know if the browser can really handle this
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.format', 33151, 'i16') }}}; // float, signed, 32-bit
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.channels', 'SDL.audio.channels', 'i8') }}};
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.silence', makeGetValue('desired', 'SDL.structs.AudioSpec.silence', 'i8', 0, 1), 'i8') }}}; // unclear if browsers can provide this
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.samples', 'SDL.audio.samples', 'i16') }}};
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.callback', 'SDL.audio.callback', '*') }}};
+ {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.userdata', 'SDL.audio.userdata', '*') }}};
+ }
+
var totalSamples = SDL.audio.samples*SDL.audio.channels;
SDL.audio.bufferSize = totalSamples*2; // hardcoded 16-bit audio
SDL.audio.buffer = _malloc(SDL.audio.bufferSize);
@@ -1197,7 +1209,7 @@ var LibrarySDL = {
SDL_PauseAudio: function(pauseOn) {
if (SDL.audio.paused !== pauseOn) {
- SDL.audio.timer = pauseOn ? SDL.audio.timer && clearInterval(SDL.audio.timer) : setInterval(SDL.audio.caller, 1/35);
+ SDL.audio.timer = pauseOn ? SDL.audio.timer && clearInterval(SDL.audio.timer) : Browser.safeSetInterval(SDL.audio.caller, 1/35);
}
SDL.audio.paused = pauseOn;
},
@@ -1349,6 +1361,9 @@ var LibrarySDL = {
channelInfo.audio = audio = audio.cloneNode(true);
audio.numChannels = info.audio.numChannels;
audio.frequency = info.audio.frequency;
+
+ // TODO: handle N loops. Behavior matches Mix_PlayMusic
+ audio.loop = loops != 0;
if (SDL.channelFinished) {
audio['onended'] = function() { // TODO: cache these
Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
@@ -1450,7 +1465,7 @@ var LibrarySDL = {
loops = Math.max(loops, 1);
var audio = SDL.audios[id].audio;
if (!audio) return 0;
- audio.loop = loops != 1; // TODO: handle N loops for finite N
+ audio.loop = loops != 0; // TODO: handle N loops for finite N
if (SDL.audios[id].buffer) {
audio["mozWriteAudio"](SDL.audios[id].buffer);
} else {
diff --git a/src/parseTools.js b/src/parseTools.js
index f30883b5..3949491e 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -129,9 +129,13 @@ function isPointerType(type) {
return type[type.length-1] == '*';
}
+function isArrayType(type) {
+ return /^\[\d+\ x\ (.*)\]/.test(type);
+}
+
function isStructType(type) {
if (isPointerType(type)) return false;
- if (/^\[\d+\ x\ (.*)\]/.test(type)) return true; // [15 x ?] blocks. Like structs
+ if (isArrayType(type)) return true;
if (/<?{ ?[^}]* ?}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
// See comment in isStructPointerType()
return type[0] == '%';
@@ -286,18 +290,18 @@ function isVarArgsFunctionType(type) {
return type.substr(-varArgsSuffix.length) == varArgsSuffix;
}
-function getNumVars(type) { // how many variables are needed to represent this type
+function getNumLegalizedVars(type) { // how many legalized variables are needed to represent this type
if (type in Runtime.FLOAT_TYPES) return 1;
return Math.max(getNumIntChunks(type), 1);
}
-function countNormalArgs(type, out) {
+function countNormalArgs(type, out, legalized) {
out = out || {};
if (!isFunctionType(type, out)) return -1;
var ret = 0;
if (out.segments) {
for (var i = 0; i < out.segments.length; i++) {
- ret += getNumVars(out.segments[i][0].text);
+ ret += legalized ? getNumLegalizedVars(out.segments[i][0].text) : 1;
}
}
if (isVarArgsFunctionType(type)) ret--;
@@ -1754,10 +1758,11 @@ function getGetElementPtrIndexes(item) {
indexes.push(getFastValue(Runtime.getNativeTypeSize(type), '*', offset, 'i32'));
}
}
- item.params.slice(2, item.params.length).forEach(function(arg) {
+ item.params.slice(2, item.params.length).forEach(function(arg, i) {
var curr = arg;
// TODO: If index is constant, optimize
var typeData = Types.types[type];
+ assert(typeData || i == item.params.length - 3); // can be null, when we get to the end (a basic type)
if (isStructType(type) && typeData.needsFlattening) {
if (typeData.flatFactor) {
indexes.push(getFastValue(curr, '*', typeData.flatFactor, 'i32'));
@@ -1773,16 +1778,15 @@ function getGetElementPtrIndexes(item) {
indexes.push(curr);
}
}
- if (!isNumber(curr) || parseInt(curr) < 0) {
- // We have a *variable* to index with, or a negative number. In both
- // cases, in theory we might need to do something dynamic here. FIXME?
- // But, most likely all the possible types are the same, so do that case here now...
- for (var i = 1; i < typeData.fields.length; i++) {
- assert(typeData.fields[0] === typeData.fields[i]);
+ if (typeData) {
+ if (isArrayType(type)) {
+ type = typeData.fields[0]; // all the same, so accept even out-of-bounds this way
+ } else {
+ assert(isNumber(curr)); // cannot be dynamic
+ type = typeData.fields[curr];
}
- curr = 0;
+ assert(type);
}
- type = typeData && typeData.fields[curr] ? typeData.fields[curr] : '';
});
var ret = getFastValues(indexes, '+', 'i32');
@@ -2034,12 +2038,20 @@ function processMathop(item) {
}
var bitsBefore = parseInt((item.params[0] ? item.params[0].type : item.type).substr(1)); // remove i to leave the number of bits left after this
var bitsLeft = parseInt(((item.params[1] && item.params[1].ident) ? item.params[1].ident : item.type).substr(1)); // remove i to leave the number of bits left after this operation
+ var rawBits = getBits(item.type);
+ assert(rawBits <= 64);
function integerizeBignum(value) {
return makeInlineCalculation('VALUE-VALUE%1', value, 'tempBigIntI');
}
- if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)') && USE_TYPED_ARRAYS == 2) {
+ if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)' || rawBits > 32) && USE_TYPED_ARRAYS == 2) {
+ // this code assumes i64 for the most part
+ if (ASSERTIONS && rawBits > 1 && rawBits < 64) {
+ warnOnce('processMathop processing illegal non-i64 value');
+ if (VERBOSE) printErr([op, item.type, rawBits, type, paramTypes, idents]);
+ }
+
var warnI64_1 = function() {
warnOnce('Arithmetic on 64-bit integers in mode 1 is rounded and flaky, like mode 0!');
};
diff --git a/src/postamble.js b/src/postamble.js
index d0b737f8..49fd9b3e 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -104,7 +104,7 @@ function run(args) {
setTimeout(function() {
Module['setStatus']('');
}, 1);
- doRun();
+ if (!ABORT) doRun();
}, 1);
return 0;
} else {
diff --git a/src/preamble.js b/src/preamble.js
index dbe5e655..4c61a86e 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -231,7 +231,7 @@ var setjmpId = 1; // Used in setjmp/longjmp
var setjmpLabels = {};
#endif
-var ABORT = false;
+var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort()
var undef = 0;
// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
@@ -475,7 +475,11 @@ function allocate(slab, types, allocator, ptr) {
#if USE_TYPED_ARRAYS == 2
if (singleType === 'i8') {
- HEAPU8.set(new Uint8Array(slab), ret);
+ if (slab.subarray || slab.slice) {
+ HEAPU8.set(slab, ret);
+ } else {
+ HEAPU8.set(new Uint8Array(slab), ret);
+ }
return ret;
}
#endif
@@ -809,6 +813,7 @@ function addRunDependency(id) {
if (id) {
assert(!runDependencyTracking[id]);
runDependencyTracking[id] = 1;
+#if ASSERTIONS
if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
// Check for missing dependencies every few seconds
runDependencyWatcher = setInterval(function() {
@@ -823,8 +828,9 @@ function addRunDependency(id) {
if (shown) {
Module.printErr('(end of list)');
}
- }, 6000);
+ }, 10000);
}
+#endif
} else {
Module.printErr('warning: run dependency added without ID');
}
@@ -873,6 +879,7 @@ var PGOMonitor = {
Module.print('-s DEAD_FUNCTIONS=\'' + JSON.stringify(dead) + '\'\n');
}
};
+Module['PGOMonitor'] = PGOMonitor;
__ATEXIT__.push({ func: function() { PGOMonitor.dump() } });
addPreRun(function() { addRunDependency('pgo') });
#endif
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 61daed79..8c72b0a6 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -104,9 +104,6 @@ Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), Defau
Block::~Block() {
if (Code) free((void*)Code);
- for (BlockBranchMap::iterator iter = ProcessedBranchesIn.begin(); iter != ProcessedBranchesIn.end(); iter++) {
- delete iter->second;
- }
for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) {
delete iter->second;
}
@@ -139,10 +136,6 @@ void Block::Render(bool InLoop) {
bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later
- if (ProcessedBranchesOut.size() == 1 && ProcessedBranchesOut.begin()->second->Type == Branch::Direct) {
- SetLabel = false;
- }
-
// A setting of the label variable (label = x) is necessary if it can
// cause an impact. The main case is where we set label to x, then elsewhere
// we check if label is equal to that value, i.e., that label is an entry
@@ -379,22 +372,47 @@ void Relooper::Calculate(Block *Entry) {
Block *Curr = *iter;
TotalCodeSize += strlen(Curr->Code);
}
-
+ BlockSet Splits;
+ BlockSet Removed;
+ //DebugDump(Live, "before");
for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) {
Block *Original = *iter;
- if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue;
+ if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; // only dead ends, for now
+ if (Original->BranchesOut.find(Original) != Original->BranchesOut.end()) continue; // cannot split a looping node
if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort
// Split the node (for simplicity, we replace all the blocks, even though we could have reused the original)
- for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
- Block *Prior = iter->first;
+ PrintDebug("Splitting block %d\n", Original->Id);
+ for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
+ Block *Prior = *iter;
Block *Split = new Block(Original->Code);
- Split->BranchesIn[Prior] = new Branch(NULL);
- Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code);
+ Parent->Blocks.push_back(Split);
+ PrintDebug(" to %d\n", Split->Id);
+ Split->BranchesIn.insert(Prior);
+ Branch *Details = Prior->BranchesOut[Original];
+ Prior->BranchesOut[Split] = new Branch(Details->Condition, Details->Code);
Prior->BranchesOut.erase(Original);
- Parent->AddBlock(Split);
- Live.insert(Split);
+ for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) {
+ Block *Post = iter->first;
+ Branch *Details = iter->second;
+ Split->BranchesOut[Post] = new Branch(Details->Condition, Details->Code);
+ Post->BranchesIn.insert(Split);
+ }
+ Splits.insert(Split);
+ Removed.insert(Original);
+ }
+ for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) {
+ Block *Post = iter->first;
+ Post->BranchesIn.erase(Original);
}
+ //DebugDump(Live, "mid");
+ }
+ for (BlockSet::iterator iter = Splits.begin(); iter != Splits.end(); iter++) {
+ Live.insert(*iter);
+ }
+ for (BlockSet::iterator iter = Removed.begin(); iter != Removed.end(); iter++) {
+ Live.erase(*iter);
}
+ //DebugDump(Live, "after");
}
};
PreOptimizer Pre(this);
@@ -405,7 +423,7 @@ void Relooper::Calculate(Block *Entry) {
Block *Curr = Blocks[i];
if (Pre.Live.find(Curr) == Pre.Live.end()) continue;
for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
- iter->first->BranchesIn[Curr] = new Branch(NULL);
+ iter->first->BranchesIn.insert(Curr);
}
}
@@ -435,22 +453,21 @@ void Relooper::Calculate(Block *Entry) {
void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) {
PrintDebug("Solipsizing branches into %d\n", Target->Id);
DebugDump(From, " relevant to solipsize: ");
- for (BlockBranchMap::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) {
- Block *Prior = iter->first;
+ for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) {
+ Block *Prior = *iter;
if (From.find(Prior) == From.end()) {
iter++;
continue;
}
- Branch *TargetIn = iter->second;
Branch *PriorOut = Prior->BranchesOut[Target];
- PriorOut->Ancestor = Ancestor; // Do we need this info
- PriorOut->Type = Type; // on TargetIn too?
+ PriorOut->Ancestor = Ancestor;
+ PriorOut->Type = Type;
if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) {
Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop
}
iter++; // carefully increment iter before erasing
Target->BranchesIn.erase(Prior);
- Target->ProcessedBranchesIn[Prior] = TargetIn;
+ Target->ProcessedBranchesIn.insert(Prior);
Prior->BranchesOut.erase(Target);
Prior->ProcessedBranchesOut[Target] = PriorOut;
PrintDebug(" eliminated branch from %d\n", Prior->Id);
@@ -488,8 +505,8 @@ void Relooper::Calculate(Block *Entry) {
InnerBlocks.insert(Curr);
Blocks.erase(Curr);
// Add the elements prior to it
- for (BlockBranchMap::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) {
- Queue.insert(iter->first);
+ for (BlockSet::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) {
+ Queue.insert(*iter);
}
}
}
@@ -620,8 +637,8 @@ void Relooper::Calculate(Block *Entry) {
BlockList ToInvalidate;
for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) {
Block *Child = *iter;
- for (BlockBranchMap::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) {
- Block *Parent = iter->first;
+ for (BlockSet::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) {
+ Block *Parent = *iter;
if (Helper.Ownership[Parent] != Helper.Ownership[Child]) {
ToInvalidate.push_back(Child);
}
@@ -751,8 +768,8 @@ void Relooper::Calculate(Block *Entry) {
Block *Entry = iter->first;
BlockSet &Group = iter->second;
BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete
- for (BlockBranchMap::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) {
- Block *Origin = iterBranch->first;
+ for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) {
+ Block *Origin = *iterBranch;
if (Group.find(Origin) == Group.end()) {
// Reached from outside the group, so we cannot handle this
PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id);
@@ -821,13 +838,11 @@ void Relooper::Calculate(Block *Entry) {
// Main
BlockSet AllBlocks;
- for (int i = 0; i < Blocks.size(); i++) {
- AllBlocks.insert(Blocks[i]);
+ for (BlockSet::iterator iter = Pre.Live.begin(); iter != Pre.Live.end(); iter++) {
+ Block *Curr = *iter;
+ AllBlocks.insert(Curr);
#if DEBUG
- PrintDebug("Adding block %d (%s)\n", Blocks[i]->Id, Blocks[i]->Code);
- for (BlockBranchMap::iterator iter = Blocks[i]->BranchesOut.begin(); iter != Blocks[i]->BranchesOut.end(); iter++) {
- PrintDebug(" with branch out to %d\n", iter->first->Id);
- }
+ PrintDebug("Adding block %d (%s)\n", Curr->Id, Curr->Code);
#endif
}
@@ -874,10 +889,26 @@ void Relooper::Calculate(Block *Entry) {
func(Loop->Next); \
}
+ // Find the blocks that natural control flow can get us directly to, or through a multiple that we ignore
+ void FollowNaturalFlow(Shape *S, BlockSet &Out) {
+ SHAPE_SWITCH(S, {
+ Out.insert(Simple->Inner);
+ }, {
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ FollowNaturalFlow(iter->second, Out);
+ }
+ FollowNaturalFlow(Multiple->Next, Out);
+ }, {
+ FollowNaturalFlow(Loop->Inner, Out);
+ });
+ }
+
// Remove unneeded breaks and continues.
// A flow operation is trivially unneeded if the shape we naturally get to by normal code
// execution is the same as the flow forces us to.
void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
+ BlockSet NaturalBlocks;
+ FollowNaturalFlow(Natural, NaturalBlocks);
Shape *Next = Root;
while (Next) {
Root = Next;
@@ -892,7 +923,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
Block *Target = iter->first;
Branch *Details = iter->second;
- if (Details->Type != Branch::Direct && Target->Parent == Natural) {
+ if (Details->Type != Branch::Direct && NaturalBlocks.find(Target) != NaturalBlocks.end()) { // note: cannot handle split blocks
Details->Type = Branch::Direct;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
Multiple->NeedLoop--;
@@ -1007,12 +1038,32 @@ void Relooper::SetAsmJSMode(int On) {
#if DEBUG
// Debugging
-void DebugDump(BlockSet &Blocks, const char *prefix) {
+void Debugging::Dump(BlockSet &Blocks, const char *prefix) {
if (prefix) printf("%s ", prefix);
for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
- printf("%d ", (*iter)->Id);
+ Block *Curr = *iter;
+ printf("%d:\n", Curr->Id);
+ for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) {
+ Block *Other = iter2->first;
+ printf(" -> %d\n", Other->Id);
+ assert(Other->BranchesIn.find(Curr) != Other->BranchesIn.end());
+ }
}
- printf("\n");
+}
+
+void Debugging::Dump(Shape *S, const char *prefix) {
+ if (prefix) printf("%s ", prefix);
+ printf(" %d ", S->Id);
+ SHAPE_SWITCH(S, {
+ printf("<< Simple with block %d\n", Simple->Inner->Id);
+ }, {
+ printf("<< Multiple\n");
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ printf(" with entry %d\n", iter->first->Id);
+ }
+ }, {
+ printf("<< Loop\n");
+ });
}
static void PrintDebug(const char *Format, ...) {
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index eac03738..34b6db08 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -41,6 +41,7 @@ struct Branch {
void Render(Block *Target, bool SetLabel);
};
+typedef std::set<Block*> BlockSet;
typedef std::map<Block*, Branch*> BlockBranchMap;
// Represents a basic block of code - some instructions that end with a
@@ -52,9 +53,9 @@ struct Block {
// processed branches.
// Blocks own the Branch objects they use, and destroy them when done.
BlockBranchMap BranchesOut;
- BlockBranchMap BranchesIn; // TODO: make this just a list of Incoming, without branch info - should be just on BranchesOut
+ BlockSet BranchesIn;
BlockBranchMap ProcessedBranchesOut;
- BlockBranchMap ProcessedBranchesIn;
+ BlockSet ProcessedBranchesIn;
Shape *Parent; // The shape we are directly inside
int Id; // A unique identifier
const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input)
@@ -205,12 +206,12 @@ struct Relooper {
static void SetAsmJSMode(int On);
};
-typedef std::set<Block*> BlockSet;
typedef std::map<Block*, BlockSet> BlockBlockSetMap;
#if DEBUG
struct Debugging {
static void Dump(BlockSet &Blocks, const char *prefix=NULL);
+ static void Dump(Shape *S, const char *prefix=NULL);
};
#endif
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 96929028..5f6bae3d 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -98,14 +98,14 @@ int main() {
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
- slow_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
+ slow_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
print '.'
subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g'])
print '*'
subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w'))
print '-'
- fast_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
+ fast_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
print
if slow_out != fast_out:
diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp
index 4275941b..7da990b5 100644
--- a/src/relooper/test.cpp
+++ b/src/relooper/test.cpp
@@ -190,5 +190,46 @@ int main() {
puts(buffer);
}
+
+ if (1) {
+ Relooper::SetOutputBuffer(buffer, sizeof(buffer));
+
+ printf("\n\n-- if (expensive || expensive2) X else Y; Z --\n\n");
+
+ Block *b_a = new Block("// block A\n");
+ Block *b_b = new Block("// block B\n");
+ Block *b_c = new Block("// block C;\n");
+ Block *b_d = new Block("// block D\n");
+ Block *b_e = new Block("// block E\n");
+ Block *b_f = new Block("// block F\n");
+
+ b_a->AddBranchTo(b_c, "expensive()");
+ b_a->AddBranchTo(b_b, NULL);
+
+ b_b->AddBranchTo(b_c, "expensive2()");
+ b_b->AddBranchTo(b_d, NULL);
+
+ b_c->AddBranchTo(b_e, NULL);
+
+ b_d->AddBranchTo(b_e, NULL);
+
+ b_e->AddBranchTo(b_f, NULL);
+
+ b_f->AddBranchTo(b_e, NULL);
+
+ Relooper r;
+ r.AddBlock(b_a);
+ r.AddBlock(b_b);
+ r.AddBlock(b_c);
+ r.AddBlock(b_d);
+ r.AddBlock(b_e);
+ r.AddBlock(b_f);
+
+ r.Calculate(b_a);
+ printf("\n\n");
+ r.Render();
+
+ puts(buffer);
+ }
}
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 12d0ef39..d657c6af 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -109,3 +109,30 @@ while(1) {
// block D
}
+
+
+-- if (expensive || expensive2) X else Y; Z --
+
+
+
+// block A
+do {
+ if (expensive()) {
+ label = 33;
+ } else {
+ // block B
+ if (expensive2()) {
+ label = 33;
+ break;
+ }
+ // block D
+ }
+} while(0);
+if (label == 33) {
+ // block C;
+}
+while(1) {
+ // block E
+ // block F
+}
+
diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt
index f0bfb972..3427ff18 100644
--- a/src/relooper/test4.txt
+++ b/src/relooper/test4.txt
@@ -7,7 +7,6 @@ do {
break;
}
//21
- break;
} else {
label = 4;
}
diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt
index 1c7d0508..d18ed875 100644
--- a/src/relooper/test_debug.txt
+++ b/src/relooper/test_debug.txt
@@ -28,56 +28,88 @@ int main() {
return 0;
}
// Adding block 1 (ep)
-// with branch out to 2
-// with branch out to 4
// Adding block 2 (LBB1)
-// with branch out to 3
-// with branch out to 4
// Adding block 3 (LBB2)
-// with branch out to 4
// Adding block 4 (LBB3)
// Process() called
// Process() running
- blocks : 1 2 3 4
- entries: 1
+ blocks : 1:
+ -> 2
+ -> 4
+2:
+ -> 3
+ -> 4
+3:
+ -> 4
+4:
+ entries: 1:
+ -> 2
+ -> 4
// creating simple block with block #1
// Solipsizing branches into 2
- relevant to solipsize: 1
+ relevant to solipsize: 1:
+ -> 2
+ -> 4
// eliminated branch from 1
// Solipsizing branches into 4
- relevant to solipsize: 1
+ relevant to solipsize: 1:
+ -> 4
// eliminated branch from 1
// Process() running
- blocks : 2 3 4
- entries: 2 4
+ blocks : 2:
+ -> 3
+ -> 4
+3:
+ -> 4
+4:
+ entries: 2:
+ -> 3
+ -> 4
+4:
// Investigated independent groups:
- group: 2 3
+ group: 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// Independent groups: 1
// Handleable independent groups: 1
// creating multiple block with 1 inner groups
// multiple group with entry 2:
- 2 3
+ 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// Solipsizing branches into 4
- relevant to solipsize: 2 3
+ relevant to solipsize: 2:
+ -> 3
+ -> 4
+3:
+ -> 4
// eliminated branch from 2
// eliminated branch from 3
// Process() called
// Process() running
- blocks : 2 3
- entries: 2
+ blocks : 2:
+ -> 3
+3:
+ entries: 2:
+ -> 3
// creating simple block with block #2
// Solipsizing branches into 3
- relevant to solipsize: 2
+ relevant to solipsize: 2:
+ -> 3
// eliminated branch from 2
// Process() running
- blocks : 3
- entries: 3
+ blocks : 3:
+ entries: 3:
// creating simple block with block #3
// Process() returning
- remaining blocks after multiple: 4
+ remaining blocks after multiple: 4:
// Process() running
- blocks : 4
- entries: 4
+ blocks : 4:
+ entries: 4:
// creating simple block with block #4
// Process() returning
// === Optimizing shapes ===
diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt
index 5122257e..b278e240 100644
--- a/src/relooper/test_fuzz1.txt
+++ b/src/relooper/test_fuzz1.txt
@@ -3,13 +3,10 @@
print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
print(5); state = check();
print(6); state = check();
-do {
- if (state == 7) {
- print(7); state = check();
- label = 3;
- break;
- }
-} while(0);
+if (state == 7) {
+ print(7); state = check();
+ label = 3;
+}
L5: while(1) {
if (label == 3) {
label = 0;
diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt
index 9548205c..29b2dba4 100644
--- a/src/relooper/test_fuzz5.txt
+++ b/src/relooper/test_fuzz5.txt
@@ -3,22 +3,18 @@
print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
L1: while(1) {
print(7); state = check();
- do {
- if (state % 3 == 1) {
- label = 3;
- } else if (state % 3 == 0) {
- print(8); state = check();
- if (state % 2 == 0) {
- label = 5;
- break;
- } else {
- label = 7;
- break;
- }
+ if (state % 3 == 1) {
+ label = 3;
+ } else if (state % 3 == 0) {
+ print(8); state = check();
+ if (state % 2 == 0) {
+ label = 5;
} else {
- break L1;
+ label = 7;
}
- } while(0);
+ } else {
+ break;
+ }
while(1) {
if (label == 3) {
label = 0;
diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt
index bd45e8fd..d5a5ab7b 100644
--- a/src/relooper/test_fuzz6.txt
+++ b/src/relooper/test_fuzz6.txt
@@ -82,7 +82,6 @@ while(1) {
print(56); state = check();// ....................................................................................................................................................................................................................
print(34); state = check();// ..........................................................................................................................................
label = 74;
- continue;
}
print(62); state = check();// .......................................................................................
}
diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh
index 61e1a2fb..88db35fb 100755
--- a/src/relooper/testit.sh
+++ b/src/relooper/testit.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
echo "test"
./test &> test.out
diff --git a/src/relooper/updateit.sh b/src/relooper/updateit.sh
index 8c434753..da9fa9aa 100755
--- a/src/relooper/updateit.sh
+++ b/src/relooper/updateit.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
./test &> test.txt
./test2 &> test2.txt
./test3 &> test3.txt
diff --git a/src/settings.js b/src/settings.js
index d3abb06e..7e607996 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -36,6 +36,7 @@ var ASSERTIONS = 1; // Whether we should add runtime assertions, for example to
// exceed it's size, whether all allocations (stack and static) are
// of positive size, etc., whether we should throw if we encounter a bad __label__, i.e.,
// if code flow runs into a fault
+ // ASSERTIONS == 2 gives even more runtime checks
var VERBOSE = 0; // When set to 1, will generate more verbose output during compilation.
var INVOKE_RUN = 1; // Whether we will run the main() function. Disable if you embed the generated
@@ -174,6 +175,7 @@ var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js).
// want it back. A simple way to set it in C++ is
// emscripten_run_script("Runtime.debug = ...;");
var SOCKET_DEBUG = 0; // Log out socket/network data transfer.
+var SOCKET_WEBRTC = 0; // Select socket backend, either webrtc or websockets.
var OPENAL_DEBUG = 0; // Print out debugging information from our OpenAL implementation.
@@ -193,7 +195,7 @@ var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catc
// introduce silent failures, which is good).
// DISABLE_EXCEPTION_CATCHING = 0 - generate code to actually catch exceptions
// DISABLE_EXCEPTION_CATCHING = 1 - disable exception catching at all
- // DISABLE_EXCEPTION_CATCHING = 2 - disable exception catching, but enables
+ // DISABLE_EXCEPTION_CATCHING = 2 - disable exception catching, but enables
// catching in whitelist
// TODO: Make this also remove cxa_begin_catch etc., optimize relooper
// for it, etc. (perhaps do all of this as preprocessing on .ll?)
@@ -238,7 +240,8 @@ var NAMED_GLOBALS = 0; // If 1, we use global variables for globals. Otherwise
// they are referred to by a base plus an offset (called an indexed global),
// saving global variables but adding runtime overhead.
-var EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported. These functions are kept alive
+var EXPORTED_FUNCTIONS = ['_main', '_malloc'];
+ // Functions that are explicitly exported. These functions are kept alive
// through LLVM dead code elimination, and also made accessible outside of
// the generated code even after running closure compiler (on "Module").
// Note the necessary prefix of "_".
diff --git a/src/shell.js b/src/shell.js
index ed80c09a..873bcc65 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -1,5 +1,6 @@
try {
this['Module'] = Module;
+ Module.test;
} catch(e) {
this['Module'] = Module = {};
}
diff --git a/src/socket.io.js b/src/socket.io.js
new file mode 100644
index 00000000..3fe6a5a7
--- /dev/null
+++ b/src/socket.io.js
@@ -0,0 +1,3870 @@
+/*! Socket.IO.js build:0.9.11, development. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */
+
+(function(global) {
+
+var io = ('undefined' === typeof module ? {} : module.exports);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports) {
+
+ /**
+ * IO namespace.
+ *
+ * @namespace
+ */
+
+ var io = exports;
+
+ /**
+ * Socket.IO version
+ *
+ * @api public
+ */
+
+ io.version = '0.9.11';
+
+ /**
+ * Protocol implemented.
+ *
+ * @api public
+ */
+
+ io.protocol = 1;
+
+ /**
+ * Available transports, these will be populated with the available transports
+ *
+ * @api public
+ */
+
+ io.transports = [];
+
+ /**
+ * Keep track of jsonp callbacks.
+ *
+ * @api private
+ */
+
+ io.j = [];
+
+ /**
+ * Keep track of our io.Sockets
+ *
+ * @api private
+ */
+ io.sockets = {};
+
+
+ /**
+ * Manages connections to hosts.
+ *
+ * @param {String} uri
+ * @Param {Boolean} force creation of new socket (defaults to false)
+ * @api public
+ */
+
+ io.connect = function (host, details) {
+ var uri = io.util.parseUri(host)
+ , uuri
+ , socket;
+
+ if (global && global.location) {
+ uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);
+ uri.host = uri.host || (global.document
+ ? global.document.domain : global.location.hostname);
+ uri.port = uri.port || global.location.port;
+ }
+
+ uuri = io.util.uniqueUri(uri);
+
+ var options = {
+ host: uri.host
+ , secure: 'https' == uri.protocol
+ , port: uri.port || ('https' == uri.protocol ? 443 : 80)
+ , query: uri.query || ''
+ };
+
+ io.util.merge(options, details);
+
+ if (options['force new connection'] || !io.sockets[uuri]) {
+ socket = new io.Socket(options);
+ }
+
+ if (!options['force new connection'] && socket) {
+ io.sockets[uuri] = socket;
+ }
+
+ socket = socket || io.sockets[uuri];
+
+ // if path is different from '' or /
+ return socket.of(uri.path.length > 1 ? uri.path : '');
+ };
+
+})('object' === typeof module ? module.exports : (io = {}));
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports) {
+
+ /**
+ * Utilities namespace.
+ *
+ * @namespace
+ */
+
+ var util = exports.util = {};
+
+ /**
+ * Parses an URI
+ *
+ * @author Steven Levithan <stevenlevithan.com> (MIT license)
+ * @api public
+ */
+
+ var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
+
+ var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
+ 'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
+ 'anchor'];
+
+ util.parseUri = function (str) {
+ var m = re.exec(str || '')
+ , uri = {}
+ , i = 14;
+
+ while (i--) {
+ uri[parts[i]] = m[i] || '';
+ }
+
+ return uri;
+ };
+
+ /**
+ * Produces a unique url that identifies a Socket.IO connection.
+ *
+ * @param {Object} uri
+ * @api public
+ */
+
+ util.uniqueUri = function (uri) {
+ var protocol = uri.protocol
+ , host = uri.host
+ , port = uri.port;
+
+ if ('document' in global) {
+ host = host || document.domain;
+ port = port || (protocol == 'https'
+ && document.location.protocol !== 'https:' ? 443 : document.location.port);
+ } else {
+ host = host || 'localhost';
+
+ if (!port && protocol == 'https') {
+ port = 443;
+ }
+ }
+
+ return (protocol || 'http') + '://' + host + ':' + (port || 80);
+ };
+
+ /**
+ * Mergest 2 query strings in to once unique query string
+ *
+ * @param {String} base
+ * @param {String} addition
+ * @api public
+ */
+
+ util.query = function (base, addition) {
+ var query = util.chunkQuery(base || '')
+ , components = [];
+
+ util.merge(query, util.chunkQuery(addition || ''));
+ for (var part in query) {
+ if (query.hasOwnProperty(part)) {
+ components.push(part + '=' + query[part]);
+ }
+ }
+
+ return components.length ? '?' + components.join('&') : '';
+ };
+
+ /**
+ * Transforms a querystring in to an object
+ *
+ * @param {String} qs
+ * @api public
+ */
+
+ util.chunkQuery = function (qs) {
+ var query = {}
+ , params = qs.split('&')
+ , i = 0
+ , l = params.length
+ , kv;
+
+ for (; i < l; ++i) {
+ kv = params[i].split('=');
+ if (kv[0]) {
+ query[kv[0]] = kv[1];
+ }
+ }
+
+ return query;
+ };
+
+ /**
+ * Executes the given function when the page is loaded.
+ *
+ * io.util.load(function () { console.log('page loaded'); });
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+ var pageLoaded = false;
+
+ util.load = function (fn) {
+ if ('document' in global && document.readyState === 'complete' || pageLoaded) {
+ return fn();
+ }
+
+ util.on(global, 'load', fn, false);
+ };
+
+ /**
+ * Adds an event.
+ *
+ * @api private
+ */
+
+ util.on = function (element, event, fn, capture) {
+ if (element.attachEvent) {
+ element.attachEvent('on' + event, fn);
+ } else if (element.addEventListener) {
+ element.addEventListener(event, fn, capture);
+ }
+ };
+
+ /**
+ * Generates the correct `XMLHttpRequest` for regular and cross domain requests.
+ *
+ * @param {Boolean} [xdomain] Create a request that can be used cross domain.
+ * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
+ * @api private
+ */
+
+ util.request = function (xdomain) {
+
+ if (xdomain && 'undefined' != typeof XDomainRequest && !util.ua.hasCORS) {
+ return new XDomainRequest();
+ }
+
+ if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
+ return new XMLHttpRequest();
+ }
+
+ if (!xdomain) {
+ try {
+ return new window[(['Active'].concat('Object').join('X'))]('Microsoft.XMLHTTP');
+ } catch(e) { }
+ }
+
+ return null;
+ };
+
+ /**
+ * XHR based transport constructor.
+ *
+ * @constructor
+ * @api public
+ */
+
+ /**
+ * Change the internal pageLoaded value.
+ */
+
+ if ('undefined' != typeof window) {
+ util.load(function () {
+ pageLoaded = true;
+ });
+ }
+
+ /**
+ * Defers a function to ensure a spinner is not displayed by the browser
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+ util.defer = function (fn) {
+ if (!util.ua.webkit || 'undefined' != typeof importScripts) {
+ return fn();
+ }
+
+ util.load(function () {
+ setTimeout(fn, 100);
+ });
+ };
+
+ /**
+ * Merges two objects.
+ *
+ * @api public
+ */
+
+ util.merge = function merge (target, additional, deep, lastseen) {
+ var seen = lastseen || []
+ , depth = typeof deep == 'undefined' ? 2 : deep
+ , prop;
+
+ for (prop in additional) {
+ if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
+ if (typeof target[prop] !== 'object' || !depth) {
+ target[prop] = additional[prop];
+ seen.push(additional[prop]);
+ } else {
+ util.merge(target[prop], additional[prop], depth - 1, seen);
+ }
+ }
+ }
+
+ return target;
+ };
+
+ /**
+ * Merges prototypes from objects
+ *
+ * @api public
+ */
+
+ util.mixin = function (ctor, ctor2) {
+ util.merge(ctor.prototype, ctor2.prototype);
+ };
+
+ /**
+ * Shortcut for prototypical and static inheritance.
+ *
+ * @api private
+ */
+
+ util.inherit = function (ctor, ctor2) {
+ function f() {};
+ f.prototype = ctor2.prototype;
+ ctor.prototype = new f;
+ };
+
+ /**
+ * Checks if the given object is an Array.
+ *
+ * io.util.isArray([]); // true
+ * io.util.isArray({}); // false
+ *
+ * @param Object obj
+ * @api public
+ */
+
+ util.isArray = Array.isArray || function (obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+ };
+
+ /**
+ * Intersects values of two arrays into a third
+ *
+ * @api public
+ */
+
+ util.intersect = function (arr, arr2) {
+ var ret = []
+ , longest = arr.length > arr2.length ? arr : arr2
+ , shortest = arr.length > arr2.length ? arr2 : arr;
+
+ for (var i = 0, l = shortest.length; i < l; i++) {
+ if (~util.indexOf(longest, shortest[i]))
+ ret.push(shortest[i]);
+ }
+
+ return ret;
+ };
+
+ /**
+ * Array indexOf compatibility.
+ *
+ * @see bit.ly/a5Dxa2
+ * @api public
+ */
+
+ util.indexOf = function (arr, o, i) {
+
+ for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;
+ i < j && arr[i] !== o; i++) {}
+
+ return j <= i ? -1 : i;
+ };
+
+ /**
+ * Converts enumerables to array.
+ *
+ * @api public
+ */
+
+ util.toArray = function (enu) {
+ var arr = [];
+
+ for (var i = 0, l = enu.length; i < l; i++)
+ arr.push(enu[i]);
+
+ return arr;
+ };
+
+ /**
+ * UA / engines detection namespace.
+ *
+ * @namespace
+ */
+
+ util.ua = {};
+
+ /**
+ * Whether the UA supports CORS for XHR.
+ *
+ * @api public
+ */
+
+ util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
+ try {
+ var a = new XMLHttpRequest();
+ } catch (e) {
+ return false;
+ }
+
+ return a.withCredentials != undefined;
+ })();
+
+ /**
+ * Detect webkit.
+ *
+ * @api public
+ */
+
+ util.ua.webkit = 'undefined' != typeof navigator
+ && /webkit/i.test(navigator.userAgent);
+
+ /**
+ * Detect iPad/iPhone/iPod.
+ *
+ * @api public
+ */
+
+ util.ua.iDevice = 'undefined' != typeof navigator
+ && /iPad|iPhone|iPod/i.test(navigator.userAgent);
+
+})('undefined' != typeof io ? io : module.exports);
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.EventEmitter = EventEmitter;
+
+ /**
+ * Event emitter constructor.
+ *
+ * @api public.
+ */
+
+ function EventEmitter () {};
+
+ /**
+ * Adds a listener
+ *
+ * @api public
+ */
+
+ EventEmitter.prototype.on = function (name, fn) {
+ if (!this.$events) {
+ this.$events = {};
+ }
+
+ if (!this.$events[name]) {
+ this.$events[name] = fn;
+ } else if (io.util.isArray(this.$events[name])) {
+ this.$events[name].push(fn);
+ } else {
+ this.$events[name] = [this.$events[name], fn];
+ }
+
+ return this;
+ };
+
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
+
+ /**
+ * Adds a volatile listener.
+ *
+ * @api public
+ */
+
+ EventEmitter.prototype.once = function (name, fn) {
+ var self = this;
+
+ function on () {
+ self.removeListener(name, on);
+ fn.apply(this, arguments);
+ };
+
+ on.listener = fn;
+ this.on(name, on);
+
+ return this;
+ };
+
+ /**
+ * Removes a listener.
+ *
+ * @api public
+ */
+
+ EventEmitter.prototype.removeListener = function (name, fn) {
+ if (this.$events && this.$events[name]) {
+ var list = this.$events[name];
+
+ if (io.util.isArray(list)) {
+ var pos = -1;
+
+ for (var i = 0, l = list.length; i < l; i++) {
+ if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
+ pos = i;
+ break;
+ }
+ }
+
+ if (pos < 0) {
+ return this;
+ }
+
+ list.splice(pos, 1);
+
+ if (!list.length) {
+ delete this.$events[name];
+ }
+ } else if (list === fn || (list.listener && list.listener === fn)) {
+ delete this.$events[name];
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners for an event.
+ *
+ * @api public
+ */
+
+ EventEmitter.prototype.removeAllListeners = function (name) {
+ if (name === undefined) {
+ this.$events = {};
+ return this;
+ }
+
+ if (this.$events && this.$events[name]) {
+ this.$events[name] = null;
+ }
+
+ return this;
+ };
+
+ /**
+ * Gets all listeners for a certain event.
+ *
+ * @api publci
+ */
+
+ EventEmitter.prototype.listeners = function (name) {
+ if (!this.$events) {
+ this.$events = {};
+ }
+
+ if (!this.$events[name]) {
+ this.$events[name] = [];
+ }
+
+ if (!io.util.isArray(this.$events[name])) {
+ this.$events[name] = [this.$events[name]];
+ }
+
+ return this.$events[name];
+ };
+
+ /**
+ * Emits an event.
+ *
+ * @api public
+ */
+
+ EventEmitter.prototype.emit = function (name) {
+ if (!this.$events) {
+ return false;
+ }
+
+ var handler = this.$events[name];
+
+ if (!handler) {
+ return false;
+ }
+
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if ('function' == typeof handler) {
+ handler.apply(this, args);
+ } else if (io.util.isArray(handler)) {
+ var listeners = handler.slice();
+
+ for (var i = 0, l = listeners.length; i < l; i++) {
+ listeners[i].apply(this, args);
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+ };
+
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+/**
+ * Based on JSON2 (http://www.JSON.org/js.html).
+ */
+
+(function (exports, nativeJSON) {
+ "use strict";
+
+ // use native JSON if it's available
+ if (nativeJSON && nativeJSON.parse){
+ return exports.JSON = {
+ parse: nativeJSON.parse
+ , stringify: nativeJSON.stringify
+ };
+ }
+
+ var JSON = exports.JSON = {};
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ function date(d, key) {
+ return isFinite(d.valueOf()) ?
+ d.getUTCFullYear() + '-' +
+ f(d.getUTCMonth() + 1) + '-' +
+ f(d.getUTCDate()) + 'T' +
+ f(d.getUTCHours()) + ':' +
+ f(d.getUTCMinutes()) + ':' +
+ f(d.getUTCSeconds()) + 'Z' : null;
+ };
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' : '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value instanceof Date) {
+ value = date(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' : gap ?
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ if (typeof rep[i] === 'string') {
+ k = rep[i];
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' : gap ?
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
+ '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ JSON.parse = function (text, reviver) {
+ // The parse method takes a text and an optional reviver function, and returns
+ // a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+ // The walk method is used to recursively walk the resulting structure so
+ // that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+ // Parsing happens in four stages. In the first stage, we replace certain
+ // Unicode characters with escape sequences. JavaScript handles many characters
+ // incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+ // In the second stage, we run the text against regular expressions that look
+ // for non-JSON patterns. We are especially concerned with '()' and 'new'
+ // because they can cause invocation, and '=' because it can cause mutation.
+ // But just to be safe, we want to reject all unexpected forms.
+
+ // We split the second stage into 4 regexp operations in order to work around
+ // crippling inefficiencies in IE's and Safari's regexp engines. First we
+ // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+ // replace all simple value tokens with ']' characters. Third, we delete all
+ // open brackets that follow a colon or comma or that begin the text. Finally,
+ // we look to see that the remaining characters are only whitespace or ']' or
+ // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+ // In the third stage we use the eval function to compile the text into a
+ // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+ // in JavaScript: it can begin a block or an object literal. We wrap the text
+ // in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+ // In the optional fourth stage, we recursively walk the new structure, passing
+ // each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+ // If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , typeof JSON !== 'undefined' ? JSON : undefined
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Parser namespace.
+ *
+ * @namespace
+ */
+
+ var parser = exports.parser = {};
+
+ /**
+ * Packet types.
+ */
+
+ var packets = parser.packets = [
+ 'disconnect'
+ , 'connect'
+ , 'heartbeat'
+ , 'message'
+ , 'json'
+ , 'event'
+ , 'ack'
+ , 'error'
+ , 'noop'
+ ];
+
+ /**
+ * Errors reasons.
+ */
+
+ var reasons = parser.reasons = [
+ 'transport not supported'
+ , 'client not handshaken'
+ , 'unauthorized'
+ ];
+
+ /**
+ * Errors advice.
+ */
+
+ var advice = parser.advice = [
+ 'reconnect'
+ ];
+
+ /**
+ * Shortcuts.
+ */
+
+ var JSON = io.JSON
+ , indexOf = io.util.indexOf;
+
+ /**
+ * Encodes a packet.
+ *
+ * @api private
+ */
+
+ parser.encodePacket = function (packet) {
+ var type = indexOf(packets, packet.type)
+ , id = packet.id || ''
+ , endpoint = packet.endpoint || ''
+ , ack = packet.ack
+ , data = null;
+
+ switch (packet.type) {
+ case 'error':
+ var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
+ , adv = packet.advice ? indexOf(advice, packet.advice) : '';
+
+ if (reason !== '' || adv !== '')
+ data = reason + (adv !== '' ? ('+' + adv) : '');
+
+ break;
+
+ case 'message':
+ if (packet.data !== '')
+ data = packet.data;
+ break;
+
+ case 'event':
+ var ev = { name: packet.name };
+
+ if (packet.args && packet.args.length) {
+ ev.args = packet.args;
+ }
+
+ data = JSON.stringify(ev);
+ break;
+
+ case 'json':
+ data = JSON.stringify(packet.data);
+ break;
+
+ case 'connect':
+ if (packet.qs)
+ data = packet.qs;
+ break;
+
+ case 'ack':
+ data = packet.ackId
+ + (packet.args && packet.args.length
+ ? '+' + JSON.stringify(packet.args) : '');
+ break;
+ }
+
+ // construct packet with required fragments
+ var encoded = [
+ type
+ , id + (ack == 'data' ? '+' : '')
+ , endpoint
+ ];
+
+ // data fragment is optional
+ if (data !== null && data !== undefined)
+ encoded.push(data);
+
+ return encoded.join(':');
+ };
+
+ /**
+ * Encodes multiple messages (payload).
+ *
+ * @param {Array} messages
+ * @api private
+ */
+
+ parser.encodePayload = function (packets) {
+ var decoded = '';
+
+ if (packets.length == 1)
+ return packets[0];
+
+ for (var i = 0, l = packets.length; i < l; i++) {
+ var packet = packets[i];
+ decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
+ }
+
+ return decoded;
+ };
+
+ /**
+ * Decodes a packet
+ *
+ * @api private
+ */
+
+ var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
+
+ parser.decodePacket = function (data) {
+ var pieces = data.match(regexp);
+
+ if (!pieces) return {};
+
+ var id = pieces[2] || ''
+ , data = pieces[5] || ''
+ , packet = {
+ type: packets[pieces[1]]
+ , endpoint: pieces[4] || ''
+ };
+
+ // whether we need to acknowledge the packet
+ if (id) {
+ packet.id = id;
+ if (pieces[3])
+ packet.ack = 'data';
+ else
+ packet.ack = true;
+ }
+
+ // handle different packet types
+ switch (packet.type) {
+ case 'error':
+ var pieces = data.split('+');
+ packet.reason = reasons[pieces[0]] || '';
+ packet.advice = advice[pieces[1]] || '';
+ break;
+
+ case 'message':
+ packet.data = data || '';
+ break;
+
+ case 'event':
+ try {
+ var opts = JSON.parse(data);
+ packet.name = opts.name;
+ packet.args = opts.args;
+ } catch (e) { }
+
+ packet.args = packet.args || [];
+ break;
+
+ case 'json':
+ try {
+ packet.data = JSON.parse(data);
+ } catch (e) { }
+ break;
+
+ case 'connect':
+ packet.qs = data || '';
+ break;
+
+ case 'ack':
+ var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
+ if (pieces) {
+ packet.ackId = pieces[1];
+ packet.args = [];
+
+ if (pieces[3]) {
+ try {
+ packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
+ } catch (e) { }
+ }
+ }
+ break;
+
+ case 'disconnect':
+ case 'heartbeat':
+ break;
+ };
+
+ return packet;
+ };
+
+ /**
+ * Decodes data payload. Detects multiple messages
+ *
+ * @return {Array} messages
+ * @api public
+ */
+
+ parser.decodePayload = function (data) {
+ // IE doesn't like data[i] for unicode chars, charAt works fine
+ if (data.charAt(0) == '\ufffd') {
+ var ret = [];
+
+ for (var i = 1, length = ''; i < data.length; i++) {
+ if (data.charAt(i) == '\ufffd') {
+ ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
+ i += Number(length) + 1;
+ length = '';
+ } else {
+ length += data.charAt(i);
+ }
+ }
+
+ return ret;
+ } else {
+ return [parser.decodePacket(data)];
+ }
+ };
+
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.Transport = Transport;
+
+ /**
+ * This is the transport template for all supported transport methods.
+ *
+ * @constructor
+ * @api public
+ */
+
+ function Transport (socket, sessid) {
+ this.socket = socket;
+ this.sessid = sessid;
+ };
+
+ /**
+ * Apply EventEmitter mixin.
+ */
+
+ io.util.mixin(Transport, io.EventEmitter);
+
+
+ /**
+ * Indicates whether heartbeats is enabled for this transport
+ *
+ * @api private
+ */
+
+ Transport.prototype.heartbeats = function () {
+ return true;
+ };
+
+ /**
+ * Handles the response from the server. When a new response is received
+ * it will automatically update the timeout, decode the message and
+ * forwards the response to the onMessage function for further processing.
+ *
+ * @param {String} data Response from the server.
+ * @api private
+ */
+
+ Transport.prototype.onData = function (data) {
+ this.clearCloseTimeout();
+
+ // If the connection in currently open (or in a reopening state) reset the close
+ // timeout since we have just received data. This check is necessary so
+ // that we don't reset the timeout on an explicitly disconnected connection.
+ if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {
+ this.setCloseTimeout();
+ }
+
+ if (data !== '') {
+ // todo: we should only do decodePayload for xhr transports
+ var msgs = io.parser.decodePayload(data);
+
+ if (msgs && msgs.length) {
+ for (var i = 0, l = msgs.length; i < l; i++) {
+ this.onPacket(msgs[i]);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Handles packets.
+ *
+ * @api private
+ */
+
+ Transport.prototype.onPacket = function (packet) {
+ this.socket.setHeartbeatTimeout();
+
+ if (packet.type == 'heartbeat') {
+ return this.onHeartbeat();
+ }
+
+ if (packet.type == 'connect' && packet.endpoint == '') {
+ this.onConnect();
+ }
+
+ if (packet.type == 'error' && packet.advice == 'reconnect') {
+ this.isOpen = false;
+ }
+
+ this.socket.onPacket(packet);
+
+ return this;
+ };
+
+ /**
+ * Sets close timeout
+ *
+ * @api private
+ */
+
+ Transport.prototype.setCloseTimeout = function () {
+ if (!this.closeTimeout) {
+ var self = this;
+
+ this.closeTimeout = setTimeout(function () {
+ self.onDisconnect();
+ }, this.socket.closeTimeout);
+ }
+ };
+
+ /**
+ * Called when transport disconnects.
+ *
+ * @api private
+ */
+
+ Transport.prototype.onDisconnect = function () {
+ if (this.isOpen) this.close();
+ this.clearTimeouts();
+ this.socket.onDisconnect();
+ return this;
+ };
+
+ /**
+ * Called when transport connects
+ *
+ * @api private
+ */
+
+ Transport.prototype.onConnect = function () {
+ this.socket.onConnect();
+ return this;
+ };
+
+ /**
+ * Clears close timeout
+ *
+ * @api private
+ */
+
+ Transport.prototype.clearCloseTimeout = function () {
+ if (this.closeTimeout) {
+ clearTimeout(this.closeTimeout);
+ this.closeTimeout = null;
+ }
+ };
+
+ /**
+ * Clear timeouts
+ *
+ * @api private
+ */
+
+ Transport.prototype.clearTimeouts = function () {
+ this.clearCloseTimeout();
+
+ if (this.reopenTimeout) {
+ clearTimeout(this.reopenTimeout);
+ }
+ };
+
+ /**
+ * Sends a packet
+ *
+ * @param {Object} packet object.
+ * @api private
+ */
+
+ Transport.prototype.packet = function (packet) {
+ this.send(io.parser.encodePacket(packet));
+ };
+
+ /**
+ * Send the received heartbeat message back to server. So the server
+ * knows we are still connected.
+ *
+ * @param {String} heartbeat Heartbeat response from the server.
+ * @api private
+ */
+
+ Transport.prototype.onHeartbeat = function (heartbeat) {
+ this.packet({ type: 'heartbeat' });
+ };
+
+ /**
+ * Called when the transport opens.
+ *
+ * @api private
+ */
+
+ Transport.prototype.onOpen = function () {
+ this.isOpen = true;
+ this.clearCloseTimeout();
+ this.socket.onOpen();
+ };
+
+ /**
+ * Notifies the base when the connection with the Socket.IO server
+ * has been disconnected.
+ *
+ * @api private
+ */
+
+ Transport.prototype.onClose = function () {
+ var self = this;
+
+ /* FIXME: reopen delay causing a infinit loop
+ this.reopenTimeout = setTimeout(function () {
+ self.open();
+ }, this.socket.options['reopen delay']);*/
+
+ this.isOpen = false;
+ this.socket.onClose();
+ this.onDisconnect();
+ };
+
+ /**
+ * Generates a connection url based on the Socket.IO URL Protocol.
+ * See <https://github.com/learnboost/socket.io-node/> for more details.
+ *
+ * @returns {String} Connection url
+ * @api private
+ */
+
+ Transport.prototype.prepareUrl = function () {
+ var options = this.socket.options;
+
+ return this.scheme() + '://'
+ + options.host + ':' + options.port + '/'
+ + options.resource + '/' + io.protocol
+ + '/' + this.name + '/' + this.sessid;
+ };
+
+ /**
+ * Checks if the transport is ready to start a connection.
+ *
+ * @param {Socket} socket The socket instance that needs a transport
+ * @param {Function} fn The callback
+ * @api private
+ */
+
+ Transport.prototype.ready = function (socket, fn) {
+ fn.call(this);
+ };
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.Socket = Socket;
+
+ /**
+ * Create a new `Socket.IO client` which can establish a persistent
+ * connection with a Socket.IO enabled server.
+ *
+ * @api public
+ */
+
+ function Socket (options) {
+ this.options = {
+ port: 80
+ , secure: false
+ , document: 'document' in global ? document : false
+ , resource: 'socket.io'
+ , transports: io.transports
+ , 'connect timeout': 10000
+ , 'try multiple transports': true
+ , 'reconnect': true
+ , 'reconnection delay': 500
+ , 'reconnection limit': Infinity
+ , 'reopen delay': 3000
+ , 'max reconnection attempts': 10
+ , 'sync disconnect on unload': false
+ , 'auto connect': true
+ , 'flash policy port': 10843
+ , 'manualFlush': false
+ };
+
+ io.util.merge(this.options, options);
+
+ this.connected = false;
+ this.open = false;
+ this.connecting = false;
+ this.reconnecting = false;
+ this.namespaces = {};
+ this.buffer = [];
+ this.doBuffer = false;
+
+ if (this.options['sync disconnect on unload'] &&
+ (!this.isXDomain() || io.util.ua.hasCORS)) {
+ var self = this;
+ io.util.on(global, 'beforeunload', function () {
+ self.disconnectSync();
+ }, false);
+ }
+
+ if (this.options['auto connect']) {
+ this.connect();
+ }
+};
+
+ /**
+ * Apply EventEmitter mixin.
+ */
+
+ io.util.mixin(Socket, io.EventEmitter);
+
+ /**
+ * Returns a namespace listener/emitter for this socket
+ *
+ * @api public
+ */
+
+ Socket.prototype.of = function (name) {
+ if (!this.namespaces[name]) {
+ this.namespaces[name] = new io.SocketNamespace(this, name);
+
+ if (name !== '') {
+ this.namespaces[name].packet({ type: 'connect' });
+ }
+ }
+
+ return this.namespaces[name];
+ };
+
+ /**
+ * Emits the given event to the Socket and all namespaces
+ *
+ * @api private
+ */
+
+ Socket.prototype.publish = function () {
+ this.emit.apply(this, arguments);
+
+ var nsp;
+
+ for (var i in this.namespaces) {
+ if (this.namespaces.hasOwnProperty(i)) {
+ nsp = this.of(i);
+ nsp.$emit.apply(nsp, arguments);
+ }
+ }
+ };
+
+ /**
+ * Performs the handshake
+ *
+ * @api private
+ */
+
+ function empty () { };
+
+ Socket.prototype.handshake = function (fn) {
+ var self = this
+ , options = this.options;
+
+ function complete (data) {
+ if (data instanceof Error) {
+ self.connecting = false;
+ self.onError(data.message);
+ } else {
+ fn.apply(null, data.split(':'));
+ }
+ };
+
+ var url = [
+ 'http' + (options.secure ? 's' : '') + ':/'
+ , options.host + ':' + options.port
+ , options.resource
+ , io.protocol
+ , io.util.query(this.options.query, 't=' + +new Date)
+ ].join('/');
+
+ if (this.isXDomain() && !io.util.ua.hasCORS) {
+ var insertAt = document.getElementsByTagName('script')[0]
+ , script = document.createElement('script');
+
+ script.src = url + '&jsonp=' + io.j.length;
+ insertAt.parentNode.insertBefore(script, insertAt);
+
+ io.j.push(function (data) {
+ complete(data);
+ script.parentNode.removeChild(script);
+ });
+ } else {
+ var xhr = io.util.request();
+
+ xhr.open('GET', url, true);
+ if (this.isXDomain()) {
+ xhr.withCredentials = true;
+ }
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState == 4) {
+ xhr.onreadystatechange = empty;
+
+ if (xhr.status == 200) {
+ complete(xhr.responseText);
+ } else if (xhr.status == 403) {
+ self.onError(xhr.responseText);
+ } else {
+ self.connecting = false;
+ !self.reconnecting && self.onError(xhr.responseText);
+ }
+ }
+ };
+ xhr.send(null);
+ }
+ };
+
+ /**
+ * Find an available transport based on the options supplied in the constructor.
+ *
+ * @api private
+ */
+
+ Socket.prototype.getTransport = function (override) {
+ var transports = override || this.transports, match;
+
+ for (var i = 0, transport; transport = transports[i]; i++) {
+ if (io.Transport[transport]
+ && io.Transport[transport].check(this)
+ && (!this.isXDomain() || io.Transport[transport].xdomainCheck(this))) {
+ return new io.Transport[transport](this, this.sessionid);
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * Connects to the server.
+ *
+ * @param {Function} [fn] Callback.
+ * @returns {io.Socket}
+ * @api public
+ */
+
+ Socket.prototype.connect = function (fn) {
+ if (this.connecting) {
+ return this;
+ }
+
+ var self = this;
+ self.connecting = true;
+
+ this.handshake(function (sid, heartbeat, close, transports) {
+ self.sessionid = sid;
+ self.closeTimeout = close * 1000;
+ self.heartbeatTimeout = heartbeat * 1000;
+ if(!self.transports)
+ self.transports = self.origTransports = (transports ? io.util.intersect(
+ transports.split(',')
+ , self.options.transports
+ ) : self.options.transports);
+
+ self.setHeartbeatTimeout();
+
+ function connect (transports){
+ if (self.transport) self.transport.clearTimeouts();
+
+ self.transport = self.getTransport(transports);
+ if (!self.transport) return self.publish('connect_failed');
+
+ // once the transport is ready
+ self.transport.ready(self, function () {
+ self.connecting = true;
+ self.publish('connecting', self.transport.name);
+ self.transport.open();
+
+ if (self.options['connect timeout']) {
+ self.connectTimeoutTimer = setTimeout(function () {
+ if (!self.connected) {
+ self.connecting = false;
+
+ if (self.options['try multiple transports']) {
+ var remaining = self.transports;
+
+ while (remaining.length > 0 && remaining.splice(0,1)[0] !=
+ self.transport.name) {}
+
+ if (remaining.length){
+ connect(remaining);
+ } else {
+ self.publish('connect_failed');
+ }
+ }
+ }
+ }, self.options['connect timeout']);
+ }
+ });
+ }
+
+ connect(self.transports);
+
+ self.once('connect', function (){
+ clearTimeout(self.connectTimeoutTimer);
+
+ fn && typeof fn == 'function' && fn();
+ });
+ });
+
+ return this;
+ };
+
+ /**
+ * Clears and sets a new heartbeat timeout using the value given by the
+ * server during the handshake.
+ *
+ * @api private
+ */
+
+ Socket.prototype.setHeartbeatTimeout = function () {
+ clearTimeout(this.heartbeatTimeoutTimer);
+ if(this.transport && !this.transport.heartbeats()) return;
+
+ var self = this;
+ this.heartbeatTimeoutTimer = setTimeout(function () {
+ self.transport.onClose();
+ }, this.heartbeatTimeout);
+ };
+
+ /**
+ * Sends a message.
+ *
+ * @param {Object} data packet.
+ * @returns {io.Socket}
+ * @api public
+ */
+
+ Socket.prototype.packet = function (data) {
+ if (this.connected && !this.doBuffer) {
+ this.transport.packet(data);
+ } else {
+ this.buffer.push(data);
+ }
+
+ return this;
+ };
+
+ /**
+ * Sets buffer state
+ *
+ * @api private
+ */
+
+ Socket.prototype.setBuffer = function (v) {
+ this.doBuffer = v;
+
+ if (!v && this.connected && this.buffer.length) {
+ if (!this.options['manualFlush']) {
+ this.flushBuffer();
+ }
+ }
+ };
+
+ /**
+ * Flushes the buffer data over the wire.
+ * To be invoked manually when 'manualFlush' is set to true.
+ *
+ * @api public
+ */
+
+ Socket.prototype.flushBuffer = function() {
+ this.transport.payload(this.buffer);
+ this.buffer = [];
+ };
+
+
+ /**
+ * Disconnect the established connect.
+ *
+ * @returns {io.Socket}
+ * @api public
+ */
+
+ Socket.prototype.disconnect = function () {
+ if (this.connected || this.connecting) {
+ if (this.open) {
+ this.of('').packet({ type: 'disconnect' });
+ }
+
+ // handle disconnection immediately
+ this.onDisconnect('booted');
+ }
+
+ return this;
+ };
+
+ /**
+ * Disconnects the socket with a sync XHR.
+ *
+ * @api private
+ */
+
+ Socket.prototype.disconnectSync = function () {
+ // ensure disconnection
+ var xhr = io.util.request();
+ var uri = [
+ 'http' + (this.options.secure ? 's' : '') + ':/'
+ , this.options.host + ':' + this.options.port
+ , this.options.resource
+ , io.protocol
+ , ''
+ , this.sessionid
+ ].join('/') + '/?disconnect=1';
+
+ xhr.open('GET', uri, false);
+ xhr.send(null);
+
+ // handle disconnection immediately
+ this.onDisconnect('booted');
+ };
+
+ /**
+ * Check if we need to use cross domain enabled transports. Cross domain would
+ * be a different port or different domain name.
+ *
+ * @returns {Boolean}
+ * @api private
+ */
+
+ Socket.prototype.isXDomain = function () {
+
+ var port = global.location.port ||
+ ('https:' == global.location.protocol ? 443 : 80);
+
+ return this.options.host !== global.location.hostname
+ || this.options.port != port;
+ };
+
+ /**
+ * Called upon handshake.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onConnect = function () {
+ if (!this.connected) {
+ this.connected = true;
+ this.connecting = false;
+ if (!this.doBuffer) {
+ // make sure to flush the buffer
+ this.setBuffer(false);
+ }
+ this.emit('connect');
+ }
+ };
+
+ /**
+ * Called when the transport opens
+ *
+ * @api private
+ */
+
+ Socket.prototype.onOpen = function () {
+ this.open = true;
+ };
+
+ /**
+ * Called when the transport closes.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onClose = function () {
+ this.open = false;
+ clearTimeout(this.heartbeatTimeoutTimer);
+ };
+
+ /**
+ * Called when the transport first opens a connection
+ *
+ * @param text
+ */
+
+ Socket.prototype.onPacket = function (packet) {
+ this.of(packet.endpoint).onPacket(packet);
+ };
+
+ /**
+ * Handles an error.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onError = function (err) {
+ if (err && err.advice) {
+ if (err.advice === 'reconnect' && (this.connected || this.connecting)) {
+ this.disconnect();
+ if (this.options.reconnect) {
+ this.reconnect();
+ }
+ }
+ }
+
+ this.publish('error', err && err.reason ? err.reason : err);
+ };
+
+ /**
+ * Called when the transport disconnects.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onDisconnect = function (reason) {
+ var wasConnected = this.connected
+ , wasConnecting = this.connecting;
+
+ this.connected = false;
+ this.connecting = false;
+ this.open = false;
+
+ if (wasConnected || wasConnecting) {
+ this.transport.close();
+ this.transport.clearTimeouts();
+ if (wasConnected) {
+ this.publish('disconnect', reason);
+
+ if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
+ this.reconnect();
+ }
+ }
+ }
+ };
+
+ /**
+ * Called upon reconnection.
+ *
+ * @api private
+ */
+
+ Socket.prototype.reconnect = function () {
+ this.reconnecting = true;
+ this.reconnectionAttempts = 0;
+ this.reconnectionDelay = this.options['reconnection delay'];
+
+ var self = this
+ , maxAttempts = this.options['max reconnection attempts']
+ , tryMultiple = this.options['try multiple transports']
+ , limit = this.options['reconnection limit'];
+
+ function reset () {
+ if (self.connected) {
+ for (var i in self.namespaces) {
+ if (self.namespaces.hasOwnProperty(i) && '' !== i) {
+ self.namespaces[i].packet({ type: 'connect' });
+ }
+ }
+ self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
+ }
+
+ clearTimeout(self.reconnectionTimer);
+
+ self.removeListener('connect_failed', maybeReconnect);
+ self.removeListener('connect', maybeReconnect);
+
+ self.reconnecting = false;
+
+ delete self.reconnectionAttempts;
+ delete self.reconnectionDelay;
+ delete self.reconnectionTimer;
+ delete self.redoTransports;
+
+ self.options['try multiple transports'] = tryMultiple;
+ };
+
+ function maybeReconnect () {
+ if (!self.reconnecting) {
+ return;
+ }
+
+ if (self.connected) {
+ return reset();
+ };
+
+ if (self.connecting && self.reconnecting) {
+ return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
+ }
+
+ if (self.reconnectionAttempts++ >= maxAttempts) {
+ if (!self.redoTransports) {
+ self.on('connect_failed', maybeReconnect);
+ self.options['try multiple transports'] = true;
+ self.transports = self.origTransports;
+ self.transport = self.getTransport();
+ self.redoTransports = true;
+ self.connect();
+ } else {
+ self.publish('reconnect_failed');
+ reset();
+ }
+ } else {
+ if (self.reconnectionDelay < limit) {
+ self.reconnectionDelay *= 2; // exponential back off
+ }
+
+ self.connect();
+ self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
+ self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
+ }
+ };
+
+ this.options['try multiple transports'] = false;
+ this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
+
+ this.on('connect', maybeReconnect);
+ };
+
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.SocketNamespace = SocketNamespace;
+
+ /**
+ * Socket namespace constructor.
+ *
+ * @constructor
+ * @api public
+ */
+
+ function SocketNamespace (socket, name) {
+ this.socket = socket;
+ this.name = name || '';
+ this.flags = {};
+ this.json = new Flag(this, 'json');
+ this.ackPackets = 0;
+ this.acks = {};
+ };
+
+ /**
+ * Apply EventEmitter mixin.
+ */
+
+ io.util.mixin(SocketNamespace, io.EventEmitter);
+
+ /**
+ * Copies emit since we override it
+ *
+ * @api private
+ */
+
+ SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
+
+ /**
+ * Creates a new namespace, by proxying the request to the socket. This
+ * allows us to use the synax as we do on the server.
+ *
+ * @api public
+ */
+
+ SocketNamespace.prototype.of = function () {
+ return this.socket.of.apply(this.socket, arguments);
+ };
+
+ /**
+ * Sends a packet.
+ *
+ * @api private
+ */
+
+ SocketNamespace.prototype.packet = function (packet) {
+ packet.endpoint = this.name;
+ this.socket.packet(packet);
+ this.flags = {};
+ return this;
+ };
+
+ /**
+ * Sends a message
+ *
+ * @api public
+ */
+
+ SocketNamespace.prototype.send = function (data, fn) {
+ var packet = {
+ type: this.flags.json ? 'json' : 'message'
+ , data: data
+ };
+
+ if ('function' == typeof fn) {
+ packet.id = ++this.ackPackets;
+ packet.ack = true;
+ this.acks[packet.id] = fn;
+ }
+
+ return this.packet(packet);
+ };
+
+ /**
+ * Emits an event
+ *
+ * @api public
+ */
+
+ SocketNamespace.prototype.emit = function (name) {
+ var args = Array.prototype.slice.call(arguments, 1)
+ , lastArg = args[args.length - 1]
+ , packet = {
+ type: 'event'
+ , name: name
+ };
+
+ if ('function' == typeof lastArg) {
+ packet.id = ++this.ackPackets;
+ packet.ack = 'data';
+ this.acks[packet.id] = lastArg;
+ args = args.slice(0, args.length - 1);
+ }
+
+ packet.args = args;
+
+ return this.packet(packet);
+ };
+
+ /**
+ * Disconnects the namespace
+ *
+ * @api private
+ */
+
+ SocketNamespace.prototype.disconnect = function () {
+ if (this.name === '') {
+ this.socket.disconnect();
+ } else {
+ this.packet({ type: 'disconnect' });
+ this.$emit('disconnect');
+ }
+
+ return this;
+ };
+
+ /**
+ * Handles a packet
+ *
+ * @api private
+ */
+
+ SocketNamespace.prototype.onPacket = function (packet) {
+ var self = this;
+
+ function ack () {
+ self.packet({
+ type: 'ack'
+ , args: io.util.toArray(arguments)
+ , ackId: packet.id
+ });
+ };
+
+ switch (packet.type) {
+ case 'connect':
+ this.$emit('connect');
+ break;
+
+ case 'disconnect':
+ if (this.name === '') {
+ this.socket.onDisconnect(packet.reason || 'booted');
+ } else {
+ this.$emit('disconnect', packet.reason);
+ }
+ break;
+
+ case 'message':
+ case 'json':
+ var params = ['message', packet.data];
+
+ if (packet.ack == 'data') {
+ params.push(ack);
+ } else if (packet.ack) {
+ this.packet({ type: 'ack', ackId: packet.id });
+ }
+
+ this.$emit.apply(this, params);
+ break;
+
+ case 'event':
+ var params = [packet.name].concat(packet.args);
+
+ if (packet.ack == 'data')
+ params.push(ack);
+
+ this.$emit.apply(this, params);
+ break;
+
+ case 'ack':
+ if (this.acks[packet.ackId]) {
+ this.acks[packet.ackId].apply(this, packet.args);
+ delete this.acks[packet.ackId];
+ }
+ break;
+
+ case 'error':
+ if (packet.advice){
+ this.socket.onError(packet);
+ } else {
+ if (packet.reason == 'unauthorized') {
+ this.$emit('connect_failed', packet.reason);
+ } else {
+ this.$emit('error', packet.reason);
+ }
+ }
+ break;
+ }
+ };
+
+ /**
+ * Flag interface.
+ *
+ * @api private
+ */
+
+ function Flag (nsp, name) {
+ this.namespace = nsp;
+ this.name = name;
+ };
+
+ /**
+ * Send a message
+ *
+ * @api public
+ */
+
+ Flag.prototype.send = function () {
+ this.namespace.flags[this.name] = true;
+ this.namespace.send.apply(this.namespace, arguments);
+ };
+
+ /**
+ * Emit an event
+ *
+ * @api public
+ */
+
+ Flag.prototype.emit = function () {
+ this.namespace.flags[this.name] = true;
+ this.namespace.emit.apply(this.namespace, arguments);
+ };
+
+})(
+ 'undefined' != typeof io ? io : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.websocket = WS;
+
+ /**
+ * The WebSocket transport uses the HTML5 WebSocket API to establish an
+ * persistent connection with the Socket.IO server. This transport will also
+ * be inherited by the FlashSocket fallback as it provides a API compatible
+ * polyfill for the WebSockets.
+ *
+ * @constructor
+ * @extends {io.Transport}
+ * @api public
+ */
+
+ function WS (socket) {
+ io.Transport.apply(this, arguments);
+ };
+
+ /**
+ * Inherits from Transport.
+ */
+
+ io.util.inherit(WS, io.Transport);
+
+ /**
+ * Transport name
+ *
+ * @api public
+ */
+
+ WS.prototype.name = 'websocket';
+
+ /**
+ * Initializes a new `WebSocket` connection with the Socket.IO server. We attach
+ * all the appropriate listeners to handle the responses from the server.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ WS.prototype.open = function () {
+ var query = io.util.query(this.socket.options.query)
+ , self = this
+ , Socket
+
+
+ if (!Socket) {
+ Socket = global.MozWebSocket || global.WebSocket;
+ }
+
+ this.websocket = new Socket(this.prepareUrl() + query);
+
+ this.websocket.onopen = function () {
+ self.onOpen();
+ self.socket.setBuffer(false);
+ };
+ this.websocket.onmessage = function (ev) {
+ self.onData(ev.data);
+ };
+ this.websocket.onclose = function () {
+ self.onClose();
+ self.socket.setBuffer(true);
+ };
+ this.websocket.onerror = function (e) {
+ self.onError(e);
+ };
+
+ return this;
+ };
+
+ /**
+ * Send a message to the Socket.IO server. The message will automatically be
+ * encoded in the correct message format.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ // Do to a bug in the current IDevices browser, we need to wrap the send in a
+ // setTimeout, when they resume from sleeping the browser will crash if
+ // we don't allow the browser time to detect the socket has been closed
+ if (io.util.ua.iDevice) {
+ WS.prototype.send = function (data) {
+ var self = this;
+ setTimeout(function() {
+ self.websocket.send(data);
+ },0);
+ return this;
+ };
+ } else {
+ WS.prototype.send = function (data) {
+ this.websocket.send(data);
+ return this;
+ };
+ }
+
+ /**
+ * Payload
+ *
+ * @api private
+ */
+
+ WS.prototype.payload = function (arr) {
+ for (var i = 0, l = arr.length; i < l; i++) {
+ this.packet(arr[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Disconnect the established `WebSocket` connection.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ WS.prototype.close = function () {
+ this.websocket.close();
+ return this;
+ };
+
+ /**
+ * Handle the errors that `WebSocket` might be giving when we
+ * are attempting to connect or send messages.
+ *
+ * @param {Error} e The error.
+ * @api private
+ */
+
+ WS.prototype.onError = function (e) {
+ this.socket.onError(e);
+ };
+
+ /**
+ * Returns the appropriate scheme for the URI generation.
+ *
+ * @api private
+ */
+ WS.prototype.scheme = function () {
+ return this.socket.options.secure ? 'wss' : 'ws';
+ };
+
+ /**
+ * Checks if the browser has support for native `WebSockets` and that
+ * it's not the polyfill created for the FlashSocket transport.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+ WS.check = function () {
+ return ('WebSocket' in global && !('__addTask' in WebSocket))
+ || 'MozWebSocket' in global;
+ };
+
+ /**
+ * Check if the `WebSocket` transport support cross domain communications.
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ WS.xdomainCheck = function () {
+ return true;
+ };
+
+ /**
+ * Add the transport to your public io.transports array.
+ *
+ * @api private
+ */
+
+ io.transports.push('websocket');
+
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.flashsocket = Flashsocket;
+
+ /**
+ * The FlashSocket transport. This is a API wrapper for the HTML5 WebSocket
+ * specification. It uses a .swf file to communicate with the server. If you want
+ * to serve the .swf file from a other server than where the Socket.IO script is
+ * coming from you need to use the insecure version of the .swf. More information
+ * about this can be found on the github page.
+ *
+ * @constructor
+ * @extends {io.Transport.websocket}
+ * @api public
+ */
+
+ function Flashsocket () {
+ io.Transport.websocket.apply(this, arguments);
+ };
+
+ /**
+ * Inherits from Transport.
+ */
+
+ io.util.inherit(Flashsocket, io.Transport.websocket);
+
+ /**
+ * Transport name
+ *
+ * @api public
+ */
+
+ Flashsocket.prototype.name = 'flashsocket';
+
+ /**
+ * Disconnect the established `FlashSocket` connection. This is done by adding a
+ * new task to the FlashSocket. The rest will be handled off by the `WebSocket`
+ * transport.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ Flashsocket.prototype.open = function () {
+ var self = this
+ , args = arguments;
+
+ WebSocket.__addTask(function () {
+ io.Transport.websocket.prototype.open.apply(self, args);
+ });
+ return this;
+ };
+
+ /**
+ * Sends a message to the Socket.IO server. This is done by adding a new
+ * task to the FlashSocket. The rest will be handled off by the `WebSocket`
+ * transport.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ Flashsocket.prototype.send = function () {
+ var self = this, args = arguments;
+ WebSocket.__addTask(function () {
+ io.Transport.websocket.prototype.send.apply(self, args);
+ });
+ return this;
+ };
+
+ /**
+ * Disconnects the established `FlashSocket` connection.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ Flashsocket.prototype.close = function () {
+ WebSocket.__tasks.length = 0;
+ io.Transport.websocket.prototype.close.call(this);
+ return this;
+ };
+
+ /**
+ * The WebSocket fall back needs to append the flash container to the body
+ * element, so we need to make sure we have access to it. Or defer the call
+ * until we are sure there is a body element.
+ *
+ * @param {Socket} socket The socket instance that needs a transport
+ * @param {Function} fn The callback
+ * @api private
+ */
+
+ Flashsocket.prototype.ready = function (socket, fn) {
+ function init () {
+ var options = socket.options
+ , port = options['flash policy port']
+ , path = [
+ 'http' + (options.secure ? 's' : '') + ':/'
+ , options.host + ':' + options.port
+ , options.resource
+ , 'static/flashsocket'
+ , 'WebSocketMain' + (socket.isXDomain() ? 'Insecure' : '') + '.swf'
+ ];
+
+ // Only start downloading the swf file when the checked that this browser
+ // actually supports it
+ if (!Flashsocket.loaded) {
+ if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') {
+ // Set the correct file based on the XDomain settings
+ WEB_SOCKET_SWF_LOCATION = path.join('/');
+ }
+
+ if (port !== 843) {
+ WebSocket.loadFlashPolicyFile('xmlsocket://' + options.host + ':' + port);
+ }
+
+ WebSocket.__initialize();
+ Flashsocket.loaded = true;
+ }
+
+ fn.call(self);
+ }
+
+ var self = this;
+ if (document.body) return init();
+
+ io.util.load(init);
+ };
+
+ /**
+ * Check if the FlashSocket transport is supported as it requires that the Adobe
+ * Flash Player plug-in version `10.0.0` or greater is installed. And also check if
+ * the polyfill is correctly loaded.
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ Flashsocket.check = function () {
+ if (
+ typeof WebSocket == 'undefined'
+ || !('__initialize' in WebSocket) || !swfobject
+ ) return false;
+
+ return swfobject.getFlashPlayerVersion().major >= 10;
+ };
+
+ /**
+ * Check if the FlashSocket transport can be used as cross domain / cross origin
+ * transport. Because we can't see which type (secure or insecure) of .swf is used
+ * we will just return true.
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ Flashsocket.xdomainCheck = function () {
+ return true;
+ };
+
+ /**
+ * Disable AUTO_INITIALIZATION
+ */
+
+ if (typeof window != 'undefined') {
+ WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
+ }
+
+ /**
+ * Add the transport to your public io.transports array.
+ *
+ * @api private
+ */
+
+ io.transports.push('flashsocket');
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+*/
+if ('undefined' != typeof window) {
+var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O[(['Active'].concat('Object').join('X'))]!=D){try{var ad=new window[(['Active'].concat('Object').join('X'))](W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?(['Active'].concat('').join('X')):"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
+}
+// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
+// License: New BSD License
+// Reference: http://dev.w3.org/html5/websockets/
+// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
+
+(function() {
+
+ if ('undefined' == typeof window || window.WebSocket) return;
+
+ var console = window.console;
+ if (!console || !console.log || !console.error) {
+ console = {log: function(){ }, error: function(){ }};
+ }
+
+ if (!swfobject.hasFlashPlayerVersion("10.0.0")) {
+ console.error("Flash Player >= 10.0.0 is required.");
+ return;
+ }
+ if (location.protocol == "file:") {
+ console.error(
+ "WARNING: web-socket-js doesn't work in file:///... URL " +
+ "unless you set Flash Security Settings properly. " +
+ "Open the page via Web server i.e. http://...");
+ }
+
+ /**
+ * This class represents a faux web socket.
+ * @param {string} url
+ * @param {array or string} protocols
+ * @param {string} proxyHost
+ * @param {int} proxyPort
+ * @param {string} headers
+ */
+ WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {
+ var self = this;
+ self.__id = WebSocket.__nextId++;
+ WebSocket.__instances[self.__id] = self;
+ self.readyState = WebSocket.CONNECTING;
+ self.bufferedAmount = 0;
+ self.__events = {};
+ if (!protocols) {
+ protocols = [];
+ } else if (typeof protocols == "string") {
+ protocols = [protocols];
+ }
+ // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
+ // Otherwise, when onopen fires immediately, onopen is called before it is set.
+ setTimeout(function() {
+ WebSocket.__addTask(function() {
+ WebSocket.__flash.create(
+ self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);
+ });
+ }, 0);
+ };
+
+ /**
+ * Send data to the web socket.
+ * @param {string} data The data to send to the socket.
+ * @return {boolean} True for success, false for failure.
+ */
+ WebSocket.prototype.send = function(data) {
+ if (this.readyState == WebSocket.CONNECTING) {
+ throw "INVALID_STATE_ERR: Web Socket connection has not been established";
+ }
+ // We use encodeURIComponent() here, because FABridge doesn't work if
+ // the argument includes some characters. We don't use escape() here
+ // because of this:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
+ // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
+ // preserve all Unicode characters either e.g. "\uffff" in Firefox.
+ // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require
+ // additional testing.
+ var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data));
+ if (result < 0) { // success
+ return true;
+ } else {
+ this.bufferedAmount += result;
+ return false;
+ }
+ };
+
+ /**
+ * Close this web socket gracefully.
+ */
+ WebSocket.prototype.close = function() {
+ if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
+ return;
+ }
+ this.readyState = WebSocket.CLOSING;
+ WebSocket.__flash.close(this.__id);
+ };
+
+ /**
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
+ *
+ * @param {string} type
+ * @param {function} listener
+ * @param {boolean} useCapture
+ * @return void
+ */
+ WebSocket.prototype.addEventListener = function(type, listener, useCapture) {
+ if (!(type in this.__events)) {
+ this.__events[type] = [];
+ }
+ this.__events[type].push(listener);
+ };
+
+ /**
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
+ *
+ * @param {string} type
+ * @param {function} listener
+ * @param {boolean} useCapture
+ * @return void
+ */
+ WebSocket.prototype.removeEventListener = function(type, listener, useCapture) {
+ if (!(type in this.__events)) return;
+ var events = this.__events[type];
+ for (var i = events.length - 1; i >= 0; --i) {
+ if (events[i] === listener) {
+ events.splice(i, 1);
+ break;
+ }
+ }
+ };
+
+ /**
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
+ *
+ * @param {Event} event
+ * @return void
+ */
+ WebSocket.prototype.dispatchEvent = function(event) {
+ var events = this.__events[event.type] || [];
+ for (var i = 0; i < events.length; ++i) {
+ events[i](event);
+ }
+ var handler = this["on" + event.type];
+ if (handler) handler(event);
+ };
+
+ /**
+ * Handles an event from Flash.
+ * @param {Object} flashEvent
+ */
+ WebSocket.prototype.__handleEvent = function(flashEvent) {
+ if ("readyState" in flashEvent) {
+ this.readyState = flashEvent.readyState;
+ }
+ if ("protocol" in flashEvent) {
+ this.protocol = flashEvent.protocol;
+ }
+
+ var jsEvent;
+ if (flashEvent.type == "open" || flashEvent.type == "error") {
+ jsEvent = this.__createSimpleEvent(flashEvent.type);
+ } else if (flashEvent.type == "close") {
+ // TODO implement jsEvent.wasClean
+ jsEvent = this.__createSimpleEvent("close");
+ } else if (flashEvent.type == "message") {
+ var data = decodeURIComponent(flashEvent.message);
+ jsEvent = this.__createMessageEvent("message", data);
+ } else {
+ throw "unknown event type: " + flashEvent.type;
+ }
+
+ this.dispatchEvent(jsEvent);
+ };
+
+ WebSocket.prototype.__createSimpleEvent = function(type) {
+ if (document.createEvent && window.Event) {
+ var event = document.createEvent("Event");
+ event.initEvent(type, false, false);
+ return event;
+ } else {
+ return {type: type, bubbles: false, cancelable: false};
+ }
+ };
+
+ WebSocket.prototype.__createMessageEvent = function(type, data) {
+ if (document.createEvent && window.MessageEvent && !window.opera) {
+ var event = document.createEvent("MessageEvent");
+ event.initMessageEvent("message", false, false, data, null, null, window, null);
+ return event;
+ } else {
+ // IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.
+ return {type: type, data: data, bubbles: false, cancelable: false};
+ }
+ };
+
+ /**
+ * Define the WebSocket readyState enumeration.
+ */
+ WebSocket.CONNECTING = 0;
+ WebSocket.OPEN = 1;
+ WebSocket.CLOSING = 2;
+ WebSocket.CLOSED = 3;
+
+ WebSocket.__flash = null;
+ WebSocket.__instances = {};
+ WebSocket.__tasks = [];
+ WebSocket.__nextId = 0;
+
+ /**
+ * Load a new flash security policy file.
+ * @param {string} url
+ */
+ WebSocket.loadFlashPolicyFile = function(url){
+ WebSocket.__addTask(function() {
+ WebSocket.__flash.loadManualPolicyFile(url);
+ });
+ };
+
+ /**
+ * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
+ */
+ WebSocket.__initialize = function() {
+ if (WebSocket.__flash) return;
+
+ if (WebSocket.__swfLocation) {
+ // For backword compatibility.
+ window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
+ }
+ if (!window.WEB_SOCKET_SWF_LOCATION) {
+ console.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
+ return;
+ }
+ var container = document.createElement("div");
+ container.id = "webSocketContainer";
+ // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
+ // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
+ // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
+ // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
+ // the best we can do as far as we know now.
+ container.style.position = "absolute";
+ if (WebSocket.__isFlashLite()) {
+ container.style.left = "0px";
+ container.style.top = "0px";
+ } else {
+ container.style.left = "-100px";
+ container.style.top = "-100px";
+ }
+ var holder = document.createElement("div");
+ holder.id = "webSocketFlash";
+ container.appendChild(holder);
+ document.body.appendChild(container);
+ // See this article for hasPriority:
+ // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
+ swfobject.embedSWF(
+ WEB_SOCKET_SWF_LOCATION,
+ "webSocketFlash",
+ "1" /* width */,
+ "1" /* height */,
+ "10.0.0" /* SWF version */,
+ null,
+ null,
+ {hasPriority: true, swliveconnect : true, allowScriptAccess: "always"},
+ null,
+ function(e) {
+ if (!e.success) {
+ console.error("[WebSocket] swfobject.embedSWF failed");
+ }
+ });
+ };
+
+ /**
+ * Called by Flash to notify JS that it's fully loaded and ready
+ * for communication.
+ */
+ WebSocket.__onFlashInitialized = function() {
+ // We need to set a timeout here to avoid round-trip calls
+ // to flash during the initialization process.
+ setTimeout(function() {
+ WebSocket.__flash = document.getElementById("webSocketFlash");
+ WebSocket.__flash.setCallerUrl(location.href);
+ WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);
+ for (var i = 0; i < WebSocket.__tasks.length; ++i) {
+ WebSocket.__tasks[i]();
+ }
+ WebSocket.__tasks = [];
+ }, 0);
+ };
+
+ /**
+ * Called by Flash to notify WebSockets events are fired.
+ */
+ WebSocket.__onFlashEvent = function() {
+ setTimeout(function() {
+ try {
+ // Gets events using receiveEvents() instead of getting it from event object
+ // of Flash event. This is to make sure to keep message order.
+ // It seems sometimes Flash events don't arrive in the same order as they are sent.
+ var events = WebSocket.__flash.receiveEvents();
+ for (var i = 0; i < events.length; ++i) {
+ WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ }, 0);
+ return true;
+ };
+
+ // Called by Flash.
+ WebSocket.__log = function(message) {
+ console.log(decodeURIComponent(message));
+ };
+
+ // Called by Flash.
+ WebSocket.__error = function(message) {
+ console.error(decodeURIComponent(message));
+ };
+
+ WebSocket.__addTask = function(task) {
+ if (WebSocket.__flash) {
+ task();
+ } else {
+ WebSocket.__tasks.push(task);
+ }
+ };
+
+ /**
+ * Test if the browser is running flash lite.
+ * @return {boolean} True if flash lite is running, false otherwise.
+ */
+ WebSocket.__isFlashLite = function() {
+ if (!window.navigator || !window.navigator.mimeTypes) {
+ return false;
+ }
+ var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
+ if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {
+ return false;
+ }
+ return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
+ };
+
+ if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
+ if (window.addEventListener) {
+ window.addEventListener("load", function(){
+ WebSocket.__initialize();
+ }, false);
+ } else {
+ window.attachEvent("onload", function(){
+ WebSocket.__initialize();
+ });
+ }
+ }
+
+})();
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ *
+ * @api public
+ */
+
+ exports.XHR = XHR;
+
+ /**
+ * XHR constructor
+ *
+ * @costructor
+ * @api public
+ */
+
+ function XHR (socket) {
+ if (!socket) return;
+
+ io.Transport.apply(this, arguments);
+ this.sendBuffer = [];
+ };
+
+ /**
+ * Inherits from Transport.
+ */
+
+ io.util.inherit(XHR, io.Transport);
+
+ /**
+ * Establish a connection
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ XHR.prototype.open = function () {
+ this.socket.setBuffer(false);
+ this.onOpen();
+ this.get();
+
+ // we need to make sure the request succeeds since we have no indication
+ // whether the request opened or not until it succeeded.
+ this.setCloseTimeout();
+
+ return this;
+ };
+
+ /**
+ * Check if we need to send data to the Socket.IO server, if we have data in our
+ * buffer we encode it and forward it to the `post` method.
+ *
+ * @api private
+ */
+
+ XHR.prototype.payload = function (payload) {
+ var msgs = [];
+
+ for (var i = 0, l = payload.length; i < l; i++) {
+ msgs.push(io.parser.encodePacket(payload[i]));
+ }
+
+ this.send(io.parser.encodePayload(msgs));
+ };
+
+ /**
+ * Send data to the Socket.IO server.
+ *
+ * @param data The message
+ * @returns {Transport}
+ * @api public
+ */
+
+ XHR.prototype.send = function (data) {
+ this.post(data);
+ return this;
+ };
+
+ /**
+ * Posts a encoded message to the Socket.IO server.
+ *
+ * @param {String} data A encoded message.
+ * @api private
+ */
+
+ function empty () { };
+
+ XHR.prototype.post = function (data) {
+ var self = this;
+ this.socket.setBuffer(true);
+
+ function stateChange () {
+ if (this.readyState == 4) {
+ this.onreadystatechange = empty;
+ self.posting = false;
+
+ if (this.status == 200){
+ self.socket.setBuffer(false);
+ } else {
+ self.onClose();
+ }
+ }
+ }
+
+ function onload () {
+ this.onload = empty;
+ self.socket.setBuffer(false);
+ };
+
+ this.sendXHR = this.request('POST');
+
+ if (global.XDomainRequest && this.sendXHR instanceof XDomainRequest) {
+ this.sendXHR.onload = this.sendXHR.onerror = onload;
+ } else {
+ this.sendXHR.onreadystatechange = stateChange;
+ }
+
+ this.sendXHR.send(data);
+ };
+
+ /**
+ * Disconnects the established `XHR` connection.
+ *
+ * @returns {Transport}
+ * @api public
+ */
+
+ XHR.prototype.close = function () {
+ this.onClose();
+ return this;
+ };
+
+ /**
+ * Generates a configured XHR request
+ *
+ * @param {String} url The url that needs to be requested.
+ * @param {String} method The method the request should use.
+ * @returns {XMLHttpRequest}
+ * @api private
+ */
+
+ XHR.prototype.request = function (method) {
+ var req = io.util.request(this.socket.isXDomain())
+ , query = io.util.query(this.socket.options.query, 't=' + +new Date);
+
+ req.open(method || 'GET', this.prepareUrl() + query, true);
+
+ if (method == 'POST') {
+ try {
+ if (req.setRequestHeader) {
+ req.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
+ } else {
+ // XDomainRequest
+ req.contentType = 'text/plain';
+ }
+ } catch (e) {}
+ }
+
+ return req;
+ };
+
+ /**
+ * Returns the scheme to use for the transport URLs.
+ *
+ * @api private
+ */
+
+ XHR.prototype.scheme = function () {
+ return this.socket.options.secure ? 'https' : 'http';
+ };
+
+ /**
+ * Check if the XHR transports are supported
+ *
+ * @param {Boolean} xdomain Check if we support cross domain requests.
+ * @returns {Boolean}
+ * @api public
+ */
+
+ XHR.check = function (socket, xdomain) {
+ try {
+ var request = io.util.request(xdomain),
+ usesXDomReq = (global.XDomainRequest && request instanceof XDomainRequest),
+ socketProtocol = (socket && socket.options && socket.options.secure ? 'https:' : 'http:'),
+ isXProtocol = (global.location && socketProtocol != global.location.protocol);
+ if (request && !(usesXDomReq && isXProtocol)) {
+ return true;
+ }
+ } catch(e) {}
+
+ return false;
+ };
+
+ /**
+ * Check if the XHR transport supports cross domain requests.
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ XHR.xdomainCheck = function (socket) {
+ return XHR.check(socket, true);
+ };
+
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports.htmlfile = HTMLFile;
+
+ /**
+ * The HTMLFile transport creates a `forever iframe` based transport
+ * for Internet Explorer. Regular forever iframe implementations will
+ * continuously trigger the browsers buzy indicators. If the forever iframe
+ * is created inside a `htmlfile` these indicators will not be trigged.
+ *
+ * @constructor
+ * @extends {io.Transport.XHR}
+ * @api public
+ */
+
+ function HTMLFile (socket) {
+ io.Transport.XHR.apply(this, arguments);
+ };
+
+ /**
+ * Inherits from XHR transport.
+ */
+
+ io.util.inherit(HTMLFile, io.Transport.XHR);
+
+ /**
+ * Transport name
+ *
+ * @api public
+ */
+
+ HTMLFile.prototype.name = 'htmlfile';
+
+ /**
+ * Creates a new Ac...eX `htmlfile` with a forever loading iframe
+ * that can be used to listen to messages. Inside the generated
+ * `htmlfile` a reference will be made to the HTMLFile transport.
+ *
+ * @api private
+ */
+
+ HTMLFile.prototype.get = function () {
+ this.doc = new window[(['Active'].concat('Object').join('X'))]('htmlfile');
+ this.doc.open();
+ this.doc.write('<html></html>');
+ this.doc.close();
+ this.doc.parentWindow.s = this;
+
+ var iframeC = this.doc.createElement('div');
+ iframeC.className = 'socketio';
+
+ this.doc.body.appendChild(iframeC);
+ this.iframe = this.doc.createElement('iframe');
+
+ iframeC.appendChild(this.iframe);
+
+ var self = this
+ , query = io.util.query(this.socket.options.query, 't='+ +new Date);
+
+ this.iframe.src = this.prepareUrl() + query;
+
+ io.util.on(window, 'unload', function () {
+ self.destroy();
+ });
+ };
+
+ /**
+ * The Socket.IO server will write script tags inside the forever
+ * iframe, this function will be used as callback for the incoming
+ * information.
+ *
+ * @param {String} data The message
+ * @param {document} doc Reference to the context
+ * @api private
+ */
+
+ HTMLFile.prototype._ = function (data, doc) {
+ this.onData(data);
+ try {
+ var script = doc.getElementsByTagName('script')[0];
+ script.parentNode.removeChild(script);
+ } catch (e) { }
+ };
+
+ /**
+ * Destroy the established connection, iframe and `htmlfile`.
+ * And calls the `CollectGarbage` function of Internet Explorer
+ * to release the memory.
+ *
+ * @api private
+ */
+
+ HTMLFile.prototype.destroy = function () {
+ if (this.iframe){
+ try {
+ this.iframe.src = 'about:blank';
+ } catch(e){}
+
+ this.doc = null;
+ this.iframe.parentNode.removeChild(this.iframe);
+ this.iframe = null;
+
+ CollectGarbage();
+ }
+ };
+
+ /**
+ * Disconnects the established connection.
+ *
+ * @returns {Transport} Chaining.
+ * @api public
+ */
+
+ HTMLFile.prototype.close = function () {
+ this.destroy();
+ return io.Transport.XHR.prototype.close.call(this);
+ };
+
+ /**
+ * Checks if the browser supports this transport. The browser
+ * must have an `Ac...eXObject` implementation.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+ HTMLFile.check = function (socket) {
+ if (typeof window != "undefined" && (['Active'].concat('Object').join('X')) in window){
+ try {
+ var a = new window[(['Active'].concat('Object').join('X'))]('htmlfile');
+ return a && io.Transport.XHR.check(socket);
+ } catch(e){}
+ }
+ return false;
+ };
+
+ /**
+ * Check if cross domain requests are supported.
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ HTMLFile.xdomainCheck = function () {
+ // we can probably do handling for sub-domains, we should
+ // test that it's cross domain but a subdomain here
+ return false;
+ };
+
+ /**
+ * Add the transport to your public io.transports array.
+ *
+ * @api private
+ */
+
+ io.transports.push('htmlfile');
+
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+
+ /**
+ * Expose constructor.
+ */
+
+ exports['xhr-polling'] = XHRPolling;
+
+ /**
+ * The XHR-polling transport uses long polling XHR requests to create a
+ * "persistent" connection with the server.
+ *
+ * @constructor
+ * @api public
+ */
+
+ function XHRPolling () {
+ io.Transport.XHR.apply(this, arguments);
+ };
+
+ /**
+ * Inherits from XHR transport.
+ */
+
+ io.util.inherit(XHRPolling, io.Transport.XHR);
+
+ /**
+ * Merge the properties from XHR transport
+ */
+
+ io.util.merge(XHRPolling, io.Transport.XHR);
+
+ /**
+ * Transport name
+ *
+ * @api public
+ */
+
+ XHRPolling.prototype.name = 'xhr-polling';
+
+ /**
+ * Indicates whether heartbeats is enabled for this transport
+ *
+ * @api private
+ */
+
+ XHRPolling.prototype.heartbeats = function () {
+ return false;
+ };
+
+ /**
+ * Establish a connection, for iPhone and Android this will be done once the page
+ * is loaded.
+ *
+ * @returns {Transport} Chaining.
+ * @api public
+ */
+
+ XHRPolling.prototype.open = function () {
+ var self = this;
+
+ io.Transport.XHR.prototype.open.call(self);
+ return false;
+ };
+
+ /**
+ * Starts a XHR request to wait for incoming messages.
+ *
+ * @api private
+ */
+
+ function empty () {};
+
+ XHRPolling.prototype.get = function () {
+ if (!this.isOpen) return;
+
+ var self = this;
+
+ function stateChange () {
+ if (this.readyState == 4) {
+ this.onreadystatechange = empty;
+
+ if (this.status == 200) {
+ self.onData(this.responseText);
+ self.get();
+ } else {
+ self.onClose();
+ }
+ }
+ };
+
+ function onload () {
+ this.onload = empty;
+ this.onerror = empty;
+ self.retryCounter = 1;
+ self.onData(this.responseText);
+ self.get();
+ };
+
+ function onerror () {
+ self.retryCounter ++;
+ if(!self.retryCounter || self.retryCounter > 3) {
+ self.onClose();
+ } else {
+ self.get();
+ }
+ };
+
+ this.xhr = this.request();
+
+ if (global.XDomainRequest && this.xhr instanceof XDomainRequest) {
+ this.xhr.onload = onload;
+ this.xhr.onerror = onerror;
+ } else {
+ this.xhr.onreadystatechange = stateChange;
+ }
+
+ this.xhr.send(null);
+ };
+
+ /**
+ * Handle the unclean close behavior.
+ *
+ * @api private
+ */
+
+ XHRPolling.prototype.onClose = function () {
+ io.Transport.XHR.prototype.onClose.call(this);
+
+ if (this.xhr) {
+ this.xhr.onreadystatechange = this.xhr.onload = this.xhr.onerror = empty;
+ try {
+ this.xhr.abort();
+ } catch(e){}
+ this.xhr = null;
+ }
+ };
+
+ /**
+ * Webkit based browsers show a infinit spinner when you start a XHR request
+ * before the browsers onload event is called so we need to defer opening of
+ * the transport until the onload event is called. Wrapping the cb in our
+ * defer method solve this.
+ *
+ * @param {Socket} socket The socket instance that needs a transport
+ * @param {Function} fn The callback
+ * @api private
+ */
+
+ XHRPolling.prototype.ready = function (socket, fn) {
+ var self = this;
+
+ io.util.defer(function () {
+ fn.call(self);
+ });
+ };
+
+ /**
+ * Add the transport to your public io.transports array.
+ *
+ * @api private
+ */
+
+ io.transports.push('xhr-polling');
+
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+/**
+ * socket.io
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+(function (exports, io) {
+ /**
+ * There is a way to hide the loading indicator in Firefox. If you create and
+ * remove a iframe it will stop showing the current loading indicator.
+ * Unfortunately we can't feature detect that and UA sniffing is evil.
+ *
+ * @api private
+ */
+
+ var indicator = global.document && "MozAppearance" in
+ global.document.documentElement.style;
+
+ /**
+ * Expose constructor.
+ */
+
+ exports['jsonp-polling'] = JSONPPolling;
+
+ /**
+ * The JSONP transport creates an persistent connection by dynamically
+ * inserting a script tag in the page. This script tag will receive the
+ * information of the Socket.IO server. When new information is received
+ * it creates a new script tag for the new data stream.
+ *
+ * @constructor
+ * @extends {io.Transport.xhr-polling}
+ * @api public
+ */
+
+ function JSONPPolling (socket) {
+ io.Transport['xhr-polling'].apply(this, arguments);
+
+ this.index = io.j.length;
+
+ var self = this;
+
+ io.j.push(function (msg) {
+ self._(msg);
+ });
+ };
+
+ /**
+ * Inherits from XHR polling transport.
+ */
+
+ io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
+
+ /**
+ * Transport name
+ *
+ * @api public
+ */
+
+ JSONPPolling.prototype.name = 'jsonp-polling';
+
+ /**
+ * Posts a encoded message to the Socket.IO server using an iframe.
+ * The iframe is used because script tags can create POST based requests.
+ * The iframe is positioned outside of the view so the user does not
+ * notice it's existence.
+ *
+ * @param {String} data A encoded message.
+ * @api private
+ */
+
+ JSONPPolling.prototype.post = function (data) {
+ var self = this
+ , query = io.util.query(
+ this.socket.options.query
+ , 't='+ (+new Date) + '&i=' + this.index
+ );
+
+ if (!this.form) {
+ var form = document.createElement('form')
+ , area = document.createElement('textarea')
+ , id = this.iframeId = 'socketio_iframe_' + this.index
+ , iframe;
+
+ form.className = 'socketio';
+ form.style.position = 'absolute';
+ form.style.top = '0px';
+ form.style.left = '0px';
+ form.style.display = 'none';
+ form.target = id;
+ form.method = 'POST';
+ form.setAttribute('accept-charset', 'utf-8');
+ area.name = 'd';
+ form.appendChild(area);
+ document.body.appendChild(form);
+
+ this.form = form;
+ this.area = area;
+ }
+
+ this.form.action = this.prepareUrl() + query;
+
+ function complete () {
+ initIframe();
+ self.socket.setBuffer(false);
+ };
+
+ function initIframe () {
+ if (self.iframe) {
+ self.form.removeChild(self.iframe);
+ }
+
+ try {
+ // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
+ iframe = document.createElement('<iframe name="'+ self.iframeId +'">');
+ } catch (e) {
+ iframe = document.createElement('iframe');
+ iframe.name = self.iframeId;
+ }
+
+ iframe.id = self.iframeId;
+
+ self.form.appendChild(iframe);
+ self.iframe = iframe;
+ };
+
+ initIframe();
+
+ // we temporarily stringify until we figure out how to prevent
+ // browsers from turning `\n` into `\r\n` in form inputs
+ this.area.value = io.JSON.stringify(data);
+
+ try {
+ this.form.submit();
+ } catch(e) {}
+
+ if (this.iframe.attachEvent) {
+ iframe.onreadystatechange = function () {
+ if (self.iframe.readyState == 'complete') {
+ complete();
+ }
+ };
+ } else {
+ this.iframe.onload = complete;
+ }
+
+ this.socket.setBuffer(true);
+ };
+
+ /**
+ * Creates a new JSONP poll that can be used to listen
+ * for messages from the Socket.IO server.
+ *
+ * @api private
+ */
+
+ JSONPPolling.prototype.get = function () {
+ var self = this
+ , script = document.createElement('script')
+ , query = io.util.query(
+ this.socket.options.query
+ , 't='+ (+new Date) + '&i=' + this.index
+ );
+
+ if (this.script) {
+ this.script.parentNode.removeChild(this.script);
+ this.script = null;
+ }
+
+ script.async = true;
+ script.src = this.prepareUrl() + query;
+ script.onerror = function () {
+ self.onClose();
+ };
+
+ var insertAt = document.getElementsByTagName('script')[0];
+ insertAt.parentNode.insertBefore(script, insertAt);
+ this.script = script;
+
+ if (indicator) {
+ setTimeout(function () {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ document.body.removeChild(iframe);
+ }, 100);
+ }
+ };
+
+ /**
+ * Callback function for the incoming message stream from the Socket.IO server.
+ *
+ * @param {String} data The message
+ * @api private
+ */
+
+ JSONPPolling.prototype._ = function (msg) {
+ this.onData(msg);
+ if (this.isOpen) {
+ this.get();
+ }
+ return this;
+ };
+
+ /**
+ * The indicator hack only works after onload
+ *
+ * @param {Socket} socket The socket instance that needs a transport
+ * @param {Function} fn The callback
+ * @api private
+ */
+
+ JSONPPolling.prototype.ready = function (socket, fn) {
+ var self = this;
+ if (!indicator) return fn.call(this);
+
+ io.util.load(function () {
+ fn.call(self);
+ });
+ };
+
+ /**
+ * Checks if browser supports this transport.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+ JSONPPolling.check = function () {
+ return 'document' in global;
+ };
+
+ /**
+ * Check if cross domain requests are supported
+ *
+ * @returns {Boolean}
+ * @api public
+ */
+
+ JSONPPolling.xdomainCheck = function () {
+ return true;
+ };
+
+ /**
+ * Add the transport to your public io.transports array.
+ *
+ * @api private
+ */
+
+ io.transports.push('jsonp-polling');
+
+})(
+ 'undefined' != typeof io ? io.Transport : module.exports
+ , 'undefined' != typeof io ? io : module.parent.exports
+);
+
+if (typeof define === "function" && define.amd) {
+ define([], function () { return io; });
+} else {
+ return io;
+}
+
+})(window);
diff --git a/src/wrtcp.js b/src/wrtcp.js
new file mode 100644
index 00000000..e3f0e43b
--- /dev/null
+++ b/src/wrtcp.js
@@ -0,0 +1,821 @@
+/*
+The MIT License
+
+Copyright (c) 2012, Mozilla Foundation
+Copyright (c) 2012, Alan Kligman
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+(function() {
+
+ /* Notes
+ *
+ * - Continue using prefixed names for now.
+ *
+ */
+
+ var io = SocketIO;
+ var webrtcSupported = true;
+
+ var RTCPeerConnection;
+ if(window.mozRTCPeerConnection)
+ RTCPeerConnection = window.mozRTCPeerConnection;
+ else if(window.webkitRTCPeerConnection)
+ RTCPeerConnection = window.webkitRTCPeerConnection;
+ else if(window.RTCPeerConnection)
+ RTCPeerConnection = window.RTCPeerConnection
+ else
+ webrtcSupported = false;
+
+ var RTCSessionDescription;
+ if(window.mozRTCSessionDescription)
+ RTCSessionDescription = window.mozRTCSessionDescription;
+ else if(window.webkitRTCSessionDescription)
+ RTCSessionDescription = window.webkitRTCSessionDescription;
+ else if(window.RTCSessionDescription)
+ RTCSessionDescription = window.RTCSessionDescription
+ else
+ webrtcSupported = false;
+
+ var RTCIceCandidate;
+ if(window.mozRTCIceCandidate)
+ RTCIceCandidate = window.mozRTCIceCandidate;
+ else if(window.webkitRTCIceCandidate)
+ RTCIceCandidate = window.webkitRTCIceCandidate;
+ else if(window.RTCIceCandidate)
+ RTCIceCandidate = window.RTCIceCandidate;
+ else
+ webrtcSupported = false;
+
+ var getUserMedia;
+ if(!navigator.getUserMedia) {
+ if(navigator.mozGetUserMedia)
+ getUserMedia = navigator.mozGetUserMedia.bind(navigator);
+ else if(navigator.webkitGetUserMedia)
+ getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
+ else
+ webrtcSupported = false;
+ } else {
+ getUserMedia = navigator.getUserMedia.bind(navigator);
+ }
+
+ // FIXME: browser detection is gross, but I don't see another way to do this
+ var RTCConnectProtocol;
+ if(window.mozRTCPeerConnection) {
+ RTCConnectProtocol = mozRTCConnectProtocol;
+ } else if(window.webkitRTCPeerConnection) {
+ RTCConnectProtocol = webkitRTCConnectProtocol;
+ } else {
+ webrtcSupported = false;
+ }
+
+ function callback(object, method, args) {
+ if(!Array.isArray(args))
+ args = [args];
+ if(method in object && 'function' === typeof object[method]) {
+ object[method].apply(object, args);
+ }
+ };
+
+ function fail(object, method, error) {
+ if (!(error instanceof Error))
+ error = new Error(error);
+ callback(object, method, [error]);
+ };
+
+ function defer(queue, object, method, args) {
+ if(queue) {
+ queue.push([object, method, args]);
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ function processDeferredQueue(queue) {
+ while(queue.length) {
+ var deferred = queue.shift();
+ callback(deferred[0], deferred[1], deferred[2]);
+ }
+ };
+
+ var ONE_SECOND = 1000; // milliseconds
+ var DEFAULT_CONNECTION_TIMEOUT = 10 * ONE_SECOND;
+ var DEFAULT_PING_TIMEOUT = 1 * ONE_SECOND;
+ var RELIABLE_CHANNEL_OPTIONS = {
+ reliable: false
+ };
+ var UNRELIABLE_CHANNEL_OPTIONS = {
+ outOfOrderAllowed: true,
+ maxRetransmitNum: 0,
+ reliable: false
+ };
+
+ function PendingConnectionAbortError(message) {
+ this.name = "PendingConnectionAbortError";
+ this.message = (message || "");
+ };
+ PendingConnectionAbortError.prototype = Error.prototype;
+
+ function ConnectionFailedError(message) {
+ this.name = "ConnectionFailedError";
+ this.message = (message || "");
+ };
+ ConnectionFailedError.prototype = Error.prototype;
+
+ var E = {
+ PendingConnectionAbortError: PendingConnectionAbortError,
+ ConnectionFailedError: ConnectionFailedError
+ };
+
+ function WebSocketBroker(brokerUrl) {
+ this.brokerUrl = brokerUrl;
+ this.state = WebSocketBroker.OFFLINE;
+
+ this.onstatechange = null;
+ this.onreceive = null;
+ this.onerror = null;
+
+ this.socket = null;
+ this.route = null;
+ };
+
+ // States
+ WebSocketBroker.OFFLINE = 0x00;
+ WebSocketBroker.CONNECTING = 0x01;
+ WebSocketBroker.CONNECTED = 0x02;
+ // Flags
+ WebSocketBroker.ROUTED = 0x10;
+ WebSocketBroker.LISTENING = 0x20;
+
+ WebSocketBroker.prototype.setState = function setState(state, clearFlags) {
+ var clear = clearFlags ? 0x00 : 0xF0;
+ this.state &= clear >>> 0;
+ this.state |= state >>> 0;
+ callback(this, 'onstatechange', [this.state, (state | (clear & 0x0)) >>> 0]);
+ };
+ WebSocketBroker.prototype.setFlag = function setFlag(flag) {
+ this.state = (this.state | flag) >>> 0;
+ callback(this, 'onstatechange', [this.state, flag])
+ };
+ WebSocketBroker.prototype.clearFlag = function clearFlag(flag) {
+ flag = (~flag) >>> 0;
+ this.state = (this.state & flag) >>> 0;
+ callback(this, 'onstatechange', [this.state, flag])
+ };
+ WebSocketBroker.prototype.checkState = function checkState(mask) {
+ return !!(this.state & mask);
+ };
+ WebSocketBroker.prototype.connect = function connect() {
+ var that = this;
+ var socket = io.connect(this.brokerUrl + '/peer', {
+ 'sync disconnect on unload': true // partially fixes 'interrupted while page loading' warning
+ });
+
+ socket.on('connecting', function onconnecting() {
+ that.setState(WebSocketBroker.CONNECTING, true);
+ });
+
+ socket.on('connect', function onconnect() {
+ that.setState(WebSocketBroker.CONNECTED, true);
+ });
+
+ socket.on('connect_failed', function onconnect_failed() {
+ that.setState(WebSocketBroker.OFFLINE, true);
+ });
+
+ socket.on('route', function onroute(route) {
+ that.route = route;
+ that.setFlag(WebSocketBroker.ROUTED);
+ });
+
+ socket.on('disconnect', function ondisconnect() {
+ that.setState(WebSocketBroker.OFFLINE, true);
+ });
+
+ socket.on('error', function onerror(error) {
+ fail(that, 'onerror', error);
+ });
+
+ socket.on('receive', function onreceive(message) {
+ var from = message['from'];
+ var data = message['data'];
+ callback(that, 'onreceive', [from, data]);
+ });
+
+ this.socket = socket;
+ };
+ WebSocketBroker.prototype.disconnect = function disconnect() {
+ if(this.checkState(WebSocketBroker.CONNECTED)) {
+ this.socket.disconnect();
+ this.setState(WebSocketBroker.OFFLINE, true);
+ return true;
+ } else {
+ return false;
+ }
+ };
+ WebSocketBroker.prototype.listen = function listen(options) {
+ var that = this;
+ if(this.checkState(WebSocketBroker.CONNECTED)) {
+ this.socket.emit('listen', options, function onresponse(response) {
+ if(response && response['error']) {
+ var error = new Error(response['error']);
+ fail(that, 'onerror', error);
+ } else {
+ that.setFlag(WebSocketBroker.LISTENING);
+ }
+ });
+ }
+ };
+ WebSocketBroker.prototype.ignore = function ignore() {
+ var that = this;
+ if(this.checkState(WebSocketBroker.CONNECTED)) {
+ this.socket.emit('ignore', null, function onresponse(response) {
+ if(response && response['error']) {
+ var error = new Error(response['error']);
+ fail(that, 'onerror', error)
+ } else {
+ that.clearFlag(WebSocketBroker.LISTENING);
+ }
+ });
+ }
+ };
+ WebSocketBroker.prototype.send = function send(to, message) {
+ var that = this;
+ if(this.checkState(WebSocketBroker.CONNECTED)) {
+ this.socket.emit('send', {'to': to, 'data': message}, function onresponse(response) {
+ if(response && response['error']) {
+ var error = new Error(response['error']);
+ fail(that, 'onerror', error)
+ }
+ });
+ };
+ };
+
+ var dataChannels = {
+ 'reliable': 'RELIABLE',
+ 'unreliable': 'UNRELIABLE',
+ '@control': 'RELIABLE'
+ };
+ var nextDataConnectionPort = 1;
+ function CommonRTCConnectProtocol() {
+ // FIXME: these timeouts should be configurable
+ this.connectionTimeout = 10 * ONE_SECOND;
+ this.pingTimeout = 1 * ONE_SECOND;
+ };
+ CommonRTCConnectProtocol.prototype.process = function process(message) {
+ var that = this;
+
+ var type = message['type'];
+ switch(type) {
+ case 'ice':
+ var candidate = JSON.parse(message['candidate']);
+ if(candidate)
+ this.handleIce(candidate);
+ break;
+
+ case 'offer':
+ that.ports.remote = message['port'];
+ var offer = {
+ 'type': 'offer',
+ 'sdp': message['description']
+ };
+ this.handleOffer(offer);
+ break;
+
+ case 'answer':
+ that.ports.remote = message['port'];
+ var answer = {
+ 'type': 'answer',
+ 'sdp': message['description']
+ };
+ this.handleAnswer(answer);
+ break;
+
+ case 'abort':
+ this.handleAbort();
+ break;
+
+ default:
+ fail(this, 'onerror', 'unknown message');
+ }
+ };
+ CommonRTCConnectProtocol.prototype.handleAbort = function handleAbort() {
+ fail(this, 'onerror', new Error(E.RTCConnectProtocolAbort));
+ };
+ CommonRTCConnectProtocol.prototype.initialize = function initialize(cb) {
+ var that = this;
+
+ if(this.peerConnection)
+ return cb();
+
+ // FIXME: peer connection servers should be configurable
+ this.peerConnection = new RTCPeerConnection(this.connectionServers, this.connectionOptions);
+ this.peerConnection.onicecandidate = function(event) {
+ var message = {
+ 'type': 'ice',
+ 'candidate': JSON.stringify(event.candidate)
+ };
+ callback(that, 'onmessage', message);
+ };
+ this.peerConnection.onaddstream = function(event) {
+ that.streams['remote'] = event.stream;
+ };
+ this.peerConnection.onstatechange = function(event) {
+ console.log(event.target.readyState);
+ };
+
+ function createStream(useFake) {
+ useFake = (!useVideo && !useAudio) ? true : useFake;
+ var useVideo = !!that.options['video'];
+ var useAudio = !!that.options['audio'];
+ var mediaOptions = {
+ video: useVideo,
+ audio: (!useVideo && !useAudio) ? true : useAudio,
+ fake: useFake
+ };
+ getUserMedia(mediaOptions,
+ function(stream) {
+ that.peerConnection.addStream(stream);
+ that.streams['local'] = stream;
+ cb();
+ },
+ function(error) {
+ console.error('!', error);
+ if(!useFake)
+ createStream(true);
+ else
+ fail(that, 'onerror', error);
+ }
+ );
+ }
+
+ createStream();
+ };
+ CommonRTCConnectProtocol.prototype.handleIce = function handleIce(candidate) {
+ var that = this;
+
+ function setIce() {
+ if(!that.peerConnection.remoteDescription) {
+ return
+ }
+ that.peerConnection.addIceCandidate(new RTCIceCandidate(candidate),
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+ };
+
+ this.initialize(setIce);
+ };
+ CommonRTCConnectProtocol.prototype.initiate = function initiate() {
+ var that = this;
+ this.initiator = true;
+
+ function createDataChannels() {
+ var labels = Object.keys(dataChannels);
+ labels.forEach(function(label) {
+ var channelOptions = that.channelOptions[dataChannels[label]];
+ var channel = that._pending[label] = that.peerConnection.createDataChannel(label, channelOptions);
+ channel.binaryType = that.options['binaryType'];
+ channel.onopen = function() {
+ that.channels[label] = channel;
+ delete that._pending[label];
+ if(Object.keys(that.channels).length === labels.length) {
+ that.complete = true;
+ callback(that, 'oncomplete', []);
+ }
+ };
+ channel.onerror = function(error) {
+ console.error(error);
+ fail(that, 'onerror', error);
+ };
+ });
+ createOffer();
+ };
+
+ function createOffer() {
+ that.peerConnection.createOffer(setLocal,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+ };
+
+ function setLocal(description) {
+ that.peerConnection.setLocalDescription(new RTCSessionDescription(description), complete,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+
+ function complete() {
+ var message = {
+ 'type': 'offer',
+ 'description': description['sdp'],
+ 'port': that.ports.local
+ };
+ callback(that, 'onmessage', message);
+ };
+ };
+
+ this.initialize(createDataChannels);
+ };
+ CommonRTCConnectProtocol.prototype.handleOffer = function handleOffer(offer) {
+ var that = this;
+
+ function handleDataChannels() {
+ var labels = Object.keys(dataChannels);
+ that.peerConnection.ondatachannel = function(event) {
+ var channel = event.channel;
+ var label = channel.label;
+ that._pending[label] = channel;
+ channel.binaryType = that.options['binaryType'];
+ channel.onopen = function() {
+ that.channels[label] = channel;
+ delete that._pending[label];
+ if(Object.keys(that.channels).length === labels.length) {
+ that.complete = true;
+ callback(that, 'oncomplete', []);
+ }
+ };
+ channel.onerror = function(error) {
+ console.error(error);
+ fail(that, 'onerror', error);
+ };
+ };
+ setRemote();
+ };
+
+ function setRemote() {
+ that.peerConnection.setRemoteDescription(new RTCSessionDescription(offer), createAnswer,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+ };
+
+ function createAnswer() {
+ that.peerConnection.createAnswer(setLocal,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+ };
+
+ function setLocal(description) {
+ that.peerConnection.setLocalDescription(new RTCSessionDescription(description), complete,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+
+ function complete() {
+ var message = {
+ 'type': 'answer',
+ 'description': description['sdp'],
+ 'port': that.ports.local
+ };
+ callback(that, 'onmessage', message);
+ };
+ };
+
+ this.initialize(handleDataChannels);
+ };
+ CommonRTCConnectProtocol.prototype.handleAnswer = function handleAnswer(answer) {
+ var that = this;
+
+ function setRemote() {
+ that.peerConnection.setRemoteDescription(new RTCSessionDescription(answer), complete,
+ function(error) {
+ fail(that, 'onerror', error);
+ }
+ );
+ };
+
+ function complete() {
+ };
+
+ this.initialize(setRemote);
+ };
+
+ function mozRTCConnectProtocol(options) {
+ this.options = options;
+ this.onmessage = null;
+ this.oncomplete = null;
+ this.onerror = null;
+
+ this.complete = false;
+ this.ports = {
+ local: nextDataConnectionPort ++,
+ remote: null
+ };
+ this.streams = {
+ local: null,
+ remote: null
+ };
+ this.initiator = false;
+
+ this.peerConnection = null;
+ this.channels = {};
+ this._pending = {};
+ this.connectionServers = null;
+ this.connectionOptions = null;
+ this.channelOptions = {
+ RELIABLE: {
+ // defaults
+ },
+ UNRELIABLE: {
+ outOfOrderAllowed: true,
+ maxRetransmitNum: 0
+ }
+ };
+ };
+ mozRTCConnectProtocol.prototype = new CommonRTCConnectProtocol();
+ mozRTCConnectProtocol.prototype.constructor = mozRTCConnectProtocol;
+
+ function webkitRTCConnectProtocol(options) {
+ this.options = options;
+ this.onmessage = null;
+ this.oncomplete = null;
+ this.onerror = null;
+
+ this.complete = false;
+ this.ports = {
+ local: nextDataConnectionPort ++,
+ remote: null
+ };
+ this.streams = {
+ local: null,
+ remote: null
+ };
+ this.initiator = false;
+
+ this.peerConnection = null;
+ this.channels = {};
+ this._pending = {};
+ this.connectionServers = {iceServers:[{url:'stun:23.21.150.121'}]};
+ this.connectionOptions = {
+ 'optional': [{ 'RtpDataChannels': true }]
+ };
+ this.channelOptions = {
+ RELIABLE: {
+ // FIXME: reliable channels do not work in chrome yet
+ reliable: false
+ },
+ UNRELIABLE: {
+ reliable: false
+ }
+ };
+ };
+ webkitRTCConnectProtocol.prototype = new CommonRTCConnectProtocol();
+ webkitRTCConnectProtocol.prototype.constructor = webkitRTCConnectProtocol;
+
+ // FIXME: this could use a cleanup
+ var nextConnectionId = 1;
+ function Connection(options, peerConnection, streams, channels) {
+ var that = this;
+ this.id = nextConnectionId ++;
+ this.streams = streams;
+ this.connected = false;
+ this.messageFlag = false;
+
+ this.onmessage = null;
+ this.ondisconnect = null;
+ this.onerror = null;
+
+ this.peerConnection = peerConnection;
+
+ // DataChannels
+ this.channels = channels;
+
+ this.connectionTimer = null;
+ this.pingTimer = null;
+
+ function handleConnectionTimerExpired() {
+ if(!that.connected)
+ return
+ this.connectionTimer = null;
+ if(false === that.messageFlag) {
+ that.channels['@control'].send('ping');
+ this.pingTimer = window.setTimeout(handlePingTimerExpired, options['pingTimeout']);
+ } else {
+ that.messageFlag = false;
+ this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
+ }
+ };
+ function handlePingTimerExpired() {
+ if(!that.connected)
+ return
+ this.pingTimer = null;
+ if(false === that.messageFlag) {
+ that.connected = false;
+ that.close();
+ } else {
+ that.messageFlag = false;
+ this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
+ }
+ };
+
+ Object.keys(this.channels).forEach(function(label) {
+ var channel = that.channels[label];
+ if(label.match('^@')) // check for internal channels
+ return;
+
+ channel.onmessage = function onmessage(message) {
+ that.messageFlag = true;
+ callback(that, 'onmessage', [label, message]);
+ };
+ });
+ this.channels['@control'].onmessage = function onmessage(message) {
+ that.messageFlag = true;
+ if(that.connected) {
+ var data = message.data;
+ if('ping' === data) {
+ that.channels['@control'].send('pong');
+ } else if('pong' === data) {
+ // ok
+ } else if('quit' === data) {
+ that.close();
+ }
+ }
+ };
+
+ this.connected = true;
+ this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
+ };
+ Connection.prototype.close = function close() {
+ console.log('close connection');
+ if(this.connected) {
+ this.channels['@control'].send('quit');
+ }
+ this.connected = false;
+ this.peerConnection.close();
+ if(this.connectionTimer) {
+ window.clearInterval(this.connectionTimer);
+ this.connectionTimer = null;
+ }
+ if(this.pingTimer) {
+ window.clearInterval(this.pingTimer);
+ this.pingTimer = null;
+ }
+ this.peerConnection = null;
+ callback(this, 'ondisconnect', []);
+ };
+ Connection.prototype.send = function send(label, message) {
+ this.channels[label].send(message);
+ };
+
+ function PendingConnection(route, incoming) {
+ this.route = route;
+ this.incoming = incoming;
+ this.proceed = true;
+ };
+ PendingConnection.prototype.accept = function accept() {
+ this.proceed = true;
+ };
+ PendingConnection.prototype.reject = function reject() {
+ this.proceed = false;
+ };
+
+ function Peer(brokerUrl, options) {
+ if(!webrtcSupported)
+ throw new Error("WebRTC not supported");
+
+ var that = this;
+ this.brokerUrl = brokerUrl;
+ this.options = options = options || {};
+ options['binaryType'] = options['binaryType'] || 'arraybuffer';
+ options['connectionTimeout'] = options['connectionTimeout'] || 10 * ONE_SECOND;
+ options['pingTimeout'] = options['pingTimeout'] || 1 * ONE_SECOND;
+
+ this.onconnection = null;
+ this.onpending = null;
+ this.onroute = null;
+ this.onerror = null;
+
+ this.broker = new WebSocketBroker(brokerUrl);
+ this.pending = {};
+
+ this.queues = {
+ connected: [],
+ listening: []
+ };
+
+ this.broker.onstatechange = function onstatechange(state, mask) {
+ if(that.queues.connected.length && that.broker.checkState(WebSocketBroker.ROUTED)) {
+ processDeferredQueue(that.queues.connected);
+ if(that.queues.listening.length && that.broker.checkState(WebSocketBroker.LISTENING)) {
+ processDeferredQueue(that.queues.listening);
+ }
+ }
+ if(mask & WebSocketBroker.ROUTED) {
+ callback(that, 'onroute', that.broker.route);
+ }
+ };
+
+ this.broker.onreceive = function onreceive(from, message) {
+ var handshake;
+ if(!that.pending.hasOwnProperty(from)) {
+ if(!that.broker.checkState(WebSocketBroker.LISTENING)) {
+ return;
+ }
+
+ var pendingConnection = new PendingConnection(from, /*incoming*/ true);
+ callback(that, 'onpending', [pendingConnection]);
+ if(!pendingConnection['proceed'])
+ return;
+
+ var handshake = that.pending[from] = new RTCConnectProtocol(that.options);
+ handshake.oncomplete = function() {
+ var connection = new Connection(that.options, handshake.peerConnection, handshake.streams, handshake.channels);
+ connection['route'] = from;
+ delete that.pending[from];
+ callback(that, 'onconnection', [connection]);
+ };
+ handshake.onmessage = function(message) {
+ that.broker.send(from, message);
+ };
+ handshake.onerror = function(error) {
+ delete that.pending[from];
+ callback(that, 'onerror', [error]);
+ };
+ } else {
+ handshake = that.pending[from];
+ }
+ handshake.process(message);
+ };
+
+ this.broker.connect();
+ };
+ Peer.prototype.listen = function listen(options) {
+ if(!this.broker.checkState(WebSocketBroker.ROUTED))
+ return defer(this.queues.connected, this, 'listen', [options]);
+
+ options = options || {};
+ options['url'] = options['url'] || window.location.toString();
+ options['listed'] = (undefined !== options['listed']) ? options['listed'] : true;
+ options['metadata'] = options['metadata'] || {};
+
+ this.broker.listen(options);
+ };
+ Peer.prototype.ignore = function ignore() {
+ throw new Error('not implemented');
+ };
+ Peer.prototype.connect = function connect(route) {
+ if(!this.broker.checkState(WebSocketBroker.ROUTED))
+ return defer(this.queues.connected, this, 'connect', [route]);
+
+ var that = this;
+
+ if(this.pending.hasOwnProperty(route))
+ throw new Error('already connecting to this host'); // FIXME: we can handle this better
+
+ var pendingConnection = new PendingConnection(route, /*incoming*/ false);
+ callback(that, 'onpending', [pendingConnection]);
+ if(!pendingConnection['proceed'])
+ return;
+
+ var handshake = this.pending[route] = new RTCConnectProtocol(this.options);
+ handshake.oncomplete = function() {
+ var connection = new Connection(this.options, handshake.peerConnection, handshake.streams, handshake.channels);
+ connection['route'] = route;
+ delete that.pending[route];
+ callback(that, 'onconnection', [connection]);
+ };
+ handshake.onmessage = function(message) {
+ that.broker.send(route, message);
+ };
+ handshake.onerror = function(error) {
+ delete that.pending[route];
+ fail(that, 'onerror', error);
+ };
+
+ handshake.initiate();
+ };
+ Peer.prototype.close = function close() {
+ this.broker.disconnect();
+ };
+ Peer.E = E;
+
+ return Peer;
+
+})(); \ No newline at end of file
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 7aa2a55e..cd465e45 100644
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -18,7 +18,6 @@ namespace emscripten {
};
namespace internal {
- typedef void (*GenericFunction)();
typedef long GenericEnumValue;
// Implemented in JavaScript. Don't call these directly.
@@ -60,6 +59,10 @@ namespace emscripten {
TYPEID emvalType,
const char* name);
+ void _embind_register_memory_view(
+ TYPEID memoryViewType,
+ const char* name);
+
void _embind_register_function(
const char* name,
unsigned argCount,
@@ -414,11 +417,10 @@ namespace emscripten {
// TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*)
template<typename T>
- inline void* getContext(const T& t) {
+ inline T* getContext(const T& t) {
// not a leak because this is called once per binding
- void* p = malloc(sizeof(T));
- assert(p);
- memcpy(p, &t, sizeof(T));
+ T* p = reinterpret_cast<T*>(malloc(sizeof(T)));
+ new(p) T(t);
return p;
}
@@ -749,38 +751,19 @@ namespace emscripten {
template<typename ReturnType, typename... Args>
ReturnType call(const char* name, Args&&... args) const {
- return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ return wrapped.call<ReturnType>(name, std::forward<Args>(args)...);
}
template<typename ReturnType, typename... Args, typename Default>
ReturnType optional_call(const char* name, Default def, Args&&... args) const {
- if (has_function(name)) {
- return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ if (wrapped.has_function(name)) {
+ return call<ReturnType>(name, std::forward<Args>(args)...);
} else {
return def();
}
}
private:
- bool has_function(const char* name) const {
- return wrapped.has_function(name);
- }
-
- // this class only exists because you can't partially specialize function templates
- template<typename ReturnType, typename... Args>
- struct Caller {
- static ReturnType call(const val& v, const char* name, Args&&... args) {
- return v.call(name, std::forward<Args>(args)...).template as<ReturnType>();
- }
- };
-
- template<typename... Args>
- struct Caller<void, Args...> {
- static void call(const val& v, const char* name, Args&&... args) {
- v.call_void(name, std::forward<Args>(args)...);
- }
- };
-
val wrapped;
};
@@ -844,23 +827,8 @@ namespace emscripten {
}
};
- template<typename PointerType>
- struct ptr {
- typedef PointerType pointer_type;
- };
-
namespace internal {
template<typename T>
- struct is_ptr {
- enum { value = false };
- };
-
- template<typename T>
- struct is_ptr<ptr<T>> {
- enum { value = true };
- };
-
- template<typename T>
struct SmartPtrIfNeeded {
template<typename U>
SmartPtrIfNeeded(U& cls) {
@@ -881,7 +849,6 @@ namespace emscripten {
public:
class_() = delete;
- template<typename = typename std::enable_if<!internal::is_ptr<ClassType>::value>::type>
explicit class_(const char* name) {
using namespace internal;
@@ -927,16 +894,17 @@ namespace emscripten {
policies...);
}
- template<typename... Args, typename... Policies>
- class_& constructor(ClassType* (*factory)(Args...), Policies...) {
+ template<typename... Args, typename ReturnType, typename... Policies>
+ class_& constructor(ReturnType (*factory)(Args...), Policies...) {
using namespace internal;
- typename WithPolicies<Policies...>::template ArgTypeList<AllowedRawPointer<ClassType>, Args...> args;
+ // TODO: allows all raw pointers... policies need a rethink
+ typename WithPolicies<allow_raw_pointers, Policies...>::template ArgTypeList<ReturnType, Args...> args;
_embind_register_class_constructor(
TypeID<ClassType>::get(),
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&Invoker<ClassType*, Args...>::invoke),
+ reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke),
reinterpret_cast<GenericFunction>(factory));
return *this;
}
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index 61634b0e..28e6063c 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -1,3 +1,6 @@
+#ifndef __emscripten_h__
+#define __emscripten_h__
+
/**
* This file contains a few useful things for compiling C/C++ code
* with Emscripten, an LLVM-to-JavaScript compiler.
@@ -136,6 +139,14 @@ inline void emscripten_async_call(void (*func)(void *), void *arg, int millis) {
#endif
/*
+ * Exits the program immediately, but leaves the runtime alive
+ * so that you can continue to run code later (so global destructors
+ * etc. are not run). This is implicitly performed when you do
+ * an asynchronous operation like emscripten_async_call.
+ */
+extern void emscripten_exit_with_live_runtime();
+
+/*
* Hide the OS mouse cursor over the canvas. Note that SDL's
* SDL_ShowCursor command shows and hides the SDL cursor, not
* the OS one. This command is useful to hide the OS cursor
@@ -373,3 +384,5 @@ void emscripten_jcache_printf_(...); /* internal use */
}
#endif
+#endif // __emscripten_h__
+
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index edd070e3..b712d164 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -10,7 +10,6 @@ namespace emscripten {
extern "C" {
void _emval_register_symbol(const char*);
- typedef struct _EM_SIG* EM_SIG;
typedef struct _EM_VAL* EM_VAL;
void _emval_incref(EM_VAL value);
@@ -39,34 +38,67 @@ namespace emscripten {
unsigned argCount,
internal::TYPEID argTypes[]
/*, ... */);
- EM_VAL _emval_call_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ... */);
- void _emval_call_void_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ...*/);
+
+ // DO NOT call this more than once per signature. It will leak function pointer offsets!
+ GenericFunction _emval_get_method_caller(
+ unsigned argCount, // including return value
+ internal::TYPEID argTypes[]);
bool _emval_has_function(
EM_VAL value,
const char* methodName);
}
- }
- template<const char* address>
- struct symbol_registrar {
- symbol_registrar() {
- internal::_emval_register_symbol(address);
- }
- };
+ template<const char* address>
+ struct symbol_registrar {
+ symbol_registrar() {
+ internal::_emval_register_symbol(address);
+ }
+ };
+
+ template<typename ReturnType, typename... Args>
+ struct Signature {
+ typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(EM_VAL value, const char* methodName, typename BindingType<Args>::WireType...);
+
+ static MethodCaller get_method_caller() {
+ static MethodCaller fp = reinterpret_cast<MethodCaller>(init_method_caller());
+ return fp;
+ }
+
+ private:
+ static GenericFunction init_method_caller() {
+ WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
+ return _emval_get_method_caller(args.count, args.types);
+ }
+ };
+
+ template<typename ReturnType, typename... Args>
+ struct MethodCaller {
+ static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) {
+ auto caller = Signature<ReturnType, Args...>::get_method_caller();
+ auto wireType = caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ WireDeleter<ReturnType> deleter(wireType);
+ return BindingType<ReturnType>::fromWireType(wireType);
+ }
+ };
+
+ template<typename... Args>
+ struct MethodCaller<void, Args...> {
+ static void call(EM_VAL handle, const char* methodName, Args&&... args) {
+ auto caller = Signature<void, Args...>::get_method_caller();
+ return caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ }
+ };
+ }
#define EMSCRIPTEN_SYMBOL(name) \
static const char name##_symbol[] = #name; \
- static const symbol_registrar<name##_symbol> name##_registrar
+ static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
class val {
public:
@@ -158,7 +190,7 @@ namespace emscripten {
}
bool hasOwnProperty(const char* key) const {
- return val::global("Object")["prototype"]["hasOwnProperty"].call("call", *this, val(key)).as<bool>();
+ return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key));
}
template<typename... Args>
@@ -211,45 +243,11 @@ namespace emscripten {
toWireType(std::forward<Args>(args))...));
}
- template<typename ...Args>
- val call(const char* name, Args&&... args) const {
+ template<typename ReturnValue, typename... Args>
+ ReturnValue call(const char* name, Args&&... args) const {
using namespace internal;
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef EM_VAL (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_method);
- return val(
- typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...));
- }
-
- template<typename ...Args>
- void call_void(const char* name, Args&&... args) const {
- using namespace internal;
-
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef void (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_void_method);
- return typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...);
+ return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
}
bool has_function(const char* name) const {
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index 6fb15fc7..a5892216 100644
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -13,6 +13,8 @@
namespace emscripten {
namespace internal {
+ typedef void (*GenericFunction)();
+
typedef const struct _TYPEID* TYPEID;
// This implementation is technically not legal, as it's not
@@ -146,6 +148,7 @@ namespace emscripten {
template<>
struct BindingType<void> {
+ typedef void WireType;
};
template<>
@@ -309,4 +312,82 @@ namespace emscripten {
WireType wt;
};
}
+
+ struct memory_view {
+ enum class Type {
+ Int8Array,
+ Uint8Array,
+ Int16Array,
+ Uint16Array,
+ Int32Array,
+ Uint32Array,
+ Float32Array,
+ Float64Array,
+ };
+
+ memory_view() = delete;
+ explicit memory_view(size_t size, const void* data)
+ : type(Type::Uint8Array)
+ , size(size)
+ , data(data)
+ {}
+ explicit memory_view(Type type, size_t size, const void* data)
+ : type(type)
+ , size(size)
+ , data(data)
+ {}
+
+ const Type type;
+ const size_t size; // in elements, not bytes
+ const void* const data;
+ };
+
+ inline memory_view typed_memory_view(size_t size, const int8_t* data) {
+ return memory_view(memory_view::Type::Int8Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const uint8_t* data) {
+ return memory_view(memory_view::Type::Uint8Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const int16_t* data) {
+ return memory_view(memory_view::Type::Int16Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const uint16_t* data) {
+ return memory_view(memory_view::Type::Uint16Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const int32_t* data) {
+ return memory_view(memory_view::Type::Int32Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const uint32_t* data) {
+ return memory_view(memory_view::Type::Uint32Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const float* data) {
+ return memory_view(memory_view::Type::Float32Array, size, data);
+ }
+
+ inline memory_view typed_memory_view(size_t size, const double* data) {
+ return memory_view(memory_view::Type::Float64Array, size, data);
+ }
+
+ namespace internal {
+ template<>
+ struct BindingType<memory_view> {
+ // This non-word-sized WireType only works because I
+ // happen to know that clang will pass aggregates as
+ // pointers to stack elements and we never support
+ // converting JavaScript typed arrays back into
+ // memory_view. (That is, fromWireType is not implemented
+ // on the C++ side, nor is toWireType implemented in
+ // JavaScript.)
+ typedef memory_view WireType;
+ static WireType toWireType(const memory_view& mv) {
+ return mv;
+ }
+ };
+ }
}
diff --git a/system/include/libcxx/exception b/system/include/libcxx/exception
index 37bfc57e..102b10d6 100644
--- a/system/include/libcxx/exception
+++ b/system/include/libcxx/exception
@@ -91,8 +91,8 @@ class _LIBCPP_EXCEPTION_ABI exception
{
public:
_LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {}
- virtual ~exception() _NOEXCEPT;
- virtual const char* what() const _NOEXCEPT;
+ virtual ~exception() _NOEXCEPT {} // XXX EMSCRIPTEN - implement in header
+ virtual const char* what() const _NOEXCEPT { return "std::exception"; } // XXX EMSCRIPTEN - implement in header
};
class _LIBCPP_EXCEPTION_ABI bad_exception
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index ec1648a9..12264dfd 100644
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -59,4 +59,5 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
_embind_register_std_string(TypeID<std::string>::get(), "std::string");
_embind_register_std_wstring(TypeID<std::wstring>::get(), sizeof(wchar_t), "std::wstring");
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
+ _embind_register_memory_view(TypeID<memory_view>::get(), "emscripten::memory_view");
}
diff --git a/system/lib/libcxx/symbols b/system/lib/libcxx/symbols
index 93dfda65..84f4ddc9 100644
--- a/system/lib/libcxx/symbols
+++ b/system/lib/libcxx/symbols
@@ -2925,4 +2925,3 @@
W _ZTv0_n12_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev
T _ZTv0_n12_NSt3__19strstreamD0Ev
T _ZTv0_n12_NSt3__19strstreamD1Ev
- D llvm.global_ctors
diff --git a/tests/aniso.c b/tests/aniso.c
index e02c20ac..1126265e 100644
--- a/tests/aniso.c
+++ b/tests/aniso.c
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
const char *exts = (const char *)glGetString(GL_EXTENSIONS);
assert(hasext(exts, "GL_EXT_texture_filter_anisotropic"));
-
+
GLint aniso;
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
printf("Max anisotropy: %d (using that)\n", aniso);
@@ -73,10 +73,8 @@ int main(int argc, char *argv[])
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 600, 600 );
@@ -155,7 +153,7 @@ int main(int argc, char *argv[])
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
int w = 10;
int n = 15;
@@ -200,7 +198,7 @@ int main(int argc, char *argv[])
}
*/
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(2000);
@@ -208,8 +206,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/cases/emptystruct.ll b/tests/cases/emptystruct.ll
index 67967e65..ecf0e295 100644
--- a/tests/cases/emptystruct.ll
+++ b/tests/cases/emptystruct.ll
@@ -6,6 +6,8 @@ target triple = "i386-pc-linux-gnu"
@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1]
+@.waka = extern_weak global i8* ; no initializer!
+
define i32 @main() nounwind {
entry:
%z = alloca %struct.s, align 4
diff --git a/tests/cases/fp80.ll b/tests/cases/fp80_ta2.ll
index 7fc0db4a..7fc0db4a 100644
--- a/tests/cases/fp80.ll
+++ b/tests/cases/fp80_ta2.ll
diff --git a/tests/cases/muli33_ta2.ll b/tests/cases/muli33_ta2.ll
new file mode 100644
index 00000000..b33b04f7
--- /dev/null
+++ b/tests/cases/muli33_ta2.ll
@@ -0,0 +1,114 @@
+; ModuleID = '/tmp/tmpt0JpDh/a.out.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+@.str = private unnamed_addr constant [7 x i8] c"20\0A91\0A\00", align 1
+@.str1 = private unnamed_addr constant [6 x i8] c"%u %u\00", align 1
+@.str2 = private unnamed_addr constant [10 x i8] c"res = %u\0A\00", align 1
+
+define i32 @main() nounwind {
+ %j = alloca i32, align 4
+ %k4 = alloca i32, align 4
+ %t = alloca [100 x [100 x i32]], align 4
+ store i32 20, i32* %j, align 4
+ store i32 91, i32* %k4, align 4
+ br label %.lr.ph.i
+
+.lr.ph.i: ; preds = %.lr.ph.i, %0
+ %j.07.i = phi i32 [ %7, %.lr.ph.i ], [ 0, %0 ]
+ %1 = and i32 %j.07.i, 1
+ %2 = icmp eq i32 %1, 0
+ %3 = sub i32 0, %j.07.i
+ %.p.i = select i1 %2, i32 %j.07.i, i32 %3
+ %4 = add i32 %.p.i, 8
+ %5 = urem i32 %4, 101
+ %6 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 0, i32 %j.07.i
+ store i32 %5, i32* %6, align 4
+ %7 = add i32 %j.07.i, 1
+ %8 = icmp ult i32 %7, 10000
+ br i1 %8, label %.lr.ph.i, label %init.exit
+
+init.exit: ; preds = %.lr.ph.i
+ %9 = call i32 (i8*, i8*, ...)* @sscanf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0), i32* %j, i32* %k4) nounwind
+ store i32 53, i32* %j, align 4
+ br label %.preheader
+
+.preheader: ; preds = %29, %init.exit
+ %indvars.iv23 = phi i32 [ -29, %init.exit ], [ %indvars.iv.next24, %29 ]
+ %indvars.iv21 = phi i32 [ -28, %init.exit ], [ %indvars.iv.next22, %29 ]
+ %indvars.iv19 = phi i32 [ -27, %init.exit ], [ %indvars.iv.next20, %29 ]
+ %indvars.iv17 = phi i32 [ 109, %init.exit ], [ %indvars.iv.next18, %29 ]
+ %indvars.iv15 = phi i32 [ -75923, %init.exit ], [ %indvars.iv.next16, %29 ]
+ %indvars.iv13 = phi i32 [ 5593, %init.exit ], [ %indvars.iv.next14, %29 ]
+ %indvars.iv = phi i32 [ -262, %init.exit ], [ %indvars.iv.next, %29 ]
+ %10 = phi i32 [ 53, %init.exit ], [ %.pre-phi, %29 ]
+ %11 = zext i32 %indvars.iv19 to i33
+ %12 = zext i32 %indvars.iv21 to i33
+ %13 = mul i33 %11, %12
+ %14 = icmp ult i32 %10, 27
+ br i1 %14, label %.lr.ph, label %.preheader._crit_edge
+
+.preheader._crit_edge: ; preds = %.preheader
+ %.pre = add i32 %10, -1
+ br label %29
+
+.lr.ph: ; preds = %.preheader
+ %15 = zext i32 %indvars.iv23 to i33
+ %16 = mul i33 %13, %15
+ %17 = lshr i33 %16, 1
+ %18 = lshr i33 %13, 1
+ %19 = trunc i33 %17 to i32
+ %20 = trunc i33 %18 to i32
+ %21 = mul i32 %19, 1431655766
+ %22 = mul i32 %indvars.iv17, %20
+ %23 = add i32 %10, -1
+ %24 = add i32 %10, 1
+ %25 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 %24, i32 %23
+ %.promoted = load i32* %25, align 4
+ %26 = add i32 %.promoted, %indvars.iv15
+ %27 = add i32 %26, %22
+ %28 = add i32 %27, %21
+ store i32 %28, i32* %25, align 4
+ br label %29
+
+.lr.ph.i3.preheader: ; preds = %29
+ store i32 2, i32* %j, align 4
+ store i32 %.lcssa69, i32* %k4, align 4
+ br label %.lr.ph.i3
+
+; <label>:29 ; preds = %.lr.ph, %.preheader._crit_edge
+ %.pre-phi = phi i32 [ %.pre, %.preheader._crit_edge ], [ %23, %.lr.ph ]
+ %.lcssa69 = phi i32 [ %10, %.preheader._crit_edge ], [ 27, %.lr.ph ]
+ %30 = icmp ugt i32 %.pre-phi, 2
+ %indvars.iv.next = add i32 %indvars.iv, 6
+ %indvars.iv.next14 = add i32 %indvars.iv13, %indvars.iv
+ %indvars.iv.next16 = add i32 %indvars.iv15, %indvars.iv13
+ %indvars.iv.next18 = add i32 %indvars.iv17, -2
+ %indvars.iv.next20 = add i32 %indvars.iv19, 1
+ %indvars.iv.next22 = add i32 %indvars.iv21, 1
+ %indvars.iv.next24 = add i32 %indvars.iv23, 1
+ br i1 %30, label %.preheader, label %.lr.ph.i3.preheader
+
+.lr.ph.i3: ; preds = %.lr.ph.i3, %.lr.ph.i3.preheader
+ %sum.07.i = phi i32 [ %37, %.lr.ph.i3 ], [ 0, %.lr.ph.i3.preheader ]
+ %j.06.i = phi i32 [ %38, %.lr.ph.i3 ], [ 0, %.lr.ph.i3.preheader ]
+ %31 = and i32 %j.06.i, 1
+ %32 = icmp eq i32 %31, 0
+ %33 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 0, i32 %j.06.i
+ %34 = load i32* %33, align 4
+ %35 = sub i32 0, %34
+ %36 = select i1 %32, i32 %34, i32 %35
+ %37 = add i32 %36, %sum.07.i
+ %38 = add i32 %j.06.i, 1
+ %39 = icmp ult i32 %38, 10000
+ br i1 %39, label %.lr.ph.i3, label %checkSum.exit
+
+checkSum.exit: ; preds = %.lr.ph.i3
+ %40 = add i32 %37, 2
+ %41 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str2, i32 0, i32 0), i32 %40) nounwind
+ ret i32 0
+}
+
+declare i32 @sscanf(i8* nocapture, i8* nocapture, ...) nounwind
+
+declare i32 @printf(i8* nocapture, ...) nounwind
diff --git a/tests/cases/muli33_ta2.txt b/tests/cases/muli33_ta2.txt
new file mode 100644
index 00000000..21e0231f
--- /dev/null
+++ b/tests/cases/muli33_ta2.txt
@@ -0,0 +1 @@
+res = 3164
diff --git a/tests/cases/oob_ta2.ll b/tests/cases/oob_ta2.ll
new file mode 100644
index 00000000..3c94c13c
--- /dev/null
+++ b/tests/cases/oob_ta2.ll
@@ -0,0 +1,25 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+%structy = type { [2 x [10 x i8]] }
+
+@.str1 = private unnamed_addr constant [10 x i8] c"1234567890", align 1
+@.str2 = private unnamed_addr constant [10 x i8] c"wakawaka\0A\00", align 1
+@.stry = private unnamed_addr constant [2 x %structy] { %structy { [10 x i8] @.str1, [10 x i8] @.str2 }, %structy { [10 x i8] @.str1, [10 x i8] @.str2 } }
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main(i32 %argc, i8** %argv) {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %ind = add i32 %argc, 13
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([2 x %structy]* @.stry, i32 0, i32 2, i32 0, i32 %ind))
+ %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
+ ret i32 1 ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/philoop_ta2.ll b/tests/cases/philoop_ta2.ll
new file mode 100644
index 00000000..5036c7ba
--- /dev/null
+++ b/tests/cases/philoop_ta2.ll
@@ -0,0 +1,305 @@
+; ModuleID = '/tmp/tmpVIBz29/a.out.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+@.str = private unnamed_addr constant [13 x i8] c"99\0A70\0A26\0A97\0A\00", align 1
+@.str1 = private unnamed_addr constant [12 x i8] c"%u %u %u %u\00", align 1
+@.str2 = private unnamed_addr constant [10 x i8] c"res = %u\0A\00", align 1
+
+define i32 @main() nounwind {
+ %jp0 = alloca i32, align 4
+ %i1 = alloca i32, align 4
+ %jq3 = alloca i32, align 4
+ %i = alloca i32, align 4
+ %cq = alloca [100 x i32], align 4
+ %ye = alloca [100 x i32], align 4
+ %g = alloca [100 x i32], align 4
+ %z = alloca [100 x i32], align 4
+ %za = alloca [100 x [100 x i32]], align 4
+ %a0 = alloca [100 x i32], align 4
+ store i32 99, i32* %jp0, align 4
+ store i32 70, i32* %i1, align 4
+ store i32 26, i32* %jq3, align 4
+ store i32 97, i32* %i, align 4
+ br label %.lr.ph.i
+
+.lr.ph.i: ; preds = %.lr.ph.i, %0
+ %j.07.i = phi i32 [ %7, %.lr.ph.i ], [ 0, %0 ]
+ %1 = and i32 %j.07.i, 1
+ %2 = icmp eq i32 %1, 0
+ %3 = sub i32 0, %j.07.i
+ %.p.i = select i1 %2, i32 %j.07.i, i32 %3
+ %4 = add i32 %.p.i, 2
+ %5 = urem i32 %4, 101
+ %6 = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 %j.07.i
+ store i32 %5, i32* %6, align 4
+ %7 = add i32 %j.07.i, 1
+ %8 = icmp ult i32 %7, 100
+ br i1 %8, label %.lr.ph.i, label %.lr.ph.i44.preheader
+
+.lr.ph.i44.preheader: ; preds = %.lr.ph.i
+ %9 = getelementptr inbounds [100 x i32]* %a0, i32 0, i32 0
+ br label %.lr.ph.i44
+
+.lr.ph.i44: ; preds = %.lr.ph.i44, %.lr.ph.i44.preheader
+ %j.07.i42 = phi i32 [ %16, %.lr.ph.i44 ], [ 0, %.lr.ph.i44.preheader ]
+ %10 = and i32 %j.07.i42, 1
+ %11 = icmp eq i32 %10, 0
+ %12 = sub i32 0, %j.07.i42
+ %.p.i43 = select i1 %11, i32 %j.07.i42, i32 %12
+ %13 = add i32 %.p.i43, 90
+ %14 = urem i32 %13, 101
+ %15 = getelementptr inbounds [100 x i32]* %ye, i32 0, i32 %j.07.i42
+ store i32 %14, i32* %15, align 4
+ %16 = add i32 %j.07.i42, 1
+ %17 = icmp ult i32 %16, 100
+ br i1 %17, label %.lr.ph.i44, label %.lr.ph.i40
+
+.lr.ph.i40: ; preds = %.lr.ph.i40, %.lr.ph.i44
+ %j.07.i38 = phi i32 [ %24, %.lr.ph.i40 ], [ 0, %.lr.ph.i44 ]
+ %18 = and i32 %j.07.i38, 1
+ %19 = icmp eq i32 %18, 0
+ %20 = sub i32 0, %j.07.i38
+ %.p.i39 = select i1 %19, i32 %j.07.i38, i32 %20
+ %21 = add i32 %.p.i39, 73
+ %22 = urem i32 %21, 101
+ %23 = getelementptr inbounds [100 x i32]* %g, i32 0, i32 %j.07.i38
+ store i32 %22, i32* %23, align 4
+ %24 = add i32 %j.07.i38, 1
+ %25 = icmp ult i32 %24, 100
+ br i1 %25, label %.lr.ph.i40, label %.lr.ph.i36
+
+.lr.ph.i36: ; preds = %.lr.ph.i36, %.lr.ph.i40
+ %j.07.i34 = phi i32 [ %32, %.lr.ph.i36 ], [ 0, %.lr.ph.i40 ]
+ %26 = and i32 %j.07.i34, 1
+ %27 = icmp eq i32 %26, 0
+ %28 = sub i32 0, %j.07.i34
+ %.p.i35 = select i1 %27, i32 %j.07.i34, i32 %28
+ %29 = add i32 %.p.i35, 54
+ %30 = urem i32 %29, 101
+ %31 = getelementptr inbounds [100 x i32]* %z, i32 0, i32 %j.07.i34
+ store i32 %30, i32* %31, align 4
+ %32 = add i32 %j.07.i34, 1
+ %33 = icmp ult i32 %32, 100
+ br i1 %33, label %.lr.ph.i36, label %.lr.ph.i32
+
+.lr.ph.i32: ; preds = %.lr.ph.i32, %.lr.ph.i36
+ %j.07.i30 = phi i32 [ %40, %.lr.ph.i32 ], [ 0, %.lr.ph.i36 ]
+ %34 = and i32 %j.07.i30, 1
+ %35 = icmp eq i32 %34, 0
+ %36 = sub i32 0, %j.07.i30
+ %.p.i31 = select i1 %35, i32 %j.07.i30, i32 %36
+ %37 = add i32 %.p.i31, 66
+ %38 = urem i32 %37, 101
+ %39 = getelementptr inbounds [100 x [100 x i32]]* %za, i32 0, i32 0, i32 %j.07.i30
+ store i32 %38, i32* %39, align 4
+ %40 = add i32 %j.07.i30, 1
+ %41 = icmp ult i32 %40, 10000
+ br i1 %41, label %.lr.ph.i32, label %.lr.ph.i28
+
+.lr.ph.i28: ; preds = %.lr.ph.i28, %.lr.ph.i32
+ %j.07.i26 = phi i32 [ %48, %.lr.ph.i28 ], [ 0, %.lr.ph.i32 ]
+ %42 = and i32 %j.07.i26, 1
+ %43 = icmp eq i32 %42, 0
+ %44 = sub i32 0, %j.07.i26
+ %.p.i27 = select i1 %43, i32 %j.07.i26, i32 %44
+ %45 = add i32 %.p.i27, 71
+ %46 = urem i32 %45, 101
+ %47 = getelementptr inbounds [100 x i32]* %a0, i32 0, i32 %j.07.i26
+ store i32 %46, i32* %47, align 4
+ %48 = add i32 %j.07.i26, 1
+ %49 = icmp ult i32 %48, 100
+ br i1 %49, label %.lr.ph.i28, label %init.exit29
+
+init.exit29: ; preds = %.lr.ph.i28
+ %50 = call i32 (i8*, i8*, ...)* @sscanf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @.str1, i32 0, i32 0), i32* %jp0, i32* %i1, i32* %jq3, i32* %i) nounwind
+ %51 = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 46
+ %52 = load i32* %51, align 4
+ %53 = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 20
+ %54 = load i32* %53, align 4
+ %55 = icmp ult i32 %52, %54
+ br i1 %55, label %.preheader61, label %56
+
+; <label>:56 ; preds = %init.exit29
+ %57 = load i32* %9, align 4
+ %58 = getelementptr inbounds [100 x i32]* %ye, i32 0, i32 24
+ %59 = load i32* %58, align 4
+ %60 = sub i32 %59, %57
+ store i32 %60, i32* %58, align 4
+ br label %.preheader61
+
+.preheader61: ; preds = %56, %init.exit29
+ store i32 2, i32* %jp0, align 4
+ %.phi.trans.insert = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 1
+ %.pre = load i32* %.phi.trans.insert, align 4
+ br label %61
+
+.preheader58: ; preds = %61
+ store i32 80, i32* %jp0, align 4
+ store i32 94, i32* %i1, align 4
+ br label %76
+
+; <label>:61 ; preds = %61, %.preheader61
+ %62 = phi i32 [ %.pre, %.preheader61 ], [ %66, %61 ]
+ %63 = phi i32 [ 2, %.preheader61 ], [ %71, %61 ]
+ %64 = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 %63
+ %65 = load i32* %64, align 4
+ %66 = add i32 %65, -4
+ store i32 %66, i32* %64, align 4
+ %67 = add i32 %63, -1
+ %68 = getelementptr inbounds [100 x i32]* %ye, i32 0, i32 %67
+ %69 = load i32* %68, align 4
+ %70 = mul i32 %62, %69
+ %71 = add i32 %63, 1
+ %72 = getelementptr inbounds [100 x i32]* %g, i32 0, i32 %71
+ %73 = load i32* %72, align 4
+ %74 = sub i32 %73, %70
+ store i32 %74, i32* %72, align 4
+ %75 = icmp ult i32 %71, 80
+ br i1 %75, label %61, label %.preheader58
+
+.preheader55: ; preds = %76
+ store i32 2, i32* %i1, align 4
+ store i32 44, i32* %jq3, align 4
+ br label %.preheader
+
+; <label>:76 ; preds = %76, %.preheader58
+ %77 = phi i32 [ 94, %.preheader58 ], [ %80, %76 ]
+ %78 = getelementptr inbounds [100 x i32]* %ye, i32 0, i32 %77
+ %79 = load i32* %78, align 4
+ %80 = add i32 %77, -1
+ %81 = getelementptr inbounds [100 x i32]* %z, i32 0, i32 %80
+ store i32 %79, i32* %81, align 4
+ %82 = icmp ugt i32 %80, 2
+ br i1 %82, label %76, label %.preheader55
+
+.preheader: ; preds = %95, %.preheader55
+ %83 = phi i32 [ 44, %.preheader55 ], [ %84, %95 ]
+ %84 = add i32 %83, -1
+ %85 = getelementptr inbounds [100 x [100 x i32]]* %za, i32 0, i32 %84, i32 %83
+ %.promoted = load i32* %85, align 4
+ %.pre75 = load i32* %9, align 4
+ %.phi.trans.insert76 = getelementptr inbounds [100 x i32]* %a0, i32 0, i32 1
+ %.pre77 = load i32* %.phi.trans.insert76, align 4
+ br label %86
+
+; <label>:86 ; preds = %86, %.preheader
+ %87 = phi i32 [ %.pre77, %.preheader ], [ %88, %86 ]
+ %88 = phi i32 [ %.pre75, %.preheader ], [ %87, %86 ]
+ %89 = phi i32 [ 1, %.preheader ], [ %92, %86 ]
+ %90 = phi i32 [ %.promoted, %.preheader ], [ %91, %86 ]
+ %91 = mul i32 %90, %87
+ %92 = add i32 %89, 1
+ %93 = getelementptr inbounds [100 x i32]* %a0, i32 0, i32 %92
+ store i32 %88, i32* %93, align 4
+ %94 = icmp ult i32 %92, 46
+ br i1 %94, label %86, label %95
+
+; <label>:95 ; preds = %86
+ store i32 %91, i32* %85, align 4
+ %96 = icmp ugt i32 %84, 1
+ br i1 %96, label %.preheader, label %97
+
+; <label>:97 ; preds = %95
+ store i32 1, i32* %jq3, align 4
+ store i32 46, i32* %i, align 4
+ br label %.lr.ph.i24
+
+.lr.ph.i24: ; preds = %.lr.ph.i24, %97
+ %sum.07.i22 = phi i32 [ %104, %.lr.ph.i24 ], [ 0, %97 ]
+ %j.06.i23 = phi i32 [ %105, %.lr.ph.i24 ], [ 0, %97 ]
+ %98 = and i32 %j.06.i23, 1
+ %99 = icmp eq i32 %98, 0
+ %100 = getelementptr inbounds [100 x i32]* %cq, i32 0, i32 %j.06.i23
+ %101 = load i32* %100, align 4
+ %102 = sub i32 0, %101
+ %103 = select i1 %99, i32 %101, i32 %102
+ %104 = add i32 %103, %sum.07.i22
+ %105 = add i32 %j.06.i23, 1
+ %106 = icmp ult i32 %105, 100
+ br i1 %106, label %.lr.ph.i24, label %.lr.ph.i20
+
+.lr.ph.i20: ; preds = %.lr.ph.i20, %.lr.ph.i24
+ %sum.07.i18 = phi i32 [ %113, %.lr.ph.i20 ], [ 0, %.lr.ph.i24 ]
+ %j.06.i19 = phi i32 [ %114, %.lr.ph.i20 ], [ 0, %.lr.ph.i24 ]
+ %107 = and i32 %j.06.i19, 1
+ %108 = icmp eq i32 %107, 0
+ %109 = getelementptr inbounds [100 x i32]* %ye, i32 0, i32 %j.06.i19
+ %110 = load i32* %109, align 4
+ %111 = sub i32 0, %110
+ %112 = select i1 %108, i32 %110, i32 %111
+ %113 = add i32 %112, %sum.07.i18
+ %114 = add i32 %j.06.i19, 1
+ %115 = icmp ult i32 %114, 100
+ br i1 %115, label %.lr.ph.i20, label %.lr.ph.i16
+
+.lr.ph.i16: ; preds = %.lr.ph.i16, %.lr.ph.i20
+ %sum.07.i14 = phi i32 [ %122, %.lr.ph.i16 ], [ 0, %.lr.ph.i20 ]
+ %j.06.i15 = phi i32 [ %123, %.lr.ph.i16 ], [ 0, %.lr.ph.i20 ]
+ %116 = and i32 %j.06.i15, 1
+ %117 = icmp eq i32 %116, 0
+ %118 = getelementptr inbounds [100 x i32]* %g, i32 0, i32 %j.06.i15
+ %119 = load i32* %118, align 4
+ %120 = sub i32 0, %119
+ %121 = select i1 %117, i32 %119, i32 %120
+ %122 = add i32 %121, %sum.07.i14
+ %123 = add i32 %j.06.i15, 1
+ %124 = icmp ult i32 %123, 100
+ br i1 %124, label %.lr.ph.i16, label %.lr.ph.i12
+
+.lr.ph.i12: ; preds = %.lr.ph.i12, %.lr.ph.i16
+ %sum.07.i10 = phi i32 [ %131, %.lr.ph.i12 ], [ 0, %.lr.ph.i16 ]
+ %j.06.i11 = phi i32 [ %132, %.lr.ph.i12 ], [ 0, %.lr.ph.i16 ]
+ %125 = and i32 %j.06.i11, 1
+ %126 = icmp eq i32 %125, 0
+ %127 = getelementptr inbounds [100 x i32]* %z, i32 0, i32 %j.06.i11
+ %128 = load i32* %127, align 4
+ %129 = sub i32 0, %128
+ %130 = select i1 %126, i32 %128, i32 %129
+ %131 = add i32 %130, %sum.07.i10
+ %132 = add i32 %j.06.i11, 1
+ %133 = icmp ult i32 %132, 100
+ br i1 %133, label %.lr.ph.i12, label %.lr.ph.i8
+
+.lr.ph.i8: ; preds = %.lr.ph.i8, %.lr.ph.i12
+ %sum.07.i6 = phi i32 [ %140, %.lr.ph.i8 ], [ 0, %.lr.ph.i12 ]
+ %j.06.i7 = phi i32 [ %141, %.lr.ph.i8 ], [ 0, %.lr.ph.i12 ]
+ %134 = and i32 %j.06.i7, 1
+ %135 = icmp eq i32 %134, 0
+ %136 = getelementptr inbounds [100 x [100 x i32]]* %za, i32 0, i32 0, i32 %j.06.i7
+ %137 = load i32* %136, align 4
+ %138 = sub i32 0, %137
+ %139 = select i1 %135, i32 %137, i32 %138
+ %140 = add i32 %139, %sum.07.i6
+ %141 = add i32 %j.06.i7, 1
+ %142 = icmp ult i32 %141, 10000
+ br i1 %142, label %.lr.ph.i8, label %.lr.ph.i5
+
+.lr.ph.i5: ; preds = %.lr.ph.i5, %.lr.ph.i8
+ %sum.07.i = phi i32 [ %149, %.lr.ph.i5 ], [ 0, %.lr.ph.i8 ]
+ %j.06.i = phi i32 [ %150, %.lr.ph.i5 ], [ 0, %.lr.ph.i8 ]
+ %143 = and i32 %j.06.i, 1
+ %144 = icmp eq i32 %143, 0
+ %145 = getelementptr inbounds [100 x i32]* %a0, i32 0, i32 %j.06.i
+ %146 = load i32* %145, align 4
+ %147 = sub i32 0, %146
+ %148 = select i1 %144, i32 %146, i32 %147
+ %149 = add i32 %148, %sum.07.i
+ %150 = add i32 %j.06.i, 1
+ %151 = icmp ult i32 %150, 100
+ br i1 %151, label %.lr.ph.i5, label %checkSum.exit
+
+checkSum.exit: ; preds = %.lr.ph.i5
+ %152 = add i32 %104, 82
+ %153 = add i32 %152, %113
+ %154 = sub i32 %153, %122
+ %155 = add i32 %154, %131
+ %156 = sub i32 %155, %140
+ %157 = add i32 %156, %149
+ %158 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str2, i32 0, i32 0), i32 %157) nounwind
+ ret i32 0
+}
+
+declare i32 @sscanf(i8* nocapture, i8* nocapture, ...) nounwind
+
+declare i32 @printf(i8* nocapture, ...) nounwind
diff --git a/tests/cases/philoop_ta2.txt b/tests/cases/philoop_ta2.txt
new file mode 100644
index 00000000..d5117fe8
--- /dev/null
+++ b/tests/cases/philoop_ta2.txt
@@ -0,0 +1 @@
+res = 1962923669
diff --git a/tests/embind/build_benchmark b/tests/embind/build_benchmark
index 6faad18b..3d5d816b 100644
--- a/tests/embind/build_benchmark
+++ b/tests/embind/build_benchmark
@@ -1,2 +1,2 @@
#!/bin/bash
-EMCC_LLVM_TARGET=le32-unknown-nacl ~/projects/emscripten/emcc --minify 0 --bind --post-js embind.benchmark.js -O2 --shell-file shell.html -o embind_benchmark.html embind_benchmark.cpp
+EMCC_LLVM_TARGET=le32-unknown-nacl ../../emcc --minify 0 --bind --post-js embind.benchmark.js -O2 --shell-file shell.html -o embind_benchmark.html embind_benchmark.cpp
diff --git a/tests/embind/embind.benchmark.js b/tests/embind/embind.benchmark.js
index 7b20db88..3669bc28 100644
--- a/tests/embind/embind.benchmark.js
+++ b/tests/embind/embind.benchmark.js
@@ -248,3 +248,38 @@ function _call_through_interface1() {
Module.print("C++ -> JS std::wstring through interface " + N + " iters: " + elapsed + " msecs.");
obj.delete();
}
+
+function _call_through_interface2() {
+ var N = 1000000;
+ var total = 0;
+ var obj = Module['Interface'].implement({
+ call_with_typed_array: function(ta) {
+ total += ta.length;
+ },
+ call_with_memory_view: function(ta) {
+ total += ta.length;
+ },
+ });
+
+ var start = _emscripten_get_now();
+ Module['callInterface2'](N, obj);
+ var elapsed = _emscripten_get_now() - start;
+ Module.print("C++ -> JS typed array instantiation " + N + " iters: " + elapsed + " msecs.");
+
+ var start = _emscripten_get_now();
+ Module['callInterface3'](N, obj);
+ var elapsed = _emscripten_get_now() - start;
+ Module.print("C++ -> JS memory_view instantiation" + N + " iters: " + elapsed + " msecs.");
+ obj.delete();
+}
+
+function _returns_val_benchmark() {
+ var N = 1000000;
+ var v = 1;
+ var start = _emscripten_get_now();
+ for(var i = 0; i < N; ++i) {
+ v = Module['returns_val'](v);
+ }
+ var elapsed = _emscripten_get_now() - start;
+ Module.print("returns_val " + N + " iters: " + elapsed + " msecs");
+}
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index 52b2cad8..e60e1ab3 100644
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -5,6 +5,8 @@ module({
var CheckForLeaks = fixture("check for leaks", function() {
this.setUp(function() {
+ cm.setDelayFunction(undefined);
+
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
cm._mallocDebug(2);
assert.equal(0, cm.count_emval_handles());
@@ -12,6 +14,7 @@ module({
}
});
this.tearDown(function() {
+ cm.flushPendingDeletes();
if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
cm._mallocAssertAllMemoryFree();
assert.equal(0, cm.count_emval_handles());
@@ -490,6 +493,15 @@ module({
assert.equal(true, cm.emval_test_not(false));
});
+ test("can pass booleans as integers", function() {
+ assert.equal(1, cm.emval_test_as_unsigned(true));
+ assert.equal(0, cm.emval_test_as_unsigned(false));
+ });
+
+ test("can pass booleans as floats", function() {
+ assert.equal(2, cm.const_ref_adder(true, true));
+ });
+
test("convert double to unsigned", function() {
var rv = cm.emval_test_as_unsigned(1.5);
assert.equal('number', typeof rv);
@@ -672,6 +684,15 @@ module({
c.delete();
});
+ test("access multiple smart ptr ctors", function() {
+ var a = new cm.MultipleSmartCtors(10);
+ assert.equal(a.WhichCtorCalled(), 1);
+ var b = new cm.MultipleCtors(20, 20);
+ assert.equal(b.WhichCtorCalled(), 2);
+ a.delete();
+ b.delete();
+ });
+
test("wrong number of constructor arguments throws", function() {
assert.throws(cm.BindingError, function() { new cm.MultipleCtors(); });
assert.throws(cm.BindingError, function() { new cm.MultipleCtors(1,2,3,4); });
@@ -1559,6 +1580,28 @@ module({
impl.delete();
});
+ test("returning null shared pointer from interfaces implemented in JS code does not leak", function() {
+ var impl = cm.AbstractClass.implement({
+ returnsSharedPtr: function() {
+ return null;
+ }
+ });
+ cm.callReturnsSharedPtrMethod(impl);
+ impl.delete();
+ // Let the memory leak test superfixture check that no leaks occurred.
+ });
+
+ test("returning a new shared pointer from interfaces implemented in JS code does not leak", function() {
+ var impl = cm.AbstractClass.implement({
+ returnsSharedPtr: function() {
+ return cm.embind_test_return_smart_derived_ptr();
+ }
+ });
+ cm.callReturnsSharedPtrMethod(impl);
+ impl.delete();
+ // Let the memory leak test superfixture check that no leaks occurred.
+ });
+
test("void methods work", function() {
var saved = {};
var impl = cm.AbstractClass.implement({
@@ -1728,6 +1771,116 @@ module({
e.delete();
f.delete();
});
+
+ BaseFixture.extend("memory view", function() {
+ test("can pass memory view from C++ to JS", function() {
+ var views = [];
+ cm.callWithMemoryView(function(view) {
+ views.push(view);
+ });
+ assert.equal(3, views.length);
+
+ assert.instanceof(views[0], Uint8Array);
+ assert.equal(8, views[0].length);
+ assert.deepEqual([0, 1, 2, 3, 4, 5, 6, 7], [].slice.call(new Uint8Array(views[0])));
+
+ assert.instanceof(views[1], Float32Array);
+ assert.equal(4, views[1].length);
+ assert.deepEqual([1.5, 2.5, 3.5, 4.5], [].slice.call(views[1]));
+
+ assert.instanceof(views[2], Int16Array);
+ assert.equal(4, views[2].length);
+ assert.deepEqual([1000, 100, 10, 1], [].slice.call(views[2]));
+ });
+ });
+
+ BaseFixture.extend("delete pool", function() {
+ test("can delete objects later", function() {
+ var v = new cm.ValHolder({});
+ v.deleteLater();
+ assert.deepEqual({}, v.getVal());
+ cm.flushPendingDeletes();
+ assert.throws(cm.BindingError, function() {
+ v.getVal();
+ });
+ });
+
+ test("calling deleteLater twice is an error", function() {
+ var v = new cm.ValHolder({});
+ v.deleteLater();
+ assert.throws(cm.BindingError, function() {
+ v.deleteLater();
+ });
+ });
+
+ test("deleteLater returns the object", function() {
+ var v = (new cm.ValHolder({})).deleteLater();
+ assert.deepEqual({}, v.getVal());
+ });
+
+ test("deleteLater throws if object is already deleted", function() {
+ var v = new cm.ValHolder({});
+ v.delete();
+ assert.throws(cm.BindingError, function() {
+ v.deleteLater();
+ });
+ });
+
+ test("delete throws if object is already scheduled for deletion", function() {
+ var v = new cm.ValHolder({});
+ v.deleteLater();
+ assert.throws(cm.BindingError, function() {
+ v.delete();
+ });
+ });
+
+ test("deleteLater invokes delay function", function() {
+ var runLater;
+ cm.setDelayFunction(function(fn) {
+ runLater = fn;
+ });
+
+ var v = new cm.ValHolder({});
+ assert.false(runLater);
+ v.deleteLater();
+ assert.true(runLater);
+ assert.false(v.isDeleted());
+ runLater();
+ assert.true(v.isDeleted());
+ });
+
+ test("deleteLater twice invokes delay function once", function() {
+ var count = 0;
+ var runLater;
+ cm.setDelayFunction(function(fn) {
+ ++count;
+ runLater = fn;
+ });
+
+ (new cm.ValHolder({})).deleteLater();
+ (new cm.ValHolder({})).deleteLater();
+ assert.equal(1, count);
+ runLater();
+ (new cm.ValHolder({})).deleteLater();
+ assert.equal(2, count);
+ });
+
+ test('The delay function is immediately invoked if the deletion queue is not empty', function() {
+ (new cm.ValHolder({})).deleteLater();
+ var count = 0;
+ cm.setDelayFunction(function(fn) {
+ ++count;
+ });
+ assert.equal(1, count);
+ });
+
+ // The idea is that an interactive application would
+ // periodically flush the deleteLater queue by calling
+ //
+ // setDelayFunction(function(fn) {
+ // setTimeout(fn, 0);
+ // });
+ });
});
/* global run_all_tests */
diff --git a/tests/embind/embind_benchmark.cpp b/tests/embind/embind_benchmark.cpp
index b6a834c9..5ae9a6be 100644
--- a/tests/embind/embind_benchmark.cpp
+++ b/tests/embind/embind_benchmark.cpp
@@ -50,6 +50,14 @@ extern void pass_gameobject_ptr_benchmark_embind_js();
extern void call_through_interface0();
extern void call_through_interface1();
+extern void call_through_interface2();
+
+extern void returns_val_benchmark();
+}
+
+emscripten::val returns_val(emscripten::val value)
+{
+ return emscripten::val(value.as<unsigned>() + 1);
}
class Vec3
@@ -135,19 +143,45 @@ class Interface
public:
virtual void call0() = 0;
virtual std::wstring call1(const std::wstring& str1, const std::wstring& str2) = 0;
+ virtual void call_with_typed_array(size_t size, const void*) = 0;
+ virtual void call_with_memory_view(size_t size, const void*) = 0;
};
+EMSCRIPTEN_SYMBOL(HEAP8);
+EMSCRIPTEN_SYMBOL(buffer);
+
+EMSCRIPTEN_SYMBOL(call0);
+EMSCRIPTEN_SYMBOL(call1);
+EMSCRIPTEN_SYMBOL(call_with_typed_array);
+EMSCRIPTEN_SYMBOL(call_with_memory_view);
+EMSCRIPTEN_SYMBOL(Uint8Array);
+
class InterfaceWrapper : public emscripten::wrapper<Interface>
{
public:
EMSCRIPTEN_WRAPPER(InterfaceWrapper);
void call0() override {
- return call<void>("call0");
+ return call<void>(call0_symbol);
}
std::wstring call1(const std::wstring& str1, const std::wstring& str2) {
- return call<std::wstring>("call1", str1, str2);
+ return call<std::wstring>(call1_symbol, str1, str2);
+ }
+
+ void call_with_typed_array(size_t size, const void* data) {
+ return call<void>(
+ call_with_typed_array_symbol,
+ emscripten::val::global(Uint8Array_symbol).new_(
+ emscripten::val::module_property(HEAP8_symbol)[buffer_symbol],
+ reinterpret_cast<uintptr_t>(data),
+ size));
+ }
+
+ void call_with_memory_view(size_t size, const void* data) {
+ return call<void>(
+ call_with_memory_view_symbol,
+ emscripten::memory_view(size, data));
}
};
@@ -180,6 +214,33 @@ void callInterface1(unsigned N, Interface& o) {
}
}
+void callInterface2(unsigned N, Interface& o) {
+ int i = 0;
+ for (unsigned i = 0; i < N; i += 8) {
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ o.call_with_typed_array(sizeof(int), &i);
+ }
+}
+
+void callInterface3(unsigned N, Interface& o) {
+ for (unsigned i = 0; i < N; i += 8) {
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ o.call_with_memory_view(sizeof(int), &i);
+ }
+}
+
EMSCRIPTEN_BINDINGS(benchmark)
{
using namespace emscripten;
@@ -225,6 +286,10 @@ EMSCRIPTEN_BINDINGS(benchmark)
function("callInterface0", &callInterface0);
function("callInterface1", &callInterface1);
+ function("callInterface2", &callInterface2);
+ function("callInterface3", &callInterface3);
+
+ function("returns_val", &returns_val);
}
void __attribute__((noinline)) emscripten_get_now_benchmark(int N)
@@ -435,4 +500,6 @@ int main()
emscripten_get_now();
call_through_interface0();
call_through_interface1();
+ call_through_interface2();
+ returns_val_benchmark();
}
diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp
index 23761efc..3561b8a1 100644
--- a/tests/embind/embind_test.cpp
+++ b/tests/embind/embind_test.cpp
@@ -1084,6 +1084,7 @@ public:
return "optional" + s;
}
+ virtual std::shared_ptr<Derived> returnsSharedPtr() = 0;
virtual void differentArguments(int i, double d, unsigned char f, double q, std::string) = 0;
};
@@ -1103,6 +1104,10 @@ public:
}, s);
}
+ std::shared_ptr<Derived> returnsSharedPtr() {
+ return call<std::shared_ptr<Derived> >("returnsSharedPtr");
+ }
+
void differentArguments(int i, double d, unsigned char f, double q, std::string s) {
return call<void>("differentArguments", i, d, f, q, s);
}
@@ -1116,6 +1121,10 @@ class ConcreteClass : public AbstractClass {
void differentArguments(int i, double d, unsigned char f, double q, std::string s) {
}
+
+ std::shared_ptr<Derived> returnsSharedPtr() {
+ return std::shared_ptr<Derived>();
+ }
};
std::shared_ptr<AbstractClass> getAbstractClass() {
@@ -1130,6 +1139,11 @@ std::string callOptionalMethod(AbstractClass& ac, std::string s) {
return ac.optionalMethod(s);
}
+void callReturnsSharedPtrMethod(AbstractClass& ac) {
+ std::shared_ptr<Derived> sp = ac.returnsSharedPtr();
+ // unused: sp
+}
+
void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f, double q, std::string s) {
return ac.differentArguments(i, d, f, q, s);
}
@@ -1145,9 +1159,29 @@ EMSCRIPTEN_BINDINGS(interface_tests) {
function("getAbstractClass", &getAbstractClass);
function("callAbstractMethod", &callAbstractMethod);
function("callOptionalMethod", &callOptionalMethod);
+ function("callReturnsSharedPtrMethod", &callReturnsSharedPtrMethod);
function("callDifferentArguments", &callDifferentArguments);
}
+template<typename T, size_t sizeOfArray>
+constexpr size_t getElementCount(T (&)[sizeOfArray]) {
+ return sizeOfArray;
+}
+
+static void callWithMemoryView(val v) {
+ // static so the JS test can read the memory after callTakeMemoryView runs
+ static unsigned char data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ v(memory_view(getElementCount(data), data));
+ static float f[] = { 1.5f, 2.5f, 3.5f, 4.5f };
+ v(typed_memory_view(getElementCount(f), f));
+ static short s[] = { 1000, 100, 10, 1 };
+ v(typed_memory_view(getElementCount(s), s));
+}
+
+EMSCRIPTEN_BINDINGS(memory_view_tests) {
+ function("callWithMemoryView", &callWithMemoryView);
+}
+
class HasExternalConstructor {
public:
HasExternalConstructor(const std::string& str)
@@ -1831,7 +1865,7 @@ int overloaded_function(int i, int j) {
class MultipleCtors {
public:
- int value;
+ int value = 0;
MultipleCtors(int i) {
value = 1;
@@ -1854,6 +1888,25 @@ public:
}
};
+class MultipleSmartCtors {
+public:
+ int value = 0;
+
+ MultipleSmartCtors(int i) {
+ value = 1;
+ assert(i == 10);
+ }
+ MultipleSmartCtors(int i, int j) {
+ value = 2;
+ assert(i == 20);
+ assert(j == 20);
+ }
+
+ int WhichCtorCalled() const {
+ return value;
+ }
+};
+
class MultipleOverloads {
public:
MultipleOverloads() {}
@@ -1960,7 +2013,15 @@ EMSCRIPTEN_BINDINGS(overloads) {
.constructor<int>()
.constructor<int, int>()
.constructor<int, int, int>()
- .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled);
+ .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled)
+ ;
+
+ class_<MultipleSmartCtors>("MultipleSmartCtors")
+ .smart_ptr<std::shared_ptr<MultipleSmartCtors>>()
+ .constructor(&std::make_shared<MultipleSmartCtors, int>)
+ .constructor(&std::make_shared<MultipleSmartCtors, int, int>)
+ .function("WhichCtorCalled", &MultipleSmartCtors::WhichCtorCalled)
+ ;
class_<MultipleOverloads>("MultipleOverloads")
.constructor<>()
diff --git a/tests/files.cpp b/tests/files.cpp
index 04baa151..176cdb62 100644
--- a/tests/files.cpp
+++ b/tests/files.cpp
@@ -56,6 +56,9 @@ int main()
fwrite(data, 1, 5, outf);
fclose(outf);
+ FILE *devNull = fopen("/dev/null", "rb");
+ assert(devNull);
+
char data2[10];
FILE *inf = fopen("go.out", "rb");
int num = fread(data2, 1, 10, inf);
diff --git a/tests/full_es2_sdlproc.c b/tests/full_es2_sdlproc.c
new file mode 100644
index 00000000..d9ac072b
--- /dev/null
+++ b/tests/full_es2_sdlproc.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Ported to GLES2.
+ * Kristian Høgsberg <krh@bitplanet.net>
+ * May 3, 2010
+ *
+ * Improve GLES2 port:
+ * * Refactor gear drawing.
+ * * Use correct normals for surfaces.
+ * * Improve shader.
+ * * Use perspective projection transformation.
+ * * Add FPS count.
+ * * Add comments.
+ * Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ * Jul 13, 2010
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#define _GNU_SOURCE
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glut.h>
+
+#ifndef HAVE_BUILTIN_SINCOS
+#include "sincos.h"
+#endif
+
+#define STRIPS_PER_TOOTH 7
+#define VERTICES_PER_TOOTH 34
+#define GEAR_VERTEX_STRIDE 6
+
+/**
+ * Struct describing the vertices in triangle strip
+ */
+struct vertex_strip {
+ /** The first vertex in the strip */
+ GLint first;
+ /** The number of consecutive vertices in the strip after the first */
+ GLint count;
+};
+
+/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
+typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
+
+/**
+ * Struct representing a gear.
+ */
+struct gear {
+ /** The array of vertices comprising the gear */
+ GearVertex *vertices;
+ /** The number of vertices comprising the gear */
+ int nvertices;
+ /** The array of triangle strips comprising the gear */
+ struct vertex_strip *strips;
+ /** The number of triangle strips comprising the gear */
+ int nstrips;
+ /** The Vertex Buffer Object holding the vertices in the graphics card */
+ GLuint vbo;
+};
+
+/** The view rotation [x, y, z] */
+static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 };
+/** The gears */
+static struct gear *gear1, *gear2, *gear3;
+/** The current gear rotation angle */
+static GLfloat angle = 0.0;
+/** The location of the shader uniforms */
+static GLuint ModelViewProjectionMatrix_location,
+ NormalMatrix_location,
+ LightSourcePosition_location,
+ MaterialColor_location;
+/** The projection matrix */
+static GLfloat ProjectionMatrix[16];
+/** The direction of the directional light for the scene */
+static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0};
+
+/**
+ * Fills a gear vertex.
+ *
+ * @param v the vertex to fill
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coortinate
+ * @param n pointer to the normal table
+ *
+ * @return the operation error code
+ */
+static GearVertex *
+vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3])
+{
+ v[0][0] = x;
+ v[0][1] = y;
+ v[0][2] = z;
+ v[0][3] = n[0];
+ v[0][4] = n[1];
+ v[0][5] = n[2];
+
+ return v + 1;
+}
+
+/**
+ * Create a gear wheel.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ *
+ * @return pointer to the constructed struct gear
+ */
+static struct gear *
+create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLfloat r0, r1, r2;
+ GLfloat da;
+ GearVertex *v;
+ struct gear *gear;
+ double s[5], c[5];
+ GLfloat normal[3];
+ int cur_strip = 0;
+ int i;
+
+ /* Allocate memory for the gear */
+ gear = malloc(sizeof *gear);
+ if (gear == NULL)
+ return NULL;
+
+ /* Calculate the radii used in the gear */
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ /* Allocate memory for the triangle strip information */
+ gear->nstrips = STRIPS_PER_TOOTH * teeth;
+ gear->strips = calloc(gear->nstrips, sizeof (*gear->strips));
+
+ /* Allocate memory for the vertices */
+ gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
+ v = gear->vertices;
+
+ for (i = 0; i < teeth; i++) {
+ /* Calculate needed sin/cos for varius angles */
+ sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]);
+ sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
+ sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
+ sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
+ sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
+
+ /* A set of macros for making the creation of the gears easier */
+#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] }
+#define SET_NORMAL(x, y, z) do { \
+ normal[0] = (x); normal[1] = (y); normal[2] = (z); \
+} while(0)
+
+#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
+
+#define START_STRIP do { \
+ gear->strips[cur_strip].first = v - gear->vertices; \
+} while(0);
+
+#define END_STRIP do { \
+ int _tmp = (v - gear->vertices); \
+ gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \
+ cur_strip++; \
+} while (0)
+
+#define QUAD_WITH_NORMAL(p1, p2) do { \
+ SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \
+ v = GEAR_VERT(v, (p1), -1); \
+ v = GEAR_VERT(v, (p1), 1); \
+ v = GEAR_VERT(v, (p2), -1); \
+ v = GEAR_VERT(v, (p2), 1); \
+} while(0)
+
+ struct point {
+ GLfloat x;
+ GLfloat y;
+ };
+
+ /* Create the 7 points (only x,y coords) used to draw a tooth */
+ struct point p[7] = {
+ GEAR_POINT(r2, 1), // 0
+ GEAR_POINT(r2, 2), // 1
+ GEAR_POINT(r1, 0), // 2
+ GEAR_POINT(r1, 3), // 3
+ GEAR_POINT(r0, 0), // 4
+ GEAR_POINT(r1, 4), // 5
+ GEAR_POINT(r0, 4), // 6
+ };
+
+ /* Front face */
+ START_STRIP;
+ SET_NORMAL(0, 0, 1.0);
+ v = GEAR_VERT(v, 0, +1);
+ v = GEAR_VERT(v, 1, +1);
+ v = GEAR_VERT(v, 2, +1);
+ v = GEAR_VERT(v, 3, +1);
+ v = GEAR_VERT(v, 4, +1);
+ v = GEAR_VERT(v, 5, +1);
+ v = GEAR_VERT(v, 6, +1);
+ END_STRIP;
+
+ /* Inner face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(4, 6);
+ END_STRIP;
+
+ /* Back face */
+ START_STRIP;
+ SET_NORMAL(0, 0, -1.0);
+ v = GEAR_VERT(v, 6, -1);
+ v = GEAR_VERT(v, 5, -1);
+ v = GEAR_VERT(v, 4, -1);
+ v = GEAR_VERT(v, 3, -1);
+ v = GEAR_VERT(v, 2, -1);
+ v = GEAR_VERT(v, 1, -1);
+ v = GEAR_VERT(v, 0, -1);
+ END_STRIP;
+
+ /* Outer face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(0, 2);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(1, 0);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(3, 1);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(5, 3);
+ END_STRIP;
+ }
+
+ gear->nvertices = (v - gear->vertices);
+
+ /* Store the vertices in a vertex buffer object (VBO) */
+ glGenBuffers(1, &gear->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+ glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex),
+ gear->vertices, GL_STATIC_DRAW);
+
+ return gear;
+}
+
+/**
+ * Multiplies two 4x4 matrices.
+ *
+ * The result is stored in matrix m.
+ *
+ * @param m the first matrix to multiply
+ * @param n the second matrix to multiply
+ */
+static void
+multiply(GLfloat *m, const GLfloat *n)
+{
+ GLfloat tmp[16];
+ const GLfloat *row, *column;
+ div_t d;
+ int i, j;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = 0;
+ d = div(i, 4);
+ row = n + d.quot * 4;
+ column = m + d.rem;
+ for (j = 0; j < 4; j++)
+ tmp[i] += row[j] * column[j * 4];
+ }
+ memcpy(m, &tmp, sizeof tmp);
+}
+
+/**
+ * Rotates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to rotate
+ * @param angle the angle to rotate
+ * @param x the x component of the direction to rotate to
+ * @param y the y component of the direction to rotate to
+ * @param z the z component of the direction to rotate to
+ */
+static void
+rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ double s, c;
+
+ sincos(angle, &s, &c);
+ GLfloat r[16] = {
+ x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
+ x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
+ x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
+ 0, 0, 0, 1
+ };
+
+ multiply(m, r);
+}
+
+
+/**
+ * Translates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to translate
+ * @param x the x component of the direction to translate to
+ * @param y the y component of the direction to translate to
+ * @param z the z component of the direction to translate to
+ */
+static void
+translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
+
+ multiply(m, t);
+}
+
+/**
+ * Creates an identity 4x4 matrix.
+ *
+ * @param m the matrix make an identity matrix
+ */
+static void
+identity(GLfloat *m)
+{
+ GLfloat t[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Transposes a 4x4 matrix.
+ *
+ * @param m the matrix to transpose
+ */
+static void
+transpose(GLfloat *m)
+{
+ GLfloat t[16] = {
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]};
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Inverts a 4x4 matrix.
+ *
+ * This function can currently handle only pure translation-rotation matrices.
+ * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
+ * for an explanation.
+ */
+static void
+invert(GLfloat *m)
+{
+ GLfloat t[16];
+ identity(t);
+
+ // Extract and invert the translation part 't'. The inverse of a
+ // translation matrix can be calculated by negating the translation
+ // coordinates.
+ t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];
+
+ // Invert the rotation part 'r'. The inverse of a rotation matrix is
+ // equal to its transpose.
+ m[12] = m[13] = m[14] = 0;
+ transpose(m);
+
+ // inv(m) = inv(r) * inv(t)
+ multiply(m, t);
+}
+
+/**
+ * Calculate a perspective projection transformation.
+ *
+ * @param m the matrix to save the transformation in
+ * @param fovy the field of view in the y direction
+ * @param aspect the view aspect ratio
+ * @param zNear the near clipping plane
+ * @param zFar the far clipping plane
+ */
+void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ GLfloat tmp[16];
+ identity(tmp);
+
+ double sine, cosine, cotangent, deltaZ;
+ GLfloat radians = fovy / 2 * M_PI / 180;
+
+ deltaZ = zFar - zNear;
+ sincos(radians, &sine, &cosine);
+
+ if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
+ return;
+
+ cotangent = cosine / sine;
+
+ tmp[0] = cotangent / aspect;
+ tmp[5] = cotangent;
+ tmp[10] = -(zFar + zNear) / deltaZ;
+ tmp[11] = -1;
+ tmp[14] = -2 * zNear * zFar / deltaZ;
+ tmp[15] = 0;
+
+ memcpy(m, tmp, sizeof(tmp));
+}
+
+/**
+ * Draws a gear.
+ *
+ * @param gear the gear to draw
+ * @param transform the current transformation matrix
+ * @param x the x position to draw the gear at
+ * @param y the y position to draw the gear at
+ * @param angle the rotation angle of the gear
+ * @param color the color of the gear
+ */
+static void
+draw_gear(struct gear *gear, GLfloat *transform,
+ GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4])
+{
+ GLfloat model_view[16];
+ GLfloat normal_matrix[16];
+ GLfloat model_view_projection[16];
+
+ /* Translate and rotate the gear */
+ memcpy(model_view, transform, sizeof (model_view));
+ translate(model_view, x, y, 0);
+ rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1);
+
+ /* Create and set the ModelViewProjectionMatrix */
+ memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection));
+ multiply(model_view_projection, model_view);
+
+ glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE,
+ model_view_projection);
+
+ /*
+ * Create and set the NormalMatrix. It's the inverse transpose of the
+ * ModelView matrix.
+ */
+ memcpy(normal_matrix, model_view, sizeof (normal_matrix));
+ invert(normal_matrix);
+ transpose(normal_matrix);
+ glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix);
+
+ /* Set the gear color */
+ glUniform4fv(MaterialColor_location, 1, color);
+
+ /* Set the vertex buffer object to use */
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+
+ /* Set up the position of the attributes in the vertex buffer object */
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), NULL);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
+
+ /* Enable the attributes */
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+
+ /* Draw the triangle strips that comprise the gear */
+ int n;
+ for (n = 0; n < gear->nstrips; n++)
+ glDrawElements(GL_TRIANGLE_STRIP, gear->strips[n].count, GL_FLOAT, gear->strips[n].first);
+
+ /* Disable the attributes */
+ glDisableVertexAttribArray(1);
+ glDisableVertexAttribArray(0);
+}
+
+/**
+ * Draws the gears.
+ */
+static void
+gears_draw(void)
+{
+ const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+ GLfloat transform[16];
+ identity(transform);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Translate and rotate the view */
+ translate(transform, 0, 0, -20);
+ rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0);
+ rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0);
+ rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1);
+
+ /* Draw the gears */
+ draw_gear(gear1, transform, -3.0, -2.0, angle, red);
+ draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green);
+ draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue);
+
+ glutSwapBuffers();
+}
+
+/**
+ * Handles a new window size or exposure.
+ *
+ * @param width the window width
+ * @param height the window height
+ */
+static void
+gears_reshape(int width, int height)
+{
+ /* Update the projection matrix */
+ perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0);
+
+ /* Set the viewport */
+ glViewport(0, 0, (GLint) width, (GLint) height);
+}
+
+/**
+ * Handles special glut events.
+ *
+ * @param special the event to handle.
+ */
+static void
+gears_special(int special, int crap, int morecrap)
+{
+ switch (special) {
+ case GLUT_KEY_LEFT:
+ view_rot[1] += 5.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ view_rot[1] -= 5.0;
+ break;
+ case GLUT_KEY_UP:
+ view_rot[0] += 5.0;
+ break;
+ case GLUT_KEY_DOWN:
+ view_rot[0] -= 5.0;
+ break;
+ }
+}
+
+static void
+gears_idle(void)
+{
+ static int frames = 0;
+ static double tRot0 = -1.0, tRate0 = -1.0;
+ double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+
+ if (tRot0 < 0.0)
+ tRot0 = t;
+ dt = t - tRot0;
+ tRot0 = t;
+
+ /* advance rotation for next frame */
+ angle += 70.0 * dt; /* 70 degrees per second */
+ if (angle > 3600.0)
+ angle -= 3600.0;
+
+ glutPostRedisplay();
+ frames++;
+
+ if (tRate0 < 0.0)
+ tRate0 = t;
+ if (t - tRate0 >= 5.0) {
+ GLfloat seconds = t - tRate0;
+ GLfloat fps = frames / seconds;
+ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+ fps);
+ tRate0 = t;
+ frames = 0;
+ }
+}
+
+static const char vertex_shader[] =
+"attribute vec3 position;\n"
+"attribute vec3 normal;\n"
+"\n"
+"uniform mat4 ModelViewProjectionMatrix;\n"
+"uniform mat4 NormalMatrix;\n"
+"uniform vec4 LightSourcePosition;\n"
+"uniform vec4 MaterialColor;\n"
+"\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" // Transform the normal to eye coordinates\n"
+" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n"
+"\n"
+" // The LightSourcePosition is actually its direction for directional light\n"
+" vec3 L = normalize(LightSourcePosition.xyz);\n"
+"\n"
+" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n"
+" // to get the actual color that we will use to draw this vertex with\n"
+" float diffuse = max(dot(N, L), 0.0);\n"
+" Color = diffuse * MaterialColor;\n"
+"\n"
+" // Transform the position to clip coordinates\n"
+" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n"
+"}";
+
+static const char fragment_shader[] =
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" gl_FragColor = Color;\n"
+"}";
+
+static void
+gears_init(void)
+{
+ GLuint v, f, program;
+ const char *p;
+ char msg[512];
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ /* Compile the vertex shader */
+ p = vertex_shader;
+ v = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(v, 1, &p, NULL);
+ glCompileShader(v);
+ glGetShaderInfoLog(v, sizeof msg, NULL, msg);
+ printf("vertex shader info: %s\n", msg);
+
+ /* Compile the fragment shader */
+ p = fragment_shader;
+ f = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(f, 1, &p, NULL);
+ glCompileShader(f);
+ glGetShaderInfoLog(f, sizeof msg, NULL, msg);
+ printf("fragment shader info: %s\n", msg);
+
+ /* Create and link the shader program */
+ program = glCreateProgram();
+ glAttachShader(program, v);
+ glAttachShader(program, f);
+ glBindAttribLocation(program, 0, "position");
+ glBindAttribLocation(program, 1, "normal");
+
+ glLinkProgram(program);
+ glGetProgramInfoLog(program, sizeof msg, NULL, msg);
+ printf("info: %s\n", msg);
+
+ /* Enable the shaders */
+ glUseProgram(program);
+
+ /* Get the locations of the uniforms so we can access them */
+ ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
+ NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix");
+ LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition");
+ MaterialColor_location = glGetUniformLocation(program, "MaterialColor");
+
+ /* Set the LightSourcePosition uniform which is constant throught the program */
+ glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition);
+
+ /* make the gears */
+ gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
+ gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7);
+ gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7);
+}
+
+int
+main(int argc, char *argv[])
+{
+ if (argc == 12) SDL_GL_GetProcAddress("glWhatevah");
+
+ /* Initialize the window */
+ glutInit(&argc, argv);
+ glutInitWindowSize(300, 300);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+
+ glutCreateWindow("es2gears");
+
+ gears_idle();
+ gears_init();
+ gears_draw();
+
+ int result = 1;
+ REPORT_RESULT();
+
+ return 0;
+}
diff --git a/tests/gl_ps.c b/tests/gl_ps.c
index 6ea0e3db..4fa79922 100644
--- a/tests/gl_ps.c
+++ b/tests/gl_ps.c
@@ -115,11 +115,11 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
+
#if !EMSCRIPTEN
glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
#endif
@@ -135,30 +135,30 @@ int main(int argc, char *argv[])
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -169,25 +169,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
shaders();
// Bind the texture to which subsequent calls refer to
@@ -218,7 +218,7 @@ int main(int argc, char *argv[])
glDisableClientState(GL_VERTEX_ARRAY);
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(3000);
@@ -226,8 +226,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/gl_ps_workaround.c b/tests/gl_ps_workaround.c
deleted file mode 100644
index 1e2a5c41..00000000
--- a/tests/gl_ps_workaround.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*******************************************************************
- * *
- * Using SDL With OpenGL *
- * *
- * Tutorial by Kyle Foley (sdw) *
- * *
- * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
- * *
- *******************************************************************/
-
-/*
-THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
-AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
-
-THE ORIGINAL AUTHOR IS KYLE FOLEY.
-
-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
-RESULTING FROM THE USE, MODIFICATION, OR
-REDISTRIBUTION OF THIS SOFTWARE.
-*/
-
-#if !EMSCRIPTEN
-#define USE_GLEW 1
-#endif
-
-#if USE_GLEW
-#include "GL/glew.h"
-#endif
-
-#include "SDL/SDL.h"
-#include "SDL/SDL_image.h"
-#if !USE_GLEW
-#include "SDL/SDL_opengl.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-void shaders() {
-#if USE_GLEW
- glewInit();
-#endif
-
- GLint ok;
-
- const char *vertexShader = "void main(void) \n"
- "{ \n"
- " gl_Position = ftransform(); \n"
- " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
- " gl_FrontColor = gl_Color; \n"
- "} \n";
- const char *fragmentShader = "uniform sampler2D tex0; \n"
- "void main(void) \n"
- "{ \n"
- " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n"
- "} \n";
-
- GLuint vs = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vs, 1, &vertexShader, NULL);
- glCompileShader(vs);
- glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
- assert(ok);
-
- GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fs, 1, &fragmentShader, NULL);
- glCompileShader(fs);
- glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
- assert(ok);
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, vs);
- glAttachShader(program, fs);
- glLinkProgram(program);
- glGetProgramiv(program, GL_LINK_STATUS, &ok);
- assert(ok);
-
- glUseProgram(program);
-}
-
-int main(int argc, char *argv[])
-{
- SDL_Surface *screen;
-
- // Slightly different SDL initialization
- if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
- printf("Unable to initialize SDL: %s\n", SDL_GetError());
- return 1;
- }
-
- SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
-
- screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
- if ( !screen ) {
- printf("Unable to set video mode: %s\n", SDL_GetError());
- return 1;
- }
-
- // Set the OpenGL state after creating the context with SDL_SetVideoMode
-
- glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
-
- glViewport( 0, 0, 640, 480 );
-
- glMatrixMode( GL_PROJECTION );
- GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
- 0, -2.0/480, 0, 0,
- 0, 0, -1, 0,
- -1, 1, 0, 1 };
- glLoadMatrixf(matrixData); // test loadmatrix
-
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
-
- // Load the OpenGL texture
-
- GLuint texture; // Texture object handle
- SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
- // Check that the image's width is a power of 2
- if ( (surface->w & (surface->w - 1)) != 0 ) {
- printf("warning: image.bmp's width is not a power of 2\n");
- }
-
- // Also check if the height is a power of 2
- if ( (surface->h & (surface->h - 1)) != 0 ) {
- printf("warning: image.bmp's height is not a power of 2\n");
- }
-
- // Have OpenGL generate a texture object handle for us
- glGenTextures( 1, &texture );
-
- // Bind the texture object
- glBindTexture( GL_TEXTURE_2D, texture );
-
- // Set the texture's stretching properties
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-
- //SDL_LockSurface(surface);
-
- // Add some greyness
- memset(surface->pixels, 0x66, surface->w*surface->h);
-
- // Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
-
- //SDL_UnlockSurface(surface);
- }
- else {
- printf("SDL could not load image.bmp: %s\n", SDL_GetError());
- SDL_Quit();
- return 1;
- }
-
- // Free the SDL_Surface only if it was successfully created
- if ( surface ) {
- SDL_FreeSurface( surface );
- }
-
- // Clear the screen before drawing
- glClear( GL_COLOR_BUFFER_BIT );
-
- shaders();
-
- // Bind the texture to which subsequent calls refer to
- glBindTexture( GL_TEXTURE_2D, texture );
-
- // Use clientside vertex pointers to render two items. In this test we have each
- // attribute in a separate buffer, packed (i.e. stride == 0)
- GLfloat vertexData[] = { 10, 10,
- 300, 10,
- 300, 128,
- 10, 128,
- 410, 10,
- 600, 10,
- 630, 200,
- 310, 250,
- 100, 300,
- 300, 300,
- 300, 400,
- 100, 400 };
- GLfloat textureData[] = { 0, 0,
- 1, 0,
- 1, 1,
- 0, 1,
- 0, 0.5,
- 1, 0.5,
- 1, 1,
- 0.5, 1,
- 0, 0,
- 1, 0,
- 1, 1,
- 0, 1, };
-
- glEnableClientState(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); // XXX
- glTexCoordPointer(2, GL_FLOAT, 0, textureData);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, vertexData);
-
- glDrawArrays(GL_QUADS, 0, 12);
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- SDL_GL_SwapBuffers();
-
-#if !EMSCRIPTEN
- // Wait for 3 seconds to give us a chance to see the image
- SDL_Delay(3000);
-#endif
-
- // Now we can delete the OpenGL texture and close down SDL
- glDeleteTextures( 1, &texture );
-
- SDL_Quit();
-
- return 0;
-}
diff --git a/tests/gl_ps_workaround2.c b/tests/gl_ps_workaround2.c
deleted file mode 100644
index e5bd2fd1..00000000
--- a/tests/gl_ps_workaround2.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*******************************************************************
- * *
- * Using SDL With OpenGL *
- * *
- * Tutorial by Kyle Foley (sdw) *
- * *
- * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
- * *
- *******************************************************************/
-
-/*
-THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
-AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
-
-THE ORIGINAL AUTHOR IS KYLE FOLEY.
-
-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
-RESULTING FROM THE USE, MODIFICATION, OR
-REDISTRIBUTION OF THIS SOFTWARE.
-*/
-
-#if !EMSCRIPTEN
-#define USE_GLEW 1
-#endif
-
-#if USE_GLEW
-#include "GL/glew.h"
-#endif
-
-#include "SDL/SDL.h"
-#include "SDL/SDL_image.h"
-#if !USE_GLEW
-#include "SDL/SDL_opengl.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-void shaders() {
-#if USE_GLEW
- glewInit();
-#endif
-
- GLint ok;
-
- const char *vertexShader = "void main(void) \n"
- "{ \n"
- " gl_Position = ftransform(); \n"
- " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
- " gl_FrontColor = gl_Color; \n"
- "} \n";
- const char *fragmentShader = "uniform sampler2D tex0; \n"
- "void main(void) \n"
- "{ \n"
- " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n"
- "} \n";
-
- GLuint vs = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vs, 1, &vertexShader, NULL);
- glCompileShader(vs);
- glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
- assert(ok);
-
- GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fs, 1, &fragmentShader, NULL);
- glCompileShader(fs);
- glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
- assert(ok);
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, vs);
- glAttachShader(program, fs);
- glLinkProgram(program);
- glGetProgramiv(program, GL_LINK_STATUS, &ok);
- assert(ok);
-
- glUseProgram(program);
-}
-
-int main(int argc, char *argv[])
-{
- SDL_Surface *screen;
-
- // Slightly different SDL initialization
- if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
- printf("Unable to initialize SDL: %s\n", SDL_GetError());
- return 1;
- }
-
- SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
-
- screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
- if ( !screen ) {
- printf("Unable to set video mode: %s\n", SDL_GetError());
- return 1;
- }
-
- // Set the OpenGL state after creating the context with SDL_SetVideoMode
-
- glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
-
- glViewport( 0, 0, 640, 480 );
-
- glMatrixMode( GL_PROJECTION );
- GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
- 0, -2.0/480, 0, 0,
- 0, 0, -1, 0,
- -1, 1, 0, 1 };
- glLoadMatrixf(matrixData); // test loadmatrix
-
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
-
- // Load the OpenGL texture
-
- GLuint texture; // Texture object handle
- SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
- // Check that the image's width is a power of 2
- if ( (surface->w & (surface->w - 1)) != 0 ) {
- printf("warning: image.bmp's width is not a power of 2\n");
- }
-
- // Also check if the height is a power of 2
- if ( (surface->h & (surface->h - 1)) != 0 ) {
- printf("warning: image.bmp's height is not a power of 2\n");
- }
-
- // Have OpenGL generate a texture object handle for us
- glGenTextures( 1, &texture );
-
- // Bind the texture object
- glBindTexture( GL_TEXTURE_2D, texture );
-
- // Set the texture's stretching properties
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-
- //SDL_LockSurface(surface);
-
- // Add some greyness
- memset(surface->pixels, 0x66, surface->w*surface->h);
-
- // Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
-
- //SDL_UnlockSurface(surface);
- }
- else {
- printf("SDL could not load image.bmp: %s\n", SDL_GetError());
- SDL_Quit();
- return 1;
- }
-
- // Free the SDL_Surface only if it was successfully created
- if ( surface ) {
- SDL_FreeSurface( surface );
- }
-
- // Clear the screen before drawing
- glClear( GL_COLOR_BUFFER_BIT );
-
- shaders();
-
- // Bind the texture to which subsequent calls refer to
- glBindTexture( GL_TEXTURE_2D, texture );
-
- // Use clientside vertex pointers to render two items. In this test we have each
- // attribute in a separate buffer, packed (i.e. stride == 0)
- GLfloat vertexData[] = { 10, 10,
- 300, 10,
- 300, 128,
- 10, 128,
- 410, 10,
- 600, 10,
- 630, 200,
- 310, 250,
- 100, 300,
- 300, 300,
- 300, 400,
- 100, 400 };
- GLfloat textureData[] = { 0, 0,
- 1, 0,
- 1, 1,
- 0, 1,
- 0, 0.5,
- 1, 0.5,
- 1, 1,
- 0.5, 1,
- 0, 0,
- 1, 0,
- 1, 1,
- 0, 1, };
-
- glEnable(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); and also glEnableClientState! XXX two workarounds here
- glTexCoordPointer(2, GL_FLOAT, 0, textureData);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, vertexData);
-
- glDrawArrays(GL_QUADS, 0, 12);
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- SDL_GL_SwapBuffers();
-
-#if !EMSCRIPTEN
- // Wait for 3 seconds to give us a chance to see the image
- SDL_Delay(3000);
-#endif
-
- // Now we can delete the OpenGL texture and close down SDL
- glDeleteTextures( 1, &texture );
-
- SDL_Quit();
-
- return 0;
-}
diff --git a/tests/glbegin_points.c b/tests/glbegin_points.c
index b28cca4e..9128a4f5 100644
--- a/tests/glbegin_points.c
+++ b/tests/glbegin_points.c
@@ -46,14 +46,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -66,30 +64,30 @@ int main(int argc, char *argv[])
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -151,7 +149,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(3000);
@@ -159,8 +157,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/linpack.c b/tests/linpack.c
new file mode 100644
index 00000000..363415c3
--- /dev/null
+++ b/tests/linpack.c
@@ -0,0 +1,1153 @@
+/* gcc linpack.c cpuidc64.o cpuida64.o -m64 -lrt -lc -lm -o linpack
+ *
+ * Linpack 100x100 Benchmark In C/C++ For PCs
+ *
+ * Different compilers can produce different floating point numeric
+ * results, probably due to compiling instructions in a different
+ * sequence. As the program checks these, they may need to be changed.
+ * The log file indicates non-standard results and these values can
+ * be copied and pasted into this program. See // Values near the
+ * end of main().
+ *
+ * Different compilers do not optimise the code in the same way.
+ * This can lead to wide variations in benchmark speeds. See results
+ * with MS6 compiler ID and compare with those from same CPUs from
+ * the Watcom compiler generated code.
+ *
+ ***************************************************************************
+*/
+
+#define _CRT_SECURE_NO_WARNINGS 1
+#ifdef WIN32
+#include <Windows.h>
+#else
+#include <sys/time.h>
+#endif
+
+#define UNROLL
+#define DP
+
+#ifdef SP
+#define REAL float
+#define ZERO 0.0
+#define ONE 1.0
+#define PREC "Single"
+#endif
+
+#ifdef DP
+#define REAL double
+#define ZERO 0.0e0
+#define ONE 1.0e0
+#define PREC "Double"
+#endif
+
+#ifdef ROLL
+#define ROLLING "Rolled"
+#endif
+#ifdef UNROLL
+#define ROLLING "Unrolled"
+#endif
+
+ // VERSION
+
+ #ifdef CNNT
+ #define options "Non-optimised"
+ #define opt "0"
+ #else
+// #define options "Optimised"
+ #define options "Opt 3 64 Bit"
+ #define opt "1"
+ #endif
+
+#define NTIMES 10
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+/* this is truly rank, but it's minimally invasive, and lifted in part from the STREAM scores */
+
+static double secs;
+
+#ifndef WIN32
+
+double mysecond()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ int i;
+
+ i = gettimeofday(&tp,&tzp);
+ return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
+}
+#else
+
+double mysecond()
+{
+ static LARGE_INTEGER freq = {0};
+ LARGE_INTEGER count = {0};
+ if(freq.QuadPart == 0LL) {
+ QueryPerformanceFrequency(&freq);
+ }
+ QueryPerformanceCounter(&count);
+ return (double)count.QuadPart / (double)freq.QuadPart;
+}
+
+#endif
+
+void start_time()
+{
+ secs = mysecond();
+}
+
+void end_time()
+{
+ secs = mysecond() - secs;
+}
+
+void print_time (int row);
+void matgen (REAL a[], int lda, int n, REAL b[], REAL *norma);
+void dgefa (REAL a[], int lda, int n, int ipvt[], int *info);
+void dgesl (REAL a[],int lda,int n,int ipvt[],REAL b[],int job);
+void dmxpy (int n1, REAL y[], int n2, int ldm, REAL x[], REAL m[]);
+void daxpy (int n, REAL da, REAL dx[], int incx, REAL dy[], int incy);
+REAL epslon (REAL x);
+int idamax (int n, REAL dx[], int incx);
+void dscal (int n, REAL da, REAL dx[], int incx);
+REAL ddot (int n, REAL dx[], int incx, REAL dy[], int incy);
+
+static REAL atime[9][15];
+double runSecs = 1;
+
+
+int main (int argc, char *argv[])
+{
+ static REAL aa[200*200],a[200*201],b[200],x[200];
+ REAL cray,ops,total,norma,normx;
+ REAL resid,residn,eps,tm2,epsn,x1,x2;
+ REAL mflops;
+ static int ipvt[200],n,i,j,ntimes,info,lda,ldaa;
+ int endit, pass, loop;
+ REAL overhead1, overhead2, time2;
+ REAL max1, max2;
+ char was[5][20];
+ char expect[5][20];
+ char title[5][20];
+ int errors;
+
+
+ printf("\n");
+
+ printf("##########################################\n");
+
+
+
+ lda = 201;
+ ldaa = 200;
+ cray = .056;
+ n = 100;
+
+ fprintf(stdout, "%s ", ROLLING);
+ fprintf(stdout, "%s ", PREC);
+ fprintf(stdout,"Precision Linpack Benchmark - PC Version in 'C/C++'\n\n");
+
+ fprintf(stdout,"Optimisation %s\n\n",options);
+
+ ops = (2.0e0*(n*n*n))/3.0 + 2.0*(n*n);
+
+ matgen(a,lda,n,b,&norma);
+ start_time();
+ dgefa(a,lda,n,ipvt,&info);
+ end_time();
+ atime[0][0] = secs;
+ start_time();
+ dgesl(a,lda,n,ipvt,b,0);
+ end_time();
+ atime[1][0] = secs;
+ total = atime[0][0] + atime[1][0];
+
+/* compute a residual to verify results. */
+
+ for (i = 0; i < n; i++) {
+ x[i] = b[i];
+ }
+ matgen(a,lda,n,b,&norma);
+ for (i = 0; i < n; i++) {
+ b[i] = -b[i];
+ }
+ dmxpy(n,b,n,lda,x,a);
+ resid = 0.0;
+ normx = 0.0;
+ for (i = 0; i < n; i++) {
+ resid = (resid > fabs((double)b[i]))
+ ? resid : fabs((double)b[i]);
+ normx = (normx > fabs((double)x[i]))
+ ? normx : fabs((double)x[i]);
+ }
+ eps = epslon(ONE);
+ residn = resid/( n*norma*normx*eps );
+ epsn = eps;
+ x1 = x[0] - 1;
+ x2 = x[n-1] - 1;
+
+ printf("norm resid resid machep");
+ printf(" x[0]-1 x[n-1]-1\n");
+ printf("%6.1f %17.8e%17.8e%17.8e%17.8e\n\n",
+ (double)residn, (double)resid, (double)epsn,
+ (double)x1, (double)x2);
+
+ printf("Times are reported for matrices of order %5d\n",n);
+ printf("1 pass times for array with leading dimension of%5d\n\n",lda);
+ printf(" dgefa dgesl total Mflops unit");
+ printf(" ratio\n");
+
+ atime[2][0] = total;
+ if (total > 0.0)
+ {
+ atime[3][0] = ops/(1.0e6*total);
+ atime[4][0] = 2.0/atime[3][0];
+ }
+ else
+ {
+ atime[3][0] = 0.0;
+ atime[4][0] = 0.0;
+ }
+ atime[5][0] = total/cray;
+
+ print_time(0);
+
+/************************************************************************
+ * Calculate overhead of executing matgen procedure *
+ ************************************************************************/
+
+ printf("\nCalculating matgen overhead\n");
+ pass = -20;
+ loop = NTIMES;
+ do
+ {
+ start_time();
+ pass = pass + 1;
+ for ( i = 0 ; i < loop ; i++)
+ {
+ matgen(a,lda,n,b,&norma);
+ }
+ end_time();
+ overhead1 = secs;
+ printf("%10d times %6.2f seconds\n", loop, overhead1);
+ if (overhead1 > runSecs)
+ {
+ pass = 0;
+ }
+ if (pass < 0)
+ {
+ if (overhead1 < 0.1)
+ {
+ loop = loop * 10;
+ }
+ else
+ {
+ loop = loop * 2;
+ }
+ }
+ }
+ while (pass < 0);
+
+ overhead1 = overhead1 / (double)loop;
+
+ printf("Overhead for 1 matgen %12.5f seconds\n\n", overhead1);
+
+/************************************************************************
+ * Calculate matgen/dgefa passes for runSecs seconds *
+ ************************************************************************/
+
+ printf("Calculating matgen/dgefa passes for %d seconds\n", (int)runSecs);
+ pass = -20;
+ ntimes = NTIMES;
+ do
+ {
+ start_time();
+ pass = pass + 1;
+ for ( i = 0 ; i < ntimes ; i++)
+ {
+ matgen(a,lda,n,b,&norma);
+ dgefa(a,lda,n,ipvt,&info );
+ }
+ end_time();
+ time2 = secs;
+ printf("%10d times %6.2f seconds\n", ntimes, time2);
+ if (time2 > runSecs)
+ {
+ pass = 0;
+ }
+ if (pass < 0)
+ {
+ if (time2 < 0.1)
+ {
+ ntimes = ntimes * 10;
+ }
+ else
+ {
+ ntimes = ntimes * 2;
+ }
+ }
+ }
+ while (pass < 0);
+
+ ntimes = (int)(runSecs * (double)ntimes / time2);
+ if (ntimes == 0) ntimes = 1;
+
+ printf("Passes used %10d \n\n", ntimes);
+ printf("Times for array with leading dimension of%4d\n\n",lda);
+ printf(" dgefa dgesl total Mflops unit");
+ printf(" ratio\n");
+
+/************************************************************************
+ * Execute 5 passes *
+ ************************************************************************/
+
+ tm2 = ntimes * overhead1;
+ atime[3][6] = 0;
+
+ for (j=1 ; j<6 ; j++)
+ {
+ start_time();
+ for (i = 0; i < ntimes; i++)
+ {
+ matgen(a,lda,n,b,&norma);
+ dgefa(a,lda,n,ipvt,&info );
+ }
+ end_time();
+ atime[0][j] = (secs - tm2)/ntimes;
+
+ start_time();
+ for (i = 0; i < ntimes; i++)
+ {
+ dgesl(a,lda,n,ipvt,b,0);
+ }
+ end_time();
+
+ atime[1][j] = secs/ntimes;
+ total = atime[0][j] + atime[1][j];
+ atime[2][j] = total;
+ atime[3][j] = ops/(1.0e6*total);
+ atime[4][j] = 2.0/atime[3][j];
+ atime[5][j] = total/cray;
+ atime[3][6] = atime[3][6] + atime[3][j];
+
+ print_time(j);
+ }
+ atime[3][6] = atime[3][6] / 5.0;
+ printf("Average %11.2f\n",
+ (double)atime[3][6]);
+
+ printf("\nCalculating matgen2 overhead\n");
+
+/************************************************************************
+ * Calculate overhead of executing matgen procedure *
+ ************************************************************************/
+
+ start_time();
+ for ( i = 0 ; i < loop ; i++)
+ {
+ matgen(aa,ldaa,n,b,&norma);
+ }
+ end_time();
+ overhead2 = secs;
+ overhead2 = overhead2 / (double)loop;
+
+ printf("Overhead for 1 matgen %12.5f seconds\n\n", overhead2);
+ printf("Times for array with leading dimension of%4d\n\n",ldaa);
+ printf(" dgefa dgesl total Mflops unit");
+ printf(" ratio\n");
+
+/************************************************************************
+ * Execute 5 passes *
+ ************************************************************************/
+
+ tm2 = ntimes * overhead2;
+ atime[3][12] = 0;
+
+ for (j=7 ; j<12 ; j++)
+ {
+ start_time();
+ for (i = 0; i < ntimes; i++)
+ {
+ matgen(aa,ldaa,n,b,&norma);
+ dgefa(aa,ldaa,n,ipvt,&info );
+ }
+ end_time();
+ atime[0][j] = (secs - tm2)/ntimes;
+
+ start_time();
+ for (i = 0; i < ntimes; i++)
+ {
+ dgesl(aa,ldaa,n,ipvt,b,0);
+ }
+ end_time();
+ atime[1][j] = secs/ntimes;
+ total = atime[0][j] + atime[1][j];
+ atime[2][j] = total;
+ atime[3][j] = ops/(1.0e6*total);
+ atime[4][j] = 2.0/atime[3][j];
+ atime[5][j] = total/cray;
+ atime[3][12] = atime[3][12] + atime[3][j];
+
+ print_time(j);
+ }
+ atime[3][12] = atime[3][12] / 5.0;
+ printf("Average %11.2f\n",
+ (double)atime[3][12]);
+
+/************************************************************************
+ * Use minimum average as overall Mflops rating *
+ ************************************************************************/
+
+ mflops = atime[3][6];
+ if (atime[3][12] < mflops) mflops = atime[3][12];
+
+ printf("\n");
+ printf( "%s ", ROLLING);
+ printf( "%s ", PREC);
+ printf(" Precision %11.2f Mflops \n\n",mflops);
+
+
+ max1 = 0;
+ for (i=1 ; i<6 ; i++)
+ {
+ if (atime[3][i] > max1) max1 = atime[3][i];
+ }
+
+ max2 = 0;
+ for (i=7 ; i<12 ; i++)
+ {
+ if (atime[3][i] > max2) max2 = atime[3][i];
+ }
+ if (max1 < max2) max2 = max1;
+
+ sprintf(was[0], "%16.1f",(double)residn);
+ sprintf(was[1], "%16.8e",(double)resid);
+ sprintf(was[2], "%16.8e",(double)epsn);
+ sprintf(was[3], "%16.8e",(double)x1);
+ sprintf(was[4], "%16.8e",(double)x2);
+
+/*
+ // Values for Watcom
+
+ sprintf(expect[0], " 0.4");
+ sprintf(expect[1], " 7.41628980e-014");
+ sprintf(expect[2], " 1.00000000e-015");
+ sprintf(expect[3], "-1.49880108e-014");
+ sprintf(expect[4], "-1.89848137e-014");
+ // Values for Visual C++
+
+ sprintf(expect[0], " 1.7");
+ sprintf(expect[1], " 7.41628980e-014");
+ sprintf(expect[2], " 2.22044605e-016");
+ sprintf(expect[3], "-1.49880108e-014");
+ sprintf(expect[4], "-1.89848137e-014");
+
+ // Values for Ubuntu GCC 32 Bit
+
+ sprintf(expect[0], " 1.9");
+ sprintf(expect[1], " 8.39915160e-14");
+ sprintf(expect[2], " 2.22044605e-16");
+ sprintf(expect[3], " -6.22835117e-14");
+ sprintf(expect[4], " -4.16333634e-14");
+*/
+
+ // Values for Ubuntu GCC 32 Bit
+
+ sprintf(expect[0], " 1.7");
+ sprintf(expect[1], " 7.41628980e-14");
+ sprintf(expect[2], " 2.22044605e-16");
+ sprintf(expect[3], " -1.49880108e-14");
+ sprintf(expect[4], " -1.89848137e-14");
+
+ sprintf(title[0], "norm. resid");
+ sprintf(title[1], "resid ");
+ sprintf(title[2], "machep ");
+ sprintf(title[3], "x[0]-1 ");
+ sprintf(title[4], "x[n-1]-1 ");
+
+ if (strtol(opt, NULL, 10) == 0)
+ {
+ sprintf(expect[2], " 8.88178420e-016");
+ }
+ errors = 0;
+
+ printf ("\n");
+}
+
+/*----------------------*/
+void print_time (int row)
+
+{
+printf("%11.5f%11.5f%11.5f%11.2f%11.4f%11.4f\n", (double)atime[0][row],
+ (double)atime[1][row], (double)atime[2][row], (double)atime[3][row],
+ (double)atime[4][row], (double)atime[5][row]);
+ return;
+}
+
+/*----------------------*/
+
+void matgen (REAL a[], int lda, int n, REAL b[], REAL *norma)
+
+
+/* We would like to declare a[][lda], but c does not allow it. In this
+function, references to a[i][j] are written a[lda*i+j]. */
+
+{
+ int init, i, j;
+
+ init = 1325;
+ *norma = 0.0;
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < n; i++) {
+ init = 3125*init % 65536;
+ a[lda*j+i] = (init - 32768.0)/16384.0;
+ *norma = (a[lda*j+i] > *norma) ? a[lda*j+i] : *norma;
+
+ /* alternative for some compilers
+ if (fabs(a[lda*j+i]) > *norma) *norma = fabs(a[lda*j+i]);
+ */
+ }
+ }
+ for (i = 0; i < n; i++) {
+ b[i] = 0.0;
+ }
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < n; i++) {
+ b[i] = b[i] + a[lda*j+i];
+ }
+ }
+ return;
+}
+
+/*----------------------*/
+void dgefa(REAL a[], int lda, int n, int ipvt[], int *info)
+
+
+/* We would like to declare a[][lda], but c does not allow it. In this
+function, references to a[i][j] are written a[lda*i+j]. */
+/*
+ dgefa factors a double precision matrix by gaussian elimination.
+
+ dgefa is usually called by dgeco, but it can be called
+ directly with a saving in time if rcond is not needed.
+ (time for dgeco) = (1 + 9/n)*(time for dgefa) .
+
+ on entry
+
+ a REAL precision[n][lda]
+ the matrix to be factored.
+
+ lda integer
+ the leading dimension of the array a .
+
+ n integer
+ the order of the matrix a .
+
+ on return
+
+ a an upper triangular matrix and the multipliers
+ which were used to obtain it.
+ the factorization can be written a = l*u where
+ l is a product of permutation and unit lower
+ triangular matrices and u is upper triangular.
+
+ ipvt integer[n]
+ an integer vector of pivot indices.
+
+ info integer
+ = 0 normal value.
+ = k if u[k][k] .eq. 0.0 . this is not an error
+ condition for this subroutine, but it does
+ indicate that dgesl or dgedi will divide by zero
+ if called. use rcond in dgeco for a reliable
+ indication of singularity.
+
+ linpack. this version dated 08/14/78 .
+ cleve moler, university of new mexico, argonne national lab.
+
+ functions
+
+ blas daxpy,dscal,idamax
+*/
+
+{
+/* internal variables */
+
+REAL t;
+int j,k,kp1,l,nm1;
+
+
+/* gaussian elimination with partial pivoting */
+
+ *info = 0;
+ nm1 = n - 1;
+ if (nm1 >= 0) {
+ for (k = 0; k < nm1; k++) {
+ kp1 = k + 1;
+
+ /* find l = pivot index */
+
+ l = idamax(n-k,&a[lda*k+k],1) + k;
+ ipvt[k] = l;
+
+ /* zero pivot implies this column already
+ triangularized */
+
+ if (a[lda*k+l] != ZERO) {
+
+ /* interchange if necessary */
+
+ if (l != k) {
+ t = a[lda*k+l];
+ a[lda*k+l] = a[lda*k+k];
+ a[lda*k+k] = t;
+ }
+
+ /* compute multipliers */
+
+ t = -ONE/a[lda*k+k];
+ dscal(n-(k+1),t,&a[lda*k+k+1],1);
+
+ /* row elimination with column indexing */
+
+ for (j = kp1; j < n; j++) {
+ t = a[lda*j+l];
+ if (l != k) {
+ a[lda*j+l] = a[lda*j+k];
+ a[lda*j+k] = t;
+ }
+ daxpy(n-(k+1),t,&a[lda*k+k+1],1,
+ &a[lda*j+k+1],1);
+ }
+ }
+ else {
+ *info = k;
+ }
+ }
+ }
+ ipvt[n-1] = n-1;
+ if (a[lda*(n-1)+(n-1)] == ZERO) *info = n-1;
+ return;
+}
+
+/*----------------------*/
+
+void dgesl(REAL a[],int lda,int n,int ipvt[],REAL b[],int job )
+
+
+/* We would like to declare a[][lda], but c does not allow it. In this
+function, references to a[i][j] are written a[lda*i+j]. */
+
+/*
+ dgesl solves the double precision system
+ a * x = b or trans(a) * x = b
+ using the factors computed by dgeco or dgefa.
+
+ on entry
+
+ a double precision[n][lda]
+ the output from dgeco or dgefa.
+
+ lda integer
+ the leading dimension of the array a .
+
+ n integer
+ the order of the matrix a .
+
+ ipvt integer[n]
+ the pivot vector from dgeco or dgefa.
+
+ b double precision[n]
+ the right hand side vector.
+
+ job integer
+ = 0 to solve a*x = b ,
+ = nonzero to solve trans(a)*x = b where
+ trans(a) is the transpose.
+
+ on return
+
+ b the solution vector x .
+
+ error condition
+
+ a division by zero will occur if the input factor contains a
+ zero on the diagonal. technically this indicates singularity
+ but it is often caused by improper arguments or improper
+ setting of lda . it will not occur if the subroutines are
+ called correctly and if dgeco has set rcond .gt. 0.0
+ or dgefa has set info .eq. 0 .
+
+ to compute inverse(a) * c where c is a matrix
+ with p columns
+ dgeco(a,lda,n,ipvt,rcond,z)
+ if (!rcond is too small){
+ for (j=0,j<p,j++)
+ dgesl(a,lda,n,ipvt,c[j][0],0);
+ }
+
+ linpack. this version dated 08/14/78 .
+ cleve moler, university of new mexico, argonne national lab.
+
+ functions
+
+ blas daxpy,ddot
+*/
+{
+/* internal variables */
+
+ REAL t;
+ int k,kb,l,nm1;
+
+ nm1 = n - 1;
+ if (job == 0) {
+
+ /* job = 0 , solve a * x = b
+ first solve l*y = b */
+
+ if (nm1 >= 1) {
+ for (k = 0; k < nm1; k++) {
+ l = ipvt[k];
+ t = b[l];
+ if (l != k){
+ b[l] = b[k];
+ b[k] = t;
+ }
+ daxpy(n-(k+1),t,&a[lda*k+k+1],1,&b[k+1],1 );
+ }
+ }
+
+ /* now solve u*x = y */
+
+ for (kb = 0; kb < n; kb++) {
+ k = n - (kb + 1);
+ b[k] = b[k]/a[lda*k+k];
+ t = -b[k];
+ daxpy(k,t,&a[lda*k+0],1,&b[0],1 );
+ }
+ }
+ else {
+
+ /* job = nonzero, solve trans(a) * x = b
+ first solve trans(u)*y = b */
+
+ for (k = 0; k < n; k++) {
+ t = ddot(k,&a[lda*k+0],1,&b[0],1);
+ b[k] = (b[k] - t)/a[lda*k+k];
+ }
+
+ /* now solve trans(l)*x = y */
+
+ if (nm1 >= 1) {
+ for (kb = 1; kb < nm1; kb++) {
+ k = n - (kb+1);
+ b[k] = b[k] + ddot(n-(k+1),&a[lda*k+k+1],1,&b[k+1],1);
+ l = ipvt[k];
+ if (l != k) {
+ t = b[l];
+ b[l] = b[k];
+ b[k] = t;
+ }
+ }
+ }
+ }
+ return;
+}
+
+/*----------------------*/
+
+void daxpy(int n, REAL da, REAL dx[], int incx, REAL dy[], int incy)
+/*
+ constant times a vector plus a vector.
+ jack dongarra, linpack, 3/11/78.
+*/
+
+{
+ int i,ix,iy,m,mp1;
+
+ mp1 = 0;
+ m = 0;
+
+ if(n <= 0) return;
+ if (da == ZERO) return;
+
+ if(incx != 1 || incy != 1) {
+
+ /* code for unequal increments or equal increments
+ not equal to 1 */
+
+ ix = 0;
+ iy = 0;
+ if(incx < 0) ix = (-n+1)*incx;
+ if(incy < 0)iy = (-n+1)*incy;
+ for (i = 0;i < n; i++) {
+ dy[iy] = dy[iy] + da*dx[ix];
+ ix = ix + incx;
+ iy = iy + incy;
+
+ }
+ return;
+ }
+
+ /* code for both increments equal to 1 */
+
+
+#ifdef ROLL
+
+ for (i = 0;i < n; i++) {
+ dy[i] = dy[i] + da*dx[i];
+ }
+
+
+#endif
+
+#ifdef UNROLL
+
+ m = n % 4;
+ if ( m != 0) {
+ for (i = 0; i < m; i++)
+ dy[i] = dy[i] + da*dx[i];
+
+ if (n < 4) return;
+ }
+ for (i = m; i < n; i = i + 4) {
+ dy[i] = dy[i] + da*dx[i];
+ dy[i+1] = dy[i+1] + da*dx[i+1];
+ dy[i+2] = dy[i+2] + da*dx[i+2];
+ dy[i+3] = dy[i+3] + da*dx[i+3];
+
+ }
+
+#endif
+return;
+}
+
+/*----------------------*/
+
+REAL ddot(int n, REAL dx[], int incx, REAL dy[], int incy)
+/*
+ forms the dot product of two vectors.
+ jack dongarra, linpack, 3/11/78.
+*/
+
+{
+ REAL dtemp;
+ int i,ix,iy,m,mp1;
+
+ mp1 = 0;
+ m = 0;
+
+ dtemp = ZERO;
+
+ if(n <= 0) return(ZERO);
+
+ if(incx != 1 || incy != 1) {
+
+ /* code for unequal increments or equal increments
+ not equal to 1 */
+
+ ix = 0;
+ iy = 0;
+ if (incx < 0) ix = (-n+1)*incx;
+ if (incy < 0) iy = (-n+1)*incy;
+ for (i = 0;i < n; i++) {
+ dtemp = dtemp + dx[ix]*dy[iy];
+ ix = ix + incx;
+ iy = iy + incy;
+
+ }
+ return(dtemp);
+ }
+
+ /* code for both increments equal to 1 */
+
+
+#ifdef ROLL
+
+ for (i=0;i < n; i++)
+ dtemp = dtemp + dx[i]*dy[i];
+
+ return(dtemp);
+
+#endif
+
+#ifdef UNROLL
+
+
+ m = n % 5;
+ if (m != 0) {
+ for (i = 0; i < m; i++)
+ dtemp = dtemp + dx[i]*dy[i];
+ if (n < 5) return(dtemp);
+ }
+ for (i = m; i < n; i = i + 5) {
+ dtemp = dtemp + dx[i]*dy[i] +
+ dx[i+1]*dy[i+1] + dx[i+2]*dy[i+2] +
+ dx[i+3]*dy[i+3] + dx[i+4]*dy[i+4];
+ }
+ return(dtemp);
+
+#endif
+
+}
+
+/*----------------------*/
+void dscal(int n, REAL da, REAL dx[], int incx)
+
+/* scales a vector by a constant.
+ jack dongarra, linpack, 3/11/78.
+*/
+
+{
+ int i,m,mp1,nincx;
+
+ mp1 = 0;
+ m = 0;
+
+ if(n <= 0)return;
+ if(incx != 1) {
+
+ /* code for increment not equal to 1 */
+
+ nincx = n*incx;
+ for (i = 0; i < nincx; i = i + incx)
+ dx[i] = da*dx[i];
+
+ return;
+ }
+
+ /* code for increment equal to 1 */
+
+
+#ifdef ROLL
+
+ for (i = 0; i < n; i++)
+ dx[i] = da*dx[i];
+
+
+#endif
+
+#ifdef UNROLL
+
+
+ m = n % 5;
+ if (m != 0) {
+ for (i = 0; i < m; i++)
+ dx[i] = da*dx[i];
+ if (n < 5) return;
+ }
+ for (i = m; i < n; i = i + 5){
+ dx[i] = da*dx[i];
+ dx[i+1] = da*dx[i+1];
+ dx[i+2] = da*dx[i+2];
+ dx[i+3] = da*dx[i+3];
+ dx[i+4] = da*dx[i+4];
+ }
+
+#endif
+
+}
+
+/*----------------------*/
+int idamax(int n, REAL dx[], int incx)
+
+/*
+ finds the index of element having max. absolute value.
+ jack dongarra, linpack, 3/11/78.
+*/
+
+
+{
+ REAL dmax;
+ int i, ix, itemp;
+
+ if( n < 1 ) return(-1);
+ if(n ==1 ) return(0);
+ if(incx != 1) {
+
+ /* code for increment not equal to 1 */
+
+ ix = 1;
+ dmax = fabs((double)dx[0]);
+ ix = ix + incx;
+ for (i = 1; i < n; i++) {
+ if(fabs((double)dx[ix]) > dmax) {
+ itemp = i;
+ dmax = fabs((double)dx[ix]);
+ }
+ ix = ix + incx;
+ }
+ }
+ else {
+
+ /* code for increment equal to 1 */
+
+ itemp = 0;
+ dmax = fabs((double)dx[0]);
+ for (i = 1; i < n; i++) {
+ if(fabs((double)dx[i]) > dmax) {
+ itemp = i;
+ dmax = fabs((double)dx[i]);
+ }
+ }
+ }
+ return (itemp);
+}
+
+/*----------------------*/
+REAL epslon (REAL x)
+
+/*
+ estimate unit roundoff in quantities of size x.
+*/
+
+{
+ REAL a,b,c,eps;
+/*
+ this program should function properly on all systems
+ satisfying the following two assumptions,
+ 1. the base used in representing dfloating point
+ numbers is not a power of three.
+ 2. the quantity a in statement 10 is represented to
+ the accuracy used in dfloating point variables
+ that are stored in memory.
+ the statement number 10 and the go to 10 are intended to
+ force optimizing compilers to generate code satisfying
+ assumption 2.
+ under these assumptions, it should be true that,
+ a is not exactly equal to four-thirds,
+ b has a zero for its last bit or digit,
+ c is not exactly equal to one,
+ eps measures the separation of 1.0 from
+ the next larger dfloating point number.
+ the developers of eispack would appreciate being informed
+ about any systems where these assumptions do not hold.
+
+ *****************************************************************
+ this routine is one of the auxiliary routines used by eispack iii
+ to avoid machine dependencies.
+ *****************************************************************
+
+ this version dated 4/6/83.
+*/
+
+ a = 4.0e0/3.0e0;
+ eps = ZERO;
+ while (eps == ZERO) {
+ b = a - ONE;
+ c = b + b + b;
+ eps = fabs((double)(c-ONE));
+ }
+ return(eps*fabs((double)x));
+}
+
+/*----------------------*/
+void dmxpy (int n1, REAL y[], int n2, int ldm, REAL x[], REAL m[])
+
+
+/* We would like to declare m[][ldm], but c does not allow it. In this
+function, references to m[i][j] are written m[ldm*i+j]. */
+
+/*
+ purpose:
+ multiply matrix m times vector x and add the result to vector y.
+
+ parameters:
+
+ n1 integer, number of elements in vector y, and number of rows in
+ matrix m
+
+ y double [n1], vector of length n1 to which is added
+ the product m*x
+
+ n2 integer, number of elements in vector x, and number of columns
+ in matrix m
+
+ ldm integer, leading dimension of array m
+
+ x double [n2], vector of length n2
+
+ m double [ldm][n2], matrix of n1 rows and n2 columns
+
+ ----------------------------------------------------------------------
+*/
+{
+ int j,i,jmin;
+ /* cleanup odd vector */
+
+ j = n2 % 2;
+ if (j >= 1) {
+ j = j - 1;
+ for (i = 0; i < n1; i++)
+ y[i] = (y[i]) + x[j]*m[ldm*j+i];
+ }
+
+ /* cleanup odd group of two vectors */
+
+ j = n2 % 4;
+ if (j >= 2) {
+ j = j - 1;
+ for (i = 0; i < n1; i++)
+ y[i] = ( (y[i])
+ + x[j-1]*m[ldm*(j-1)+i]) + x[j]*m[ldm*j+i];
+ }
+
+ /* cleanup odd group of four vectors */
+
+ j = n2 % 8;
+ if (j >= 4) {
+ j = j - 1;
+ for (i = 0; i < n1; i++)
+ y[i] = ((( (y[i])
+ + x[j-3]*m[ldm*(j-3)+i])
+ + x[j-2]*m[ldm*(j-2)+i])
+ + x[j-1]*m[ldm*(j-1)+i]) + x[j]*m[ldm*j+i];
+ }
+
+ /* cleanup odd group of eight vectors */
+
+ j = n2 % 16;
+ if (j >= 8) {
+ j = j - 1;
+ for (i = 0; i < n1; i++)
+ y[i] = ((((((( (y[i])
+ + x[j-7]*m[ldm*(j-7)+i]) + x[j-6]*m[ldm*(j-6)+i])
+ + x[j-5]*m[ldm*(j-5)+i]) + x[j-4]*m[ldm*(j-4)+i])
+ + x[j-3]*m[ldm*(j-3)+i]) + x[j-2]*m[ldm*(j-2)+i])
+ + x[j-1]*m[ldm*(j-1)+i]) + x[j] *m[ldm*j+i];
+ }
+
+ /* main loop - groups of sixteen vectors */
+
+ jmin = (n2%16)+16;
+ for (j = jmin-1; j < n2; j = j + 16) {
+ for (i = 0; i < n1; i++)
+ y[i] = ((((((((((((((( (y[i])
+ + x[j-15]*m[ldm*(j-15)+i])
+ + x[j-14]*m[ldm*(j-14)+i])
+ + x[j-13]*m[ldm*(j-13)+i])
+ + x[j-12]*m[ldm*(j-12)+i])
+ + x[j-11]*m[ldm*(j-11)+i])
+ + x[j-10]*m[ldm*(j-10)+i])
+ + x[j- 9]*m[ldm*(j- 9)+i])
+ + x[j- 8]*m[ldm*(j- 8)+i])
+ + x[j- 7]*m[ldm*(j- 7)+i])
+ + x[j- 6]*m[ldm*(j- 6)+i])
+ + x[j- 5]*m[ldm*(j- 5)+i])
+ + x[j- 4]*m[ldm*(j- 4)+i])
+ + x[j- 3]*m[ldm*(j- 3)+i])
+ + x[j- 2]*m[ldm*(j- 2)+i])
+ + x[j- 1]*m[ldm*(j- 1)+i])
+ + x[j] *m[ldm*j+i];
+ }
+ return;
+}
+
+
+
diff --git a/tests/runner.py b/tests/runner.py
index afb71ad9..0f8883c8 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -904,26 +904,26 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
void interface_clock_changed()
{
- UINT8 m_divshift;
- INT32 m_divisor;
+ UINT8 m_divshift;
+ INT32 m_divisor;
- //INT64 attos = m_attoseconds_per_cycle;
- INT64 attos = 279365114840;
- m_divshift = 0;
- while (attos >= (1UL << 31))
- {
- m_divshift++;
- printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31);
- attos >>= 1;
- }
- m_divisor = attos;
+ //INT64 attos = m_attoseconds_per_cycle;
+ INT64 attos = 279365114840;
+ m_divshift = 0;
+ while (attos >= (1UL << 31))
+ {
+ m_divshift++;
+ printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31);
+ attos >>= 1;
+ }
+ m_divisor = attos;
- printf("m_divisor is %i\n",m_divisor);
+ printf("m_divisor is %i\n",m_divisor);
}
int main() {
- interface_clock_changed();
- return 0;
+ interface_clock_changed();
+ return 0;
}
'''
self.do_run(src, '''m_divshift is 1, on 279365114840 >?= 2147483648
@@ -997,8 +997,8 @@ m_divisor is 1091269979
volatile UINT64 testu64a = 14746250828952703000U;
while ((UINT64)testu32a * (UINT64)bigu32 < testu64a) {
- printf("testu64a is %llu\n", testu64a);
- testu64a /= 2;
+ printf("testu64a is %llu\n", testu64a);
+ testu64a /= 2;
}
return 0;
@@ -1456,28 +1456,28 @@ c5,de,15,8a
quint64 v = strtoull("4433ffeeddccbb00", NULL, 16);
printf("%lld\n", v);
- const string string64bitInt = "4433ffeeddccbb00";
- stringstream s(string64bitInt);
- quint64 int64bitInt = 0;
+ const string string64bitInt = "4433ffeeddccbb00";
+ stringstream s(string64bitInt);
+ quint64 int64bitInt = 0;
printf("1\n");
- s >> hex >> int64bitInt;
+ s >> hex >> int64bitInt;
printf("2\n");
- stringstream out;
- out << hex << qbswap(int64bitInt);
+ stringstream out;
+ out << hex << qbswap(int64bitInt);
- cout << out.str() << endl;
- cout << hex << int64bitInt << endl;
- cout << string64bitInt << endl;
+ cout << out.str() << endl;
+ cout << hex << int64bitInt << endl;
+ cout << string64bitInt << endl;
- if (out.str() != "bbccddeeff3344")
- {
- cout << "Failed!" << endl;
- }
- else
- {
- cout << "Succeeded!" << endl;
- }
+ if (out.str() != "bbccddeeff3344")
+ {
+ cout << "Failed!" << endl;
+ }
+ else
+ {
+ cout << "Succeeded!" << endl;
+ }
return 0;
}
@@ -1916,6 +1916,47 @@ Succeeded!
expected = open(path_from_root('tests', 'hyperbolic', 'output.txt'), 'r').read()
self.do_run(src, expected)
+ def test_frexp(self):
+ src = '''
+ #include <stdio.h>
+ #include <math.h>
+ #include <assert.h>
+
+ static const double tol=1e-16;
+
+ void test_value(double value)
+ {
+ int exponent;
+ double x=frexp(value, &exponent);
+ double expected=x*pow(2.0, exponent);
+
+ printf("%f=%f*2^%d\\n", value, x, exponent);
+
+ assert(fabs(expected-value)<tol);
+ assert(x==0 || (fabs(x)>=5e-1 && fabs(x)<1)); // x has a magnitude in the interval [1/2, 1)
+ }
+
+ int main()
+ {
+ test_value(0);
+ test_value(100.1);
+ test_value(-100.1);
+ test_value(.5);
+ test_value(-.5);
+ test_value(1-1e-16);
+ test_value(-(1-1e-16));
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''0.000000=0.000000*2^0
+100.100000=0.782031*2^7
+-100.100000=-0.782031*2^7
+0.500000=0.500000*2^0
+-0.500000=-0.500000*2^0
+1.000000=1.000000*2^0
+-1.000000=-1.000000*2^0''')
+
def test_getgep(self):
# Generated code includes getelementptr (getelementptr, 0, 1), i.e., GEP as the first param to GEP
src = '''
@@ -2203,8 +2244,8 @@ returned |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie',
}
'''
expected = '''
- <Numerical argument out of domain>
- <Resource temporarily unavailable>
+ <Math arg out of domain of func>
+ <No more processes>
<34>
<123>
'''
@@ -2452,28 +2493,34 @@ returned |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie',
static jmp_buf buf;
void second(void) {
- printf("second\n"); // prints
- longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
+ printf("second\n");
+ longjmp(buf,-1);
}
void first(void) {
- second();
- printf("first\n"); // does not print
+ printf("first\n"); // prints
+ longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
int main() {
volatile int x = 0;
- if ( ! setjmp(buf) ) {
+ int jmpval = setjmp(buf);
+ if (!jmpval) {
+ x++; // should be properly restored once longjmp jumps back
+ first(); // when executed, setjmp returns 1
+ printf("skipped\n"); // does not print
+ } else if (jmpval == 1) { // when first() jumps back, setjmp returns 1
+ printf("result: %d %d\n", x, jmpval); // prints
x++;
- first(); // when executed, setjmp returns 0
- } else { // when longjmp jumps back, setjmp returns 1
- printf("main: %d\n", x); // prints
+ second(); // when executed, setjmp returns -1
+ } else if (jmpval == -1) { // when second() jumps back, setjmp returns -1
+ printf("result: %d %d\n", x, jmpval); // prints
}
return 0;
}
'''
- self.do_run(src, 'second\nmain: 1\n')
+ self.do_run(src, 'first\nresult: 1 1\nsecond\nresult: 2 -1')
def test_longjmp2(self):
src = r'''
@@ -3023,6 +3070,28 @@ setjmp exception execution path, level: 0, prev_jmp: -1
Exiting setjmp function, level: 0, prev_jmp: -1
''')
+ def test_std_exception(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ Settings.DISABLE_EXCEPTION_CATCHING = 0
+ self.emcc_args += ['-s', 'SAFE_HEAP=0']
+
+ src = r'''
+ #include <stdio.h>
+ #include <exception>
+
+ int main()
+ {
+ std::exception e;
+ try {
+ throw e;
+ } catch(std::exception e) {
+ printf("caught std::exception\n");
+ }
+ return 0;
+ }
+ '''
+ self.do_run(src, 'caught std::exception')
+
def test_exit_stack(self):
if self.emcc_args is None: return self.skip('requires emcc')
if Settings.ASM_JS: return self.skip('uses report_stack without exporting')
@@ -4002,15 +4071,15 @@ def process(filename):
// see related things in openjpeg
typedef struct opj_mqc_state {
- unsigned int qeval;
- int mps;
- struct opj_mqc_state *nmps;
- struct opj_mqc_state *nlps;
+ unsigned int qeval;
+ int mps;
+ struct opj_mqc_state *nmps;
+ struct opj_mqc_state *nlps;
} opj_mqc_state_t;
static opj_mqc_state_t mqc_states[2] = {
- {0x5600, 0, &mqc_states[2], &mqc_states[3]},
- {0x5602, 1, &mqc_states[3], &mqc_states[2]},
+ {0x5600, 0, &mqc_states[2], &mqc_states[3]},
+ {0x5602, 1, &mqc_states[3], &mqc_states[2]},
};
int main() {
@@ -4065,7 +4134,7 @@ def process(filename):
int main( int argc, const char *argv[] ) {
unsigned int x = 0xfffffff1;
- x >>= 0; // force it to be unsigned for purpose of checking our switch comparison in signed/unsigned
+ x >>= (argc-1); // force it to be unsigned for purpose of checking our switch comparison in signed/unsigned
printf("*%d,%d,%d,%d,%d,%d*\\n", switcher('a'), switcher('b'), switcher('c'), switcher(x), switcher(-15), switcher('e'));
return 0;
}
@@ -4504,6 +4573,212 @@ The current type of b is: 9
self.do_run(src, '*1*', force_c=True)
+ def test_strtoll_hex(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ # tests strtoll for hex strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "0x4 -0x3A +0xDEADBEEF";
+ char *end_char;
+
+ // undefined base
+ long long int l1 = strtoll(STRING, &end_char, 0);
+ long long int l2 = strtoll(end_char, &end_char, 0);
+ long long int l3 = strtoll(end_char, NULL, 0);
+
+ // defined base
+ long long int l4 = strtoll(STRING, &end_char, 16);
+ long long int l5 = strtoll(end_char, &end_char, 16);
+ long long int l6 = strtoll(end_char, NULL, 16);
+
+ printf("%d%d%d%d%d%d\n", l1==0x4, l2==-0x3a, l3==0xdeadbeef, l4==0x4, l5==-0x3a, l6==0xdeadbeef);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
+ def test_strtoll_dec(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ # tests strtoll for decimal strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "4 -38 +4711";
+ char *end_char;
+
+ // undefined base
+ long long int l1 = strtoll(STRING, &end_char, 0);
+ long long int l2 = strtoll(end_char, &end_char, 0);
+ long long int l3 = strtoll(end_char, NULL, 0);
+
+ // defined base
+ long long int l4 = strtoll(STRING, &end_char, 10);
+ long long int l5 = strtoll(end_char, &end_char, 10);
+ long long int l6 = strtoll(end_char, NULL, 10);
+
+ printf("%d%d%d%d%d%d\n", l1==4, l2==-38, l3==4711, l4==4, l5==-38, l6==4711);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
+ def test_strtoll_bin(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ # tests strtoll for binary strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "1 -101 +1011";
+ char *end_char;
+
+ // defined base
+ long long int l4 = strtoll(STRING, &end_char, 2);
+ long long int l5 = strtoll(end_char, &end_char, 2);
+ long long int l6 = strtoll(end_char, NULL, 2);
+
+ printf("%d%d%d\n", l4==1, l5==-5, l6==11);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111')
+
+ def test_strtoll_oct(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ # tests strtoll for decimal strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "0 -035 +04711";
+ char *end_char;
+
+ // undefined base
+ long long int l1 = strtoll(STRING, &end_char, 0);
+ long long int l2 = strtoll(end_char, &end_char, 0);
+ long long int l3 = strtoll(end_char, NULL, 0);
+
+ // defined base
+ long long int l4 = strtoll(STRING, &end_char, 8);
+ long long int l5 = strtoll(end_char, &end_char, 8);
+ long long int l6 = strtoll(end_char, NULL, 8);
+
+ printf("%d%d%d%d%d%d\n", l1==0, l2==-29, l3==2505, l4==0, l5==-29, l6==2505);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
+ def test_strtol_hex(self):
+ # tests strtoll for hex strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "0x4 -0x3A +0xDEAD";
+ char *end_char;
+
+ // undefined base
+ long l1 = strtol(STRING, &end_char, 0);
+ long l2 = strtol(end_char, &end_char, 0);
+ long l3 = strtol(end_char, NULL, 0);
+
+ // defined base
+ long l4 = strtol(STRING, &end_char, 16);
+ long l5 = strtol(end_char, &end_char, 16);
+ long l6 = strtol(end_char, NULL, 16);
+
+ printf("%d%d%d%d%d%d\n", l1==0x4, l2==-0x3a, l3==0xdead, l4==0x4, l5==-0x3a, l6==0xdead);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
+ def test_strtol_dec(self):
+ # tests strtoll for decimal strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "4 -38 +4711";
+ char *end_char;
+
+ // undefined base
+ long l1 = strtol(STRING, &end_char, 0);
+ long l2 = strtol(end_char, &end_char, 0);
+ long l3 = strtol(end_char, NULL, 0);
+
+ // defined base
+ long l4 = strtol(STRING, &end_char, 10);
+ long l5 = strtol(end_char, &end_char, 10);
+ long l6 = strtol(end_char, NULL, 10);
+
+ printf("%d%d%d%d%d%d\n", l1==4, l2==-38, l3==4711, l4==4, l5==-38, l6==4711);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
+ def test_strtol_bin(self):
+ # tests strtoll for binary strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "1 -101 +1011";
+ char *end_char;
+
+ // defined base
+ long l4 = strtol(STRING, &end_char, 2);
+ long l5 = strtol(end_char, &end_char, 2);
+ long l6 = strtol(end_char, NULL, 2);
+
+ printf("%d%d%d\n", l4==1, l5==-5, l6==11);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111')
+
+ def test_strtol_oct(self):
+ # tests strtoll for decimal strings (0x...)
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main() {
+ const char *STRING = "0 -035 +04711";
+ char *end_char;
+
+ // undefined base
+ long l1 = strtol(STRING, &end_char, 0);
+ long l2 = strtol(end_char, &end_char, 0);
+ long l3 = strtol(end_char, NULL, 0);
+
+ // defined base
+ long l4 = strtol(STRING, &end_char, 8);
+ long l5 = strtol(end_char, &end_char, 8);
+ long l6 = strtol(end_char, NULL, 8);
+
+ printf("%d%d%d%d%d%d\n", l1==0, l2==-29, l3==2505, l4==0, l5==-29, l6==2505);
+ return 0;
+ }
+ '''
+ self.do_run(src, '111111')
+
def test_atexit(self):
# Confirms they are called in reverse order
src = r'''
@@ -4581,25 +4856,25 @@ The current type of b is: 9
typedef struct
{
- int (*f)(void *);
- void *d;
- char s[16];
+ int (*f)(void *);
+ void *d;
+ char s[16];
} LMEXFunctionStruct;
int f(void *user)
{
- return 0;
+ return 0;
}
static LMEXFunctionStruct const a[] =
{
- {f, (void *)(int)'a', "aa"}
+ {f, (void *)(int)'a', "aa"}
};
int main()
{
printf("ok\n");
- return a[0].f(a[0].d);
+ return a[0].f(a[0].d);
}
'''
self.do_run(src, 'ok\n')
@@ -6233,6 +6508,19 @@ Pass: 0.000012 0.000012''')
'''
self.do_run(src, '1\n30\n2\n1000000,-123\n')
+ def test_sscanf_caps(self):
+ src = r'''
+ #include "stdio.h"
+
+ int main(){
+ unsigned int a;
+ float e, f, g;
+ sscanf("a 1.1 1.1 1.1", "%x %E %F %G", &a, &e, &f, &g);
+ printf("%d %.1F %.1F %.1F\n", a, e, f, g);
+ }
+ '''
+ self.do_run(src, '10 1.1 1.1 1.1');
+
def test_langinfo(self):
src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read()
expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read()
@@ -6363,6 +6651,31 @@ def process(filename):
self.emcc_args += ['--embed-file', 'eol.txt']
self.do_run(src, 'SUCCESS\n')
+ def test_fscanf(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ open(os.path.join(self.get_dir(), 'three_numbers.txt'), 'w').write('''-1 0.1 -.1''')
+ src = r'''
+ #include <stdio.h>
+ #include <assert.h>
+ #include <float.h>
+ int main()
+ {
+ float x = FLT_MAX, y = FLT_MAX, z = FLT_MAX;
+
+ FILE* fp = fopen("three_numbers.txt", "r");
+ if (fp) {
+ int match = fscanf(fp, " %f %f %f ", &x, &y, &z);
+ printf("match = %d\n", match);
+ printf("x = %0.1f, y = %0.1f, z = %0.1f\n", x, y, z);
+ } else {
+ printf("failed to open three_numbers.txt\n");
+ }
+ return 0;
+ }
+ '''
+ self.emcc_args += ['--embed-file', 'three_numbers.txt']
+ self.do_run(src, 'match = 3\nx = -1.0, y = 0.1, z = -0.1\n')
+
def test_folders(self):
add_pre_run = '''
def process(filename):
@@ -6573,7 +6886,7 @@ def process(filename):
printf("f_blocks: %lu\n", s.f_blocks);
printf("f_bfree: %lu\n", s.f_bfree);
printf("f_bavail: %lu\n", s.f_bavail);
- printf("f_files: %lu\n", s.f_files);
+ printf("f_files: %d\n", s.f_files > 5);
printf("f_ffree: %lu\n", s.f_ffree);
printf("f_favail: %lu\n", s.f_favail);
printf("f_fsid: %lu\n", s.f_fsid);
@@ -6591,7 +6904,7 @@ def process(filename):
f_blocks: 1000000
f_bfree: 500000
f_bavail: 500000
- f_files: 10
+ f_files: 1
f_ffree: 1000000
f_favail: 1000000
f_fsid: 42
@@ -7729,7 +8042,9 @@ void*:16
for (int i = 0; i < 10; i++) {
int* map = (int*)mmap(0, 5000, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1, 0);
+ /* TODO: Should we align to 4k?
assert(((int)map) % 4096 == 0); // aligned
+ */
assert(munmap(map, 5000) == 0);
}
@@ -7941,7 +8256,7 @@ def process(filename):
if Settings.ASM_JS:
self.banned_js_engines = [NODE_JS] # TODO investigate
- if self.emcc_args is not None and '-O2' in self.emcc_args:
+ if self.emcc_args is not None and '-O2' in self.emcc_args and 'ASM_JS=0' not in self.emcc_args: # without asm, closure minifies Math.imul badly
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
Settings.CORRECT_SIGNS = 1
@@ -8572,9 +8887,43 @@ def process(filename):
open('dead_funcs', 'w').write(pgo_output[pgo_output.find('['):-1])
self.emcc_args += ['-s', 'DEAD_FUNCTIONS=@' + self.in_dir('dead_funcs')]
self.do_run(src, output)
+ self.emcc_args.pop()
+ self.emcc_args.pop()
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed2.js'))
assert open('pgoed.js').read() == open('pgoed2.js').read()
+ # with relative response in settings element itself
+
+ open('dead_funcs', 'w').write(pgo_output[pgo_output.find('['):-1])
+ self.emcc_args += ['-s', 'DEAD_FUNCTIONS=@dead_funcs']
+ self.do_run(src, output)
+ self.emcc_args.pop()
+ self.emcc_args.pop()
+ shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed2.js'))
+ assert open('pgoed.js').read() == open('pgoed2.js').read()
+
+ def test_exported_response(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ extern "C" {
+ int other_function() { return 5; }
+ }
+
+ int main() {
+ printf("waka!\n");
+ return 0;
+ }
+ '''
+ open('exps', 'w').write('["_main","_other_function"]')
+
+ self.emcc_args += ['-s', 'EXPORTED_FUNCTIONS=@exps']
+ self.do_run(src, '''waka!''')
+ assert 'other_function' in open('src.cpp.o.js').read()
+
def test_add_function(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8614,6 +8963,28 @@ def process(filename):
Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS # flip the test
self.do_run(src, '''Hello 7 from JS!''')
+ def test_embind(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ Building.COMPILER_TEST_OPTS += ['--bind']
+
+ src = r'''
+ #include<stdio.h>
+ #include<emscripten/val.h>
+
+ using namespace emscripten;
+
+ int main() {
+ val Math = val::global("Math");
+
+ // two ways to call Math.abs
+ printf("abs(-10): %d\n", Math.call<int>("abs", -10));
+ printf("abs(-11): %d\n", Math["abs"](-11).as<int>());
+
+ return 0;
+ }
+ '''
+ self.do_run(src, 'abs(-10): 10\nabs(-11): 11');
+
def test_scriptaclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8664,7 +9035,7 @@ def process(filename):
'''
# XXX disable due to possible v8 bug -- self.do_run(src, '*166*\n*ok*', post_build=post)
- if self.emcc_args is not None and '-O2' in self.emcc_args:
+ if self.emcc_args is not None and '-O2' in self.emcc_args and 'ASM_JS=0' not in self.emcc_args: # without asm, closure minifies Math.imul badly
self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right
# Way 2: use CppHeaderParser
@@ -9997,6 +10368,25 @@ f.close()
self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
+ def test_symlink(self):
+ if os.name == 'nt':
+ return self.skip('Windows FS does not need to be tested for symlinks support, since it does not have them.')
+ open(os.path.join(self.get_dir(), 'foobar.xxx'), 'w').write('int main(){ return 0; }')
+ os.symlink(os.path.join(self.get_dir(), 'foobar.xxx'), os.path.join(self.get_dir(), 'foobar.c'))
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'foobar.c'), '-o', os.path.join(self.get_dir(), 'foobar')], stdout=PIPE, stderr=PIPE).communicate()
+ assert os.path.exists(os.path.join(self.get_dir(), 'foobar'))
+ try_delete(os.path.join(self.get_dir(), 'foobar'))
+ try_delete(os.path.join(self.get_dir(), 'foobar.xxx'))
+ try_delete(os.path.join(self.get_dir(), 'foobar.c'))
+
+ open(os.path.join(self.get_dir(), 'foobar.c'), 'w').write('int main(){ return 0; }')
+ os.symlink(os.path.join(self.get_dir(), 'foobar.c'), os.path.join(self.get_dir(), 'foobar.xxx'))
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'foobar.xxx'), '-o', os.path.join(self.get_dir(), 'foobar')], stdout=PIPE, stderr=PIPE).communicate()
+ assert os.path.exists(os.path.join(self.get_dir(), 'foobar'))
+ try_delete(os.path.join(self.get_dir(), 'foobar'))
+ try_delete(os.path.join(self.get_dir(), 'foobar.xxx'))
+ try_delete(os.path.join(self.get_dir(), 'foobar.c'))
+
def test_multiply_defined_libsymbols(self):
lib = "int mult() { return 1; }"
lib_name = os.path.join(self.get_dir(), 'libA.c')
@@ -10135,8 +10525,8 @@ f.close()
#define _TESTA_H_
class TestA {
- public:
- TestA();
+ public:
+ TestA();
};
#endif
@@ -10146,8 +10536,8 @@ f.close()
#define _TESTB_H_
class TestB {
- public:
- TestB();
+ public:
+ TestB();
};
#endif
@@ -10157,7 +10547,7 @@ f.close()
#include <testa.h>
TestA::TestA() {
- printf("TestA\n");
+ printf("TestA\n");
}
''')
open('testb.cpp', 'w').write(r'''
@@ -10167,8 +10557,8 @@ f.close()
/*
*/
TestB::TestB() {
- printf("TestB\n");
- TestA* testa = new TestA();
+ printf("TestB\n");
+ TestA* testa = new TestA();
}
''')
open('main.cpp', 'w').write(r'''
@@ -10179,9 +10569,9 @@ f.close()
/*
*/
int main(int argc, char** argv) {
- printf("Main\n");
- TestA* testa = new TestA();
- TestB* testb = new TestB();
+ printf("Main\n");
+ TestA* testa = new TestA();
+ TestB* testb = new TestB();
}
''')
@@ -11388,7 +11778,9 @@ elif 'browser' in str(sys.argv):
self.run_browser('page.html', '', '/report_result?1')
def test_preload_file(self):
- open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''load me right before running the code please''')
+ absolute_src_path = os.path.join(self.get_dir(), 'somefile.txt').replace('\\', '/')
+ open(absolute_src_path, 'w').write('''load me right before running the code please''')
+
def make_main(path):
print path
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
@@ -11407,26 +11799,92 @@ elif 'browser' in str(sys.argv):
REPORT_RESULT();
return 0;
}
- ''' % path))
-
- make_main('somefile.txt')
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '-o', 'page.html']).communicate()
- self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+ ''' % path))
+
+ test_cases = [
+ # (source preload-file string, file on target FS to load)
+ ("somefile.txt", "somefile.txt"),
+ ("./somefile.txt", "somefile.txt"),
+ ("somefile.txt@file.txt", "file.txt"),
+ ("./somefile.txt@file.txt", "file.txt"),
+ ("./somefile.txt@./file.txt", "file.txt"),
+ ("somefile.txt@/file.txt", "file.txt"),
+ ("somefile.txt@/", "somefile.txt"),
+ (absolute_src_path + "@file.txt", "file.txt"),
+ (absolute_src_path + "@/file.txt", "file.txt"),
+ (absolute_src_path + "@/", "somefile.txt"),
+ ("somefile.txt@/directory/file.txt", "/directory/file.txt"),
+ ("somefile.txt@/directory/file.txt", "directory/file.txt"),
+ (absolute_src_path + "@/directory/file.txt", "directory/file.txt")]
+
+ for test in test_cases:
+ (srcpath, dstpath) = test
+ make_main(dstpath)
+ print srcpath
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', srcpath, '-o', 'page.html']).communicate()
+ self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
# By absolute path
- make_main(os.path.join(self.get_dir(), 'somefile.txt'))
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', os.path.join(self.get_dir(), 'somefile.txt'), '-o', 'page.html']).communicate()
+ make_main(absolute_src_path)
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', absolute_src_path, '-o', 'page.html']).communicate()
self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+ # Test subdirectory handling with asset packaging.
+ os.makedirs(os.path.join(self.get_dir(), 'assets/sub/asset1/').replace('\\', '/'))
+ os.makedirs(os.path.join(self.get_dir(), 'assets/sub/asset2/').replace('\\', '/'))
+ open(os.path.join(self.get_dir(), 'assets/sub/asset1/file1.txt'), 'w').write('''load me right before running the code please''')
+ open(os.path.join(self.get_dir(), 'assets/sub/asset2/file2.txt'), 'w').write('''load me right before running the code please''')
+ absolute_assets_src_path = os.path.join(self.get_dir(), 'assets').replace('\\', '/')
+ def make_main_two_files(path1, path2):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
+ #include <stdio.h>
+ #include <string.h>
+ #include <emscripten.h>
+ int main() {
+ FILE *f = fopen("%s", "r");
+ char buf[100];
+ fread(buf, 1, 20, f);
+ buf[20] = 0;
+ fclose(f);
+ printf("|%%s|\n", buf);
+
+ int result = !strcmp("load me right before", buf);
+
+ f = fopen("%s", "r");
+ if (f == NULL)
+ result = 0;
+ fclose(f);
+ REPORT_RESULT();
+ return 0;
+ }
+ ''' % (path1, path2)))
+
+ test_cases = [
+ # (source directory to embed, file1 on target FS to load, file2 on target FS to load)
+ ("assets", "assets/sub/asset1/file1.txt", "assets/sub/asset2/file2.txt"),
+ ("assets/", "assets/sub/asset1/file1.txt", "assets/sub/asset2/file2.txt"),
+ ("assets@/", "/sub/asset1/file1.txt", "/sub/asset2/file2.txt"),
+ ("assets/@/", "/sub/asset1/file1.txt", "/sub/asset2/file2.txt"),
+ ("assets@./", "/sub/asset1/file1.txt", "/sub/asset2/file2.txt"),
+ (absolute_assets_src_path + "@/", "/sub/asset1/file1.txt", "/sub/asset2/file2.txt"),
+ (absolute_assets_src_path + "@/assets", "/assets/sub/asset1/file1.txt", "/assets/sub/asset2/file2.txt")]
+
+ for test in test_cases:
+ (srcpath, dstpath1, dstpath2) = test
+ make_main_two_files(dstpath1, dstpath2)
+ print srcpath
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', srcpath, '-o', 'page.html']).communicate()
+ self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+
# Should still work with -o subdir/..
- make_main(os.path.join(self.get_dir(), 'somefile.txt'))
+ make_main(absolute_src_path)
try:
os.mkdir(os.path.join(self.get_dir(), 'dirrey'))
except:
pass
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', os.path.join(self.get_dir(), 'somefile.txt'), '-o', 'dirrey/page.html']).communicate()
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', absolute_src_path, '-o', 'dirrey/page.html']).communicate()
self.run_browser('dirrey/page.html', 'You should see |load me right before|.', '/report_result?1')
# With FS.preloadFile
@@ -12042,6 +12500,9 @@ elif 'browser' in str(sys.argv):
self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true')
assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for"
+ def test_fulles2_sdlproc(self):
+ self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1'])
+
def test_glgears_deriv(self):
self.reftest(path_from_root('tests', 'gears.png'))
Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', '-s', 'GL_TESTING=1',
@@ -12155,14 +12616,6 @@ elif 'browser' in str(sys.argv):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
self.btest('gl_ps_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'])
- def test_gl_ps_workaround(self):
- shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
- self.btest('gl_ps_workaround.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'])
-
- def test_gl_ps_workaround2(self):
- shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
- self.btest('gl_ps_workaround2.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'])
-
def test_gl_ps_strides(self):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png'])
@@ -12479,20 +12932,22 @@ elif 'browser' in str(sys.argv):
def test_websockets_bi(self):
for datagram in [0,1]:
- try:
- with self.WebsockHarness(8992, self.make_relay_server(8992, 8994)):
- with self.WebsockHarness(8994, no_server=True):
- Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995', '-DTEST_DGRAM=%d' % datagram]).communicate()
- self.btest('websockets_bi.c', expected='2499', args=['-DTEST_DGRAM=%d' % datagram])
- finally:
- self.clean_pids()
+ for fileops in [0,1]:
+ try:
+ print >> sys.stderr, 'test_websocket_bi datagram %d, fileops %d' % (datagram, fileops)
+ with self.WebsockHarness(8992, self.make_relay_server(8992, 8994)):
+ with self.WebsockHarness(8994, no_server=True):
+ Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995', '-DTEST_DGRAM=%d' % datagram]).communicate()
+ self.btest('websockets_bi.c', expected='2499', args=['-DSOCKK=8993', '-DTEST_DGRAM=%d' % datagram, '-DTEST_FILE_OPS=%s' % fileops])
+ finally:
+ self.clean_pids()
def test_websockets_bi_listen(self):
try:
with self.WebsockHarness(6992, self.make_relay_server(6992, 6994)):
with self.WebsockHarness(6994, no_server=True):
Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=6995']).communicate()
- self.btest('websockets_bi_listener.c', expected='2499')
+ self.btest('websockets_bi_listener.c', expected='2499', args=['-DSOCKK=6993'])
finally:
self.clean_pids()
@@ -12508,7 +12963,7 @@ elif 'browser' in str(sys.argv):
with self.WebsockHarness(3992, self.make_relay_server(3992, 3994)):
with self.WebsockHarness(3994, no_server=True):
Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side_bigdata.c'), '-o', 'side.html', '-DSOCKK=3995', '-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')]).communicate()
- self.btest('websockets_bi_bigdata.c', expected='0', args=['-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')])
+ self.btest('websockets_bi_bigdata.c', expected='0', args=['-DSOCKK=3993', '-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')])
finally:
self.clean_pids()
@@ -13013,6 +13468,11 @@ elif 'benchmark' in str(sys.argv):
src = open(path_from_root('tests', 'life.c'), 'r').read()
self.do_benchmark('life', src, '''--------------------------------''', shared_args=['-std=c99'], force_c=True)
+ def test_linpack(self):
+ def output_parser(output):
+ return 100.0/float(re.search('Unrolled Double Precision +([\d\.]+) Mflops', output).group(1))
+ self.do_benchmark('linpack', open(path_from_root('tests', 'linpack.c')).read(), '''Unrolled Double Precision''', force_c=True, output_parser=output_parser)
+
def test_zzz_java_nbody(self): # tests xmlvm compiled java, including bitcasts of doubles, i64 math, etc.
args = [path_from_root('tests', 'nbody-java', x) for x in os.listdir(path_from_root('tests', 'nbody-java')) if x.endswith('.c')] + \
['-I' + path_from_root('tests', 'nbody-java')]
@@ -13036,7 +13496,7 @@ elif 'benchmark' in str(sys.argv):
def test_zzz_lua_scimark(self):
def output_parser(output):
- return 1.0/float(re.search('\nSciMark +([\d\.]+) ', output).group(1))
+ return 100.0/float(re.search('\nSciMark +([\d\.]+) ', output).group(1))
self.lua('scimark', '[small problem sizes]', output_parser=output_parser)
@@ -13606,7 +14066,7 @@ if __name__ == '__main__':
which = map(lambda mode: mode+'.'+test, test_modes)
else:
which = [which]
-
+
print >> sys.stderr, ','.join(which)
for test in which:
print >> sys.stderr, 'will skip "%s"' % test
diff --git a/tests/s3tc.c b/tests/s3tc.c
index c2736feb..16ee783f 100644
--- a/tests/s3tc.c
+++ b/tests/s3tc.c
@@ -63,14 +63,12 @@ int main(int argc, char *argv[])
const char *exts = (const char *)glGetString(GL_EXTENSIONS);
assert(hasext(exts, "GL_ARB_texture_compression"));
assert(hasext(exts, "GL_EXT_texture_compression_s3tc"));
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -110,7 +108,7 @@ int main(int argc, char *argv[])
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -143,7 +141,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(1500);
@@ -151,8 +149,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c
index 57974109..90ed02d9 100644
--- a/tests/s3tc_crunch.c
+++ b/tests/s3tc_crunch.c
@@ -63,14 +63,12 @@ int main(int argc, char *argv[])
const char *exts = (const char *)glGetString(GL_EXTENSIONS);
assert(hasext(exts, "GL_ARB_texture_compression"));
assert(hasext(exts, "GL_EXT_texture_compression_s3tc"));
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -158,7 +156,7 @@ int main(int argc, char *argv[])
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -195,7 +193,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(1500);
@@ -203,8 +201,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_audio.c b/tests/sdl_audio.c
index ce3bf5a9..ae1b89e9 100644
--- a/tests/sdl_audio.c
+++ b/tests/sdl_audio.c
@@ -9,7 +9,7 @@ Mix_Chunk *sound, *sound2;
int play2();
int play() {
- int channel = Mix_PlayChannel(-1, sound, 1);
+ int channel = Mix_PlayChannel(-1, sound, 0);
assert(channel == 0);
emscripten_run_script("setTimeout(Module['_play2'], 500)");
@@ -26,7 +26,7 @@ void done(int channel) {
int play2() {
Mix_ChannelFinished(done);
- int channel2 = Mix_PlayChannel(-1, sound2, 1);
+ int channel2 = Mix_PlayChannel(-1, sound2, 0);
assert(channel2 == 1);
return channel2;
}
diff --git a/tests/sdl_fog_density.c b/tests/sdl_fog_density.c
index 95773419..cab6a4d2 100644
--- a/tests/sdl_fog_density.c
+++ b/tests/sdl_fog_density.c
@@ -47,14 +47,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -63,33 +61,33 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1000, 1000 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -148,9 +146,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -168,7 +164,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);
@@ -176,8 +172,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_fog_exp2.c b/tests/sdl_fog_exp2.c
index a09a5e3d..dba0c708 100644
--- a/tests/sdl_fog_exp2.c
+++ b/tests/sdl_fog_exp2.c
@@ -47,14 +47,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -63,33 +61,33 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1000, 1000 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -149,9 +147,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -169,7 +165,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);
@@ -177,8 +173,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_fog_linear.c b/tests/sdl_fog_linear.c
index 8fc18b7c..f0805650 100644
--- a/tests/sdl_fog_linear.c
+++ b/tests/sdl_fog_linear.c
@@ -47,14 +47,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -63,33 +61,33 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1000, 1000 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -150,9 +148,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -170,7 +166,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);
@@ -178,8 +174,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_fog_negative.c b/tests/sdl_fog_negative.c
index 2d589a47..1ede63a7 100644
--- a/tests/sdl_fog_negative.c
+++ b/tests/sdl_fog_negative.c
@@ -47,14 +47,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -63,33 +61,33 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1000, 1000 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -147,9 +145,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, -1 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -167,7 +163,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);
@@ -175,8 +171,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_fog_simple.c b/tests/sdl_fog_simple.c
index be023593..6c052bf5 100644
--- a/tests/sdl_fog_simple.c
+++ b/tests/sdl_fog_simple.c
@@ -47,14 +47,10 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
glViewport( 0, 0, 640, 480 );
@@ -63,33 +59,38 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1000, 1000 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
+ // Delay Enable to after MatrixMode to assure we've activated
+ // immediate mode. Otherwise, we don't properly record that
+ // TEXTURE_2D is enabled for imm mode emulation.
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +101,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -147,9 +148,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -167,7 +166,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);
@@ -175,8 +174,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_ogl.c b/tests/sdl_ogl.c
index 6b6a5b4a..e7071dcd 100644
--- a/tests/sdl_ogl.c
+++ b/tests/sdl_ogl.c
@@ -46,14 +46,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -62,33 +60,33 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1, 1 );
-
+
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -99,25 +97,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -140,9 +138,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -160,7 +156,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(3000);
@@ -168,8 +164,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_ogl_defaultMatrixMode.c b/tests/sdl_ogl_defaultMatrixMode.c
index 0da0a326..eec2a831 100644
--- a/tests/sdl_ogl_defaultMatrixMode.c
+++ b/tests/sdl_ogl_defaultMatrixMode.c
@@ -46,14 +46,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -66,30 +64,30 @@ int main(int argc, char *argv[])
glLoadIdentity();
glOrtho( 0, 640, 480, 0, -1, 1 );
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -141,9 +139,7 @@ int main(int argc, char *argv[])
glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
glEnd();
-#if !EMSCRIPTEN
glDisable(GL_TEXTURE_2D);
-#endif
glColor3ub(90, 255, 255);
glBegin( GL_QUADS );
@@ -161,7 +157,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(3000);
@@ -169,8 +165,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c
index fcc53a40..1889d926 100644
--- a/tests/sdl_ogl_p.c
+++ b/tests/sdl_ogl_p.c
@@ -46,14 +46,12 @@ int main(int argc, char *argv[])
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
-
+
// Set the OpenGL state after creating the context with SDL_SetVideoMode
glClearColor( 0, 0, 0, 0 );
-
-#if !EMSCRIPTEN
- glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
-#endif
+
+ glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline.
glViewport( 0, 0, 640, 480 );
@@ -66,30 +64,30 @@ int main(int argc, char *argv[])
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
-
+
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
-
- if ( (surface = IMG_Load("screenshot.png")) ) {
-
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}
-
+
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}
-
+
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
-
+
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
-
+
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -100,25 +98,25 @@ int main(int argc, char *argv[])
memset(surface->pixels, 0x66, surface->w*surface->h);
// Edit the texture object's image data using the information SDL_Surface gives us
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
//SDL_UnlockSurface(surface);
- }
+ }
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
- }
-
+ }
+
// Free the SDL_Surface only if it was successfully created
- if ( surface ) {
+ if ( surface ) {
SDL_FreeSurface( surface );
}
-
+
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
-
+
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
@@ -151,7 +149,7 @@ int main(int argc, char *argv[])
glEnd();
SDL_GL_SwapBuffers();
-
+
#if !EMSCRIPTEN
// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(3000);
@@ -159,8 +157,8 @@ int main(int argc, char *argv[])
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );
-
+
SDL_Quit();
-
+
return 0;
}
diff --git a/tests/time/src.c b/tests/time/src.c
index d33885fe..61faedfe 100644
--- a/tests/time/src.c
+++ b/tests/time/src.c
@@ -2,6 +2,8 @@
#include <stdlib.h>
#include <time.h>
#include <string.h>
+#include <assert.h>
+#include <math.h>
int main() {
time_t xmas2002 = 1040786563ll;
@@ -64,6 +66,9 @@ int main() {
// Verify time() returns reasonable value (between 2011 and 2030).
time_t t4 = 0;
time(&t4);
+ timespec ts;
+ assert(clock_gettime(0, &ts) == 0);
+ assert(abs(ts.tv_sec - t4) <= 2);
printf("time: %d\n", t4 > 1309635200ll && t4 < 1893362400ll);
// Verify difftime() calculates accurate time difference.
diff --git a/tests/unistd/login.out b/tests/unistd/login.out
index c1919c3c..50e850ae 100644
--- a/tests/unistd/login.out
+++ b/tests/unistd/login.out
@@ -3,7 +3,7 @@ errno: 0
gethostname/2 ret: -1
gethostname/2: em------------------------
-errno: 36
+errno: 91
gethostname/256 ret: 0
gethostname/256: emscripten
diff --git a/tests/unistd/misc.out b/tests/unistd/misc.out
index a872a258..43971955 100644
--- a/tests/unistd/misc.out
+++ b/tests/unistd/misc.out
@@ -11,8 +11,8 @@ lockf(good): 0, errno: 0
lockf(bad): -1, errno: 9
nice: 0, errno: 1
pause: -1, errno: 4
-pipe(good): -1, errno: 38
-pipe(bad): -1, errno: 38
+pipe(good): -1, errno: 88
+pipe(bad): -1, errno: 88
execl: -1, errno: 8
execle: -1, errno: 8
execlp: -1, errno: 8
@@ -29,8 +29,8 @@ alarm: 0, errno: 0
ualarm: 0, errno: 0
fork: -1, errno: 11
vfork: -1, errno: 11
-crypt: (null), errno: 38
-encrypt, errno: 38
+crypt: (null), errno: 88
+encrypt, errno: 88
getgid: 0, errno: 0
getegid: 0, errno: 0
getuid: 0, errno: 0
diff --git a/tests/unistd/unlink.out b/tests/unistd/unlink.out
index 1dcec761..f7a894cb 100644
--- a/tests/unistd/unlink.out
+++ b/tests/unistd/unlink.out
@@ -37,6 +37,6 @@ access(/empty-forbidden) after rmdir: 0
access(/full) before: 0
errno: 21
access(/full) after unlink: 0
-errno: 39
+errno: 90
access(/full) after rmdir: 0
diff --git a/tests/websockets.c b/tests/websockets.c
index 8e719baa..8882f5ba 100644
--- a/tests/websockets.c
+++ b/tests/websockets.c
@@ -56,7 +56,7 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize)
}
if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
- fprintf(stderr, "error in get_all_buf!");
+ fprintf(stderr, "error in get_all_buf! %d", errno);
exit(EXIT_FAILURE);
}
return offset;
diff --git a/tests/websockets_bi.c b/tests/websockets_bi.c
index 18cdd664..fb60177b 100644
--- a/tests/websockets_bi.c
+++ b/tests/websockets_bi.c
@@ -14,6 +14,10 @@
#define EXPECTED_BYTES 28
+#ifndef SOCKK
+#define SOCKK 8992
+#endif
+
int SocketFD;
unsigned int get_all_buf(int sock, char* output, unsigned int maxsize)
@@ -25,7 +29,11 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize)
char buffer[1024];
int n;
unsigned int offset = 0;
+#if TEST_FILE_OPS
+ while((errno = 0, (n = read(sock, buffer, sizeof(buffer)))>0) ||
+#else
while((errno = 0, (n = recv(sock, buffer, sizeof(buffer), 0))>0) ||
+#endif
errno == EINTR) {
if(n>0)
{
@@ -96,13 +104,7 @@ int main(void)
memset(&stSockAddr, 0, sizeof(stSockAddr));
stSockAddr.sin_family = AF_INET;
- stSockAddr.sin_port = htons(
-#if EMSCRIPTEN
- 8993
-#else
- 8992
-#endif
- );
+ stSockAddr.sin_port = htons(SOCKK);
Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr);
if (0 > Res) {
diff --git a/tests/websockets_bi_side.c b/tests/websockets_bi_side.c
index 12b790fd..1d557ed8 100644
--- a/tests/websockets_bi_side.c
+++ b/tests/websockets_bi_side.c
@@ -54,10 +54,17 @@ int main(void)
exit(EXIT_FAILURE);
}
+#if TEST_FILE_OPS
+ printf("write..\n");
+
+ char data[] = "hello from the other siide (fileops)\n";
+ write(SocketFD, data, sizeof(data));
+#else
printf("send..\n");
char data[] = "hello from the other siide\n";
send(SocketFD, data, sizeof(data), 0);
+#endif
printf("stall..\n");
diff --git a/third_party/lzma.js/lzip/Makefile b/third_party/lzma.js/lzip/Makefile
index ca6a6ef7..8a5baee3 100644
--- a/third_party/lzma.js/lzip/Makefile
+++ b/third_party/lzma.js/lzip/Makefile
@@ -16,7 +16,8 @@ datadir = $(prefix)/share
infodir = $(datadir)/info
mandir = $(datadir)/man
sysconfdir = $(prefix)/etc
-CPPFLAGS = -DDECODER_ONLY=$(DECODER_ONLY)
+CXX = g++
+CPPFLAGS =
CXXFLAGS = -Wall -W -O2
LDFLAGS =
@@ -27,16 +28,16 @@ INSTALL_DATA = $(INSTALL) -p -m 644
INSTALL_DIR = $(INSTALL) -d -m 755
SHELL = /bin/sh
-objs = decoder.o encoder.o fast_encoder.o main.o
-recobjs = decoder.o lziprecover.o
-unzobjs = unzcrash.o
+objs = arg_parser.o decoder.o encoder.o fast_encoder.o main.o
+recobjs = arg_parser.o decoder.o lziprecover.o
+unzobjs = arg_parser.o unzcrash.o
.PHONY : all install install-info install-man install-strip \
uninstall uninstall-info uninstall-man \
doc info man check dist clean distclean
-all : $(progname)
+all : $(progname) lziprecover
$(progname) : $(objs)
$(CXX) $(LDFLAGS) -o $@ $(objs)
@@ -63,12 +64,13 @@ unzcrash.o : testsuite/unzcrash.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
$(objs) : Makefile
+arg_parser.o : arg_parser.h
decoder.o : lzip.h decoder.h
encoder.o : lzip.h encoder.h
fast_encoder.o : lzip.h encoder.h fast_encoder.h
-main.o : lzip.h decoder.h encoder.h fast_encoder.h
-lziprecover.o : lzip.h decoder.h Makefile
-unzcrash.o : Makefile
+main.o : arg_parser.h lzip.h decoder.h encoder.h fast_encoder.h
+lziprecover.o : arg_parser.h lzip.h decoder.h Makefile
+unzcrash.o : arg_parser.h Makefile
doc : info man
diff --git a/tools/cache.py b/tools/cache.py
index 13a53fe9..c316a1fd 100644
--- a/tools/cache.py
+++ b/tools/cache.py
@@ -49,7 +49,10 @@ class JCache:
def ensure(self):
self.cache.ensure()
if not os.path.exists(self.dirname):
- os.makedirs(self.dirname)
+ try:
+ os.makedirs(self.dirname)
+ except (IOError, OSError):
+ pass
def get_shortkey(self, keys):
if type(keys) not in [list, tuple]:
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index 8da7a5bc..41a2c2b6 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -107,10 +107,9 @@ function label() {
}
}
function switchy() {
- var no = 0, yes = 0, a = 0, b = 0;
+ var yes = 0;
while (1) switch (label | 0) {
case 1:
- no = 100;
break;
case 2:
yes = 111;
@@ -120,8 +119,6 @@ function switchy() {
print(yes / 2);
continue;
case 3:
- a = 5;
- b = a;
break;
}
}
@@ -364,4 +361,4604 @@ function __ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_(
STACKTOP = __stackBase__;
return;
}
+function _java_nio_charset_Charset_forNameInternal___java_lang_String($n1) {
+ $n1 = $n1 | 0;
+ var $_r0_sroa_0 = 0, $_r0_sroa_1 = 0, $_r1_sroa_0 = 0, $_r2_sroa_0 = 0, $_r3_sroa_0 = 0, $_r3_sroa_1 = 0, $_r5_sroa_0 = 0, $local_env_w4567aaac23b1b6 = 0, $local_env_w4567aaac23b1c16 = 0, $local_env_w4567aaac23b1c22 = 0, $local_env_w4567aaac23b1c24 = 0, $local_env_w4567aaac23b1c26 = 0, $local_env_w4567aaac23b1c29 = 0, $local_env_w4567aaac23b1c31 = 0, $local_env_w4567aaac23b1c35 = 0, $local_env_w4567aaac23b1c40 = 0, $local_env_w4567aaac23b1c42 = 0, $local_env_w4567aaac23b1c44 = 0, $local_env_w4567aaac23b1c48 = 0, $local_env_w4567aaac23b1c50 = 0, $5 = 0, $16 = 0, $18 = 0, $19 = 0, $21 = 0, $25 = 0, $40 = 0, $52 = 0, $57 = 0, $61 = 0, $tib1_0_ph_i543 = 0, $72 = 0, $tib1_0_lcssa_i546 = 0, $dimension_tib1_0_lcssa_i547 = 0, $77 = 0, $79 = 0, $dimension_tib1_029_i549 = 0, $82 = 0, $83 = 0, $86 = 0, $88 = 0, $dimension_tib2_024_i551 = 0, $91 = 0, $92 = 0, $95 = 0, $tib2_0_lcssa_in_i553 = 0, $dimension_tib2_0_lcssa_i554 = 0, $tib2_0_lcssa_i555 = 0, $tib1_121_i558 = 0, $i_0_i561 = 0, $113 = 0, $_r1_sroa_0_0_load600 = 0, $119 = 0, $122 = 0, $139 = 0, $145 = 0, $149 = 0, $151 = 0, $153 = 0, $155 = 0, $159 = 0, $170 = 0, $175 = 0, $179 = 0, $tib1_0_ph_i521 = 0, $190 = 0, $tib1_0_lcssa_i524 = 0, $dimension_tib1_0_lcssa_i525 = 0, $195 = 0, $197 = 0, $dimension_tib1_029_i527 = 0, $200 = 0, $201 = 0, $204 = 0, $206 = 0, $dimension_tib2_024_i529 = 0, $209 = 0, $210 = 0, $213 = 0, $tib2_0_lcssa_in_i531 = 0, $dimension_tib2_0_lcssa_i532 = 0, $tib2_0_lcssa_i533 = 0, $tib1_121_i536 = 0, $i_0_i539 = 0, $231 = 0, $238 = 0, $240 = 0, $_r1_sroa_0_0_load = 0, $246 = 0, $249 = 0, $266 = 0, $273 = 0, $275 = 0, $284 = 0, $286 = 0, $290 = 0, $305 = 0, $310 = 0, $323 = 0, $328 = 0, $332 = 0, $tib1_0_ph_i500 = 0, $343 = 0, $tib1_0_lcssa_i503 = 0, $dimension_tib1_0_lcssa_i504 = 0, $348 = 0, $350 = 0, $dimension_tib1_029_i506 = 0, $353 = 0, $354 = 0, $357 = 0, $359 = 0, $dimension_tib2_024_i508 = 0, $362 = 0, $363 = 0, $366 = 0, $tib2_0_lcssa_in_i510 = 0, $dimension_tib2_0_lcssa_i511 = 0, $tib2_0_lcssa_i512 = 0, $tib1_121_i515 = 0, $i_0_i518 = 0, $384 = 0, $392 = 0, $394 = 0, $395 = 0, $397 = 0, $401 = 0, $416 = 0, $424 = 0, $426 = 0, $427 = 0, $429 = 0, $433 = 0, $446 = 0, $451 = 0, $455 = 0, $tib1_0_ph_i479 = 0, $466 = 0, $tib1_0_lcssa_i482 = 0, $dimension_tib1_0_lcssa_i483 = 0, $471 = 0, $473 = 0, $dimension_tib1_029_i485 = 0, $476 = 0, $477 = 0, $480 = 0, $482 = 0, $dimension_tib2_024_i487 = 0, $485 = 0, $486 = 0, $489 = 0, $tib2_0_lcssa_in_i489 = 0, $dimension_tib2_0_lcssa_i490 = 0, $tib2_0_lcssa_i491 = 0, $tib1_121_i494 = 0, $i_0_i497 = 0, $507 = 0, $519 = 0, $521 = 0, $525 = 0, $534 = 0, $539 = 0, $542 = 0, $546 = 0, $548 = 0, $557 = 0, $562 = 0, $566 = 0, $tib1_0_ph_i458 = 0, $577 = 0, $tib1_0_lcssa_i461 = 0, $dimension_tib1_0_lcssa_i462 = 0, $582 = 0, $584 = 0, $dimension_tib1_029_i464 = 0, $587 = 0, $588 = 0, $591 = 0, $593 = 0, $dimension_tib2_024_i466 = 0, $596 = 0, $597 = 0, $600 = 0, $tib2_0_lcssa_in_i468 = 0, $dimension_tib2_0_lcssa_i469 = 0, $tib2_0_lcssa_i470 = 0, $tib1_121_i473 = 0, $i_0_i476 = 0, $618 = 0, $623 = 0, $625 = 0, $629 = 0, $632 = 0, $643 = 0, $644 = 0, $649 = 0, $653 = 0, $tib1_0_ph_i437 = 0, $664 = 0, $tib1_0_lcssa_i440 = 0, $dimension_tib1_0_lcssa_i441 = 0, $669 = 0, $671 = 0, $dimension_tib1_029_i443 = 0, $674 = 0, $675 = 0, $678 = 0, $680 = 0, $dimension_tib2_024_i445 = 0, $683 = 0, $684 = 0, $687 = 0, $tib2_0_lcssa_in_i447 = 0, $dimension_tib2_0_lcssa_i448 = 0, $tib2_0_lcssa_i449 = 0, $tib1_121_i452 = 0, $i_0_i455 = 0, $705 = 0, $711 = 0, $716 = 0, $720 = 0, $tib1_0_ph_i416 = 0, $731 = 0, $tib1_0_lcssa_i419 = 0, $dimension_tib1_0_lcssa_i420 = 0, $736 = 0, $738 = 0, $dimension_tib1_029_i422 = 0, $741 = 0, $742 = 0, $745 = 0, $747 = 0, $dimension_tib2_024_i424 = 0, $750 = 0, $751 = 0, $754 = 0, $tib2_0_lcssa_in_i426 = 0, $dimension_tib2_0_lcssa_i427 = 0, $tib2_0_lcssa_i428 = 0, $tib1_121_i431 = 0, $i_0_i434 = 0, $772 = 0, $780 = 0, $782 = 0, $783 = 0, $785 = 0, $789 = 0, $798 = 0, $808 = 0, $809 = 0, $814 = 0, $818 = 0, $tib1_0_ph_i395 = 0, $829 = 0, $tib1_0_lcssa_i398 = 0, $dimension_tib1_0_lcssa_i399 = 0, $834 = 0, $836 = 0, $dimension_tib1_029_i401 = 0, $839 = 0, $840 = 0, $843 = 0, $845 = 0, $dimension_tib2_024_i403 = 0, $848 = 0, $849 = 0, $852 = 0, $tib2_0_lcssa_in_i405 = 0, $dimension_tib2_0_lcssa_i406 = 0, $tib2_0_lcssa_i407 = 0, $tib1_121_i410 = 0, $i_0_i413 = 0, $870 = 0, $876 = 0, $881 = 0, $885 = 0, $tib1_0_ph_i374 = 0, $896 = 0, $tib1_0_lcssa_i377 = 0, $dimension_tib1_0_lcssa_i378 = 0, $901 = 0, $903 = 0, $dimension_tib1_029_i380 = 0, $906 = 0, $907 = 0, $910 = 0, $912 = 0, $dimension_tib2_024_i382 = 0, $915 = 0, $916 = 0, $919 = 0, $tib2_0_lcssa_in_i384 = 0, $dimension_tib2_0_lcssa_i385 = 0, $tib2_0_lcssa_i386 = 0, $tib1_121_i389 = 0, $i_0_i392 = 0, $937 = 0, $945 = 0, $947 = 0, $948 = 0, $950 = 0, $954 = 0, $_r0_sroa_0_0_load607 = 0, $969 = 0, $974 = 0, $978 = 0, $tib1_0_ph_i353 = 0, $989 = 0, $tib1_0_lcssa_i356 = 0, $dimension_tib1_0_lcssa_i357 = 0, $994 = 0, $996 = 0, $dimension_tib1_029_i359 = 0, $999 = 0, $1000 = 0, $1003 = 0, $1005 = 0, $dimension_tib2_024_i361 = 0, $1008 = 0, $1009 = 0, $1012 = 0, $tib2_0_lcssa_in_i363 = 0, $dimension_tib2_0_lcssa_i364 = 0, $tib2_0_lcssa_i365 = 0, $tib1_121_i368 = 0, $i_0_i371 = 0, $1030 = 0, $1036 = 0, $1038 = 0, $1042 = 0, $1050 = 0, $1056 = 0, $1064 = 0, $1066 = 0, $1067 = 0, $1069 = 0, $1073 = 0, $1083 = 0, $1084 = 0, $1089 = 0, $1093 = 0, $tib1_0_ph_i332 = 0, $1104 = 0, $tib1_0_lcssa_i335 = 0, $dimension_tib1_0_lcssa_i336 = 0, $1109 = 0, $1111 = 0, $dimension_tib1_029_i338 = 0, $1114 = 0, $1115 = 0, $1118 = 0, $1120 = 0, $dimension_tib2_024_i340 = 0, $1123 = 0, $1124 = 0, $1127 = 0, $tib2_0_lcssa_in_i342 = 0, $dimension_tib2_0_lcssa_i343 = 0, $tib2_0_lcssa_i344 = 0, $tib1_121_i347 = 0, $i_0_i350 = 0, $1145 = 0, $1151 = 0, $1156 = 0, $1160 = 0, $tib1_0_ph_i311 = 0, $1171 = 0, $tib1_0_lcssa_i314 = 0, $dimension_tib1_0_lcssa_i315 = 0, $1176 = 0, $1178 = 0, $dimension_tib1_029_i317 = 0, $1181 = 0, $1182 = 0, $1185 = 0, $1187 = 0, $dimension_tib2_024_i319 = 0, $1190 = 0, $1191 = 0, $1194 = 0, $tib2_0_lcssa_in_i321 = 0, $dimension_tib2_0_lcssa_i322 = 0, $tib2_0_lcssa_i323 = 0, $tib1_121_i326 = 0, $i_0_i329 = 0, $1212 = 0, $1222 = 0, $1232 = 0, $1233 = 0, $1238 = 0, $1242 = 0, $tib1_0_ph_i290 = 0, $1253 = 0, $tib1_0_lcssa_i293 = 0, $dimension_tib1_0_lcssa_i294 = 0, $1258 = 0, $1260 = 0, $dimension_tib1_029_i296 = 0, $1263 = 0, $1264 = 0, $1267 = 0, $1269 = 0, $dimension_tib2_024_i298 = 0, $1272 = 0, $1273 = 0, $1276 = 0, $tib2_0_lcssa_in_i300 = 0, $dimension_tib2_0_lcssa_i301 = 0, $tib2_0_lcssa_i302 = 0, $tib1_121_i305 = 0, $i_0_i308 = 0, $1294 = 0, $1300 = 0, $1305 = 0, $1309 = 0, $tib1_0_ph_i269 = 0, $1320 = 0, $tib1_0_lcssa_i272 = 0, $dimension_tib1_0_lcssa_i273 = 0, $1325 = 0, $1327 = 0, $dimension_tib1_029_i275 = 0, $1330 = 0, $1331 = 0, $1334 = 0, $1336 = 0, $dimension_tib2_024_i277 = 0, $1339 = 0, $1340 = 0, $1343 = 0, $tib2_0_lcssa_in_i279 = 0, $dimension_tib2_0_lcssa_i280 = 0, $tib2_0_lcssa_i281 = 0, $tib1_121_i284 = 0, $i_0_i287 = 0, $1361 = 0, $1369 = 0, $1371 = 0, $1372 = 0, $1374 = 0, $1378 = 0, $_r0_sroa_0_0_load604 = 0, $1391 = 0, $1400 = 0, $1401 = 0, $1406 = 0, $1410 = 0, $tib1_0_ph_i248 = 0, $1421 = 0, $tib1_0_lcssa_i251 = 0, $dimension_tib1_0_lcssa_i252 = 0, $1426 = 0, $1428 = 0, $dimension_tib1_029_i254 = 0, $1431 = 0, $1432 = 0, $1435 = 0, $1437 = 0, $dimension_tib2_024_i256 = 0, $1440 = 0, $1441 = 0, $1444 = 0, $tib2_0_lcssa_in_i258 = 0, $dimension_tib2_0_lcssa_i259 = 0, $tib2_0_lcssa_i260 = 0, $tib1_121_i263 = 0, $i_0_i266 = 0, $1462 = 0, $1468 = 0, $1473 = 0, $1477 = 0, $tib1_0_ph_i227 = 0, $1488 = 0, $tib1_0_lcssa_i230 = 0, $dimension_tib1_0_lcssa_i231 = 0, $1493 = 0, $1495 = 0, $dimension_tib1_029_i233 = 0, $1498 = 0, $1499 = 0, $1502 = 0, $1504 = 0, $dimension_tib2_024_i235 = 0, $1507 = 0, $1508 = 0, $1511 = 0, $tib2_0_lcssa_in_i237 = 0, $dimension_tib2_0_lcssa_i238 = 0, $tib2_0_lcssa_i239 = 0, $tib1_121_i242 = 0, $i_0_i245 = 0, $1529 = 0, $1536 = 0, $1538 = 0, $1539 = 0, $1541 = 0, $1545 = 0, $1551 = 0, $1553 = 0, $_r0_sroa_0_0_load602 = 0, $1570 = 0, $1575 = 0, $1579 = 0, $tib1_0_ph_i185 = 0, $1590 = 0, $tib1_0_lcssa_i188 = 0, $dimension_tib1_0_lcssa_i189 = 0, $1595 = 0, $1597 = 0, $dimension_tib1_029_i191 = 0, $1600 = 0, $1601 = 0, $1604 = 0, $1606 = 0, $dimension_tib2_024_i193 = 0, $1609 = 0, $1610 = 0, $1613 = 0, $tib2_0_lcssa_in_i195 = 0, $dimension_tib2_0_lcssa_i196 = 0, $tib2_0_lcssa_i197 = 0, $tib1_121_i200 = 0, $i_0_i203 = 0, $1631 = 0, $1638 = 0, $1640 = 0, $1641 = 0, $1643 = 0, $1647 = 0, $1653 = 0, $1655 = 0, $_r2_sroa_0_0_load = 0, $1666 = 0, $1668 = 0, $1684 = 0, $1689 = 0, $1693 = 0, $tib1_0_ph_i = 0, $1704 = 0, $tib1_0_lcssa_i = 0, $dimension_tib1_0_lcssa_i = 0, $1709 = 0, $1711 = 0, $dimension_tib1_029_i = 0, $1714 = 0, $1715 = 0, $1718 = 0, $1720 = 0, $dimension_tib2_024_i = 0, $1723 = 0, $1724 = 0, $1727 = 0, $tib2_0_lcssa_in_i = 0, $dimension_tib2_0_lcssa_i = 0, $tib2_0_lcssa_i = 0, $tib1_121_i = 0, $i_0_i = 0, $1745 = 0, label = 0, __stackBase__ = 0, setjmpLabel = 0, setjmpTable = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 536 | 0;
+ label = 1;
+ setjmpLabel = 0;
+ setjmpTable = STACKTOP;
+ STACKTOP = STACKTOP + 168 | 0;
+ HEAP32[setjmpTable >> 2] = 0;
+ while (1) switch (label | 0) {
+ case 1:
+ $_r0_sroa_1 = __stackBase__ | 0;
+ $_r3_sroa_1 = __stackBase__ + 8 | 0;
+ $local_env_w4567aaac23b1b6 = __stackBase__ + 16 | 0;
+ $local_env_w4567aaac23b1c16 = __stackBase__ + 56 | 0;
+ $local_env_w4567aaac23b1c22 = __stackBase__ + 96 | 0;
+ $local_env_w4567aaac23b1c24 = __stackBase__ + 136 | 0;
+ $local_env_w4567aaac23b1c26 = __stackBase__ + 176 | 0;
+ $local_env_w4567aaac23b1c29 = __stackBase__ + 216 | 0;
+ $local_env_w4567aaac23b1c31 = __stackBase__ + 256 | 0;
+ $local_env_w4567aaac23b1c35 = __stackBase__ + 296 | 0;
+ $local_env_w4567aaac23b1c40 = __stackBase__ + 336 | 0;
+ $local_env_w4567aaac23b1c42 = __stackBase__ + 376 | 0;
+ $local_env_w4567aaac23b1c44 = __stackBase__ + 416 | 0;
+ $local_env_w4567aaac23b1c48 = __stackBase__ + 456 | 0;
+ $local_env_w4567aaac23b1c50 = __stackBase__ + 496 | 0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 2;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 2:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 3;
+ break;
+ case 3:
+ $_r5_sroa_0 = $n1;
+ $5 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $5;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 5;
+ break;
+ case 5:
+ $_r1_sroa_0 = HEAP32[136048 >> 2] | 0;
+ invoke_ii(202, $_r1_sroa_0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 7;
+ break;
+ case 7:
+ $16 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $18 = invoke_iii(364, $16 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $19 = $local_env_w4567aaac23b1b6;
+ $21 = $18 + 16 | 0;
+ _memcpy($19 | 0, HEAP32[$21 >> 2] | 0 | 0, 40);
+ $25 = _saveSetjmp(HEAP32[$21 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 413;
+ break;
+ case 413:
+ if (($25 | 0) == 0) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 10;
+ break;
+ case 10:
+ $_r0_sroa_0 = HEAP32[140056 >> 2] | 0;
+ $40 = invoke_iii(HEAP32[((HEAP32[($_r0_sroa_0 | 0) >> 2] | 0) + 160 | 0) >> 2] | 0 | 0, $_r0_sroa_0 | 0, $_r5_sroa_0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $40;
+ $_r0_sroa_0 = $_r0_sroa_0;
+ _memcpy(HEAP32[$21 >> 2] | 0 | 0, $19 | 0, 40);
+ if (($_r0_sroa_0 | 0) == 0) {
+ label = 32;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 11:
+ _memcpy(HEAP32[$21 >> 2] | 0 | 0, $19 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 13;
+ break;
+ case 13:
+ $52 = HEAP32[($18 + 20 | 0) >> 2] | 0;
+ if (($52 | 0) == 0) {
+ label = 27;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $57 = HEAP32[$52 >> 2] | 0;
+ $61 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($57 | 0) == 82712) {
+ label = 15;
+ break;
+ } else {
+ $tib1_0_ph_i543 = $57;
+ label = 16;
+ break;
+ }
+ case 15:
+ $tib1_0_ph_i543 = HEAP32[((HEAP32[($52 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 16;
+ break;
+ case 16:
+ $72 = HEAP32[($tib1_0_ph_i543 + 56 | 0) >> 2] | 0;
+ if (($72 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i547 = 0;
+ $tib1_0_lcssa_i546 = $tib1_0_ph_i543;
+ label = 18;
+ break;
+ } else {
+ $dimension_tib1_029_i549 = 0;
+ $79 = $72;
+ label = 19;
+ break;
+ }
+ case 17:
+ $dimension_tib1_0_lcssa_i547 = $83;
+ $tib1_0_lcssa_i546 = $82;
+ label = 18;
+ break;
+ case 18:
+ $77 = HEAP32[($61 + 56 | 0) >> 2] | 0;
+ if (($77 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i554 = 0;
+ $tib2_0_lcssa_in_i553 = $61;
+ label = 21;
+ break;
+ } else {
+ $dimension_tib2_024_i551 = 0;
+ $88 = $77;
+ label = 20;
+ break;
+ }
+ case 19:
+ $82 = HEAP32[($79 + 8 | 0) >> 2] | 0;
+ $83 = $dimension_tib1_029_i549 + 1 | 0;
+ $86 = HEAP32[($82 + 56 | 0) >> 2] | 0;
+ if (($86 | 0) == 0) {
+ label = 17;
+ break;
+ } else {
+ $dimension_tib1_029_i549 = $83;
+ $79 = $86;
+ label = 19;
+ break;
+ }
+ case 20:
+ $91 = HEAP32[($88 + 8 | 0) >> 2] | 0;
+ $92 = $dimension_tib2_024_i551 + 1 | 0;
+ $95 = HEAP32[($91 + 56 | 0) >> 2] | 0;
+ if (($95 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i554 = $92;
+ $tib2_0_lcssa_in_i553 = $91;
+ label = 21;
+ break;
+ } else {
+ $dimension_tib2_024_i551 = $92;
+ $88 = $95;
+ label = 20;
+ break;
+ }
+ case 21:
+ $tib2_0_lcssa_i555 = $tib2_0_lcssa_in_i553;
+ if (($dimension_tib1_0_lcssa_i547 | 0) < ($dimension_tib2_0_lcssa_i554 | 0) | ($tib1_0_lcssa_i546 | 0) == 0) {
+ label = 27;
+ break;
+ } else {
+ $tib1_121_i558 = $tib1_0_lcssa_i546;
+ label = 22;
+ break;
+ }
+ case 22:
+ if (($tib1_121_i558 | 0) == ($tib2_0_lcssa_i555 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $i_0_i561 = 0;
+ label = 24;
+ break;
+ case 24:
+ if (($i_0_i561 | 0) < (HEAP32[($tib1_121_i558 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ if ((HEAP32[((HEAP32[($tib1_121_i558 + 112 | 0) >> 2] | 0) + ($i_0_i561 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i555 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i561 = $i_0_i561 + 1 | 0;
+ label = 24;
+ break;
+ }
+ case 26:
+ $113 = HEAP32[($tib1_121_i558 + 40 | 0) >> 2] | 0;
+ if (($113 | 0) == 0) {
+ label = 27;
+ break;
+ } else {
+ $tib1_121_i558 = $113;
+ label = 22;
+ break;
+ }
+ case 27:
+ invoke_vii(48, HEAP32[$21 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 28:
+ $_r1_sroa_0_0_load600 = $_r1_sroa_0;
+ $119 = $_r1_sroa_0_0_load600 + 4 | 0;
+ $122 = (HEAP32[$119 >> 2] | 0) + 8 | 0;
+ HEAP32[$122 >> 2] = (HEAP32[$122 >> 2] | 0) - 1 | 0;
+ if ((HEAP32[((HEAP32[$119 >> 2] | 0) + 8 | 0) >> 2] | 0 | 0) == 0) {
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ invoke_vi(28, $_r1_sroa_0_0_load600 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $139;
+ if (($139 | 0) == 0) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ invoke_iii(268, 31e3 | 0 | 0, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $139, tempInt) | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 31;
+ break;
+ case 31:
+ STACKTOP = __stackBase__;
+ return $_r0_sroa_0 | 0;
+ case 32:
+ $145 = ($_r5_sroa_0 | 0) == 0;
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 34;
+ break;
+ case 34:
+ $149 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $151 = invoke_iii(364, $149 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($145) {
+ label = 35;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 35:
+ $153 = $local_env_w4567aaac23b1c16;
+ $155 = $151 + 16 | 0;
+ _memcpy($153 | 0, HEAP32[$155 >> 2] | 0 | 0, 40);
+ $159 = _saveSetjmp(HEAP32[$155 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 414;
+ break;
+ case 414:
+ if (($159 | 0) == 0) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1457 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 37:
+ _memcpy(HEAP32[$155 >> 2] | 0 | 0, $153 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 39;
+ break;
+ case 39:
+ $170 = HEAP32[($151 + 20 | 0) >> 2] | 0;
+ if (($170 | 0) == 0) {
+ label = 53;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $175 = HEAP32[$170 >> 2] | 0;
+ $179 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($175 | 0) == 82712) {
+ label = 41;
+ break;
+ } else {
+ $tib1_0_ph_i521 = $175;
+ label = 42;
+ break;
+ }
+ case 41:
+ $tib1_0_ph_i521 = HEAP32[((HEAP32[($170 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 42;
+ break;
+ case 42:
+ $190 = HEAP32[($tib1_0_ph_i521 + 56 | 0) >> 2] | 0;
+ if (($190 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i525 = 0;
+ $tib1_0_lcssa_i524 = $tib1_0_ph_i521;
+ label = 44;
+ break;
+ } else {
+ $dimension_tib1_029_i527 = 0;
+ $197 = $190;
+ label = 45;
+ break;
+ }
+ case 43:
+ $dimension_tib1_0_lcssa_i525 = $201;
+ $tib1_0_lcssa_i524 = $200;
+ label = 44;
+ break;
+ case 44:
+ $195 = HEAP32[($179 + 56 | 0) >> 2] | 0;
+ if (($195 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i532 = 0;
+ $tib2_0_lcssa_in_i531 = $179;
+ label = 47;
+ break;
+ } else {
+ $dimension_tib2_024_i529 = 0;
+ $206 = $195;
+ label = 46;
+ break;
+ }
+ case 45:
+ $200 = HEAP32[($197 + 8 | 0) >> 2] | 0;
+ $201 = $dimension_tib1_029_i527 + 1 | 0;
+ $204 = HEAP32[($200 + 56 | 0) >> 2] | 0;
+ if (($204 | 0) == 0) {
+ label = 43;
+ break;
+ } else {
+ $dimension_tib1_029_i527 = $201;
+ $197 = $204;
+ label = 45;
+ break;
+ }
+ case 46:
+ $209 = HEAP32[($206 + 8 | 0) >> 2] | 0;
+ $210 = $dimension_tib2_024_i529 + 1 | 0;
+ $213 = HEAP32[($209 + 56 | 0) >> 2] | 0;
+ if (($213 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i532 = $210;
+ $tib2_0_lcssa_in_i531 = $209;
+ label = 47;
+ break;
+ } else {
+ $dimension_tib2_024_i529 = $210;
+ $206 = $213;
+ label = 46;
+ break;
+ }
+ case 47:
+ $tib2_0_lcssa_i533 = $tib2_0_lcssa_in_i531;
+ if (($dimension_tib1_0_lcssa_i525 | 0) < ($dimension_tib2_0_lcssa_i532 | 0) | ($tib1_0_lcssa_i524 | 0) == 0) {
+ label = 53;
+ break;
+ } else {
+ $tib1_121_i536 = $tib1_0_lcssa_i524;
+ label = 48;
+ break;
+ }
+ case 48:
+ if (($tib1_121_i536 | 0) == ($tib2_0_lcssa_i533 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $i_0_i539 = 0;
+ label = 50;
+ break;
+ case 50:
+ if (($i_0_i539 | 0) < (HEAP32[($tib1_121_i536 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 51;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 51:
+ if ((HEAP32[((HEAP32[($tib1_121_i536 + 112 | 0) >> 2] | 0) + ($i_0_i539 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i533 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i539 = $i_0_i539 + 1 | 0;
+ label = 50;
+ break;
+ }
+ case 52:
+ $231 = HEAP32[($tib1_121_i536 + 40 | 0) >> 2] | 0;
+ if (($231 | 0) == 0) {
+ label = 53;
+ break;
+ } else {
+ $tib1_121_i536 = $231;
+ label = 48;
+ break;
+ }
+ case 53:
+ invoke_vii(48, HEAP32[$155 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 54:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 56;
+ break;
+ case 56:
+ $238 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $240 = invoke_iii(364, $238 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = HEAP32[($240 + 20 | 0) >> 2] | 0;
+ $_r1_sroa_0_0_load = $_r1_sroa_0;
+ $246 = $_r1_sroa_0_0_load + 4 | 0;
+ $249 = (HEAP32[$246 >> 2] | 0) + 8 | 0;
+ HEAP32[$249 >> 2] = (HEAP32[$249 >> 2] | 0) - 1 | 0;
+ if ((HEAP32[((HEAP32[$246 >> 2] | 0) + 8 | 0) >> 2] | 0 | 0) == 0) {
+ label = 57;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 57:
+ invoke_vi(28, $_r1_sroa_0_0_load | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $266;
+ if (($266 | 0) == 0) {
+ label = 59;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ invoke_iii(268, 31e3 | 0 | 0, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $266, tempInt) | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 59;
+ break;
+ case 59:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 60;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 60:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 61;
+ break;
+ case 61:
+ $273 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $275 = invoke_iii(364, $273 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[($275 + 20 | 0) >> 2] = $_r0_sroa_0;
+ invoke_vii(48, HEAP32[($275 + 16 | 0) >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 62:
+ $284 = $local_env_w4567aaac23b1c22;
+ $286 = $151 + 16 | 0;
+ _memcpy($284 | 0, HEAP32[$286 >> 2] | 0 | 0, 40);
+ $290 = _saveSetjmp(HEAP32[$286 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 415;
+ break;
+ case 415:
+ if (($290 | 0) == 0) {
+ label = 63;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 63:
+ invoke_vi(44, $_r5_sroa_0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 65;
+ break;
+ case 65:
+ $_r0_sroa_0 = HEAP32[140064 >> 2] | 0;
+ if (($_r0_sroa_0 | 0) == 0) {
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ _memcpy(HEAP32[$286 >> 2] | 0 | 0, $284 | 0, 40);
+ label = 89;
+ break;
+ case 67:
+ if ((HEAP32[(84292 | 0) >> 2] | 0 | 0) == 0) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ invoke_v(584);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 69;
+ break;
+ case 69:
+ $305 = invoke_ii(338, 20 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[$305 >> 2] = 84288;
+ _memset($305 + 4 | 0 | 0 | 0, 0 | 0 | 0, 16 | 0 | 0);
+ $_r0_sroa_0 = $305;
+ invoke_vi(34, $_r0_sroa_0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $310 = $_r0_sroa_0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 70;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 70:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 71;
+ break;
+ case 71:
+ HEAP32[140064 >> 2] = $310;
+ _memcpy(HEAP32[$286 >> 2] | 0 | 0, $284 | 0, 40);
+ label = 89;
+ break;
+ case 72:
+ _memcpy(HEAP32[$286 >> 2] | 0 | 0, $284 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 73;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 73:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 74;
+ break;
+ case 74:
+ $323 = HEAP32[($151 + 20 | 0) >> 2] | 0;
+ if (($323 | 0) == 0) {
+ label = 88;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $328 = HEAP32[$323 >> 2] | 0;
+ $332 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($328 | 0) == 82712) {
+ label = 76;
+ break;
+ } else {
+ $tib1_0_ph_i500 = $328;
+ label = 77;
+ break;
+ }
+ case 76:
+ $tib1_0_ph_i500 = HEAP32[((HEAP32[($323 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 77;
+ break;
+ case 77:
+ $343 = HEAP32[($tib1_0_ph_i500 + 56 | 0) >> 2] | 0;
+ if (($343 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i504 = 0;
+ $tib1_0_lcssa_i503 = $tib1_0_ph_i500;
+ label = 79;
+ break;
+ } else {
+ $dimension_tib1_029_i506 = 0;
+ $350 = $343;
+ label = 80;
+ break;
+ }
+ case 78:
+ $dimension_tib1_0_lcssa_i504 = $354;
+ $tib1_0_lcssa_i503 = $353;
+ label = 79;
+ break;
+ case 79:
+ $348 = HEAP32[($332 + 56 | 0) >> 2] | 0;
+ if (($348 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i511 = 0;
+ $tib2_0_lcssa_in_i510 = $332;
+ label = 82;
+ break;
+ } else {
+ $dimension_tib2_024_i508 = 0;
+ $359 = $348;
+ label = 81;
+ break;
+ }
+ case 80:
+ $353 = HEAP32[($350 + 8 | 0) >> 2] | 0;
+ $354 = $dimension_tib1_029_i506 + 1 | 0;
+ $357 = HEAP32[($353 + 56 | 0) >> 2] | 0;
+ if (($357 | 0) == 0) {
+ label = 78;
+ break;
+ } else {
+ $dimension_tib1_029_i506 = $354;
+ $350 = $357;
+ label = 80;
+ break;
+ }
+ case 81:
+ $362 = HEAP32[($359 + 8 | 0) >> 2] | 0;
+ $363 = $dimension_tib2_024_i508 + 1 | 0;
+ $366 = HEAP32[($362 + 56 | 0) >> 2] | 0;
+ if (($366 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i511 = $363;
+ $tib2_0_lcssa_in_i510 = $362;
+ label = 82;
+ break;
+ } else {
+ $dimension_tib2_024_i508 = $363;
+ $359 = $366;
+ label = 81;
+ break;
+ }
+ case 82:
+ $tib2_0_lcssa_i512 = $tib2_0_lcssa_in_i510;
+ if (($dimension_tib1_0_lcssa_i504 | 0) < ($dimension_tib2_0_lcssa_i511 | 0) | ($tib1_0_lcssa_i503 | 0) == 0) {
+ label = 88;
+ break;
+ } else {
+ $tib1_121_i515 = $tib1_0_lcssa_i503;
+ label = 83;
+ break;
+ }
+ case 83:
+ if (($tib1_121_i515 | 0) == ($tib2_0_lcssa_i512 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 84:
+ $i_0_i518 = 0;
+ label = 85;
+ break;
+ case 85:
+ if (($i_0_i518 | 0) < (HEAP32[($tib1_121_i515 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 86;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 86:
+ if ((HEAP32[((HEAP32[($tib1_121_i515 + 112 | 0) >> 2] | 0) + ($i_0_i518 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i512 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i518 = $i_0_i518 + 1 | 0;
+ label = 85;
+ break;
+ }
+ case 87:
+ $384 = HEAP32[($tib1_121_i515 + 40 | 0) >> 2] | 0;
+ if (($384 | 0) == 0) {
+ label = 88;
+ break;
+ } else {
+ $tib1_121_i515 = $384;
+ label = 83;
+ break;
+ }
+ case 88:
+ invoke_vii(48, HEAP32[$286 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 89:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 90;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 90:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 91;
+ break;
+ case 91:
+ $392 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $394 = invoke_iii(364, $392 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $395 = $local_env_w4567aaac23b1c24;
+ $397 = $394 + 16 | 0;
+ _memcpy($395 | 0, HEAP32[$397 >> 2] | 0 | 0, 40);
+ $401 = _saveSetjmp(HEAP32[$397 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 416;
+ break;
+ case 416:
+ if (($401 | 0) == 0) {
+ label = 92;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 92:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 93;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 93:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 94;
+ break;
+ case 94:
+ $_r0_sroa_0 = HEAP32[140064 >> 2] | 0;
+ $416 = invoke_iii(HEAP32[((HEAP32[($_r0_sroa_0 | 0) >> 2] | 0) + 144 | 0) >> 2] | 0 | 0, $_r0_sroa_0 | 0, $_r5_sroa_0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $416;
+ if (($_r0_sroa_0 | 0) == 0) {
+ label = 95;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 95:
+ _memcpy(HEAP32[$397 >> 2] | 0 | 0, $395 | 0, 40);
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 96;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 96:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 97;
+ break;
+ case 97:
+ $424 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $426 = invoke_iii(364, $424 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $427 = $local_env_w4567aaac23b1c26;
+ $429 = $426 + 16 | 0;
+ _memcpy($427 | 0, HEAP32[$429 >> 2] | 0 | 0, 40);
+ $433 = _saveSetjmp(HEAP32[$429 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 417;
+ break;
+ case 417:
+ if (($433 | 0) == 0) {
+ label = 116;
+ break;
+ } else {
+ label = 127;
+ break;
+ }
+ case 98:
+ invoke_vii(24, $_r0_sroa_0 | 0, $_r5_sroa_0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ _memcpy(HEAP32[$397 >> 2] | 0 | 0, $395 | 0, 40);
+ label = 28;
+ break;
+ case 99:
+ _memcpy(HEAP32[$397 >> 2] | 0 | 0, $395 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 100;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 100:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 101;
+ break;
+ case 101:
+ $446 = HEAP32[($394 + 20 | 0) >> 2] | 0;
+ if (($446 | 0) == 0) {
+ label = 115;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 102:
+ $451 = HEAP32[$446 >> 2] | 0;
+ $455 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($451 | 0) == 82712) {
+ label = 103;
+ break;
+ } else {
+ $tib1_0_ph_i479 = $451;
+ label = 104;
+ break;
+ }
+ case 103:
+ $tib1_0_ph_i479 = HEAP32[((HEAP32[($446 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 104;
+ break;
+ case 104:
+ $466 = HEAP32[($tib1_0_ph_i479 + 56 | 0) >> 2] | 0;
+ if (($466 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i483 = 0;
+ $tib1_0_lcssa_i482 = $tib1_0_ph_i479;
+ label = 106;
+ break;
+ } else {
+ $dimension_tib1_029_i485 = 0;
+ $473 = $466;
+ label = 107;
+ break;
+ }
+ case 105:
+ $dimension_tib1_0_lcssa_i483 = $477;
+ $tib1_0_lcssa_i482 = $476;
+ label = 106;
+ break;
+ case 106:
+ $471 = HEAP32[($455 + 56 | 0) >> 2] | 0;
+ if (($471 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i490 = 0;
+ $tib2_0_lcssa_in_i489 = $455;
+ label = 109;
+ break;
+ } else {
+ $dimension_tib2_024_i487 = 0;
+ $482 = $471;
+ label = 108;
+ break;
+ }
+ case 107:
+ $476 = HEAP32[($473 + 8 | 0) >> 2] | 0;
+ $477 = $dimension_tib1_029_i485 + 1 | 0;
+ $480 = HEAP32[($476 + 56 | 0) >> 2] | 0;
+ if (($480 | 0) == 0) {
+ label = 105;
+ break;
+ } else {
+ $dimension_tib1_029_i485 = $477;
+ $473 = $480;
+ label = 107;
+ break;
+ }
+ case 108:
+ $485 = HEAP32[($482 + 8 | 0) >> 2] | 0;
+ $486 = $dimension_tib2_024_i487 + 1 | 0;
+ $489 = HEAP32[($485 + 56 | 0) >> 2] | 0;
+ if (($489 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i490 = $486;
+ $tib2_0_lcssa_in_i489 = $485;
+ label = 109;
+ break;
+ } else {
+ $dimension_tib2_024_i487 = $486;
+ $482 = $489;
+ label = 108;
+ break;
+ }
+ case 109:
+ $tib2_0_lcssa_i491 = $tib2_0_lcssa_in_i489;
+ if (($dimension_tib1_0_lcssa_i483 | 0) < ($dimension_tib2_0_lcssa_i490 | 0) | ($tib1_0_lcssa_i482 | 0) == 0) {
+ label = 115;
+ break;
+ } else {
+ $tib1_121_i494 = $tib1_0_lcssa_i482;
+ label = 110;
+ break;
+ }
+ case 110:
+ if (($tib1_121_i494 | 0) == ($tib2_0_lcssa_i491 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 111;
+ break;
+ }
+ case 111:
+ $i_0_i497 = 0;
+ label = 112;
+ break;
+ case 112:
+ if (($i_0_i497 | 0) < (HEAP32[($tib1_121_i494 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 113;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 113:
+ if ((HEAP32[((HEAP32[($tib1_121_i494 + 112 | 0) >> 2] | 0) + ($i_0_i497 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i491 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i497 = $i_0_i497 + 1 | 0;
+ label = 112;
+ break;
+ }
+ case 114:
+ $507 = HEAP32[($tib1_121_i494 + 40 | 0) >> 2] | 0;
+ if (($507 | 0) == 0) {
+ label = 115;
+ break;
+ } else {
+ $tib1_121_i494 = $507;
+ label = 110;
+ break;
+ }
+ case 115:
+ invoke_vii(48, HEAP32[$397 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 116:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 117;
+ break;
+ } else {
+ label = 118;
+ break;
+ }
+ case 117:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 118;
+ break;
+ case 118:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 119;
+ break;
+ } else {
+ label = 120;
+ break;
+ }
+ case 119:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 120;
+ break;
+ case 120:
+ $519 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $521 = invoke_iii(364, $519 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ((HEAP32[(98148 | 0) >> 2] | 0 | 0) == 0) {
+ label = 121;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 121:
+ invoke_v(408);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 122;
+ break;
+ case 122:
+ $525 = invoke_ii(338, 12 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[$525 >> 2] = 98144;
+ HEAP32[($525 + 4 | 0) >> 2] = 0;
+ HEAP32[($525 + 8 | 0) >> 2] = $521;
+ if ((HEAP32[(97532 | 0) >> 2] | 0 | 0) == 0) {
+ label = 123;
+ break;
+ } else {
+ $534 = 98144;
+ label = 124;
+ break;
+ }
+ case 123:
+ invoke_v(568);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $534 = HEAP32[$525 >> 2] | 0;
+ label = 124;
+ break;
+ case 124:
+ $539 = invoke_ii(HEAP32[(HEAP32[($534 + 116 | 0) >> 2] | 0) >> 2] | 0 | 0, $525 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r2_sroa_0 = $539;
+ _memcpy(HEAP32[$429 >> 2] | 0 | 0, $427 | 0, 40);
+ $542 = ($_r2_sroa_0 | 0) == 0;
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 125;
+ break;
+ } else {
+ label = 126;
+ break;
+ }
+ case 125:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 126;
+ break;
+ case 126:
+ $546 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $548 = invoke_iii(364, $546 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($542) {
+ label = 240;
+ break;
+ } else {
+ label = 144;
+ break;
+ }
+ case 127:
+ _memcpy(HEAP32[$429 >> 2] | 0 | 0, $427 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 128;
+ break;
+ } else {
+ label = 129;
+ break;
+ }
+ case 128:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 129;
+ break;
+ case 129:
+ $557 = HEAP32[($426 + 20 | 0) >> 2] | 0;
+ if (($557 | 0) == 0) {
+ label = 143;
+ break;
+ } else {
+ label = 130;
+ break;
+ }
+ case 130:
+ $562 = HEAP32[$557 >> 2] | 0;
+ $566 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($562 | 0) == 82712) {
+ label = 131;
+ break;
+ } else {
+ $tib1_0_ph_i458 = $562;
+ label = 132;
+ break;
+ }
+ case 131:
+ $tib1_0_ph_i458 = HEAP32[((HEAP32[($557 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 132;
+ break;
+ case 132:
+ $577 = HEAP32[($tib1_0_ph_i458 + 56 | 0) >> 2] | 0;
+ if (($577 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i462 = 0;
+ $tib1_0_lcssa_i461 = $tib1_0_ph_i458;
+ label = 134;
+ break;
+ } else {
+ $dimension_tib1_029_i464 = 0;
+ $584 = $577;
+ label = 135;
+ break;
+ }
+ case 133:
+ $dimension_tib1_0_lcssa_i462 = $588;
+ $tib1_0_lcssa_i461 = $587;
+ label = 134;
+ break;
+ case 134:
+ $582 = HEAP32[($566 + 56 | 0) >> 2] | 0;
+ if (($582 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i469 = 0;
+ $tib2_0_lcssa_in_i468 = $566;
+ label = 137;
+ break;
+ } else {
+ $dimension_tib2_024_i466 = 0;
+ $593 = $582;
+ label = 136;
+ break;
+ }
+ case 135:
+ $587 = HEAP32[($584 + 8 | 0) >> 2] | 0;
+ $588 = $dimension_tib1_029_i464 + 1 | 0;
+ $591 = HEAP32[($587 + 56 | 0) >> 2] | 0;
+ if (($591 | 0) == 0) {
+ label = 133;
+ break;
+ } else {
+ $dimension_tib1_029_i464 = $588;
+ $584 = $591;
+ label = 135;
+ break;
+ }
+ case 136:
+ $596 = HEAP32[($593 + 8 | 0) >> 2] | 0;
+ $597 = $dimension_tib2_024_i466 + 1 | 0;
+ $600 = HEAP32[($596 + 56 | 0) >> 2] | 0;
+ if (($600 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i469 = $597;
+ $tib2_0_lcssa_in_i468 = $596;
+ label = 137;
+ break;
+ } else {
+ $dimension_tib2_024_i466 = $597;
+ $593 = $600;
+ label = 136;
+ break;
+ }
+ case 137:
+ $tib2_0_lcssa_i470 = $tib2_0_lcssa_in_i468;
+ if (($dimension_tib1_0_lcssa_i462 | 0) < ($dimension_tib2_0_lcssa_i469 | 0) | ($tib1_0_lcssa_i461 | 0) == 0) {
+ label = 143;
+ break;
+ } else {
+ $tib1_121_i473 = $tib1_0_lcssa_i461;
+ label = 138;
+ break;
+ }
+ case 138:
+ if (($tib1_121_i473 | 0) == ($tib2_0_lcssa_i470 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 139;
+ break;
+ }
+ case 139:
+ $i_0_i476 = 0;
+ label = 140;
+ break;
+ case 140:
+ if (($i_0_i476 | 0) < (HEAP32[($tib1_121_i473 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 141;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 141:
+ if ((HEAP32[((HEAP32[($tib1_121_i473 + 112 | 0) >> 2] | 0) + ($i_0_i476 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i470 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i476 = $i_0_i476 + 1 | 0;
+ label = 140;
+ break;
+ }
+ case 142:
+ $618 = HEAP32[($tib1_121_i473 + 40 | 0) >> 2] | 0;
+ if (($618 | 0) == 0) {
+ label = 143;
+ break;
+ } else {
+ $tib1_121_i473 = $618;
+ label = 138;
+ break;
+ }
+ case 143:
+ invoke_vii(48, HEAP32[$429 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 144:
+ $623 = $local_env_w4567aaac23b1c29;
+ $625 = $548 + 16 | 0;
+ _memcpy($623 | 0, HEAP32[$625 >> 2] | 0 | 0, 40);
+ $629 = _saveSetjmp(HEAP32[$625 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 418;
+ break;
+ case 418:
+ if (($629 | 0) == 0) {
+ label = 145;
+ break;
+ } else {
+ label = 146;
+ break;
+ }
+ case 145:
+ $632 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $632;
+ $_r0_sroa_0 = 0;
+ $_r3_sroa_0 = $_r0_sroa_0;
+ HEAP32[($_r3_sroa_1 | 0) >> 2] = HEAP32[($_r0_sroa_1 | 0) >> 2] | 0;
+ _memcpy(HEAP32[$625 >> 2] | 0 | 0, $623 | 0, 40);
+ label = 179;
+ break;
+ case 146:
+ _memcpy(HEAP32[$625 >> 2] | 0 | 0, $623 | 0, 40);
+ if ((HEAP32[(113236 | 0) >> 2] | 0 | 0) == 0) {
+ label = 147;
+ break;
+ } else {
+ label = 148;
+ break;
+ }
+ case 147:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 148;
+ break;
+ case 148:
+ $643 = $548 + 20 | 0;
+ $644 = HEAP32[$643 >> 2] | 0;
+ if (($644 | 0) == 0) {
+ label = 162;
+ break;
+ } else {
+ label = 149;
+ break;
+ }
+ case 149:
+ $649 = HEAP32[$644 >> 2] | 0;
+ $653 = HEAP32[((HEAP32[138672 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($649 | 0) == 82712) {
+ label = 150;
+ break;
+ } else {
+ $tib1_0_ph_i437 = $649;
+ label = 151;
+ break;
+ }
+ case 150:
+ $tib1_0_ph_i437 = HEAP32[((HEAP32[($644 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 151;
+ break;
+ case 151:
+ $664 = HEAP32[($tib1_0_ph_i437 + 56 | 0) >> 2] | 0;
+ if (($664 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i441 = 0;
+ $tib1_0_lcssa_i440 = $tib1_0_ph_i437;
+ label = 153;
+ break;
+ } else {
+ $dimension_tib1_029_i443 = 0;
+ $671 = $664;
+ label = 154;
+ break;
+ }
+ case 152:
+ $dimension_tib1_0_lcssa_i441 = $675;
+ $tib1_0_lcssa_i440 = $674;
+ label = 153;
+ break;
+ case 153:
+ $669 = HEAP32[($653 + 56 | 0) >> 2] | 0;
+ if (($669 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i448 = 0;
+ $tib2_0_lcssa_in_i447 = $653;
+ label = 156;
+ break;
+ } else {
+ $dimension_tib2_024_i445 = 0;
+ $680 = $669;
+ label = 155;
+ break;
+ }
+ case 154:
+ $674 = HEAP32[($671 + 8 | 0) >> 2] | 0;
+ $675 = $dimension_tib1_029_i443 + 1 | 0;
+ $678 = HEAP32[($674 + 56 | 0) >> 2] | 0;
+ if (($678 | 0) == 0) {
+ label = 152;
+ break;
+ } else {
+ $dimension_tib1_029_i443 = $675;
+ $671 = $678;
+ label = 154;
+ break;
+ }
+ case 155:
+ $683 = HEAP32[($680 + 8 | 0) >> 2] | 0;
+ $684 = $dimension_tib2_024_i445 + 1 | 0;
+ $687 = HEAP32[($683 + 56 | 0) >> 2] | 0;
+ if (($687 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i448 = $684;
+ $tib2_0_lcssa_in_i447 = $683;
+ label = 156;
+ break;
+ } else {
+ $dimension_tib2_024_i445 = $684;
+ $680 = $687;
+ label = 155;
+ break;
+ }
+ case 156:
+ $tib2_0_lcssa_i449 = $tib2_0_lcssa_in_i447;
+ if (($dimension_tib1_0_lcssa_i441 | 0) < ($dimension_tib2_0_lcssa_i448 | 0) | ($tib1_0_lcssa_i440 | 0) == 0) {
+ label = 162;
+ break;
+ } else {
+ $tib1_121_i452 = $tib1_0_lcssa_i440;
+ label = 157;
+ break;
+ }
+ case 157:
+ if (($tib1_121_i452 | 0) == ($tib2_0_lcssa_i449 | 0)) {
+ label = 361;
+ break;
+ } else {
+ label = 158;
+ break;
+ }
+ case 158:
+ $i_0_i455 = 0;
+ label = 159;
+ break;
+ case 159:
+ if (($i_0_i455 | 0) < (HEAP32[($tib1_121_i452 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 160;
+ break;
+ } else {
+ label = 161;
+ break;
+ }
+ case 160:
+ if ((HEAP32[((HEAP32[($tib1_121_i452 + 112 | 0) >> 2] | 0) + ($i_0_i455 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i449 | 0)) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i455 = $i_0_i455 + 1 | 0;
+ label = 159;
+ break;
+ }
+ case 161:
+ $705 = HEAP32[($tib1_121_i452 + 40 | 0) >> 2] | 0;
+ if (($705 | 0) == 0) {
+ label = 162;
+ break;
+ } else {
+ $tib1_121_i452 = $705;
+ label = 157;
+ break;
+ }
+ case 162:
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 163;
+ break;
+ } else {
+ label = 164;
+ break;
+ }
+ case 163:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 164;
+ break;
+ case 164:
+ $711 = HEAP32[$643 >> 2] | 0;
+ if (($711 | 0) == 0) {
+ label = 178;
+ break;
+ } else {
+ label = 165;
+ break;
+ }
+ case 165:
+ $716 = HEAP32[$711 >> 2] | 0;
+ $720 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($716 | 0) == 82712) {
+ label = 166;
+ break;
+ } else {
+ $tib1_0_ph_i416 = $716;
+ label = 167;
+ break;
+ }
+ case 166:
+ $tib1_0_ph_i416 = HEAP32[((HEAP32[($711 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 167;
+ break;
+ case 167:
+ $731 = HEAP32[($tib1_0_ph_i416 + 56 | 0) >> 2] | 0;
+ if (($731 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i420 = 0;
+ $tib1_0_lcssa_i419 = $tib1_0_ph_i416;
+ label = 169;
+ break;
+ } else {
+ $dimension_tib1_029_i422 = 0;
+ $738 = $731;
+ label = 170;
+ break;
+ }
+ case 168:
+ $dimension_tib1_0_lcssa_i420 = $742;
+ $tib1_0_lcssa_i419 = $741;
+ label = 169;
+ break;
+ case 169:
+ $736 = HEAP32[($720 + 56 | 0) >> 2] | 0;
+ if (($736 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i427 = 0;
+ $tib2_0_lcssa_in_i426 = $720;
+ label = 172;
+ break;
+ } else {
+ $dimension_tib2_024_i424 = 0;
+ $747 = $736;
+ label = 171;
+ break;
+ }
+ case 170:
+ $741 = HEAP32[($738 + 8 | 0) >> 2] | 0;
+ $742 = $dimension_tib1_029_i422 + 1 | 0;
+ $745 = HEAP32[($741 + 56 | 0) >> 2] | 0;
+ if (($745 | 0) == 0) {
+ label = 168;
+ break;
+ } else {
+ $dimension_tib1_029_i422 = $742;
+ $738 = $745;
+ label = 170;
+ break;
+ }
+ case 171:
+ $750 = HEAP32[($747 + 8 | 0) >> 2] | 0;
+ $751 = $dimension_tib2_024_i424 + 1 | 0;
+ $754 = HEAP32[($750 + 56 | 0) >> 2] | 0;
+ if (($754 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i427 = $751;
+ $tib2_0_lcssa_in_i426 = $750;
+ label = 172;
+ break;
+ } else {
+ $dimension_tib2_024_i424 = $751;
+ $747 = $754;
+ label = 171;
+ break;
+ }
+ case 172:
+ $tib2_0_lcssa_i428 = $tib2_0_lcssa_in_i426;
+ if (($dimension_tib1_0_lcssa_i420 | 0) < ($dimension_tib2_0_lcssa_i427 | 0) | ($tib1_0_lcssa_i419 | 0) == 0) {
+ label = 178;
+ break;
+ } else {
+ $tib1_121_i431 = $tib1_0_lcssa_i419;
+ label = 173;
+ break;
+ }
+ case 173:
+ if (($tib1_121_i431 | 0) == ($tib2_0_lcssa_i428 | 0)) {
+ label = 386;
+ break;
+ } else {
+ label = 174;
+ break;
+ }
+ case 174:
+ $i_0_i434 = 0;
+ label = 175;
+ break;
+ case 175:
+ if (($i_0_i434 | 0) < (HEAP32[($tib1_121_i431 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 176;
+ break;
+ } else {
+ label = 177;
+ break;
+ }
+ case 176:
+ if ((HEAP32[((HEAP32[($tib1_121_i431 + 112 | 0) >> 2] | 0) + ($i_0_i434 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i428 | 0)) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i434 = $i_0_i434 + 1 | 0;
+ label = 175;
+ break;
+ }
+ case 177:
+ $772 = HEAP32[($tib1_121_i431 + 40 | 0) >> 2] | 0;
+ if (($772 | 0) == 0) {
+ label = 178;
+ break;
+ } else {
+ $tib1_121_i431 = $772;
+ label = 173;
+ break;
+ }
+ case 178:
+ invoke_vii(48, HEAP32[$625 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 179:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 180;
+ break;
+ } else {
+ label = 181;
+ break;
+ }
+ case 180:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 181;
+ break;
+ case 181:
+ $780 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $782 = invoke_iii(364, $780 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $783 = $local_env_w4567aaac23b1c31;
+ $785 = $782 + 16 | 0;
+ _memcpy($783 | 0, HEAP32[$785 >> 2] | 0 | 0, 40);
+ $789 = _saveSetjmp(HEAP32[$785 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 419;
+ break;
+ case 419:
+ if (($789 | 0) == 0) {
+ label = 182;
+ break;
+ } else {
+ label = 183;
+ break;
+ }
+ case 182:
+ $798 = invoke_ii(HEAP32[(HEAP32[((HEAP32[$_r3_sroa_0 >> 2] | 0) + 116 | 0) >> 2] | 0) >> 2] | 0 | 0, $_r3_sroa_0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $798;
+ _memcpy(HEAP32[$785 >> 2] | 0 | 0, $783 | 0, 40);
+ if (($_r0_sroa_0 | 0) == 0) {
+ label = 216;
+ break;
+ } else {
+ label = 322;
+ break;
+ }
+ case 183:
+ _memcpy(HEAP32[$785 >> 2] | 0 | 0, $783 | 0, 40);
+ if ((HEAP32[(113236 | 0) >> 2] | 0 | 0) == 0) {
+ label = 184;
+ break;
+ } else {
+ label = 185;
+ break;
+ }
+ case 184:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 185;
+ break;
+ case 185:
+ $808 = $782 + 20 | 0;
+ $809 = HEAP32[$808 >> 2] | 0;
+ if (($809 | 0) == 0) {
+ label = 199;
+ break;
+ } else {
+ label = 186;
+ break;
+ }
+ case 186:
+ $814 = HEAP32[$809 >> 2] | 0;
+ $818 = HEAP32[((HEAP32[138672 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($814 | 0) == 82712) {
+ label = 187;
+ break;
+ } else {
+ $tib1_0_ph_i395 = $814;
+ label = 188;
+ break;
+ }
+ case 187:
+ $tib1_0_ph_i395 = HEAP32[((HEAP32[($809 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 188;
+ break;
+ case 188:
+ $829 = HEAP32[($tib1_0_ph_i395 + 56 | 0) >> 2] | 0;
+ if (($829 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i399 = 0;
+ $tib1_0_lcssa_i398 = $tib1_0_ph_i395;
+ label = 190;
+ break;
+ } else {
+ $dimension_tib1_029_i401 = 0;
+ $836 = $829;
+ label = 191;
+ break;
+ }
+ case 189:
+ $dimension_tib1_0_lcssa_i399 = $840;
+ $tib1_0_lcssa_i398 = $839;
+ label = 190;
+ break;
+ case 190:
+ $834 = HEAP32[($818 + 56 | 0) >> 2] | 0;
+ if (($834 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i406 = 0;
+ $tib2_0_lcssa_in_i405 = $818;
+ label = 193;
+ break;
+ } else {
+ $dimension_tib2_024_i403 = 0;
+ $845 = $834;
+ label = 192;
+ break;
+ }
+ case 191:
+ $839 = HEAP32[($836 + 8 | 0) >> 2] | 0;
+ $840 = $dimension_tib1_029_i401 + 1 | 0;
+ $843 = HEAP32[($839 + 56 | 0) >> 2] | 0;
+ if (($843 | 0) == 0) {
+ label = 189;
+ break;
+ } else {
+ $dimension_tib1_029_i401 = $840;
+ $836 = $843;
+ label = 191;
+ break;
+ }
+ case 192:
+ $848 = HEAP32[($845 + 8 | 0) >> 2] | 0;
+ $849 = $dimension_tib2_024_i403 + 1 | 0;
+ $852 = HEAP32[($848 + 56 | 0) >> 2] | 0;
+ if (($852 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i406 = $849;
+ $tib2_0_lcssa_in_i405 = $848;
+ label = 193;
+ break;
+ } else {
+ $dimension_tib2_024_i403 = $849;
+ $845 = $852;
+ label = 192;
+ break;
+ }
+ case 193:
+ $tib2_0_lcssa_i407 = $tib2_0_lcssa_in_i405;
+ if (($dimension_tib1_0_lcssa_i399 | 0) < ($dimension_tib2_0_lcssa_i406 | 0) | ($tib1_0_lcssa_i398 | 0) == 0) {
+ label = 199;
+ break;
+ } else {
+ $tib1_121_i410 = $tib1_0_lcssa_i398;
+ label = 194;
+ break;
+ }
+ case 194:
+ if (($tib1_121_i410 | 0) == ($tib2_0_lcssa_i407 | 0)) {
+ label = 361;
+ break;
+ } else {
+ label = 195;
+ break;
+ }
+ case 195:
+ $i_0_i413 = 0;
+ label = 196;
+ break;
+ case 196:
+ if (($i_0_i413 | 0) < (HEAP32[($tib1_121_i410 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 197;
+ break;
+ } else {
+ label = 198;
+ break;
+ }
+ case 197:
+ if ((HEAP32[((HEAP32[($tib1_121_i410 + 112 | 0) >> 2] | 0) + ($i_0_i413 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i407 | 0)) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i413 = $i_0_i413 + 1 | 0;
+ label = 196;
+ break;
+ }
+ case 198:
+ $870 = HEAP32[($tib1_121_i410 + 40 | 0) >> 2] | 0;
+ if (($870 | 0) == 0) {
+ label = 199;
+ break;
+ } else {
+ $tib1_121_i410 = $870;
+ label = 194;
+ break;
+ }
+ case 199:
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 200;
+ break;
+ } else {
+ label = 201;
+ break;
+ }
+ case 200:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 201;
+ break;
+ case 201:
+ $876 = HEAP32[$808 >> 2] | 0;
+ if (($876 | 0) == 0) {
+ label = 215;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 202:
+ $881 = HEAP32[$876 >> 2] | 0;
+ $885 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($881 | 0) == 82712) {
+ label = 203;
+ break;
+ } else {
+ $tib1_0_ph_i374 = $881;
+ label = 204;
+ break;
+ }
+ case 203:
+ $tib1_0_ph_i374 = HEAP32[((HEAP32[($876 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 204;
+ break;
+ case 204:
+ $896 = HEAP32[($tib1_0_ph_i374 + 56 | 0) >> 2] | 0;
+ if (($896 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i378 = 0;
+ $tib1_0_lcssa_i377 = $tib1_0_ph_i374;
+ label = 206;
+ break;
+ } else {
+ $dimension_tib1_029_i380 = 0;
+ $903 = $896;
+ label = 207;
+ break;
+ }
+ case 205:
+ $dimension_tib1_0_lcssa_i378 = $907;
+ $tib1_0_lcssa_i377 = $906;
+ label = 206;
+ break;
+ case 206:
+ $901 = HEAP32[($885 + 56 | 0) >> 2] | 0;
+ if (($901 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i385 = 0;
+ $tib2_0_lcssa_in_i384 = $885;
+ label = 209;
+ break;
+ } else {
+ $dimension_tib2_024_i382 = 0;
+ $912 = $901;
+ label = 208;
+ break;
+ }
+ case 207:
+ $906 = HEAP32[($903 + 8 | 0) >> 2] | 0;
+ $907 = $dimension_tib1_029_i380 + 1 | 0;
+ $910 = HEAP32[($906 + 56 | 0) >> 2] | 0;
+ if (($910 | 0) == 0) {
+ label = 205;
+ break;
+ } else {
+ $dimension_tib1_029_i380 = $907;
+ $903 = $910;
+ label = 207;
+ break;
+ }
+ case 208:
+ $915 = HEAP32[($912 + 8 | 0) >> 2] | 0;
+ $916 = $dimension_tib2_024_i382 + 1 | 0;
+ $919 = HEAP32[($915 + 56 | 0) >> 2] | 0;
+ if (($919 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i385 = $916;
+ $tib2_0_lcssa_in_i384 = $915;
+ label = 209;
+ break;
+ } else {
+ $dimension_tib2_024_i382 = $916;
+ $912 = $919;
+ label = 208;
+ break;
+ }
+ case 209:
+ $tib2_0_lcssa_i386 = $tib2_0_lcssa_in_i384;
+ if (($dimension_tib1_0_lcssa_i378 | 0) < ($dimension_tib2_0_lcssa_i385 | 0) | ($tib1_0_lcssa_i377 | 0) == 0) {
+ label = 215;
+ break;
+ } else {
+ $tib1_121_i389 = $tib1_0_lcssa_i377;
+ label = 210;
+ break;
+ }
+ case 210:
+ if (($tib1_121_i389 | 0) == ($tib2_0_lcssa_i386 | 0)) {
+ label = 386;
+ break;
+ } else {
+ label = 211;
+ break;
+ }
+ case 211:
+ $i_0_i392 = 0;
+ label = 212;
+ break;
+ case 212:
+ if (($i_0_i392 | 0) < (HEAP32[($tib1_121_i389 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 213;
+ break;
+ } else {
+ label = 214;
+ break;
+ }
+ case 213:
+ if ((HEAP32[((HEAP32[($tib1_121_i389 + 112 | 0) >> 2] | 0) + ($i_0_i392 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i386 | 0)) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i392 = $i_0_i392 + 1 | 0;
+ label = 212;
+ break;
+ }
+ case 214:
+ $937 = HEAP32[($tib1_121_i389 + 40 | 0) >> 2] | 0;
+ if (($937 | 0) == 0) {
+ label = 215;
+ break;
+ } else {
+ $tib1_121_i389 = $937;
+ label = 210;
+ break;
+ }
+ case 215:
+ invoke_vii(48, HEAP32[$785 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 216:
+ $_r0_sroa_0 = 0;
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 217;
+ break;
+ } else {
+ label = 218;
+ break;
+ }
+ case 217:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 218;
+ break;
+ case 218:
+ $945 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $947 = invoke_iii(364, $945 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $948 = $local_env_w4567aaac23b1c35;
+ $950 = $947 + 16 | 0;
+ _memcpy($948 | 0, HEAP32[$950 >> 2] | 0 | 0, 40);
+ $954 = _saveSetjmp(HEAP32[$950 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 420;
+ break;
+ case 420:
+ if (($954 | 0) == 0) {
+ label = 219;
+ break;
+ } else {
+ label = 222;
+ break;
+ }
+ case 219:
+ $_r0_sroa_0_0_load607 = $_r0_sroa_0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 220;
+ break;
+ } else {
+ label = 221;
+ break;
+ }
+ case 220:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 221;
+ break;
+ case 221:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load607;
+ _memcpy(HEAP32[$950 >> 2] | 0 | 0, $948 | 0, 40);
+ label = 239;
+ break;
+ case 222:
+ _memcpy(HEAP32[$950 >> 2] | 0 | 0, $948 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 223;
+ break;
+ } else {
+ label = 224;
+ break;
+ }
+ case 223:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 224;
+ break;
+ case 224:
+ $969 = HEAP32[($947 + 20 | 0) >> 2] | 0;
+ if (($969 | 0) == 0) {
+ label = 238;
+ break;
+ } else {
+ label = 225;
+ break;
+ }
+ case 225:
+ $974 = HEAP32[$969 >> 2] | 0;
+ $978 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($974 | 0) == 82712) {
+ label = 226;
+ break;
+ } else {
+ $tib1_0_ph_i353 = $974;
+ label = 227;
+ break;
+ }
+ case 226:
+ $tib1_0_ph_i353 = HEAP32[((HEAP32[($969 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 227;
+ break;
+ case 227:
+ $989 = HEAP32[($tib1_0_ph_i353 + 56 | 0) >> 2] | 0;
+ if (($989 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i357 = 0;
+ $tib1_0_lcssa_i356 = $tib1_0_ph_i353;
+ label = 229;
+ break;
+ } else {
+ $dimension_tib1_029_i359 = 0;
+ $996 = $989;
+ label = 230;
+ break;
+ }
+ case 228:
+ $dimension_tib1_0_lcssa_i357 = $1000;
+ $tib1_0_lcssa_i356 = $999;
+ label = 229;
+ break;
+ case 229:
+ $994 = HEAP32[($978 + 56 | 0) >> 2] | 0;
+ if (($994 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i364 = 0;
+ $tib2_0_lcssa_in_i363 = $978;
+ label = 232;
+ break;
+ } else {
+ $dimension_tib2_024_i361 = 0;
+ $1005 = $994;
+ label = 231;
+ break;
+ }
+ case 230:
+ $999 = HEAP32[($996 + 8 | 0) >> 2] | 0;
+ $1000 = $dimension_tib1_029_i359 + 1 | 0;
+ $1003 = HEAP32[($999 + 56 | 0) >> 2] | 0;
+ if (($1003 | 0) == 0) {
+ label = 228;
+ break;
+ } else {
+ $dimension_tib1_029_i359 = $1000;
+ $996 = $1003;
+ label = 230;
+ break;
+ }
+ case 231:
+ $1008 = HEAP32[($1005 + 8 | 0) >> 2] | 0;
+ $1009 = $dimension_tib2_024_i361 + 1 | 0;
+ $1012 = HEAP32[($1008 + 56 | 0) >> 2] | 0;
+ if (($1012 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i364 = $1009;
+ $tib2_0_lcssa_in_i363 = $1008;
+ label = 232;
+ break;
+ } else {
+ $dimension_tib2_024_i361 = $1009;
+ $1005 = $1012;
+ label = 231;
+ break;
+ }
+ case 232:
+ $tib2_0_lcssa_i365 = $tib2_0_lcssa_in_i363;
+ if (($dimension_tib1_0_lcssa_i357 | 0) < ($dimension_tib2_0_lcssa_i364 | 0) | ($tib1_0_lcssa_i356 | 0) == 0) {
+ label = 238;
+ break;
+ } else {
+ $tib1_121_i368 = $tib1_0_lcssa_i356;
+ label = 233;
+ break;
+ }
+ case 233:
+ if (($tib1_121_i368 | 0) == ($tib2_0_lcssa_i365 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 234;
+ break;
+ }
+ case 234:
+ $i_0_i371 = 0;
+ label = 235;
+ break;
+ case 235:
+ if (($i_0_i371 | 0) < (HEAP32[($tib1_121_i368 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 236;
+ break;
+ } else {
+ label = 237;
+ break;
+ }
+ case 236:
+ if ((HEAP32[((HEAP32[($tib1_121_i368 + 112 | 0) >> 2] | 0) + ($i_0_i371 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i365 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i371 = $i_0_i371 + 1 | 0;
+ label = 235;
+ break;
+ }
+ case 237:
+ $1030 = HEAP32[($tib1_121_i368 + 40 | 0) >> 2] | 0;
+ if (($1030 | 0) == 0) {
+ label = 238;
+ break;
+ } else {
+ $tib1_121_i368 = $1030;
+ label = 233;
+ break;
+ }
+ case 238:
+ invoke_vii(48, HEAP32[$950 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 239:
+ $_r0_sroa_0 = 0;
+ label = 28;
+ break;
+ case 240:
+ $1036 = $local_env_w4567aaac23b1c40;
+ $1038 = $548 + 16 | 0;
+ _memcpy($1036 | 0, HEAP32[$1038 >> 2] | 0 | 0, 40);
+ $1042 = _saveSetjmp(HEAP32[$1038 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 421;
+ break;
+ case 421:
+ if (($1042 | 0) == 0) {
+ label = 241;
+ break;
+ } else {
+ label = 253;
+ break;
+ }
+ case 241:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 242;
+ break;
+ } else {
+ label = 244;
+ break;
+ }
+ case 242:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 243;
+ break;
+ } else {
+ label = 244;
+ break;
+ }
+ case 243:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 244;
+ break;
+ case 244:
+ $1050 = HEAP32[140040 >> 2] | 0;
+ if (($1050 | 0) == 0) {
+ label = 245;
+ break;
+ } else {
+ label = 246;
+ break;
+ }
+ case 245:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126768 | 0 | 0, 573 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 246:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 247;
+ break;
+ } else {
+ $1056 = $1050;
+ label = 248;
+ break;
+ }
+ case 247:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1056 = HEAP32[140040 >> 2] | 0;
+ label = 248;
+ break;
+ case 248:
+ $_r0_sroa_0 = $1056;
+ if (($_r0_sroa_0 | 0) == 0) {
+ label = 252;
+ break;
+ } else {
+ label = 249;
+ break;
+ }
+ case 249:
+ _memcpy(HEAP32[$1038 >> 2] | 0 | 0, $1036 | 0, 40);
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 250;
+ break;
+ } else {
+ label = 251;
+ break;
+ }
+ case 250:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 251;
+ break;
+ case 251:
+ $1064 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1066 = invoke_iii(364, $1064 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1067 = $local_env_w4567aaac23b1c42;
+ $1069 = $1066 + 16 | 0;
+ _memcpy($1067 | 0, HEAP32[$1069 >> 2] | 0 | 0, 40);
+ $1073 = _saveSetjmp(HEAP32[$1069 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 422;
+ break;
+ case 422:
+ if (($1073 | 0) == 0) {
+ label = 286;
+ break;
+ } else {
+ label = 289;
+ break;
+ }
+ case 252:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1581 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 253:
+ _memcpy(HEAP32[$1038 >> 2] | 0 | 0, $1036 | 0, 40);
+ if ((HEAP32[(113236 | 0) >> 2] | 0 | 0) == 0) {
+ label = 254;
+ break;
+ } else {
+ label = 255;
+ break;
+ }
+ case 254:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 255;
+ break;
+ case 255:
+ $1083 = $548 + 20 | 0;
+ $1084 = HEAP32[$1083 >> 2] | 0;
+ if (($1084 | 0) == 0) {
+ label = 269;
+ break;
+ } else {
+ label = 256;
+ break;
+ }
+ case 256:
+ $1089 = HEAP32[$1084 >> 2] | 0;
+ $1093 = HEAP32[((HEAP32[138672 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1089 | 0) == 82712) {
+ label = 257;
+ break;
+ } else {
+ $tib1_0_ph_i332 = $1089;
+ label = 258;
+ break;
+ }
+ case 257:
+ $tib1_0_ph_i332 = HEAP32[((HEAP32[($1084 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 258;
+ break;
+ case 258:
+ $1104 = HEAP32[($tib1_0_ph_i332 + 56 | 0) >> 2] | 0;
+ if (($1104 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i336 = 0;
+ $tib1_0_lcssa_i335 = $tib1_0_ph_i332;
+ label = 260;
+ break;
+ } else {
+ $dimension_tib1_029_i338 = 0;
+ $1111 = $1104;
+ label = 261;
+ break;
+ }
+ case 259:
+ $dimension_tib1_0_lcssa_i336 = $1115;
+ $tib1_0_lcssa_i335 = $1114;
+ label = 260;
+ break;
+ case 260:
+ $1109 = HEAP32[($1093 + 56 | 0) >> 2] | 0;
+ if (($1109 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i343 = 0;
+ $tib2_0_lcssa_in_i342 = $1093;
+ label = 263;
+ break;
+ } else {
+ $dimension_tib2_024_i340 = 0;
+ $1120 = $1109;
+ label = 262;
+ break;
+ }
+ case 261:
+ $1114 = HEAP32[($1111 + 8 | 0) >> 2] | 0;
+ $1115 = $dimension_tib1_029_i338 + 1 | 0;
+ $1118 = HEAP32[($1114 + 56 | 0) >> 2] | 0;
+ if (($1118 | 0) == 0) {
+ label = 259;
+ break;
+ } else {
+ $dimension_tib1_029_i338 = $1115;
+ $1111 = $1118;
+ label = 261;
+ break;
+ }
+ case 262:
+ $1123 = HEAP32[($1120 + 8 | 0) >> 2] | 0;
+ $1124 = $dimension_tib2_024_i340 + 1 | 0;
+ $1127 = HEAP32[($1123 + 56 | 0) >> 2] | 0;
+ if (($1127 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i343 = $1124;
+ $tib2_0_lcssa_in_i342 = $1123;
+ label = 263;
+ break;
+ } else {
+ $dimension_tib2_024_i340 = $1124;
+ $1120 = $1127;
+ label = 262;
+ break;
+ }
+ case 263:
+ $tib2_0_lcssa_i344 = $tib2_0_lcssa_in_i342;
+ if (($dimension_tib1_0_lcssa_i336 | 0) < ($dimension_tib2_0_lcssa_i343 | 0) | ($tib1_0_lcssa_i335 | 0) == 0) {
+ label = 269;
+ break;
+ } else {
+ $tib1_121_i347 = $tib1_0_lcssa_i335;
+ label = 264;
+ break;
+ }
+ case 264:
+ if (($tib1_121_i347 | 0) == ($tib2_0_lcssa_i344 | 0)) {
+ label = 361;
+ break;
+ } else {
+ label = 265;
+ break;
+ }
+ case 265:
+ $i_0_i350 = 0;
+ label = 266;
+ break;
+ case 266:
+ if (($i_0_i350 | 0) < (HEAP32[($tib1_121_i347 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 267;
+ break;
+ } else {
+ label = 268;
+ break;
+ }
+ case 267:
+ if ((HEAP32[((HEAP32[($tib1_121_i347 + 112 | 0) >> 2] | 0) + ($i_0_i350 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i344 | 0)) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i350 = $i_0_i350 + 1 | 0;
+ label = 266;
+ break;
+ }
+ case 268:
+ $1145 = HEAP32[($tib1_121_i347 + 40 | 0) >> 2] | 0;
+ if (($1145 | 0) == 0) {
+ label = 269;
+ break;
+ } else {
+ $tib1_121_i347 = $1145;
+ label = 264;
+ break;
+ }
+ case 269:
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 270;
+ break;
+ } else {
+ label = 271;
+ break;
+ }
+ case 270:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 271;
+ break;
+ case 271:
+ $1151 = HEAP32[$1083 >> 2] | 0;
+ if (($1151 | 0) == 0) {
+ label = 285;
+ break;
+ } else {
+ label = 272;
+ break;
+ }
+ case 272:
+ $1156 = HEAP32[$1151 >> 2] | 0;
+ $1160 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1156 | 0) == 82712) {
+ label = 273;
+ break;
+ } else {
+ $tib1_0_ph_i311 = $1156;
+ label = 274;
+ break;
+ }
+ case 273:
+ $tib1_0_ph_i311 = HEAP32[((HEAP32[($1151 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 274;
+ break;
+ case 274:
+ $1171 = HEAP32[($tib1_0_ph_i311 + 56 | 0) >> 2] | 0;
+ if (($1171 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i315 = 0;
+ $tib1_0_lcssa_i314 = $tib1_0_ph_i311;
+ label = 276;
+ break;
+ } else {
+ $dimension_tib1_029_i317 = 0;
+ $1178 = $1171;
+ label = 277;
+ break;
+ }
+ case 275:
+ $dimension_tib1_0_lcssa_i315 = $1182;
+ $tib1_0_lcssa_i314 = $1181;
+ label = 276;
+ break;
+ case 276:
+ $1176 = HEAP32[($1160 + 56 | 0) >> 2] | 0;
+ if (($1176 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i322 = 0;
+ $tib2_0_lcssa_in_i321 = $1160;
+ label = 279;
+ break;
+ } else {
+ $dimension_tib2_024_i319 = 0;
+ $1187 = $1176;
+ label = 278;
+ break;
+ }
+ case 277:
+ $1181 = HEAP32[($1178 + 8 | 0) >> 2] | 0;
+ $1182 = $dimension_tib1_029_i317 + 1 | 0;
+ $1185 = HEAP32[($1181 + 56 | 0) >> 2] | 0;
+ if (($1185 | 0) == 0) {
+ label = 275;
+ break;
+ } else {
+ $dimension_tib1_029_i317 = $1182;
+ $1178 = $1185;
+ label = 277;
+ break;
+ }
+ case 278:
+ $1190 = HEAP32[($1187 + 8 | 0) >> 2] | 0;
+ $1191 = $dimension_tib2_024_i319 + 1 | 0;
+ $1194 = HEAP32[($1190 + 56 | 0) >> 2] | 0;
+ if (($1194 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i322 = $1191;
+ $tib2_0_lcssa_in_i321 = $1190;
+ label = 279;
+ break;
+ } else {
+ $dimension_tib2_024_i319 = $1191;
+ $1187 = $1194;
+ label = 278;
+ break;
+ }
+ case 279:
+ $tib2_0_lcssa_i323 = $tib2_0_lcssa_in_i321;
+ if (($dimension_tib1_0_lcssa_i315 | 0) < ($dimension_tib2_0_lcssa_i322 | 0) | ($tib1_0_lcssa_i314 | 0) == 0) {
+ label = 285;
+ break;
+ } else {
+ $tib1_121_i326 = $tib1_0_lcssa_i314;
+ label = 280;
+ break;
+ }
+ case 280:
+ if (($tib1_121_i326 | 0) == ($tib2_0_lcssa_i323 | 0)) {
+ label = 386;
+ break;
+ } else {
+ label = 281;
+ break;
+ }
+ case 281:
+ $i_0_i329 = 0;
+ label = 282;
+ break;
+ case 282:
+ if (($i_0_i329 | 0) < (HEAP32[($tib1_121_i326 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 283;
+ break;
+ } else {
+ label = 284;
+ break;
+ }
+ case 283:
+ if ((HEAP32[((HEAP32[($tib1_121_i326 + 112 | 0) >> 2] | 0) + ($i_0_i329 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i323 | 0)) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i329 = $i_0_i329 + 1 | 0;
+ label = 282;
+ break;
+ }
+ case 284:
+ $1212 = HEAP32[($tib1_121_i326 + 40 | 0) >> 2] | 0;
+ if (($1212 | 0) == 0) {
+ label = 285;
+ break;
+ } else {
+ $tib1_121_i326 = $1212;
+ label = 280;
+ break;
+ }
+ case 285:
+ invoke_vii(48, HEAP32[$1038 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 286:
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 287;
+ break;
+ } else {
+ label = 288;
+ break;
+ }
+ case 287:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 288;
+ break;
+ case 288:
+ $_r0_sroa_0 = HEAP32[140040 >> 2] | 0;
+ $1222 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r3_sroa_0 = $1222;
+ $_r0_sroa_0 = 0;
+ $_r3_sroa_0 = $_r0_sroa_0;
+ HEAP32[($_r3_sroa_1 | 0) >> 2] = HEAP32[($_r0_sroa_1 | 0) >> 2] | 0;
+ _memcpy(HEAP32[$1069 >> 2] | 0 | 0, $1067 | 0, 40);
+ label = 179;
+ break;
+ case 289:
+ _memcpy(HEAP32[$1069 >> 2] | 0 | 0, $1067 | 0, 40);
+ if ((HEAP32[(113236 | 0) >> 2] | 0 | 0) == 0) {
+ label = 290;
+ break;
+ } else {
+ label = 291;
+ break;
+ }
+ case 290:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 291;
+ break;
+ case 291:
+ $1232 = $1066 + 20 | 0;
+ $1233 = HEAP32[$1232 >> 2] | 0;
+ if (($1233 | 0) == 0) {
+ label = 305;
+ break;
+ } else {
+ label = 292;
+ break;
+ }
+ case 292:
+ $1238 = HEAP32[$1233 >> 2] | 0;
+ $1242 = HEAP32[((HEAP32[138672 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1238 | 0) == 82712) {
+ label = 293;
+ break;
+ } else {
+ $tib1_0_ph_i290 = $1238;
+ label = 294;
+ break;
+ }
+ case 293:
+ $tib1_0_ph_i290 = HEAP32[((HEAP32[($1233 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 294;
+ break;
+ case 294:
+ $1253 = HEAP32[($tib1_0_ph_i290 + 56 | 0) >> 2] | 0;
+ if (($1253 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i294 = 0;
+ $tib1_0_lcssa_i293 = $tib1_0_ph_i290;
+ label = 296;
+ break;
+ } else {
+ $dimension_tib1_029_i296 = 0;
+ $1260 = $1253;
+ label = 297;
+ break;
+ }
+ case 295:
+ $dimension_tib1_0_lcssa_i294 = $1264;
+ $tib1_0_lcssa_i293 = $1263;
+ label = 296;
+ break;
+ case 296:
+ $1258 = HEAP32[($1242 + 56 | 0) >> 2] | 0;
+ if (($1258 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i301 = 0;
+ $tib2_0_lcssa_in_i300 = $1242;
+ label = 299;
+ break;
+ } else {
+ $dimension_tib2_024_i298 = 0;
+ $1269 = $1258;
+ label = 298;
+ break;
+ }
+ case 297:
+ $1263 = HEAP32[($1260 + 8 | 0) >> 2] | 0;
+ $1264 = $dimension_tib1_029_i296 + 1 | 0;
+ $1267 = HEAP32[($1263 + 56 | 0) >> 2] | 0;
+ if (($1267 | 0) == 0) {
+ label = 295;
+ break;
+ } else {
+ $dimension_tib1_029_i296 = $1264;
+ $1260 = $1267;
+ label = 297;
+ break;
+ }
+ case 298:
+ $1272 = HEAP32[($1269 + 8 | 0) >> 2] | 0;
+ $1273 = $dimension_tib2_024_i298 + 1 | 0;
+ $1276 = HEAP32[($1272 + 56 | 0) >> 2] | 0;
+ if (($1276 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i301 = $1273;
+ $tib2_0_lcssa_in_i300 = $1272;
+ label = 299;
+ break;
+ } else {
+ $dimension_tib2_024_i298 = $1273;
+ $1269 = $1276;
+ label = 298;
+ break;
+ }
+ case 299:
+ $tib2_0_lcssa_i302 = $tib2_0_lcssa_in_i300;
+ if (($dimension_tib1_0_lcssa_i294 | 0) < ($dimension_tib2_0_lcssa_i301 | 0) | ($tib1_0_lcssa_i293 | 0) == 0) {
+ label = 305;
+ break;
+ } else {
+ $tib1_121_i305 = $tib1_0_lcssa_i293;
+ label = 300;
+ break;
+ }
+ case 300:
+ if (($tib1_121_i305 | 0) == ($tib2_0_lcssa_i302 | 0)) {
+ label = 361;
+ break;
+ } else {
+ label = 301;
+ break;
+ }
+ case 301:
+ $i_0_i308 = 0;
+ label = 302;
+ break;
+ case 302:
+ if (($i_0_i308 | 0) < (HEAP32[($tib1_121_i305 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 303;
+ break;
+ } else {
+ label = 304;
+ break;
+ }
+ case 303:
+ if ((HEAP32[((HEAP32[($tib1_121_i305 + 112 | 0) >> 2] | 0) + ($i_0_i308 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i302 | 0)) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i308 = $i_0_i308 + 1 | 0;
+ label = 302;
+ break;
+ }
+ case 304:
+ $1294 = HEAP32[($tib1_121_i305 + 40 | 0) >> 2] | 0;
+ if (($1294 | 0) == 0) {
+ label = 305;
+ break;
+ } else {
+ $tib1_121_i305 = $1294;
+ label = 300;
+ break;
+ }
+ case 305:
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 306;
+ break;
+ } else {
+ label = 307;
+ break;
+ }
+ case 306:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 307;
+ break;
+ case 307:
+ $1300 = HEAP32[$1232 >> 2] | 0;
+ if (($1300 | 0) == 0) {
+ label = 321;
+ break;
+ } else {
+ label = 308;
+ break;
+ }
+ case 308:
+ $1305 = HEAP32[$1300 >> 2] | 0;
+ $1309 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1305 | 0) == 82712) {
+ label = 309;
+ break;
+ } else {
+ $tib1_0_ph_i269 = $1305;
+ label = 310;
+ break;
+ }
+ case 309:
+ $tib1_0_ph_i269 = HEAP32[((HEAP32[($1300 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 310;
+ break;
+ case 310:
+ $1320 = HEAP32[($tib1_0_ph_i269 + 56 | 0) >> 2] | 0;
+ if (($1320 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i273 = 0;
+ $tib1_0_lcssa_i272 = $tib1_0_ph_i269;
+ label = 312;
+ break;
+ } else {
+ $dimension_tib1_029_i275 = 0;
+ $1327 = $1320;
+ label = 313;
+ break;
+ }
+ case 311:
+ $dimension_tib1_0_lcssa_i273 = $1331;
+ $tib1_0_lcssa_i272 = $1330;
+ label = 312;
+ break;
+ case 312:
+ $1325 = HEAP32[($1309 + 56 | 0) >> 2] | 0;
+ if (($1325 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i280 = 0;
+ $tib2_0_lcssa_in_i279 = $1309;
+ label = 315;
+ break;
+ } else {
+ $dimension_tib2_024_i277 = 0;
+ $1336 = $1325;
+ label = 314;
+ break;
+ }
+ case 313:
+ $1330 = HEAP32[($1327 + 8 | 0) >> 2] | 0;
+ $1331 = $dimension_tib1_029_i275 + 1 | 0;
+ $1334 = HEAP32[($1330 + 56 | 0) >> 2] | 0;
+ if (($1334 | 0) == 0) {
+ label = 311;
+ break;
+ } else {
+ $dimension_tib1_029_i275 = $1331;
+ $1327 = $1334;
+ label = 313;
+ break;
+ }
+ case 314:
+ $1339 = HEAP32[($1336 + 8 | 0) >> 2] | 0;
+ $1340 = $dimension_tib2_024_i277 + 1 | 0;
+ $1343 = HEAP32[($1339 + 56 | 0) >> 2] | 0;
+ if (($1343 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i280 = $1340;
+ $tib2_0_lcssa_in_i279 = $1339;
+ label = 315;
+ break;
+ } else {
+ $dimension_tib2_024_i277 = $1340;
+ $1336 = $1343;
+ label = 314;
+ break;
+ }
+ case 315:
+ $tib2_0_lcssa_i281 = $tib2_0_lcssa_in_i279;
+ if (($dimension_tib1_0_lcssa_i273 | 0) < ($dimension_tib2_0_lcssa_i280 | 0) | ($tib1_0_lcssa_i272 | 0) == 0) {
+ label = 321;
+ break;
+ } else {
+ $tib1_121_i284 = $tib1_0_lcssa_i272;
+ label = 316;
+ break;
+ }
+ case 316:
+ if (($tib1_121_i284 | 0) == ($tib2_0_lcssa_i281 | 0)) {
+ label = 386;
+ break;
+ } else {
+ label = 317;
+ break;
+ }
+ case 317:
+ $i_0_i287 = 0;
+ label = 318;
+ break;
+ case 318:
+ if (($i_0_i287 | 0) < (HEAP32[($tib1_121_i284 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 319;
+ break;
+ } else {
+ label = 320;
+ break;
+ }
+ case 319:
+ if ((HEAP32[((HEAP32[($tib1_121_i284 + 112 | 0) >> 2] | 0) + ($i_0_i287 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i281 | 0)) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i287 = $i_0_i287 + 1 | 0;
+ label = 318;
+ break;
+ }
+ case 320:
+ $1361 = HEAP32[($tib1_121_i284 + 40 | 0) >> 2] | 0;
+ if (($1361 | 0) == 0) {
+ label = 321;
+ break;
+ } else {
+ $tib1_121_i284 = $1361;
+ label = 316;
+ break;
+ }
+ case 321:
+ invoke_vii(48, HEAP32[$1069 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 322:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 323;
+ break;
+ } else {
+ label = 324;
+ break;
+ }
+ case 323:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 324;
+ break;
+ case 324:
+ $1369 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1371 = invoke_iii(364, $1369 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1372 = $local_env_w4567aaac23b1c44;
+ $1374 = $1371 + 16 | 0;
+ _memcpy($1372 | 0, HEAP32[$1374 >> 2] | 0 | 0, 40);
+ $1378 = _saveSetjmp(HEAP32[$1374 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 423;
+ break;
+ case 423:
+ if (($1378 | 0) == 0) {
+ label = 325;
+ break;
+ } else {
+ label = 328;
+ break;
+ }
+ case 325:
+ $_r0_sroa_0 = 1;
+ $_r0_sroa_0_0_load604 = $_r0_sroa_0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 326;
+ break;
+ } else {
+ label = 327;
+ break;
+ }
+ case 326:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 327;
+ break;
+ case 327:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load604;
+ $1391 = invoke_ii(HEAP32[((HEAP32[((HEAP32[$_r3_sroa_0 >> 2] | 0) + 116 | 0) >> 2] | 0) + 4 | 0) >> 2] | 0 | 0, $_r3_sroa_0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $1391;
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1630 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 328:
+ _memcpy(HEAP32[$1374 >> 2] | 0 | 0, $1372 | 0, 40);
+ if ((HEAP32[(113236 | 0) >> 2] | 0 | 0) == 0) {
+ label = 329;
+ break;
+ } else {
+ label = 330;
+ break;
+ }
+ case 329:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 330;
+ break;
+ case 330:
+ $1400 = $1371 + 20 | 0;
+ $1401 = HEAP32[$1400 >> 2] | 0;
+ if (($1401 | 0) == 0) {
+ label = 344;
+ break;
+ } else {
+ label = 331;
+ break;
+ }
+ case 331:
+ $1406 = HEAP32[$1401 >> 2] | 0;
+ $1410 = HEAP32[((HEAP32[138672 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1406 | 0) == 82712) {
+ label = 332;
+ break;
+ } else {
+ $tib1_0_ph_i248 = $1406;
+ label = 333;
+ break;
+ }
+ case 332:
+ $tib1_0_ph_i248 = HEAP32[((HEAP32[($1401 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 333;
+ break;
+ case 333:
+ $1421 = HEAP32[($tib1_0_ph_i248 + 56 | 0) >> 2] | 0;
+ if (($1421 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i252 = 0;
+ $tib1_0_lcssa_i251 = $tib1_0_ph_i248;
+ label = 335;
+ break;
+ } else {
+ $dimension_tib1_029_i254 = 0;
+ $1428 = $1421;
+ label = 336;
+ break;
+ }
+ case 334:
+ $dimension_tib1_0_lcssa_i252 = $1432;
+ $tib1_0_lcssa_i251 = $1431;
+ label = 335;
+ break;
+ case 335:
+ $1426 = HEAP32[($1410 + 56 | 0) >> 2] | 0;
+ if (($1426 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i259 = 0;
+ $tib2_0_lcssa_in_i258 = $1410;
+ label = 338;
+ break;
+ } else {
+ $dimension_tib2_024_i256 = 0;
+ $1437 = $1426;
+ label = 337;
+ break;
+ }
+ case 336:
+ $1431 = HEAP32[($1428 + 8 | 0) >> 2] | 0;
+ $1432 = $dimension_tib1_029_i254 + 1 | 0;
+ $1435 = HEAP32[($1431 + 56 | 0) >> 2] | 0;
+ if (($1435 | 0) == 0) {
+ label = 334;
+ break;
+ } else {
+ $dimension_tib1_029_i254 = $1432;
+ $1428 = $1435;
+ label = 336;
+ break;
+ }
+ case 337:
+ $1440 = HEAP32[($1437 + 8 | 0) >> 2] | 0;
+ $1441 = $dimension_tib2_024_i256 + 1 | 0;
+ $1444 = HEAP32[($1440 + 56 | 0) >> 2] | 0;
+ if (($1444 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i259 = $1441;
+ $tib2_0_lcssa_in_i258 = $1440;
+ label = 338;
+ break;
+ } else {
+ $dimension_tib2_024_i256 = $1441;
+ $1437 = $1444;
+ label = 337;
+ break;
+ }
+ case 338:
+ $tib2_0_lcssa_i260 = $tib2_0_lcssa_in_i258;
+ if (($dimension_tib1_0_lcssa_i252 | 0) < ($dimension_tib2_0_lcssa_i259 | 0) | ($tib1_0_lcssa_i251 | 0) == 0) {
+ label = 344;
+ break;
+ } else {
+ $tib1_121_i263 = $tib1_0_lcssa_i251;
+ label = 339;
+ break;
+ }
+ case 339:
+ if (($tib1_121_i263 | 0) == ($tib2_0_lcssa_i260 | 0)) {
+ label = 361;
+ break;
+ } else {
+ label = 340;
+ break;
+ }
+ case 340:
+ $i_0_i266 = 0;
+ label = 341;
+ break;
+ case 341:
+ if (($i_0_i266 | 0) < (HEAP32[($tib1_121_i263 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 342;
+ break;
+ } else {
+ label = 343;
+ break;
+ }
+ case 342:
+ if ((HEAP32[((HEAP32[($tib1_121_i263 + 112 | 0) >> 2] | 0) + ($i_0_i266 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i260 | 0)) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i266 = $i_0_i266 + 1 | 0;
+ label = 341;
+ break;
+ }
+ case 343:
+ $1462 = HEAP32[($tib1_121_i263 + 40 | 0) >> 2] | 0;
+ if (($1462 | 0) == 0) {
+ label = 344;
+ break;
+ } else {
+ $tib1_121_i263 = $1462;
+ label = 339;
+ break;
+ }
+ case 344:
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 345;
+ break;
+ } else {
+ label = 346;
+ break;
+ }
+ case 345:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 346;
+ break;
+ case 346:
+ $1468 = HEAP32[$1400 >> 2] | 0;
+ if (($1468 | 0) == 0) {
+ label = 360;
+ break;
+ } else {
+ label = 347;
+ break;
+ }
+ case 347:
+ $1473 = HEAP32[$1468 >> 2] | 0;
+ $1477 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1473 | 0) == 82712) {
+ label = 348;
+ break;
+ } else {
+ $tib1_0_ph_i227 = $1473;
+ label = 349;
+ break;
+ }
+ case 348:
+ $tib1_0_ph_i227 = HEAP32[((HEAP32[($1468 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 349;
+ break;
+ case 349:
+ $1488 = HEAP32[($tib1_0_ph_i227 + 56 | 0) >> 2] | 0;
+ if (($1488 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i231 = 0;
+ $tib1_0_lcssa_i230 = $tib1_0_ph_i227;
+ label = 351;
+ break;
+ } else {
+ $dimension_tib1_029_i233 = 0;
+ $1495 = $1488;
+ label = 352;
+ break;
+ }
+ case 350:
+ $dimension_tib1_0_lcssa_i231 = $1499;
+ $tib1_0_lcssa_i230 = $1498;
+ label = 351;
+ break;
+ case 351:
+ $1493 = HEAP32[($1477 + 56 | 0) >> 2] | 0;
+ if (($1493 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i238 = 0;
+ $tib2_0_lcssa_in_i237 = $1477;
+ label = 354;
+ break;
+ } else {
+ $dimension_tib2_024_i235 = 0;
+ $1504 = $1493;
+ label = 353;
+ break;
+ }
+ case 352:
+ $1498 = HEAP32[($1495 + 8 | 0) >> 2] | 0;
+ $1499 = $dimension_tib1_029_i233 + 1 | 0;
+ $1502 = HEAP32[($1498 + 56 | 0) >> 2] | 0;
+ if (($1502 | 0) == 0) {
+ label = 350;
+ break;
+ } else {
+ $dimension_tib1_029_i233 = $1499;
+ $1495 = $1502;
+ label = 352;
+ break;
+ }
+ case 353:
+ $1507 = HEAP32[($1504 + 8 | 0) >> 2] | 0;
+ $1508 = $dimension_tib2_024_i235 + 1 | 0;
+ $1511 = HEAP32[($1507 + 56 | 0) >> 2] | 0;
+ if (($1511 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i238 = $1508;
+ $tib2_0_lcssa_in_i237 = $1507;
+ label = 354;
+ break;
+ } else {
+ $dimension_tib2_024_i235 = $1508;
+ $1504 = $1511;
+ label = 353;
+ break;
+ }
+ case 354:
+ $tib2_0_lcssa_i239 = $tib2_0_lcssa_in_i237;
+ if (($dimension_tib1_0_lcssa_i231 | 0) < ($dimension_tib2_0_lcssa_i238 | 0) | ($tib1_0_lcssa_i230 | 0) == 0) {
+ label = 360;
+ break;
+ } else {
+ $tib1_121_i242 = $tib1_0_lcssa_i230;
+ label = 355;
+ break;
+ }
+ case 355:
+ if (($tib1_121_i242 | 0) == ($tib2_0_lcssa_i239 | 0)) {
+ label = 386;
+ break;
+ } else {
+ label = 356;
+ break;
+ }
+ case 356:
+ $i_0_i245 = 0;
+ label = 357;
+ break;
+ case 357:
+ if (($i_0_i245 | 0) < (HEAP32[($tib1_121_i242 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 358;
+ break;
+ } else {
+ label = 359;
+ break;
+ }
+ case 358:
+ if ((HEAP32[((HEAP32[($tib1_121_i242 + 112 | 0) >> 2] | 0) + ($i_0_i245 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i239 | 0)) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i245 = $i_0_i245 + 1 | 0;
+ label = 357;
+ break;
+ }
+ case 359:
+ $1529 = HEAP32[($tib1_121_i242 + 40 | 0) >> 2] | 0;
+ if (($1529 | 0) == 0) {
+ label = 360;
+ break;
+ } else {
+ $tib1_121_i242 = $1529;
+ label = 355;
+ break;
+ }
+ case 360:
+ invoke_vii(48, HEAP32[$1374 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 361:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 362;
+ break;
+ } else {
+ label = 363;
+ break;
+ }
+ case 362:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 363;
+ break;
+ case 363:
+ $1536 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1538 = invoke_iii(364, $1536 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1539 = $local_env_w4567aaac23b1c48;
+ $1541 = $1538 + 16 | 0;
+ _memcpy($1539 | 0, HEAP32[$1541 >> 2] | 0 | 0, 40);
+ $1545 = _saveSetjmp(HEAP32[$1541 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 424;
+ break;
+ case 424:
+ if (($1545 | 0) == 0) {
+ label = 364;
+ break;
+ } else {
+ label = 369;
+ break;
+ }
+ case 364:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 365;
+ break;
+ } else {
+ label = 366;
+ break;
+ }
+ case 365:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 366;
+ break;
+ case 366:
+ $1551 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1553 = invoke_iii(364, $1551 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = HEAP32[($1553 + 20 | 0) >> 2] | 0;
+ $_r0_sroa_0 = 0;
+ $_r0_sroa_0_0_load602 = $_r0_sroa_0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 367;
+ break;
+ } else {
+ label = 368;
+ break;
+ }
+ case 367:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 368;
+ break;
+ case 368:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load602;
+ _memcpy(HEAP32[$1541 >> 2] | 0 | 0, $1539 | 0, 40);
+ label = 239;
+ break;
+ case 369:
+ _memcpy(HEAP32[$1541 >> 2] | 0 | 0, $1539 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 370;
+ break;
+ } else {
+ label = 371;
+ break;
+ }
+ case 370:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 371;
+ break;
+ case 371:
+ $1570 = HEAP32[($1538 + 20 | 0) >> 2] | 0;
+ if (($1570 | 0) == 0) {
+ label = 385;
+ break;
+ } else {
+ label = 372;
+ break;
+ }
+ case 372:
+ $1575 = HEAP32[$1570 >> 2] | 0;
+ $1579 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1575 | 0) == 82712) {
+ label = 373;
+ break;
+ } else {
+ $tib1_0_ph_i185 = $1575;
+ label = 374;
+ break;
+ }
+ case 373:
+ $tib1_0_ph_i185 = HEAP32[((HEAP32[($1570 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 374;
+ break;
+ case 374:
+ $1590 = HEAP32[($tib1_0_ph_i185 + 56 | 0) >> 2] | 0;
+ if (($1590 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i189 = 0;
+ $tib1_0_lcssa_i188 = $tib1_0_ph_i185;
+ label = 376;
+ break;
+ } else {
+ $dimension_tib1_029_i191 = 0;
+ $1597 = $1590;
+ label = 377;
+ break;
+ }
+ case 375:
+ $dimension_tib1_0_lcssa_i189 = $1601;
+ $tib1_0_lcssa_i188 = $1600;
+ label = 376;
+ break;
+ case 376:
+ $1595 = HEAP32[($1579 + 56 | 0) >> 2] | 0;
+ if (($1595 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i196 = 0;
+ $tib2_0_lcssa_in_i195 = $1579;
+ label = 379;
+ break;
+ } else {
+ $dimension_tib2_024_i193 = 0;
+ $1606 = $1595;
+ label = 378;
+ break;
+ }
+ case 377:
+ $1600 = HEAP32[($1597 + 8 | 0) >> 2] | 0;
+ $1601 = $dimension_tib1_029_i191 + 1 | 0;
+ $1604 = HEAP32[($1600 + 56 | 0) >> 2] | 0;
+ if (($1604 | 0) == 0) {
+ label = 375;
+ break;
+ } else {
+ $dimension_tib1_029_i191 = $1601;
+ $1597 = $1604;
+ label = 377;
+ break;
+ }
+ case 378:
+ $1609 = HEAP32[($1606 + 8 | 0) >> 2] | 0;
+ $1610 = $dimension_tib2_024_i193 + 1 | 0;
+ $1613 = HEAP32[($1609 + 56 | 0) >> 2] | 0;
+ if (($1613 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i196 = $1610;
+ $tib2_0_lcssa_in_i195 = $1609;
+ label = 379;
+ break;
+ } else {
+ $dimension_tib2_024_i193 = $1610;
+ $1606 = $1613;
+ label = 378;
+ break;
+ }
+ case 379:
+ $tib2_0_lcssa_i197 = $tib2_0_lcssa_in_i195;
+ if (($dimension_tib1_0_lcssa_i189 | 0) < ($dimension_tib2_0_lcssa_i196 | 0) | ($tib1_0_lcssa_i188 | 0) == 0) {
+ label = 385;
+ break;
+ } else {
+ $tib1_121_i200 = $tib1_0_lcssa_i188;
+ label = 380;
+ break;
+ }
+ case 380:
+ if (($tib1_121_i200 | 0) == ($tib2_0_lcssa_i197 | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 381;
+ break;
+ }
+ case 381:
+ $i_0_i203 = 0;
+ label = 382;
+ break;
+ case 382:
+ if (($i_0_i203 | 0) < (HEAP32[($tib1_121_i200 + 108 | 0) >> 2] | 0 | 0)) {
+ label = 383;
+ break;
+ } else {
+ label = 384;
+ break;
+ }
+ case 383:
+ if ((HEAP32[((HEAP32[($tib1_121_i200 + 112 | 0) >> 2] | 0) + ($i_0_i203 << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i197 | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i203 = $i_0_i203 + 1 | 0;
+ label = 382;
+ break;
+ }
+ case 384:
+ $1631 = HEAP32[($tib1_121_i200 + 40 | 0) >> 2] | 0;
+ if (($1631 | 0) == 0) {
+ label = 385;
+ break;
+ } else {
+ $tib1_121_i200 = $1631;
+ label = 380;
+ break;
+ }
+ case 385:
+ invoke_vii(48, HEAP32[$1541 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 386:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 387;
+ break;
+ } else {
+ label = 388;
+ break;
+ }
+ case 387:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 388;
+ break;
+ case 388:
+ $1638 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1640 = invoke_iii(364, $1638 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1641 = $local_env_w4567aaac23b1c50;
+ $1643 = $1640 + 16 | 0;
+ _memcpy($1641 | 0, HEAP32[$1643 >> 2] | 0 | 0, 40);
+ $1647 = _saveSetjmp(HEAP32[$1643 >> 2] | 0 | 0, label, setjmpTable) | 0;
+ label = 425;
+ break;
+ case 425:
+ if (($1647 | 0) == 0) {
+ label = 389;
+ break;
+ } else {
+ label = 396;
+ break;
+ }
+ case 389:
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 390;
+ break;
+ } else {
+ label = 391;
+ break;
+ }
+ case 390:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 391;
+ break;
+ case 391:
+ $1653 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1655 = invoke_iii(364, $1653 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = HEAP32[($1655 + 20 | 0) >> 2] | 0;
+ $_r2_sroa_0 = 0;
+ $_r2_sroa_0_0_load = $_r2_sroa_0;
+ if ((HEAP32[(98772 | 0) >> 2] | 0 | 0) == 0) {
+ label = 392;
+ break;
+ } else {
+ label = 393;
+ break;
+ }
+ case 392:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 393;
+ break;
+ case 393:
+ HEAP32[140048 >> 2] = $_r2_sroa_0_0_load;
+ if ((HEAP32[(105500 | 0) >> 2] | 0 | 0) == 0) {
+ label = 394;
+ break;
+ } else {
+ label = 395;
+ break;
+ }
+ case 394:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 395;
+ break;
+ case 395:
+ $1666 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1668 = invoke_iii(364, $1666 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[($1668 + 20 | 0) >> 2] = $_r0_sroa_0;
+ invoke_vii(48, HEAP32[($1668 + 16 | 0) >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 396:
+ _memcpy(HEAP32[$1643 >> 2] | 0 | 0, $1641 | 0, 40);
+ if ((HEAP32[(107740 | 0) >> 2] | 0 | 0) == 0) {
+ label = 397;
+ break;
+ } else {
+ label = 398;
+ break;
+ }
+ case 397:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 398;
+ break;
+ case 398:
+ $1684 = HEAP32[($1640 + 20 | 0) >> 2] | 0;
+ if (($1684 | 0) == 0) {
+ label = 412;
+ break;
+ } else {
+ label = 399;
+ break;
+ }
+ case 399:
+ $1689 = HEAP32[$1684 >> 2] | 0;
+ $1693 = HEAP32[((HEAP32[137616 >> 2] | 0) + 8 | 0) >> 2] | 0;
+ if (($1689 | 0) == 82712) {
+ label = 400;
+ break;
+ } else {
+ $tib1_0_ph_i = $1689;
+ label = 401;
+ break;
+ }
+ case 400:
+ $tib1_0_ph_i = HEAP32[((HEAP32[($1684 + 8 | 0) >> 2] | 0) + 8 | 0) >> 2] | 0;
+ label = 401;
+ break;
+ case 401:
+ $1704 = HEAP32[($tib1_0_ph_i + 56 | 0) >> 2] | 0;
+ if (($1704 | 0) == 0) {
+ $dimension_tib1_0_lcssa_i = 0;
+ $tib1_0_lcssa_i = $tib1_0_ph_i;
+ label = 403;
+ break;
+ } else {
+ $dimension_tib1_029_i = 0;
+ $1711 = $1704;
+ label = 404;
+ break;
+ }
+ case 402:
+ $dimension_tib1_0_lcssa_i = $1715;
+ $tib1_0_lcssa_i = $1714;
+ label = 403;
+ break;
+ case 403:
+ $1709 = HEAP32[($1693 + 56 | 0) >> 2] | 0;
+ if (($1709 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i = 0;
+ $tib2_0_lcssa_in_i = $1693;
+ label = 406;
+ break;
+ } else {
+ $dimension_tib2_024_i = 0;
+ $1720 = $1709;
+ label = 405;
+ break;
+ }
+ case 404:
+ $1714 = HEAP32[($1711 + 8 | 0) >> 2] | 0;
+ $1715 = $dimension_tib1_029_i + 1 | 0;
+ $1718 = HEAP32[($1714 + 56 | 0) >> 2] | 0;
+ if (($1718 | 0) == 0) {
+ label = 402;
+ break;
+ } else {
+ $dimension_tib1_029_i = $1715;
+ $1711 = $1718;
+ label = 404;
+ break;
+ }
+ case 405:
+ $1723 = HEAP32[($1720 + 8 | 0) >> 2] | 0;
+ $1724 = $dimension_tib2_024_i + 1 | 0;
+ $1727 = HEAP32[($1723 + 56 | 0) >> 2] | 0;
+ if (($1727 | 0) == 0) {
+ $dimension_tib2_0_lcssa_i = $1724;
+ $tib2_0_lcssa_in_i = $1723;
+ label = 406;
+ break;
+ } else {
+ $dimension_tib2_024_i = $1724;
+ $1720 = $1727;
+ label = 405;
+ break;
+ }
+ case 406:
+ $tib2_0_lcssa_i = $tib2_0_lcssa_in_i;
+ if (($dimension_tib1_0_lcssa_i | 0) < ($dimension_tib2_0_lcssa_i | 0) | ($tib1_0_lcssa_i | 0) == 0) {
+ label = 412;
+ break;
+ } else {
+ $tib1_121_i = $tib1_0_lcssa_i;
+ label = 407;
+ break;
+ }
+ case 407:
+ if (($tib1_121_i | 0) == ($tib2_0_lcssa_i | 0)) {
+ label = 54;
+ break;
+ } else {
+ label = 408;
+ break;
+ }
+ case 408:
+ $i_0_i = 0;
+ label = 409;
+ break;
+ case 409:
+ if (($i_0_i | 0) < (HEAP32[($tib1_121_i + 108 | 0) >> 2] | 0 | 0)) {
+ label = 410;
+ break;
+ } else {
+ label = 411;
+ break;
+ }
+ case 410:
+ if ((HEAP32[((HEAP32[($tib1_121_i + 112 | 0) >> 2] | 0) + ($i_0_i << 2) | 0) >> 2] | 0 | 0) == ($tib2_0_lcssa_i | 0)) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i = $i_0_i + 1 | 0;
+ label = 409;
+ break;
+ }
+ case 411:
+ $1745 = HEAP32[($tib1_121_i + 40 | 0) >> 2] | 0;
+ if (($1745 | 0) == 0) {
+ label = 412;
+ break;
+ } else {
+ $tib1_121_i = $1745;
+ label = 407;
+ break;
+ }
+ case 412:
+ invoke_vii(48, HEAP32[$1643 >> 2] | 0 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case -1111:
+ if ((setjmpLabel | 0) == 7) {
+ $25 = threwValue;
+ label = 413;
+ } else if ((setjmpLabel | 0) == 35) {
+ $159 = threwValue;
+ label = 414;
+ } else if ((setjmpLabel | 0) == 62) {
+ $290 = threwValue;
+ label = 415;
+ } else if ((setjmpLabel | 0) == 91) {
+ $401 = threwValue;
+ label = 416;
+ } else if ((setjmpLabel | 0) == 97) {
+ $433 = threwValue;
+ label = 417;
+ } else if ((setjmpLabel | 0) == 144) {
+ $629 = threwValue;
+ label = 418;
+ } else if ((setjmpLabel | 0) == 181) {
+ $789 = threwValue;
+ label = 419;
+ } else if ((setjmpLabel | 0) == 218) {
+ $954 = threwValue;
+ label = 420;
+ } else if ((setjmpLabel | 0) == 240) {
+ $1042 = threwValue;
+ label = 421;
+ } else if ((setjmpLabel | 0) == 251) {
+ $1073 = threwValue;
+ label = 422;
+ } else if ((setjmpLabel | 0) == 324) {
+ $1378 = threwValue;
+ label = 423;
+ } else if ((setjmpLabel | 0) == 363) {
+ $1545 = threwValue;
+ label = 424;
+ } else if ((setjmpLabel | 0) == 388) {
+ $1647 = threwValue;
+ label = 425;
+ }
+ __THREW__ = threwValue = 0;
+ break;
+ }
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index 5f75e9c1..9b9cd3f7 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -593,5 +593,6090 @@ function __ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_(
STACKTOP = __stackBase__;
return;
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_"]
+function _java_nio_charset_Charset_forNameInternal___java_lang_String($n1) {
+ $n1 = $n1 | 0;
+ var $_r0_sroa_0 = 0, $_r0_sroa_1 = 0, $_r1_sroa_0 = 0, $_r2_sroa_0 = 0, $_r3_sroa_0 = 0, $_r3_sroa_1 = 0, $_r5_sroa_0 = 0, $local_env_w4567aaac23b1b6 = 0;
+ var $local_env_w4567aaac23b1c16 = 0, $local_env_w4567aaac23b1c22 = 0, $local_env_w4567aaac23b1c24 = 0, $local_env_w4567aaac23b1c26 = 0, $local_env_w4567aaac23b1c29 = 0, $local_env_w4567aaac23b1c31 = 0, $local_env_w4567aaac23b1c35 = 0, $local_env_w4567aaac23b1c40 = 0;
+ var $local_env_w4567aaac23b1c42 = 0, $local_env_w4567aaac23b1c44 = 0, $local_env_w4567aaac23b1c48 = 0, $local_env_w4567aaac23b1c50 = 0, $1 = 0, $2 = 0, $5 = 0, $6 = 0;
+ var $7 = 0, $8 = 0, $11 = 0, $_r1_sroa_0_0_load601 = 0, $12 = 0, $13 = 0, $14 = 0, $16 = 0;
+ var $17$0 = 0, $17$1 = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $23 = 0;
+ var $24 = 0, $25 = 0, $26 = 0, $28 = 0, $29 = 0, $31 = 0, $32 = 0, $_r0_sroa_0_0_load622 = 0;
+ var $33 = 0, $34 = 0, $35 = 0, $36 = 0, $37 = 0, $38 = 0, $_r0_sroa_0_0_load621 = 0, $39 = 0;
+ var $_r5_sroa_0_0_load592 = 0, $40 = 0, $41 = 0, $_r0_sroa_0_0_load620 = 0, $42 = 0, $_r0_sroa_0_0_load619 = 0, $43 = 0, $45 = 0;
+ var $46 = 0, $47 = 0, $50 = 0, $51 = 0, $52 = 0, $53 = 0, $55 = 0, $56 = 0;
+ var $57 = 0, $58 = 0, $59 = 0, $60 = 0, $61 = 0, $62 = 0, $64 = 0, $65 = 0;
+ var $66 = 0, $67 = 0, $68 = 0, $69 = 0, $70 = 0, $tib1_0_ph_i543 = 0, $71 = 0, $72 = 0;
+ var $73 = 0, $74 = 0, $tib1_0_lcssa_i546 = 0, $dimension_tib1_0_lcssa_i547 = 0, $75 = 0, $76 = 0, $77 = 0, $78 = 0;
+ var $79 = 0, $dimension_tib1_029_i549 = 0, $80 = 0, $81 = 0, $82 = 0, $83 = 0, $84 = 0, $85 = 0;
+ var $86 = 0, $87 = 0, $88 = 0, $dimension_tib2_024_i551 = 0, $89 = 0, $90 = 0, $91 = 0, $92 = 0;
+ var $93 = 0, $94 = 0, $95 = 0, $96 = 0, $tib2_0_lcssa_in_i553 = 0, $dimension_tib2_0_lcssa_i554 = 0, $tib2_0_lcssa_i555 = 0, $97 = 0;
+ var $98 = 0, $or_cond_i556 = 0, $tib1_121_i558 = 0, $99 = 0, $100 = 0, $101 = 0, $102 = 0, $i_0_i561 = 0;
+ var $104 = 0, $106 = 0, $107 = 0, $108 = 0, $109 = 0, $110 = 0, $112 = 0, $113 = 0;
+ var $114 = 0, $115 = 0, $116 = 0, $_r1_sroa_0_0_load600 = 0, $118 = 0, $119 = 0, $120 = 0, $121 = 0;
+ var $122 = 0, $123 = 0, $124 = 0, $125 = 0, $126 = 0, $127 = 0, $128 = 0, $129 = 0;
+ var $131 = 0, $132 = 0, $133 = 0, $134 = 0, $135 = 0, $136 = 0, $137 = 0, $138 = 0;
+ var $139 = 0, $140 = 0, $142 = 0, $_r0_sroa_0_0_load618 = 0, $143 = 0, $_r5_sroa_0_0_load591 = 0, $145 = 0, $146 = 0;
+ var $147 = 0, $149 = 0, $150$0 = 0, $150$1 = 0, $151 = 0, $153 = 0, $154 = 0, $155 = 0;
+ var $156 = 0, $157 = 0, $158 = 0, $159 = 0, $160 = 0, $163 = 0, $164 = 0, $165 = 0;
+ var $168 = 0, $169 = 0, $170 = 0, $171 = 0, $173 = 0, $174 = 0, $175 = 0, $176 = 0;
+ var $177 = 0, $178 = 0, $179 = 0, $180 = 0, $182 = 0, $183 = 0, $184 = 0, $185 = 0;
+ var $186 = 0, $187 = 0, $188 = 0, $tib1_0_ph_i521 = 0, $189 = 0, $190 = 0, $191 = 0, $192 = 0;
+ var $tib1_0_lcssa_i524 = 0, $dimension_tib1_0_lcssa_i525 = 0, $193 = 0, $194 = 0, $195 = 0, $196 = 0, $197 = 0, $dimension_tib1_029_i527 = 0;
+ var $198 = 0, $199 = 0, $200 = 0, $201 = 0, $202 = 0, $203 = 0, $204 = 0, $205 = 0;
+ var $206 = 0, $dimension_tib2_024_i529 = 0, $207 = 0, $208 = 0, $209 = 0, $210 = 0, $211 = 0, $212 = 0;
+ var $213 = 0, $214 = 0, $tib2_0_lcssa_in_i531 = 0, $dimension_tib2_0_lcssa_i532 = 0, $tib2_0_lcssa_i533 = 0, $215 = 0, $216 = 0, $or_cond_i534 = 0;
+ var $tib1_121_i536 = 0, $217 = 0, $218 = 0, $219 = 0, $220 = 0, $i_0_i539 = 0, $222 = 0, $224 = 0;
+ var $225 = 0, $226 = 0, $227 = 0, $228 = 0, $230 = 0, $231 = 0, $232 = 0, $233 = 0;
+ var $234 = 0, $235 = 0, $236 = 0, $238 = 0, $239$0 = 0, $239$1 = 0, $240 = 0, $241 = 0;
+ var $242 = 0, $243 = 0, $244 = 0, $_r1_sroa_0_0_load = 0, $245 = 0, $246 = 0, $247 = 0, $248 = 0;
+ var $249 = 0, $250 = 0, $251 = 0, $252 = 0, $253 = 0, $254 = 0, $255 = 0, $256 = 0;
+ var $258 = 0, $259 = 0, $260 = 0, $261 = 0, $262 = 0, $263 = 0, $264 = 0, $265 = 0;
+ var $266 = 0, $267 = 0, $269 = 0, $270 = 0, $271 = 0, $273 = 0, $274$0 = 0, $274$1 = 0;
+ var $275 = 0, $_r0_sroa_0_0_load617 = 0, $276 = 0, $277 = 0, $278 = 0, $279 = 0, $280 = 0, $281 = 0;
+ var $282 = 0, $284 = 0, $285 = 0, $286 = 0, $287 = 0, $288 = 0, $289 = 0, $290 = 0;
+ var $291 = 0, $_r5_sroa_0_0_load590 = 0, $293 = 0, $294 = 0, $296 = 0, $297 = 0, $_r0_sroa_0_0_load616 = 0, $298 = 0;
+ var $300 = 0, $302 = 0, $303 = 0, $305 = 0, $306 = 0, $307 = 0, $308 = 0, $_r0_sroa_0_0_load615 = 0;
+ var $309 = 0, $_r0_sroa_0_0_load614 = 0, $310 = 0, $311 = 0, $312 = 0, $314 = 0, $316 = 0, $317 = 0;
+ var $318 = 0, $321 = 0, $322 = 0, $323 = 0, $324 = 0, $326 = 0, $327 = 0, $328 = 0;
+ var $329 = 0, $330 = 0, $331 = 0, $332 = 0, $333 = 0, $335 = 0, $336 = 0, $337 = 0;
+ var $338 = 0, $339 = 0, $340 = 0, $341 = 0, $tib1_0_ph_i500 = 0, $342 = 0, $343 = 0, $344 = 0;
+ var $345 = 0, $tib1_0_lcssa_i503 = 0, $dimension_tib1_0_lcssa_i504 = 0, $346 = 0, $347 = 0, $348 = 0, $349 = 0, $350 = 0;
+ var $dimension_tib1_029_i506 = 0, $351 = 0, $352 = 0, $353 = 0, $354 = 0, $355 = 0, $356 = 0, $357 = 0;
+ var $358 = 0, $359 = 0, $dimension_tib2_024_i508 = 0, $360 = 0, $361 = 0, $362 = 0, $363 = 0, $364 = 0;
+ var $365 = 0, $366 = 0, $367 = 0, $tib2_0_lcssa_in_i510 = 0, $dimension_tib2_0_lcssa_i511 = 0, $tib2_0_lcssa_i512 = 0, $368 = 0, $369 = 0;
+ var $or_cond_i513 = 0, $tib1_121_i515 = 0, $370 = 0, $371 = 0, $372 = 0, $373 = 0, $i_0_i518 = 0, $375 = 0;
+ var $377 = 0, $378 = 0, $379 = 0, $380 = 0, $381 = 0, $383 = 0, $384 = 0, $385 = 0;
+ var $386 = 0, $387 = 0, $389 = 0, $390 = 0, $392 = 0, $393$0 = 0, $393$1 = 0, $394 = 0;
+ var $395 = 0, $396 = 0, $397 = 0, $398 = 0, $399 = 0, $400 = 0, $401 = 0, $402 = 0;
+ var $404 = 0, $405 = 0, $407 = 0, $408 = 0, $_r0_sroa_0_0_load613 = 0, $409 = 0, $410 = 0, $411 = 0;
+ var $412 = 0, $413 = 0, $414 = 0, $_r0_sroa_0_0_load612 = 0, $415 = 0, $_r5_sroa_0_0_load589 = 0, $416 = 0, $417 = 0;
+ var $_r0_sroa_0_0_load611 = 0, $418 = 0, $420 = 0, $421 = 0, $422 = 0, $424 = 0, $425$0 = 0, $425$1 = 0;
+ var $426 = 0, $427 = 0, $428 = 0, $429 = 0, $430 = 0, $431 = 0, $432 = 0, $433 = 0;
+ var $434 = 0, $_r0_sroa_0_0_load610 = 0, $436 = 0, $_r5_sroa_0_0_load588 = 0, $437 = 0, $439 = 0, $440 = 0, $441 = 0;
+ var $444 = 0, $445 = 0, $446 = 0, $447 = 0, $449 = 0, $450 = 0, $451 = 0, $452 = 0;
+ var $453 = 0, $454 = 0, $455 = 0, $456 = 0, $458 = 0, $459 = 0, $460 = 0, $461 = 0;
+ var $462 = 0, $463 = 0, $464 = 0, $tib1_0_ph_i479 = 0, $465 = 0, $466 = 0, $467 = 0, $468 = 0;
+ var $tib1_0_lcssa_i482 = 0, $dimension_tib1_0_lcssa_i483 = 0, $469 = 0, $470 = 0, $471 = 0, $472 = 0, $473 = 0, $dimension_tib1_029_i485 = 0;
+ var $474 = 0, $475 = 0, $476 = 0, $477 = 0, $478 = 0, $479 = 0, $480 = 0, $481 = 0;
+ var $482 = 0, $dimension_tib2_024_i487 = 0, $483 = 0, $484 = 0, $485 = 0, $486 = 0, $487 = 0, $488 = 0;
+ var $489 = 0, $490 = 0, $tib2_0_lcssa_in_i489 = 0, $dimension_tib2_0_lcssa_i490 = 0, $tib2_0_lcssa_i491 = 0, $491 = 0, $492 = 0, $or_cond_i492 = 0;
+ var $tib1_121_i494 = 0, $493 = 0, $494 = 0, $495 = 0, $496 = 0, $i_0_i497 = 0, $498 = 0, $500 = 0;
+ var $501 = 0, $502 = 0, $503 = 0, $504 = 0, $506 = 0, $507 = 0, $508 = 0, $509 = 0;
+ var $510 = 0, $512 = 0, $513 = 0, $516 = 0, $517 = 0, $519 = 0, $520$0 = 0, $520$1 = 0;
+ var $521 = 0, $522 = 0, $523 = 0, $525 = 0, $526 = 0, $527 = 0, $528 = 0, $529 = 0;
+ var $530 = 0, $531 = 0, $532 = 0, $_phi_trans_insert = 0, $_pre = 0, $534 = 0, $535 = 0, $536 = 0;
+ var $537 = 0, $538 = 0, $539 = 0, $540 = 0, $541 = 0, $_r2_sroa_0_0_load599 = 0, $542 = 0, $543 = 0;
+ var $544 = 0, $546 = 0, $547$0 = 0, $547$1 = 0, $548 = 0, $550 = 0, $551 = 0, $552 = 0;
+ var $555 = 0, $556 = 0, $557 = 0, $558 = 0, $560 = 0, $561 = 0, $562 = 0, $563 = 0;
+ var $564 = 0, $565 = 0, $566 = 0, $567 = 0, $569 = 0, $570 = 0, $571 = 0, $572 = 0;
+ var $573 = 0, $574 = 0, $575 = 0, $tib1_0_ph_i458 = 0, $576 = 0, $577 = 0, $578 = 0, $579 = 0;
+ var $tib1_0_lcssa_i461 = 0, $dimension_tib1_0_lcssa_i462 = 0, $580 = 0, $581 = 0, $582 = 0, $583 = 0, $584 = 0, $dimension_tib1_029_i464 = 0;
+ var $585 = 0, $586 = 0, $587 = 0, $588 = 0, $589 = 0, $590 = 0, $591 = 0, $592 = 0;
+ var $593 = 0, $dimension_tib2_024_i466 = 0, $594 = 0, $595 = 0, $596 = 0, $597 = 0, $598 = 0, $599 = 0;
+ var $600 = 0, $601 = 0, $tib2_0_lcssa_in_i468 = 0, $dimension_tib2_0_lcssa_i469 = 0, $tib2_0_lcssa_i470 = 0, $602 = 0, $603 = 0, $or_cond_i471 = 0;
+ var $tib1_121_i473 = 0, $604 = 0, $605 = 0, $606 = 0, $607 = 0, $i_0_i476 = 0, $609 = 0, $611 = 0;
+ var $612 = 0, $613 = 0, $614 = 0, $615 = 0, $617 = 0, $618 = 0, $619 = 0, $620 = 0;
+ var $621 = 0, $623 = 0, $624 = 0, $625 = 0, $626 = 0, $627 = 0, $628 = 0, $629 = 0;
+ var $630 = 0, $632 = 0, $633 = 0, $_r2_sroa_0_0_load598 = 0, $_r0_sroa_0_0_load609 = 0, $_r0_sroa_0_0_load624 = 0, $634 = 0, $_r0_sroa_1_4__r3_sroa_1_4_idx108_idx = 0;
+ var $_r0_sroa_1_4_idx = 0, $635 = 0, $637 = 0, $638 = 0, $639 = 0, $642 = 0, $643 = 0, $644 = 0;
+ var $645 = 0, $647 = 0, $648 = 0, $649 = 0, $650 = 0, $651 = 0, $652 = 0, $653 = 0;
+ var $654 = 0, $656 = 0, $657 = 0, $658 = 0, $659 = 0, $660 = 0, $661 = 0, $662 = 0;
+ var $tib1_0_ph_i437 = 0, $663 = 0, $664 = 0, $665 = 0, $666 = 0, $tib1_0_lcssa_i440 = 0, $dimension_tib1_0_lcssa_i441 = 0, $667 = 0;
+ var $668 = 0, $669 = 0, $670 = 0, $671 = 0, $dimension_tib1_029_i443 = 0, $672 = 0, $673 = 0, $674 = 0;
+ var $675 = 0, $676 = 0, $677 = 0, $678 = 0, $679 = 0, $680 = 0, $dimension_tib2_024_i445 = 0, $681 = 0;
+ var $682 = 0, $683 = 0, $684 = 0, $685 = 0, $686 = 0, $687 = 0, $688 = 0, $tib2_0_lcssa_in_i447 = 0;
+ var $dimension_tib2_0_lcssa_i448 = 0, $tib2_0_lcssa_i449 = 0, $689 = 0, $690 = 0, $or_cond_i450 = 0, $tib1_121_i452 = 0, $691 = 0, $692 = 0;
+ var $693 = 0, $694 = 0, $i_0_i455 = 0, $696 = 0, $698 = 0, $699 = 0, $700 = 0, $701 = 0;
+ var $702 = 0, $704 = 0, $705 = 0, $706 = 0, $707 = 0, $708 = 0, $711 = 0, $712 = 0;
+ var $714 = 0, $715 = 0, $716 = 0, $717 = 0, $718 = 0, $719 = 0, $720 = 0, $721 = 0;
+ var $723 = 0, $724 = 0, $725 = 0, $726 = 0, $727 = 0, $728 = 0, $729 = 0, $tib1_0_ph_i416 = 0;
+ var $730 = 0, $731 = 0, $732 = 0, $733 = 0, $tib1_0_lcssa_i419 = 0, $dimension_tib1_0_lcssa_i420 = 0, $734 = 0, $735 = 0;
+ var $736 = 0, $737 = 0, $738 = 0, $dimension_tib1_029_i422 = 0, $739 = 0, $740 = 0, $741 = 0, $742 = 0;
+ var $743 = 0, $744 = 0, $745 = 0, $746 = 0, $747 = 0, $dimension_tib2_024_i424 = 0, $748 = 0, $749 = 0;
+ var $750 = 0, $751 = 0, $752 = 0, $753 = 0, $754 = 0, $755 = 0, $tib2_0_lcssa_in_i426 = 0, $dimension_tib2_0_lcssa_i427 = 0;
+ var $tib2_0_lcssa_i428 = 0, $756 = 0, $757 = 0, $or_cond_i429 = 0, $tib1_121_i431 = 0, $758 = 0, $759 = 0, $760 = 0;
+ var $761 = 0, $i_0_i434 = 0, $763 = 0, $765 = 0, $766 = 0, $767 = 0, $768 = 0, $769 = 0;
+ var $771 = 0, $772 = 0, $773 = 0, $774 = 0, $775 = 0, $777 = 0, $778 = 0, $780 = 0;
+ var $781$0 = 0, $781$1 = 0, $782 = 0, $783 = 0, $784 = 0, $785 = 0, $786 = 0, $787 = 0;
+ var $788 = 0, $789 = 0, $790 = 0, $_r3_sroa_0_0_load596 = 0, $792 = 0, $793 = 0, $794 = 0, $795 = 0;
+ var $796 = 0, $797 = 0, $_r3_sroa_0_0_load595 = 0, $798 = 0, $799 = 0, $_r0_sroa_0_0_load608 = 0, $800 = 0, $802 = 0;
+ var $803 = 0, $804 = 0, $807 = 0, $808 = 0, $809 = 0, $810 = 0, $812 = 0, $813 = 0;
+ var $814 = 0, $815 = 0, $816 = 0, $817 = 0, $818 = 0, $819 = 0, $821 = 0, $822 = 0;
+ var $823 = 0, $824 = 0, $825 = 0, $826 = 0, $827 = 0, $tib1_0_ph_i395 = 0, $828 = 0, $829 = 0;
+ var $830 = 0, $831 = 0, $tib1_0_lcssa_i398 = 0, $dimension_tib1_0_lcssa_i399 = 0, $832 = 0, $833 = 0, $834 = 0, $835 = 0;
+ var $836 = 0, $dimension_tib1_029_i401 = 0, $837 = 0, $838 = 0, $839 = 0, $840 = 0, $841 = 0, $842 = 0;
+ var $843 = 0, $844 = 0, $845 = 0, $dimension_tib2_024_i403 = 0, $846 = 0, $847 = 0, $848 = 0, $849 = 0;
+ var $850 = 0, $851 = 0, $852 = 0, $853 = 0, $tib2_0_lcssa_in_i405 = 0, $dimension_tib2_0_lcssa_i406 = 0, $tib2_0_lcssa_i407 = 0, $854 = 0;
+ var $855 = 0, $or_cond_i408 = 0, $tib1_121_i410 = 0, $856 = 0, $857 = 0, $858 = 0, $859 = 0, $i_0_i413 = 0;
+ var $861 = 0, $863 = 0, $864 = 0, $865 = 0, $866 = 0, $867 = 0, $869 = 0, $870 = 0;
+ var $871 = 0, $872 = 0, $873 = 0, $876 = 0, $877 = 0, $879 = 0, $880 = 0, $881 = 0;
+ var $882 = 0, $883 = 0, $884 = 0, $885 = 0, $886 = 0, $888 = 0, $889 = 0, $890 = 0;
+ var $891 = 0, $892 = 0, $893 = 0, $894 = 0, $tib1_0_ph_i374 = 0, $895 = 0, $896 = 0, $897 = 0;
+ var $898 = 0, $tib1_0_lcssa_i377 = 0, $dimension_tib1_0_lcssa_i378 = 0, $899 = 0, $900 = 0, $901 = 0, $902 = 0, $903 = 0;
+ var $dimension_tib1_029_i380 = 0, $904 = 0, $905 = 0, $906 = 0, $907 = 0, $908 = 0, $909 = 0, $910 = 0;
+ var $911 = 0, $912 = 0, $dimension_tib2_024_i382 = 0, $913 = 0, $914 = 0, $915 = 0, $916 = 0, $917 = 0;
+ var $918 = 0, $919 = 0, $920 = 0, $tib2_0_lcssa_in_i384 = 0, $dimension_tib2_0_lcssa_i385 = 0, $tib2_0_lcssa_i386 = 0, $921 = 0, $922 = 0;
+ var $or_cond_i387 = 0, $tib1_121_i389 = 0, $923 = 0, $924 = 0, $925 = 0, $926 = 0, $i_0_i392 = 0, $928 = 0;
+ var $930 = 0, $931 = 0, $932 = 0, $933 = 0, $934 = 0, $936 = 0, $937 = 0, $938 = 0;
+ var $939 = 0, $940 = 0, $942 = 0, $943 = 0, $945 = 0, $946$0 = 0, $946$1 = 0, $947 = 0;
+ var $948 = 0, $949 = 0, $950 = 0, $951 = 0, $952 = 0, $953 = 0, $954 = 0, $955 = 0;
+ var $_r0_sroa_0_0_load607 = 0, $957 = 0, $958 = 0, $960 = 0, $962 = 0, $963 = 0, $964 = 0, $967 = 0;
+ var $968 = 0, $969 = 0, $970 = 0, $972 = 0, $973 = 0, $974 = 0, $975 = 0, $976 = 0;
+ var $977 = 0, $978 = 0, $979 = 0, $981 = 0, $982 = 0, $983 = 0, $984 = 0, $985 = 0;
+ var $986 = 0, $987 = 0, $tib1_0_ph_i353 = 0, $988 = 0, $989 = 0, $990 = 0, $991 = 0, $tib1_0_lcssa_i356 = 0;
+ var $dimension_tib1_0_lcssa_i357 = 0, $992 = 0, $993 = 0, $994 = 0, $995 = 0, $996 = 0, $dimension_tib1_029_i359 = 0, $997 = 0;
+ var $998 = 0, $999 = 0, $1000 = 0, $1001 = 0, $1002 = 0, $1003 = 0, $1004 = 0, $1005 = 0;
+ var $dimension_tib2_024_i361 = 0, $1006 = 0, $1007 = 0, $1008 = 0, $1009 = 0, $1010 = 0, $1011 = 0, $1012 = 0;
+ var $1013 = 0, $tib2_0_lcssa_in_i363 = 0, $dimension_tib2_0_lcssa_i364 = 0, $tib2_0_lcssa_i365 = 0, $1014 = 0, $1015 = 0, $or_cond_i366 = 0, $tib1_121_i368 = 0;
+ var $1016 = 0, $1017 = 0, $1018 = 0, $1019 = 0, $i_0_i371 = 0, $1021 = 0, $1023 = 0, $1024 = 0;
+ var $1025 = 0, $1026 = 0, $1027 = 0, $1029 = 0, $1030 = 0, $1031 = 0, $1032 = 0, $1033 = 0;
+ var $1036 = 0, $1037 = 0, $1038 = 0, $1039 = 0, $1040 = 0, $1041 = 0, $1042 = 0, $1043 = 0;
+ var $1045 = 0, $1046 = 0, $_pr = 0, $1048 = 0, $1050 = 0, $1051 = 0, $1053 = 0, $1054 = 0;
+ var $_pre855 = 0, $1056 = 0, $1057 = 0, $_r0_sroa_0_0_load606 = 0, $1058 = 0, $1060 = 0, $1061 = 0, $1062 = 0;
+ var $1064 = 0, $1065$0 = 0, $1065$1 = 0, $1066 = 0, $1067 = 0, $1068 = 0, $1069 = 0, $1070 = 0;
+ var $1071 = 0, $1072 = 0, $1073 = 0, $1074 = 0, $1077 = 0, $1078 = 0, $1079 = 0, $1082 = 0;
+ var $1083 = 0, $1084 = 0, $1085 = 0, $1087 = 0, $1088 = 0, $1089 = 0, $1090 = 0, $1091 = 0;
+ var $1092 = 0, $1093 = 0, $1094 = 0, $1096 = 0, $1097 = 0, $1098 = 0, $1099 = 0, $1100 = 0;
+ var $1101 = 0, $1102 = 0, $tib1_0_ph_i332 = 0, $1103 = 0, $1104 = 0, $1105 = 0, $1106 = 0, $tib1_0_lcssa_i335 = 0;
+ var $dimension_tib1_0_lcssa_i336 = 0, $1107 = 0, $1108 = 0, $1109 = 0, $1110 = 0, $1111 = 0, $dimension_tib1_029_i338 = 0, $1112 = 0;
+ var $1113 = 0, $1114 = 0, $1115 = 0, $1116 = 0, $1117 = 0, $1118 = 0, $1119 = 0, $1120 = 0;
+ var $dimension_tib2_024_i340 = 0, $1121 = 0, $1122 = 0, $1123 = 0, $1124 = 0, $1125 = 0, $1126 = 0, $1127 = 0;
+ var $1128 = 0, $tib2_0_lcssa_in_i342 = 0, $dimension_tib2_0_lcssa_i343 = 0, $tib2_0_lcssa_i344 = 0, $1129 = 0, $1130 = 0, $or_cond_i345 = 0, $tib1_121_i347 = 0;
+ var $1131 = 0, $1132 = 0, $1133 = 0, $1134 = 0, $i_0_i350 = 0, $1136 = 0, $1138 = 0, $1139 = 0;
+ var $1140 = 0, $1141 = 0, $1142 = 0, $1144 = 0, $1145 = 0, $1146 = 0, $1147 = 0, $1148 = 0;
+ var $1151 = 0, $1152 = 0, $1154 = 0, $1155 = 0, $1156 = 0, $1157 = 0, $1158 = 0, $1159 = 0;
+ var $1160 = 0, $1161 = 0, $1163 = 0, $1164 = 0, $1165 = 0, $1166 = 0, $1167 = 0, $1168 = 0;
+ var $1169 = 0, $tib1_0_ph_i311 = 0, $1170 = 0, $1171 = 0, $1172 = 0, $1173 = 0, $tib1_0_lcssa_i314 = 0, $dimension_tib1_0_lcssa_i315 = 0;
+ var $1174 = 0, $1175 = 0, $1176 = 0, $1177 = 0, $1178 = 0, $dimension_tib1_029_i317 = 0, $1179 = 0, $1180 = 0;
+ var $1181 = 0, $1182 = 0, $1183 = 0, $1184 = 0, $1185 = 0, $1186 = 0, $1187 = 0, $dimension_tib2_024_i319 = 0;
+ var $1188 = 0, $1189 = 0, $1190 = 0, $1191 = 0, $1192 = 0, $1193 = 0, $1194 = 0, $1195 = 0;
+ var $tib2_0_lcssa_in_i321 = 0, $dimension_tib2_0_lcssa_i322 = 0, $tib2_0_lcssa_i323 = 0, $1196 = 0, $1197 = 0, $or_cond_i324 = 0, $tib1_121_i326 = 0, $1198 = 0;
+ var $1199 = 0, $1200 = 0, $1201 = 0, $i_0_i329 = 0, $1203 = 0, $1205 = 0, $1206 = 0, $1207 = 0;
+ var $1208 = 0, $1209 = 0, $1211 = 0, $1212 = 0, $1213 = 0, $1214 = 0, $1215 = 0, $1217 = 0;
+ var $1218 = 0, $1220 = 0, $1221 = 0, $1222 = 0, $_r0_sroa_0_0_load605 = 0, $_r3_sroa_0_0_load594 = 0, $_r0_sroa_0_0_load623 = 0, $1223 = 0;
+ var $_r0_sroa_1_4__r3_sroa_1_4_idx_idx = 0, $_r0_sroa_1_4_idx156 = 0, $1224 = 0, $1226 = 0, $1227 = 0, $1228 = 0, $1231 = 0, $1232 = 0;
+ var $1233 = 0, $1234 = 0, $1236 = 0, $1237 = 0, $1238 = 0, $1239 = 0, $1240 = 0, $1241 = 0;
+ var $1242 = 0, $1243 = 0, $1245 = 0, $1246 = 0, $1247 = 0, $1248 = 0, $1249 = 0, $1250 = 0;
+ var $1251 = 0, $tib1_0_ph_i290 = 0, $1252 = 0, $1253 = 0, $1254 = 0, $1255 = 0, $tib1_0_lcssa_i293 = 0, $dimension_tib1_0_lcssa_i294 = 0;
+ var $1256 = 0, $1257 = 0, $1258 = 0, $1259 = 0, $1260 = 0, $dimension_tib1_029_i296 = 0, $1261 = 0, $1262 = 0;
+ var $1263 = 0, $1264 = 0, $1265 = 0, $1266 = 0, $1267 = 0, $1268 = 0, $1269 = 0, $dimension_tib2_024_i298 = 0;
+ var $1270 = 0, $1271 = 0, $1272 = 0, $1273 = 0, $1274 = 0, $1275 = 0, $1276 = 0, $1277 = 0;
+ var $tib2_0_lcssa_in_i300 = 0, $dimension_tib2_0_lcssa_i301 = 0, $tib2_0_lcssa_i302 = 0, $1278 = 0, $1279 = 0, $or_cond_i303 = 0, $tib1_121_i305 = 0, $1280 = 0;
+ var $1281 = 0, $1282 = 0, $1283 = 0, $i_0_i308 = 0, $1285 = 0, $1287 = 0, $1288 = 0, $1289 = 0;
+ var $1290 = 0, $1291 = 0, $1293 = 0, $1294 = 0, $1295 = 0, $1296 = 0, $1297 = 0, $1300 = 0;
+ var $1301 = 0, $1303 = 0, $1304 = 0, $1305 = 0, $1306 = 0, $1307 = 0, $1308 = 0, $1309 = 0;
+ var $1310 = 0, $1312 = 0, $1313 = 0, $1314 = 0, $1315 = 0, $1316 = 0, $1317 = 0, $1318 = 0;
+ var $tib1_0_ph_i269 = 0, $1319 = 0, $1320 = 0, $1321 = 0, $1322 = 0, $tib1_0_lcssa_i272 = 0, $dimension_tib1_0_lcssa_i273 = 0, $1323 = 0;
+ var $1324 = 0, $1325 = 0, $1326 = 0, $1327 = 0, $dimension_tib1_029_i275 = 0, $1328 = 0, $1329 = 0, $1330 = 0;
+ var $1331 = 0, $1332 = 0, $1333 = 0, $1334 = 0, $1335 = 0, $1336 = 0, $dimension_tib2_024_i277 = 0, $1337 = 0;
+ var $1338 = 0, $1339 = 0, $1340 = 0, $1341 = 0, $1342 = 0, $1343 = 0, $1344 = 0, $tib2_0_lcssa_in_i279 = 0;
+ var $dimension_tib2_0_lcssa_i280 = 0, $tib2_0_lcssa_i281 = 0, $1345 = 0, $1346 = 0, $or_cond_i282 = 0, $tib1_121_i284 = 0, $1347 = 0, $1348 = 0;
+ var $1349 = 0, $1350 = 0, $i_0_i287 = 0, $1352 = 0, $1354 = 0, $1355 = 0, $1356 = 0, $1357 = 0;
+ var $1358 = 0, $1360 = 0, $1361 = 0, $1362 = 0, $1363 = 0, $1364 = 0, $1366 = 0, $1367 = 0;
+ var $1369 = 0, $1370$0 = 0, $1370$1 = 0, $1371 = 0, $1372 = 0, $1373 = 0, $1374 = 0, $1375 = 0;
+ var $1376 = 0, $1377 = 0, $1378 = 0, $1379 = 0, $_r0_sroa_0_0_load604 = 0, $1381 = 0, $1382 = 0, $_r3_sroa_0_0_load593 = 0;
+ var $1384 = 0, $1385 = 0, $1386 = 0, $1387 = 0, $1388 = 0, $1389 = 0, $1390 = 0, $_r3_sroa_0_0_load = 0;
+ var $1391 = 0, $1392 = 0, $1394 = 0, $1395 = 0, $1396 = 0, $1399 = 0, $1400 = 0, $1401 = 0;
+ var $1402 = 0, $1404 = 0, $1405 = 0, $1406 = 0, $1407 = 0, $1408 = 0, $1409 = 0, $1410 = 0;
+ var $1411 = 0, $1413 = 0, $1414 = 0, $1415 = 0, $1416 = 0, $1417 = 0, $1418 = 0, $1419 = 0;
+ var $tib1_0_ph_i248 = 0, $1420 = 0, $1421 = 0, $1422 = 0, $1423 = 0, $tib1_0_lcssa_i251 = 0, $dimension_tib1_0_lcssa_i252 = 0, $1424 = 0;
+ var $1425 = 0, $1426 = 0, $1427 = 0, $1428 = 0, $dimension_tib1_029_i254 = 0, $1429 = 0, $1430 = 0, $1431 = 0;
+ var $1432 = 0, $1433 = 0, $1434 = 0, $1435 = 0, $1436 = 0, $1437 = 0, $dimension_tib2_024_i256 = 0, $1438 = 0;
+ var $1439 = 0, $1440 = 0, $1441 = 0, $1442 = 0, $1443 = 0, $1444 = 0, $1445 = 0, $tib2_0_lcssa_in_i258 = 0;
+ var $dimension_tib2_0_lcssa_i259 = 0, $tib2_0_lcssa_i260 = 0, $1446 = 0, $1447 = 0, $or_cond_i261 = 0, $tib1_121_i263 = 0, $1448 = 0, $1449 = 0;
+ var $1450 = 0, $1451 = 0, $i_0_i266 = 0, $1453 = 0, $1455 = 0, $1456 = 0, $1457 = 0, $1458 = 0;
+ var $1459 = 0, $1461 = 0, $1462 = 0, $1463 = 0, $1464 = 0, $1465 = 0, $1468 = 0, $1469 = 0;
+ var $1471 = 0, $1472 = 0, $1473 = 0, $1474 = 0, $1475 = 0, $1476 = 0, $1477 = 0, $1478 = 0;
+ var $1480 = 0, $1481 = 0, $1482 = 0, $1483 = 0, $1484 = 0, $1485 = 0, $1486 = 0, $tib1_0_ph_i227 = 0;
+ var $1487 = 0, $1488 = 0, $1489 = 0, $1490 = 0, $tib1_0_lcssa_i230 = 0, $dimension_tib1_0_lcssa_i231 = 0, $1491 = 0, $1492 = 0;
+ var $1493 = 0, $1494 = 0, $1495 = 0, $dimension_tib1_029_i233 = 0, $1496 = 0, $1497 = 0, $1498 = 0, $1499 = 0;
+ var $1500 = 0, $1501 = 0, $1502 = 0, $1503 = 0, $1504 = 0, $dimension_tib2_024_i235 = 0, $1505 = 0, $1506 = 0;
+ var $1507 = 0, $1508 = 0, $1509 = 0, $1510 = 0, $1511 = 0, $1512 = 0, $tib2_0_lcssa_in_i237 = 0, $dimension_tib2_0_lcssa_i238 = 0;
+ var $tib2_0_lcssa_i239 = 0, $1513 = 0, $1514 = 0, $or_cond_i240 = 0, $tib1_121_i242 = 0, $1515 = 0, $1516 = 0, $1517 = 0;
+ var $1518 = 0, $i_0_i245 = 0, $1520 = 0, $1522 = 0, $1523 = 0, $1524 = 0, $1525 = 0, $1526 = 0;
+ var $1528 = 0, $1529 = 0, $1530 = 0, $1531 = 0, $1532 = 0, $1533 = 0, $1534 = 0, $1536 = 0;
+ var $1537$0 = 0, $1537$1 = 0, $1538 = 0, $1539 = 0, $1540 = 0, $1541 = 0, $1542 = 0, $1543 = 0;
+ var $1544 = 0, $1545 = 0, $1546 = 0, $1548 = 0, $1549 = 0, $1551 = 0, $1552$0 = 0, $1552$1 = 0;
+ var $1553 = 0, $1554 = 0, $1555 = 0, $1556 = 0, $1557 = 0, $_r0_sroa_0_0_load602 = 0, $1558 = 0, $1559 = 0;
+ var $1561 = 0, $1563 = 0, $1564 = 0, $1565 = 0, $1568 = 0, $1569 = 0, $1570 = 0, $1571 = 0;
+ var $1573 = 0, $1574 = 0, $1575 = 0, $1576 = 0, $1577 = 0, $1578 = 0, $1579 = 0, $1580 = 0;
+ var $1582 = 0, $1583 = 0, $1584 = 0, $1585 = 0, $1586 = 0, $1587 = 0, $1588 = 0, $tib1_0_ph_i185 = 0;
+ var $1589 = 0, $1590 = 0, $1591 = 0, $1592 = 0, $tib1_0_lcssa_i188 = 0, $dimension_tib1_0_lcssa_i189 = 0, $1593 = 0, $1594 = 0;
+ var $1595 = 0, $1596 = 0, $1597 = 0, $dimension_tib1_029_i191 = 0, $1598 = 0, $1599 = 0, $1600 = 0, $1601 = 0;
+ var $1602 = 0, $1603 = 0, $1604 = 0, $1605 = 0, $1606 = 0, $dimension_tib2_024_i193 = 0, $1607 = 0, $1608 = 0;
+ var $1609 = 0, $1610 = 0, $1611 = 0, $1612 = 0, $1613 = 0, $1614 = 0, $tib2_0_lcssa_in_i195 = 0, $dimension_tib2_0_lcssa_i196 = 0;
+ var $tib2_0_lcssa_i197 = 0, $1615 = 0, $1616 = 0, $or_cond_i198 = 0, $tib1_121_i200 = 0, $1617 = 0, $1618 = 0, $1619 = 0;
+ var $1620 = 0, $i_0_i203 = 0, $1622 = 0, $1624 = 0, $1625 = 0, $1626 = 0, $1627 = 0, $1628 = 0;
+ var $1630 = 0, $1631 = 0, $1632 = 0, $1633 = 0, $1634 = 0, $1635 = 0, $1636 = 0, $1638 = 0;
+ var $1639$0 = 0, $1639$1 = 0, $1640 = 0, $1641 = 0, $1642 = 0, $1643 = 0, $1644 = 0, $1645 = 0;
+ var $1646 = 0, $1647 = 0, $1648 = 0, $1650 = 0, $1651 = 0, $1653 = 0, $1654$0 = 0, $1654$1 = 0;
+ var $1655 = 0, $1656 = 0, $1657 = 0, $1658 = 0, $1659 = 0, $_r2_sroa_0_0_load = 0, $1660 = 0, $1661 = 0;
+ var $1663 = 0, $1664 = 0, $1666 = 0, $1667$0 = 0, $1667$1 = 0, $1668 = 0, $_r0_sroa_0_0_load = 0, $1669 = 0;
+ var $1670 = 0, $1671 = 0, $1672 = 0, $1673 = 0, $1674 = 0, $1675 = 0, $1677 = 0, $1678 = 0;
+ var $1679 = 0, $1682 = 0, $1683 = 0, $1684 = 0, $1685 = 0, $1687 = 0, $1688 = 0, $1689 = 0;
+ var $1690 = 0, $1691 = 0, $1692 = 0, $1693 = 0, $1694 = 0, $1696 = 0, $1697 = 0, $1698 = 0;
+ var $1699 = 0, $1700 = 0, $1701 = 0, $1702 = 0, $tib1_0_ph_i = 0, $1703 = 0, $1704 = 0, $1705 = 0;
+ var $1706 = 0, $tib1_0_lcssa_i = 0, $dimension_tib1_0_lcssa_i = 0, $1707 = 0, $1708 = 0, $1709 = 0, $1710 = 0, $1711 = 0;
+ var $dimension_tib1_029_i = 0, $1712 = 0, $1713 = 0, $1714 = 0, $1715 = 0, $1716 = 0, $1717 = 0, $1718 = 0;
+ var $1719 = 0, $1720 = 0, $dimension_tib2_024_i = 0, $1721 = 0, $1722 = 0, $1723 = 0, $1724 = 0, $1725 = 0;
+ var $1726 = 0, $1727 = 0, $1728 = 0, $tib2_0_lcssa_in_i = 0, $dimension_tib2_0_lcssa_i = 0, $tib2_0_lcssa_i = 0, $1729 = 0, $1730 = 0;
+ var $or_cond_i = 0, $tib1_121_i = 0, $1731 = 0, $1732 = 0, $1733 = 0, $1734 = 0, $i_0_i = 0, $1736 = 0;
+ var $1738 = 0, $1739 = 0, $1740 = 0, $1741 = 0, $1742 = 0, $1744 = 0, $1745 = 0, $1746 = 0;
+ var $1747 = 0, $1748 = 0;
+ var label = 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 536 | 0;
+ label = 1;
+ var setjmpLabel = 0;
+ var setjmpTable = STACKTOP;
+ STACKTOP = STACKTOP + 168 | 0;
+ HEAP32[setjmpTable >> 2] = 0;
+ while (1) switch (label | 0) {
+ case 1:
+ $_r0_sroa_1 = __stackBase__ | 0;
+ $_r3_sroa_1 = __stackBase__ + 8 | 0;
+ $local_env_w4567aaac23b1b6 = __stackBase__ + 16 | 0;
+ $local_env_w4567aaac23b1c16 = __stackBase__ + 56 | 0;
+ $local_env_w4567aaac23b1c22 = __stackBase__ + 96 | 0;
+ $local_env_w4567aaac23b1c24 = __stackBase__ + 136 | 0;
+ $local_env_w4567aaac23b1c26 = __stackBase__ + 176 | 0;
+ $local_env_w4567aaac23b1c29 = __stackBase__ + 216 | 0;
+ $local_env_w4567aaac23b1c31 = __stackBase__ + 256 | 0;
+ $local_env_w4567aaac23b1c35 = __stackBase__ + 296 | 0;
+ $local_env_w4567aaac23b1c40 = __stackBase__ + 336 | 0;
+ $local_env_w4567aaac23b1c42 = __stackBase__ + 376 | 0;
+ $local_env_w4567aaac23b1c44 = __stackBase__ + 416 | 0;
+ $local_env_w4567aaac23b1c48 = __stackBase__ + 456 | 0;
+ $local_env_w4567aaac23b1c50 = __stackBase__ + 496 | 0;
+ $1 = HEAP32[(98772 | 0) >> 2] | 0;
+ $2 = ($1 | 0) == 0;
+ if ($2) {
+ label = 2;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 2:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 3;
+ break;
+ case 3:
+ $_r5_sroa_0 = $n1;
+ $5 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $6 = $5;
+ $_r0_sroa_0 = $6;
+ $7 = HEAP32[(98772 | 0) >> 2] | 0;
+ $8 = ($7 | 0) == 0;
+ if ($8) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 5;
+ break;
+ case 5:
+ $11 = HEAP32[136048 >> 2] | 0;
+ $_r1_sroa_0 = $11;
+ $_r1_sroa_0_0_load601 = $_r1_sroa_0;
+ $12 = invoke_ii(202, $_r1_sroa_0_0_load601 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $13 = HEAP32[(105500 | 0) >> 2] | 0;
+ $14 = ($13 | 0) == 0;
+ if ($14) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 7;
+ break;
+ case 7:
+ $16 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $17$0 = $16;
+ $17$1 = 0;
+ $18 = invoke_iii(364, $17$0 | 0, $17$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $19 = $local_env_w4567aaac23b1b6;
+ $20 = $18 + 16 | 0;
+ $21 = $20;
+ $22 = HEAP32[$21 >> 2] | 0;
+ _memcpy($19 | 0, $22 | 0, 40);
+ $23 = HEAP32[$21 >> 2] | 0;
+ $24 = $23;
+ $25 = _saveSetjmp($24 | 0, label, setjmpTable) | 0;
+ label = 413;
+ break;
+ case 413:
+ $26 = ($25 | 0) == 0;
+ if ($26) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $28 = HEAP32[(98772 | 0) >> 2] | 0;
+ $29 = ($28 | 0) == 0;
+ if ($29) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 10;
+ break;
+ case 10:
+ $31 = HEAP32[140056 >> 2] | 0;
+ $32 = $31;
+ $_r0_sroa_0 = $32;
+ $_r0_sroa_0_0_load622 = $_r0_sroa_0;
+ $33 = $_r0_sroa_0_0_load622;
+ $34 = $33 | 0;
+ $35 = HEAP32[$34 >> 2] | 0;
+ $36 = $35 + 160 | 0;
+ $37 = HEAP32[$36 >> 2] | 0;
+ $38 = $37;
+ $_r0_sroa_0_0_load621 = $_r0_sroa_0;
+ $39 = $_r0_sroa_0_0_load621;
+ $_r5_sroa_0_0_load592 = $_r5_sroa_0;
+ $40 = invoke_iii($38 | 0, $39 | 0, $_r5_sroa_0_0_load592 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $41 = $40;
+ $_r0_sroa_0 = $41;
+ $_r0_sroa_0_0_load620 = $_r0_sroa_0;
+ $_r0_sroa_0 = $_r0_sroa_0_0_load620;
+ $42 = HEAP32[$21 >> 2] | 0;
+ _memcpy($42 | 0, $19 | 0, 40);
+ $_r0_sroa_0_0_load619 = $_r0_sroa_0;
+ $43 = ($_r0_sroa_0_0_load619 | 0) == 0;
+ if ($43) {
+ label = 32;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 11:
+ $45 = HEAP32[$21 >> 2] | 0;
+ _memcpy($45 | 0, $19 | 0, 40);
+ $46 = HEAP32[(107740 | 0) >> 2] | 0;
+ $47 = ($46 | 0) == 0;
+ if ($47) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 13;
+ break;
+ case 13:
+ $50 = $18 + 20 | 0;
+ $51 = $50;
+ $52 = HEAP32[$51 >> 2] | 0;
+ $53 = ($52 | 0) == 0;
+ if ($53) {
+ label = 27;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $55 = HEAP32[137616 >> 2] | 0;
+ $56 = $52;
+ $57 = HEAP32[$56 >> 2] | 0;
+ $58 = $57;
+ $59 = $55 + 8 | 0;
+ $60 = $59;
+ $61 = HEAP32[$60 >> 2] | 0;
+ $62 = ($57 | 0) == 82712;
+ if ($62) {
+ label = 15;
+ break;
+ } else {
+ $tib1_0_ph_i543 = $58;
+ label = 16;
+ break;
+ }
+ case 15:
+ $64 = $52 + 8 | 0;
+ $65 = $64;
+ $66 = HEAP32[$65 >> 2] | 0;
+ $67 = $66 + 8 | 0;
+ $68 = $67;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $70 = $69;
+ $tib1_0_ph_i543 = $70;
+ label = 16;
+ break;
+ case 16:
+ $71 = $tib1_0_ph_i543 + 56 | 0;
+ $72 = HEAP32[$71 >> 2] | 0;
+ $73 = ($72 | 0) == 0;
+ if ($73) {
+ var $dimension_tib1_0_lcssa_i547 = 0;
+ var $tib1_0_lcssa_i546 = $tib1_0_ph_i543;
+ label = 18;
+ break;
+ } else {
+ var $dimension_tib1_029_i549 = 0;
+ var $79 = $72;
+ label = 19;
+ break;
+ }
+ case 17:
+ $74 = $82;
+ var $dimension_tib1_0_lcssa_i547 = $83;
+ var $tib1_0_lcssa_i546 = $74;
+ label = 18;
+ break;
+ case 18:
+ $75 = $61 + 56 | 0;
+ $76 = $75;
+ $77 = HEAP32[$76 >> 2] | 0;
+ $78 = ($77 | 0) == 0;
+ if ($78) {
+ var $dimension_tib2_0_lcssa_i554 = 0;
+ var $tib2_0_lcssa_in_i553 = $61;
+ label = 21;
+ break;
+ } else {
+ var $dimension_tib2_024_i551 = 0;
+ var $88 = $77;
+ label = 20;
+ break;
+ }
+ case 19:
+ $80 = $79 + 8 | 0;
+ $81 = $80;
+ $82 = HEAP32[$81 >> 2] | 0;
+ $83 = $dimension_tib1_029_i549 + 1 | 0;
+ $84 = $82 + 56 | 0;
+ $85 = $84;
+ $86 = HEAP32[$85 >> 2] | 0;
+ $87 = ($86 | 0) == 0;
+ if ($87) {
+ label = 17;
+ break;
+ } else {
+ var $dimension_tib1_029_i549 = $83;
+ var $79 = $86;
+ label = 19;
+ break;
+ }
+ case 20:
+ $89 = $88 + 8 | 0;
+ $90 = $89;
+ $91 = HEAP32[$90 >> 2] | 0;
+ $92 = $dimension_tib2_024_i551 + 1 | 0;
+ $93 = $91 + 56 | 0;
+ $94 = $93;
+ $95 = HEAP32[$94 >> 2] | 0;
+ $96 = ($95 | 0) == 0;
+ if ($96) {
+ var $dimension_tib2_0_lcssa_i554 = $92;
+ var $tib2_0_lcssa_in_i553 = $91;
+ label = 21;
+ break;
+ } else {
+ var $dimension_tib2_024_i551 = $92;
+ var $88 = $95;
+ label = 20;
+ break;
+ }
+ case 21:
+ $tib2_0_lcssa_i555 = $tib2_0_lcssa_in_i553;
+ $97 = ($dimension_tib1_0_lcssa_i547 | 0) < ($dimension_tib2_0_lcssa_i554 | 0);
+ $98 = ($tib1_0_lcssa_i546 | 0) == 0;
+ $or_cond_i556 = $97 | $98;
+ if ($or_cond_i556) {
+ label = 27;
+ break;
+ } else {
+ $tib1_121_i558 = $tib1_0_lcssa_i546;
+ label = 22;
+ break;
+ }
+ case 22:
+ $99 = ($tib1_121_i558 | 0) == ($tib2_0_lcssa_i555 | 0);
+ if ($99) {
+ label = 54;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $100 = $tib1_121_i558 + 108 | 0;
+ $101 = HEAP32[$100 >> 2] | 0;
+ $102 = $tib1_121_i558 + 112 | 0;
+ $i_0_i561 = 0;
+ label = 24;
+ break;
+ case 24:
+ $104 = ($i_0_i561 | 0) < ($101 | 0);
+ if ($104) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $106 = HEAP32[$102 >> 2] | 0;
+ $107 = $106 + ($i_0_i561 << 2) | 0;
+ $108 = HEAP32[$107 >> 2] | 0;
+ $109 = ($108 | 0) == ($tib2_0_lcssa_i555 | 0);
+ $110 = $i_0_i561 + 1 | 0;
+ if ($109) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i561 = $110;
+ label = 24;
+ break;
+ }
+ case 26:
+ $112 = $tib1_121_i558 + 40 | 0;
+ $113 = HEAP32[$112 >> 2] | 0;
+ $114 = ($113 | 0) == 0;
+ if ($114) {
+ label = 27;
+ break;
+ } else {
+ $tib1_121_i558 = $113;
+ label = 22;
+ break;
+ }
+ case 27:
+ $115 = HEAP32[$21 >> 2] | 0;
+ $116 = $115;
+ invoke_vii(48, $116 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 28:
+ $_r1_sroa_0_0_load600 = $_r1_sroa_0;
+ $118 = $_r1_sroa_0_0_load600 + 4 | 0;
+ $119 = $118;
+ $120 = HEAP32[$119 >> 2] | 0;
+ $121 = $120 + 8 | 0;
+ $122 = $121;
+ $123 = HEAP32[$122 >> 2] | 0;
+ $124 = $123 - 1 | 0;
+ HEAP32[$122 >> 2] = $124;
+ $125 = HEAP32[$119 >> 2] | 0;
+ $126 = $125 + 8 | 0;
+ $127 = $126;
+ $128 = HEAP32[$127 >> 2] | 0;
+ $129 = ($128 | 0) == 0;
+ if ($129) {
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ invoke_vi(28, $_r1_sroa_0_0_load600 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $131 = HEAP32[$119 >> 2] | 0;
+ $132 = $131 + 16 | 0;
+ $133 = $132;
+ $134 = HEAP32[$133 >> 2] | 0;
+ $135 = $134 + 8 | 0;
+ $136 = $135;
+ $137 = HEAP32[$136 >> 2] | 0;
+ $138 = $137;
+ $139;
+ $140 = ($139 | 0) == 0;
+ if ($140) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $142 = invoke_iii(268, 31e3 | 0 | 0, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $139, tempInt) | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 31;
+ break;
+ case 31:
+ $_r0_sroa_0_0_load618 = $_r0_sroa_0;
+ $143 = $_r0_sroa_0_0_load618;
+ STACKTOP = __stackBase__;
+ return $143 | 0;
+ case 32:
+ $_r5_sroa_0_0_load591 = $_r5_sroa_0;
+ $145 = ($_r5_sroa_0_0_load591 | 0) == 0;
+ $146 = HEAP32[(105500 | 0) >> 2] | 0;
+ $147 = ($146 | 0) == 0;
+ if ($147) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 34;
+ break;
+ case 34:
+ $149 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $150$0 = $149;
+ $150$1 = 0;
+ $151 = invoke_iii(364, $150$0 | 0, $150$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($145) {
+ label = 35;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 35:
+ $153 = $local_env_w4567aaac23b1c16;
+ $154 = $151 + 16 | 0;
+ $155 = $154;
+ $156 = HEAP32[$155 >> 2] | 0;
+ _memcpy($153 | 0, $156 | 0, 40);
+ $157 = HEAP32[$155 >> 2] | 0;
+ $158 = $157;
+ $159 = _saveSetjmp($158 | 0, label, setjmpTable) | 0;
+ label = 414;
+ break;
+ case 414:
+ $160 = ($159 | 0) == 0;
+ if ($160) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1457 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 37:
+ $163 = HEAP32[$155 >> 2] | 0;
+ _memcpy($163 | 0, $153 | 0, 40);
+ $164 = HEAP32[(107740 | 0) >> 2] | 0;
+ $165 = ($164 | 0) == 0;
+ if ($165) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 39;
+ break;
+ case 39:
+ $168 = $151 + 20 | 0;
+ $169 = $168;
+ $170 = HEAP32[$169 >> 2] | 0;
+ $171 = ($170 | 0) == 0;
+ if ($171) {
+ label = 53;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $173 = HEAP32[137616 >> 2] | 0;
+ $174 = $170;
+ $175 = HEAP32[$174 >> 2] | 0;
+ $176 = $175;
+ $177 = $173 + 8 | 0;
+ $178 = $177;
+ $179 = HEAP32[$178 >> 2] | 0;
+ $180 = ($175 | 0) == 82712;
+ if ($180) {
+ label = 41;
+ break;
+ } else {
+ $tib1_0_ph_i521 = $176;
+ label = 42;
+ break;
+ }
+ case 41:
+ $182 = $170 + 8 | 0;
+ $183 = $182;
+ $184 = HEAP32[$183 >> 2] | 0;
+ $185 = $184 + 8 | 0;
+ $186 = $185;
+ $187 = HEAP32[$186 >> 2] | 0;
+ $188 = $187;
+ $tib1_0_ph_i521 = $188;
+ label = 42;
+ break;
+ case 42:
+ $189 = $tib1_0_ph_i521 + 56 | 0;
+ $190 = HEAP32[$189 >> 2] | 0;
+ $191 = ($190 | 0) == 0;
+ if ($191) {
+ var $dimension_tib1_0_lcssa_i525 = 0;
+ var $tib1_0_lcssa_i524 = $tib1_0_ph_i521;
+ label = 44;
+ break;
+ } else {
+ var $dimension_tib1_029_i527 = 0;
+ var $197 = $190;
+ label = 45;
+ break;
+ }
+ case 43:
+ $192 = $200;
+ var $dimension_tib1_0_lcssa_i525 = $201;
+ var $tib1_0_lcssa_i524 = $192;
+ label = 44;
+ break;
+ case 44:
+ $193 = $179 + 56 | 0;
+ $194 = $193;
+ $195 = HEAP32[$194 >> 2] | 0;
+ $196 = ($195 | 0) == 0;
+ if ($196) {
+ var $dimension_tib2_0_lcssa_i532 = 0;
+ var $tib2_0_lcssa_in_i531 = $179;
+ label = 47;
+ break;
+ } else {
+ var $dimension_tib2_024_i529 = 0;
+ var $206 = $195;
+ label = 46;
+ break;
+ }
+ case 45:
+ $198 = $197 + 8 | 0;
+ $199 = $198;
+ $200 = HEAP32[$199 >> 2] | 0;
+ $201 = $dimension_tib1_029_i527 + 1 | 0;
+ $202 = $200 + 56 | 0;
+ $203 = $202;
+ $204 = HEAP32[$203 >> 2] | 0;
+ $205 = ($204 | 0) == 0;
+ if ($205) {
+ label = 43;
+ break;
+ } else {
+ var $dimension_tib1_029_i527 = $201;
+ var $197 = $204;
+ label = 45;
+ break;
+ }
+ case 46:
+ $207 = $206 + 8 | 0;
+ $208 = $207;
+ $209 = HEAP32[$208 >> 2] | 0;
+ $210 = $dimension_tib2_024_i529 + 1 | 0;
+ $211 = $209 + 56 | 0;
+ $212 = $211;
+ $213 = HEAP32[$212 >> 2] | 0;
+ $214 = ($213 | 0) == 0;
+ if ($214) {
+ var $dimension_tib2_0_lcssa_i532 = $210;
+ var $tib2_0_lcssa_in_i531 = $209;
+ label = 47;
+ break;
+ } else {
+ var $dimension_tib2_024_i529 = $210;
+ var $206 = $213;
+ label = 46;
+ break;
+ }
+ case 47:
+ $tib2_0_lcssa_i533 = $tib2_0_lcssa_in_i531;
+ $215 = ($dimension_tib1_0_lcssa_i525 | 0) < ($dimension_tib2_0_lcssa_i532 | 0);
+ $216 = ($tib1_0_lcssa_i524 | 0) == 0;
+ $or_cond_i534 = $215 | $216;
+ if ($or_cond_i534) {
+ label = 53;
+ break;
+ } else {
+ $tib1_121_i536 = $tib1_0_lcssa_i524;
+ label = 48;
+ break;
+ }
+ case 48:
+ $217 = ($tib1_121_i536 | 0) == ($tib2_0_lcssa_i533 | 0);
+ if ($217) {
+ label = 54;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $218 = $tib1_121_i536 + 108 | 0;
+ $219 = HEAP32[$218 >> 2] | 0;
+ $220 = $tib1_121_i536 + 112 | 0;
+ $i_0_i539 = 0;
+ label = 50;
+ break;
+ case 50:
+ $222 = ($i_0_i539 | 0) < ($219 | 0);
+ if ($222) {
+ label = 51;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 51:
+ $224 = HEAP32[$220 >> 2] | 0;
+ $225 = $224 + ($i_0_i539 << 2) | 0;
+ $226 = HEAP32[$225 >> 2] | 0;
+ $227 = ($226 | 0) == ($tib2_0_lcssa_i533 | 0);
+ $228 = $i_0_i539 + 1 | 0;
+ if ($227) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i539 = $228;
+ label = 50;
+ break;
+ }
+ case 52:
+ $230 = $tib1_121_i536 + 40 | 0;
+ $231 = HEAP32[$230 >> 2] | 0;
+ $232 = ($231 | 0) == 0;
+ if ($232) {
+ label = 53;
+ break;
+ } else {
+ $tib1_121_i536 = $231;
+ label = 48;
+ break;
+ }
+ case 53:
+ $233 = HEAP32[$155 >> 2] | 0;
+ $234 = $233;
+ invoke_vii(48, $234 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 54:
+ $235 = HEAP32[(105500 | 0) >> 2] | 0;
+ $236 = ($235 | 0) == 0;
+ if ($236) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 56;
+ break;
+ case 56:
+ $238 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $239$0 = $238;
+ $239$1 = 0;
+ $240 = invoke_iii(364, $239$0 | 0, $239$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $241 = $240 + 20 | 0;
+ $242 = $241;
+ $243 = HEAP32[$242 >> 2] | 0;
+ $244 = $243;
+ $_r0_sroa_0 = $244;
+ $_r1_sroa_0_0_load = $_r1_sroa_0;
+ $245 = $_r1_sroa_0_0_load + 4 | 0;
+ $246 = $245;
+ $247 = HEAP32[$246 >> 2] | 0;
+ $248 = $247 + 8 | 0;
+ $249 = $248;
+ $250 = HEAP32[$249 >> 2] | 0;
+ $251 = $250 - 1 | 0;
+ HEAP32[$249 >> 2] = $251;
+ $252 = HEAP32[$246 >> 2] | 0;
+ $253 = $252 + 8 | 0;
+ $254 = $253;
+ $255 = HEAP32[$254 >> 2] | 0;
+ $256 = ($255 | 0) == 0;
+ if ($256) {
+ label = 57;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 57:
+ invoke_vi(28, $_r1_sroa_0_0_load | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $258 = HEAP32[$246 >> 2] | 0;
+ $259 = $258 + 16 | 0;
+ $260 = $259;
+ $261 = HEAP32[$260 >> 2] | 0;
+ $262 = $261 + 8 | 0;
+ $263 = $262;
+ $264 = HEAP32[$263 >> 2] | 0;
+ $265 = $264;
+ $266;
+ $267 = ($266 | 0) == 0;
+ if ($267) {
+ label = 59;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $269 = invoke_iii(268, 31e3 | 0 | 0, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $266, tempInt) | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 59;
+ break;
+ case 59:
+ $270 = HEAP32[(105500 | 0) >> 2] | 0;
+ $271 = ($270 | 0) == 0;
+ if ($271) {
+ label = 60;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 60:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 61;
+ break;
+ case 61:
+ $273 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $274$0 = $273;
+ $274$1 = 0;
+ $275 = invoke_iii(364, $274$0 | 0, $274$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0_0_load617 = $_r0_sroa_0;
+ $276 = $_r0_sroa_0_0_load617;
+ $277 = $275 + 16 | 0;
+ $278 = $275 + 20 | 0;
+ $279 = $278;
+ HEAP32[$279 >> 2] = $276;
+ $280 = $277;
+ $281 = HEAP32[$280 >> 2] | 0;
+ $282 = $281;
+ invoke_vii(48, $282 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 62:
+ $284 = $local_env_w4567aaac23b1c22;
+ $285 = $151 + 16 | 0;
+ $286 = $285;
+ $287 = HEAP32[$286 >> 2] | 0;
+ _memcpy($284 | 0, $287 | 0, 40);
+ $288 = HEAP32[$286 >> 2] | 0;
+ $289 = $288;
+ $290 = _saveSetjmp($289 | 0, label, setjmpTable) | 0;
+ label = 415;
+ break;
+ case 415:
+ $291 = ($290 | 0) == 0;
+ if ($291) {
+ label = 63;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 63:
+ $_r5_sroa_0_0_load590 = $_r5_sroa_0;
+ invoke_vi(44, $_r5_sroa_0_0_load590 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $293 = HEAP32[(98772 | 0) >> 2] | 0;
+ $294 = ($293 | 0) == 0;
+ if ($294) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 65;
+ break;
+ case 65:
+ $296 = HEAP32[140064 >> 2] | 0;
+ $297 = $296;
+ $_r0_sroa_0 = $297;
+ $_r0_sroa_0_0_load616 = $_r0_sroa_0;
+ $298 = ($_r0_sroa_0_0_load616 | 0) == 0;
+ if ($298) {
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $300 = HEAP32[$286 >> 2] | 0;
+ _memcpy($300 | 0, $284 | 0, 40);
+ label = 89;
+ break;
+ case 67:
+ $302 = HEAP32[(84292 | 0) >> 2] | 0;
+ $303 = ($302 | 0) == 0;
+ if ($303) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ invoke_v(584);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 69;
+ break;
+ case 69:
+ $305 = invoke_ii(338, 20 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $306 = $305;
+ HEAP32[$306 >> 2] = 84288;
+ $307 = $305 + 4 | 0;
+ _memset($307 | 0 | 0, 0 | 0 | 0, 16 | 0 | 0);
+ $308 = $305;
+ $_r0_sroa_0 = $308;
+ $_r0_sroa_0_0_load615 = $_r0_sroa_0;
+ $309 = $_r0_sroa_0_0_load615;
+ invoke_vi(34, $309 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0_0_load614 = $_r0_sroa_0;
+ $310 = $_r0_sroa_0_0_load614;
+ $311 = HEAP32[(98772 | 0) >> 2] | 0;
+ $312 = ($311 | 0) == 0;
+ if ($312) {
+ label = 70;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 70:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 71;
+ break;
+ case 71:
+ HEAP32[140064 >> 2] = $310;
+ $314 = HEAP32[$286 >> 2] | 0;
+ _memcpy($314 | 0, $284 | 0, 40);
+ label = 89;
+ break;
+ case 72:
+ $316 = HEAP32[$286 >> 2] | 0;
+ _memcpy($316 | 0, $284 | 0, 40);
+ $317 = HEAP32[(107740 | 0) >> 2] | 0;
+ $318 = ($317 | 0) == 0;
+ if ($318) {
+ label = 73;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 73:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 74;
+ break;
+ case 74:
+ $321 = $151 + 20 | 0;
+ $322 = $321;
+ $323 = HEAP32[$322 >> 2] | 0;
+ $324 = ($323 | 0) == 0;
+ if ($324) {
+ label = 88;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $326 = HEAP32[137616 >> 2] | 0;
+ $327 = $323;
+ $328 = HEAP32[$327 >> 2] | 0;
+ $329 = $328;
+ $330 = $326 + 8 | 0;
+ $331 = $330;
+ $332 = HEAP32[$331 >> 2] | 0;
+ $333 = ($328 | 0) == 82712;
+ if ($333) {
+ label = 76;
+ break;
+ } else {
+ $tib1_0_ph_i500 = $329;
+ label = 77;
+ break;
+ }
+ case 76:
+ $335 = $323 + 8 | 0;
+ $336 = $335;
+ $337 = HEAP32[$336 >> 2] | 0;
+ $338 = $337 + 8 | 0;
+ $339 = $338;
+ $340 = HEAP32[$339 >> 2] | 0;
+ $341 = $340;
+ $tib1_0_ph_i500 = $341;
+ label = 77;
+ break;
+ case 77:
+ $342 = $tib1_0_ph_i500 + 56 | 0;
+ $343 = HEAP32[$342 >> 2] | 0;
+ $344 = ($343 | 0) == 0;
+ if ($344) {
+ var $dimension_tib1_0_lcssa_i504 = 0;
+ var $tib1_0_lcssa_i503 = $tib1_0_ph_i500;
+ label = 79;
+ break;
+ } else {
+ var $dimension_tib1_029_i506 = 0;
+ var $350 = $343;
+ label = 80;
+ break;
+ }
+ case 78:
+ $345 = $353;
+ var $dimension_tib1_0_lcssa_i504 = $354;
+ var $tib1_0_lcssa_i503 = $345;
+ label = 79;
+ break;
+ case 79:
+ $346 = $332 + 56 | 0;
+ $347 = $346;
+ $348 = HEAP32[$347 >> 2] | 0;
+ $349 = ($348 | 0) == 0;
+ if ($349) {
+ var $dimension_tib2_0_lcssa_i511 = 0;
+ var $tib2_0_lcssa_in_i510 = $332;
+ label = 82;
+ break;
+ } else {
+ var $dimension_tib2_024_i508 = 0;
+ var $359 = $348;
+ label = 81;
+ break;
+ }
+ case 80:
+ $351 = $350 + 8 | 0;
+ $352 = $351;
+ $353 = HEAP32[$352 >> 2] | 0;
+ $354 = $dimension_tib1_029_i506 + 1 | 0;
+ $355 = $353 + 56 | 0;
+ $356 = $355;
+ $357 = HEAP32[$356 >> 2] | 0;
+ $358 = ($357 | 0) == 0;
+ if ($358) {
+ label = 78;
+ break;
+ } else {
+ var $dimension_tib1_029_i506 = $354;
+ var $350 = $357;
+ label = 80;
+ break;
+ }
+ case 81:
+ $360 = $359 + 8 | 0;
+ $361 = $360;
+ $362 = HEAP32[$361 >> 2] | 0;
+ $363 = $dimension_tib2_024_i508 + 1 | 0;
+ $364 = $362 + 56 | 0;
+ $365 = $364;
+ $366 = HEAP32[$365 >> 2] | 0;
+ $367 = ($366 | 0) == 0;
+ if ($367) {
+ var $dimension_tib2_0_lcssa_i511 = $363;
+ var $tib2_0_lcssa_in_i510 = $362;
+ label = 82;
+ break;
+ } else {
+ var $dimension_tib2_024_i508 = $363;
+ var $359 = $366;
+ label = 81;
+ break;
+ }
+ case 82:
+ $tib2_0_lcssa_i512 = $tib2_0_lcssa_in_i510;
+ $368 = ($dimension_tib1_0_lcssa_i504 | 0) < ($dimension_tib2_0_lcssa_i511 | 0);
+ $369 = ($tib1_0_lcssa_i503 | 0) == 0;
+ $or_cond_i513 = $368 | $369;
+ if ($or_cond_i513) {
+ label = 88;
+ break;
+ } else {
+ $tib1_121_i515 = $tib1_0_lcssa_i503;
+ label = 83;
+ break;
+ }
+ case 83:
+ $370 = ($tib1_121_i515 | 0) == ($tib2_0_lcssa_i512 | 0);
+ if ($370) {
+ label = 54;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 84:
+ $371 = $tib1_121_i515 + 108 | 0;
+ $372 = HEAP32[$371 >> 2] | 0;
+ $373 = $tib1_121_i515 + 112 | 0;
+ $i_0_i518 = 0;
+ label = 85;
+ break;
+ case 85:
+ $375 = ($i_0_i518 | 0) < ($372 | 0);
+ if ($375) {
+ label = 86;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 86:
+ $377 = HEAP32[$373 >> 2] | 0;
+ $378 = $377 + ($i_0_i518 << 2) | 0;
+ $379 = HEAP32[$378 >> 2] | 0;
+ $380 = ($379 | 0) == ($tib2_0_lcssa_i512 | 0);
+ $381 = $i_0_i518 + 1 | 0;
+ if ($380) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i518 = $381;
+ label = 85;
+ break;
+ }
+ case 87:
+ $383 = $tib1_121_i515 + 40 | 0;
+ $384 = HEAP32[$383 >> 2] | 0;
+ $385 = ($384 | 0) == 0;
+ if ($385) {
+ label = 88;
+ break;
+ } else {
+ $tib1_121_i515 = $384;
+ label = 83;
+ break;
+ }
+ case 88:
+ $386 = HEAP32[$286 >> 2] | 0;
+ $387 = $386;
+ invoke_vii(48, $387 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 89:
+ $389 = HEAP32[(105500 | 0) >> 2] | 0;
+ $390 = ($389 | 0) == 0;
+ if ($390) {
+ label = 90;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 90:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 91;
+ break;
+ case 91:
+ $392 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $393$0 = $392;
+ $393$1 = 0;
+ $394 = invoke_iii(364, $393$0 | 0, $393$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $395 = $local_env_w4567aaac23b1c24;
+ $396 = $394 + 16 | 0;
+ $397 = $396;
+ $398 = HEAP32[$397 >> 2] | 0;
+ _memcpy($395 | 0, $398 | 0, 40);
+ $399 = HEAP32[$397 >> 2] | 0;
+ $400 = $399;
+ $401 = _saveSetjmp($400 | 0, label, setjmpTable) | 0;
+ label = 416;
+ break;
+ case 416:
+ $402 = ($401 | 0) == 0;
+ if ($402) {
+ label = 92;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 92:
+ $404 = HEAP32[(98772 | 0) >> 2] | 0;
+ $405 = ($404 | 0) == 0;
+ if ($405) {
+ label = 93;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 93:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 94;
+ break;
+ case 94:
+ $407 = HEAP32[140064 >> 2] | 0;
+ $408 = $407;
+ $_r0_sroa_0 = $408;
+ $_r0_sroa_0_0_load613 = $_r0_sroa_0;
+ $409 = $_r0_sroa_0_0_load613;
+ $410 = $409 | 0;
+ $411 = HEAP32[$410 >> 2] | 0;
+ $412 = $411 + 144 | 0;
+ $413 = HEAP32[$412 >> 2] | 0;
+ $414 = $413;
+ $_r0_sroa_0_0_load612 = $_r0_sroa_0;
+ $415 = $_r0_sroa_0_0_load612;
+ $_r5_sroa_0_0_load589 = $_r5_sroa_0;
+ $416 = invoke_iii($414 | 0, $415 | 0, $_r5_sroa_0_0_load589 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $417 = $416;
+ $_r0_sroa_0 = $417;
+ $_r0_sroa_0_0_load611 = $_r0_sroa_0;
+ $418 = ($_r0_sroa_0_0_load611 | 0) == 0;
+ if ($418) {
+ label = 95;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 95:
+ $420 = HEAP32[$397 >> 2] | 0;
+ _memcpy($420 | 0, $395 | 0, 40);
+ $421 = HEAP32[(105500 | 0) >> 2] | 0;
+ $422 = ($421 | 0) == 0;
+ if ($422) {
+ label = 96;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 96:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 97;
+ break;
+ case 97:
+ $424 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $425$0 = $424;
+ $425$1 = 0;
+ $426 = invoke_iii(364, $425$0 | 0, $425$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $427 = $local_env_w4567aaac23b1c26;
+ $428 = $426 + 16 | 0;
+ $429 = $428;
+ $430 = HEAP32[$429 >> 2] | 0;
+ _memcpy($427 | 0, $430 | 0, 40);
+ $431 = HEAP32[$429 >> 2] | 0;
+ $432 = $431;
+ $433 = _saveSetjmp($432 | 0, label, setjmpTable) | 0;
+ label = 417;
+ break;
+ case 417:
+ $434 = ($433 | 0) == 0;
+ if ($434) {
+ label = 116;
+ break;
+ } else {
+ label = 127;
+ break;
+ }
+ case 98:
+ $_r0_sroa_0_0_load610 = $_r0_sroa_0;
+ $436 = $_r0_sroa_0_0_load610;
+ $_r5_sroa_0_0_load588 = $_r5_sroa_0;
+ invoke_vii(24, $436 | 0, $_r5_sroa_0_0_load588 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $437 = HEAP32[$397 >> 2] | 0;
+ _memcpy($437 | 0, $395 | 0, 40);
+ label = 28;
+ break;
+ case 99:
+ $439 = HEAP32[$397 >> 2] | 0;
+ _memcpy($439 | 0, $395 | 0, 40);
+ $440 = HEAP32[(107740 | 0) >> 2] | 0;
+ $441 = ($440 | 0) == 0;
+ if ($441) {
+ label = 100;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 100:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 101;
+ break;
+ case 101:
+ $444 = $394 + 20 | 0;
+ $445 = $444;
+ $446 = HEAP32[$445 >> 2] | 0;
+ $447 = ($446 | 0) == 0;
+ if ($447) {
+ label = 115;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 102:
+ $449 = HEAP32[137616 >> 2] | 0;
+ $450 = $446;
+ $451 = HEAP32[$450 >> 2] | 0;
+ $452 = $451;
+ $453 = $449 + 8 | 0;
+ $454 = $453;
+ $455 = HEAP32[$454 >> 2] | 0;
+ $456 = ($451 | 0) == 82712;
+ if ($456) {
+ label = 103;
+ break;
+ } else {
+ $tib1_0_ph_i479 = $452;
+ label = 104;
+ break;
+ }
+ case 103:
+ $458 = $446 + 8 | 0;
+ $459 = $458;
+ $460 = HEAP32[$459 >> 2] | 0;
+ $461 = $460 + 8 | 0;
+ $462 = $461;
+ $463 = HEAP32[$462 >> 2] | 0;
+ $464 = $463;
+ $tib1_0_ph_i479 = $464;
+ label = 104;
+ break;
+ case 104:
+ $465 = $tib1_0_ph_i479 + 56 | 0;
+ $466 = HEAP32[$465 >> 2] | 0;
+ $467 = ($466 | 0) == 0;
+ if ($467) {
+ var $dimension_tib1_0_lcssa_i483 = 0;
+ var $tib1_0_lcssa_i482 = $tib1_0_ph_i479;
+ label = 106;
+ break;
+ } else {
+ var $dimension_tib1_029_i485 = 0;
+ var $473 = $466;
+ label = 107;
+ break;
+ }
+ case 105:
+ $468 = $476;
+ var $dimension_tib1_0_lcssa_i483 = $477;
+ var $tib1_0_lcssa_i482 = $468;
+ label = 106;
+ break;
+ case 106:
+ $469 = $455 + 56 | 0;
+ $470 = $469;
+ $471 = HEAP32[$470 >> 2] | 0;
+ $472 = ($471 | 0) == 0;
+ if ($472) {
+ var $dimension_tib2_0_lcssa_i490 = 0;
+ var $tib2_0_lcssa_in_i489 = $455;
+ label = 109;
+ break;
+ } else {
+ var $dimension_tib2_024_i487 = 0;
+ var $482 = $471;
+ label = 108;
+ break;
+ }
+ case 107:
+ $474 = $473 + 8 | 0;
+ $475 = $474;
+ $476 = HEAP32[$475 >> 2] | 0;
+ $477 = $dimension_tib1_029_i485 + 1 | 0;
+ $478 = $476 + 56 | 0;
+ $479 = $478;
+ $480 = HEAP32[$479 >> 2] | 0;
+ $481 = ($480 | 0) == 0;
+ if ($481) {
+ label = 105;
+ break;
+ } else {
+ var $dimension_tib1_029_i485 = $477;
+ var $473 = $480;
+ label = 107;
+ break;
+ }
+ case 108:
+ $483 = $482 + 8 | 0;
+ $484 = $483;
+ $485 = HEAP32[$484 >> 2] | 0;
+ $486 = $dimension_tib2_024_i487 + 1 | 0;
+ $487 = $485 + 56 | 0;
+ $488 = $487;
+ $489 = HEAP32[$488 >> 2] | 0;
+ $490 = ($489 | 0) == 0;
+ if ($490) {
+ var $dimension_tib2_0_lcssa_i490 = $486;
+ var $tib2_0_lcssa_in_i489 = $485;
+ label = 109;
+ break;
+ } else {
+ var $dimension_tib2_024_i487 = $486;
+ var $482 = $489;
+ label = 108;
+ break;
+ }
+ case 109:
+ $tib2_0_lcssa_i491 = $tib2_0_lcssa_in_i489;
+ $491 = ($dimension_tib1_0_lcssa_i483 | 0) < ($dimension_tib2_0_lcssa_i490 | 0);
+ $492 = ($tib1_0_lcssa_i482 | 0) == 0;
+ $or_cond_i492 = $491 | $492;
+ if ($or_cond_i492) {
+ label = 115;
+ break;
+ } else {
+ $tib1_121_i494 = $tib1_0_lcssa_i482;
+ label = 110;
+ break;
+ }
+ case 110:
+ $493 = ($tib1_121_i494 | 0) == ($tib2_0_lcssa_i491 | 0);
+ if ($493) {
+ label = 54;
+ break;
+ } else {
+ label = 111;
+ break;
+ }
+ case 111:
+ $494 = $tib1_121_i494 + 108 | 0;
+ $495 = HEAP32[$494 >> 2] | 0;
+ $496 = $tib1_121_i494 + 112 | 0;
+ $i_0_i497 = 0;
+ label = 112;
+ break;
+ case 112:
+ $498 = ($i_0_i497 | 0) < ($495 | 0);
+ if ($498) {
+ label = 113;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 113:
+ $500 = HEAP32[$496 >> 2] | 0;
+ $501 = $500 + ($i_0_i497 << 2) | 0;
+ $502 = HEAP32[$501 >> 2] | 0;
+ $503 = ($502 | 0) == ($tib2_0_lcssa_i491 | 0);
+ $504 = $i_0_i497 + 1 | 0;
+ if ($503) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i497 = $504;
+ label = 112;
+ break;
+ }
+ case 114:
+ $506 = $tib1_121_i494 + 40 | 0;
+ $507 = HEAP32[$506 >> 2] | 0;
+ $508 = ($507 | 0) == 0;
+ if ($508) {
+ label = 115;
+ break;
+ } else {
+ $tib1_121_i494 = $507;
+ label = 110;
+ break;
+ }
+ case 115:
+ $509 = HEAP32[$397 >> 2] | 0;
+ $510 = $509;
+ invoke_vii(48, $510 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 116:
+ $512 = HEAP32[(98772 | 0) >> 2] | 0;
+ $513 = ($512 | 0) == 0;
+ if ($513) {
+ label = 117;
+ break;
+ } else {
+ label = 118;
+ break;
+ }
+ case 117:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 118;
+ break;
+ case 118:
+ $516 = HEAP32[(105500 | 0) >> 2] | 0;
+ $517 = ($516 | 0) == 0;
+ if ($517) {
+ label = 119;
+ break;
+ } else {
+ label = 120;
+ break;
+ }
+ case 119:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 120;
+ break;
+ case 120:
+ $519 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $520$0 = $519;
+ $520$1 = 0;
+ $521 = invoke_iii(364, $520$0 | 0, $520$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $522 = HEAP32[(98148 | 0) >> 2] | 0;
+ $523 = ($522 | 0) == 0;
+ if ($523) {
+ label = 121;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 121:
+ invoke_v(408);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 122;
+ break;
+ case 122:
+ $525 = invoke_ii(338, 12 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $526 = $525;
+ HEAP32[$526 >> 2] = 98144;
+ $527 = $525 + 4 | 0;
+ $528 = $527;
+ HEAP32[$528 >> 2] = 0;
+ $529 = $525 + 8 | 0;
+ $530 = $529;
+ HEAP32[$530 >> 2] = $521;
+ $531 = HEAP32[(97532 | 0) >> 2] | 0;
+ $532 = ($531 | 0) == 0;
+ if ($532) {
+ label = 123;
+ break;
+ } else {
+ $534 = 98144;
+ label = 124;
+ break;
+ }
+ case 123:
+ invoke_v(568);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_phi_trans_insert = $525;
+ $_pre = HEAP32[$_phi_trans_insert >> 2] | 0;
+ $534 = $_pre;
+ label = 124;
+ break;
+ case 124:
+ $535 = $534 + 116 | 0;
+ $536 = HEAP32[$535 >> 2] | 0;
+ $537 = HEAP32[$536 >> 2] | 0;
+ $538 = $537;
+ $539 = invoke_ii($538 | 0, $525 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $540 = $539;
+ $_r2_sroa_0 = $540;
+ $541 = HEAP32[$429 >> 2] | 0;
+ _memcpy($541 | 0, $427 | 0, 40);
+ $_r2_sroa_0_0_load599 = $_r2_sroa_0;
+ $542 = ($_r2_sroa_0_0_load599 | 0) == 0;
+ $543 = HEAP32[(105500 | 0) >> 2] | 0;
+ $544 = ($543 | 0) == 0;
+ if ($544) {
+ label = 125;
+ break;
+ } else {
+ label = 126;
+ break;
+ }
+ case 125:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 126;
+ break;
+ case 126:
+ $546 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $547$0 = $546;
+ $547$1 = 0;
+ $548 = invoke_iii(364, $547$0 | 0, $547$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($542) {
+ label = 240;
+ break;
+ } else {
+ label = 144;
+ break;
+ }
+ case 127:
+ $550 = HEAP32[$429 >> 2] | 0;
+ _memcpy($550 | 0, $427 | 0, 40);
+ $551 = HEAP32[(107740 | 0) >> 2] | 0;
+ $552 = ($551 | 0) == 0;
+ if ($552) {
+ label = 128;
+ break;
+ } else {
+ label = 129;
+ break;
+ }
+ case 128:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 129;
+ break;
+ case 129:
+ $555 = $426 + 20 | 0;
+ $556 = $555;
+ $557 = HEAP32[$556 >> 2] | 0;
+ $558 = ($557 | 0) == 0;
+ if ($558) {
+ label = 143;
+ break;
+ } else {
+ label = 130;
+ break;
+ }
+ case 130:
+ $560 = HEAP32[137616 >> 2] | 0;
+ $561 = $557;
+ $562 = HEAP32[$561 >> 2] | 0;
+ $563 = $562;
+ $564 = $560 + 8 | 0;
+ $565 = $564;
+ $566 = HEAP32[$565 >> 2] | 0;
+ $567 = ($562 | 0) == 82712;
+ if ($567) {
+ label = 131;
+ break;
+ } else {
+ $tib1_0_ph_i458 = $563;
+ label = 132;
+ break;
+ }
+ case 131:
+ $569 = $557 + 8 | 0;
+ $570 = $569;
+ $571 = HEAP32[$570 >> 2] | 0;
+ $572 = $571 + 8 | 0;
+ $573 = $572;
+ $574 = HEAP32[$573 >> 2] | 0;
+ $575 = $574;
+ $tib1_0_ph_i458 = $575;
+ label = 132;
+ break;
+ case 132:
+ $576 = $tib1_0_ph_i458 + 56 | 0;
+ $577 = HEAP32[$576 >> 2] | 0;
+ $578 = ($577 | 0) == 0;
+ if ($578) {
+ var $dimension_tib1_0_lcssa_i462 = 0;
+ var $tib1_0_lcssa_i461 = $tib1_0_ph_i458;
+ label = 134;
+ break;
+ } else {
+ var $dimension_tib1_029_i464 = 0;
+ var $584 = $577;
+ label = 135;
+ break;
+ }
+ case 133:
+ $579 = $587;
+ var $dimension_tib1_0_lcssa_i462 = $588;
+ var $tib1_0_lcssa_i461 = $579;
+ label = 134;
+ break;
+ case 134:
+ $580 = $566 + 56 | 0;
+ $581 = $580;
+ $582 = HEAP32[$581 >> 2] | 0;
+ $583 = ($582 | 0) == 0;
+ if ($583) {
+ var $dimension_tib2_0_lcssa_i469 = 0;
+ var $tib2_0_lcssa_in_i468 = $566;
+ label = 137;
+ break;
+ } else {
+ var $dimension_tib2_024_i466 = 0;
+ var $593 = $582;
+ label = 136;
+ break;
+ }
+ case 135:
+ $585 = $584 + 8 | 0;
+ $586 = $585;
+ $587 = HEAP32[$586 >> 2] | 0;
+ $588 = $dimension_tib1_029_i464 + 1 | 0;
+ $589 = $587 + 56 | 0;
+ $590 = $589;
+ $591 = HEAP32[$590 >> 2] | 0;
+ $592 = ($591 | 0) == 0;
+ if ($592) {
+ label = 133;
+ break;
+ } else {
+ var $dimension_tib1_029_i464 = $588;
+ var $584 = $591;
+ label = 135;
+ break;
+ }
+ case 136:
+ $594 = $593 + 8 | 0;
+ $595 = $594;
+ $596 = HEAP32[$595 >> 2] | 0;
+ $597 = $dimension_tib2_024_i466 + 1 | 0;
+ $598 = $596 + 56 | 0;
+ $599 = $598;
+ $600 = HEAP32[$599 >> 2] | 0;
+ $601 = ($600 | 0) == 0;
+ if ($601) {
+ var $dimension_tib2_0_lcssa_i469 = $597;
+ var $tib2_0_lcssa_in_i468 = $596;
+ label = 137;
+ break;
+ } else {
+ var $dimension_tib2_024_i466 = $597;
+ var $593 = $600;
+ label = 136;
+ break;
+ }
+ case 137:
+ $tib2_0_lcssa_i470 = $tib2_0_lcssa_in_i468;
+ $602 = ($dimension_tib1_0_lcssa_i462 | 0) < ($dimension_tib2_0_lcssa_i469 | 0);
+ $603 = ($tib1_0_lcssa_i461 | 0) == 0;
+ $or_cond_i471 = $602 | $603;
+ if ($or_cond_i471) {
+ label = 143;
+ break;
+ } else {
+ $tib1_121_i473 = $tib1_0_lcssa_i461;
+ label = 138;
+ break;
+ }
+ case 138:
+ $604 = ($tib1_121_i473 | 0) == ($tib2_0_lcssa_i470 | 0);
+ if ($604) {
+ label = 54;
+ break;
+ } else {
+ label = 139;
+ break;
+ }
+ case 139:
+ $605 = $tib1_121_i473 + 108 | 0;
+ $606 = HEAP32[$605 >> 2] | 0;
+ $607 = $tib1_121_i473 + 112 | 0;
+ $i_0_i476 = 0;
+ label = 140;
+ break;
+ case 140:
+ $609 = ($i_0_i476 | 0) < ($606 | 0);
+ if ($609) {
+ label = 141;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 141:
+ $611 = HEAP32[$607 >> 2] | 0;
+ $612 = $611 + ($i_0_i476 << 2) | 0;
+ $613 = HEAP32[$612 >> 2] | 0;
+ $614 = ($613 | 0) == ($tib2_0_lcssa_i470 | 0);
+ $615 = $i_0_i476 + 1 | 0;
+ if ($614) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i476 = $615;
+ label = 140;
+ break;
+ }
+ case 142:
+ $617 = $tib1_121_i473 + 40 | 0;
+ $618 = HEAP32[$617 >> 2] | 0;
+ $619 = ($618 | 0) == 0;
+ if ($619) {
+ label = 143;
+ break;
+ } else {
+ $tib1_121_i473 = $618;
+ label = 138;
+ break;
+ }
+ case 143:
+ $620 = HEAP32[$429 >> 2] | 0;
+ $621 = $620;
+ invoke_vii(48, $621 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 144:
+ $623 = $local_env_w4567aaac23b1c29;
+ $624 = $548 + 16 | 0;
+ $625 = $624;
+ $626 = HEAP32[$625 >> 2] | 0;
+ _memcpy($623 | 0, $626 | 0, 40);
+ $627 = HEAP32[$625 >> 2] | 0;
+ $628 = $627;
+ $629 = _saveSetjmp($628 | 0, label, setjmpTable) | 0;
+ label = 418;
+ break;
+ case 418:
+ $630 = ($629 | 0) == 0;
+ if ($630) {
+ label = 145;
+ break;
+ } else {
+ label = 146;
+ break;
+ }
+ case 145:
+ $632 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $633 = $632;
+ $_r0_sroa_0 = $633;
+ $_r2_sroa_0_0_load598 = $_r2_sroa_0;
+ $_r0_sroa_0_0_load609 = $_r0_sroa_0;
+ $_r0_sroa_0 = 0;
+ $_r0_sroa_0_0_load624 = $_r0_sroa_0;
+ $634 = $_r0_sroa_0_0_load624;
+ $_r3_sroa_0 = $634;
+ $_r0_sroa_1_4__r3_sroa_1_4_idx108_idx = $_r3_sroa_1 | 0;
+ $_r0_sroa_1_4_idx = $_r0_sroa_1 | 0;
+ HEAP32[$_r0_sroa_1_4__r3_sroa_1_4_idx108_idx >> 2] = HEAP32[$_r0_sroa_1_4_idx >> 2] | 0;
+ $635 = HEAP32[$625 >> 2] | 0;
+ _memcpy($635 | 0, $623 | 0, 40);
+ label = 179;
+ break;
+ case 146:
+ $637 = HEAP32[$625 >> 2] | 0;
+ _memcpy($637 | 0, $623 | 0, 40);
+ $638 = HEAP32[(113236 | 0) >> 2] | 0;
+ $639 = ($638 | 0) == 0;
+ if ($639) {
+ label = 147;
+ break;
+ } else {
+ label = 148;
+ break;
+ }
+ case 147:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 148;
+ break;
+ case 148:
+ $642 = $548 + 20 | 0;
+ $643 = $642;
+ $644 = HEAP32[$643 >> 2] | 0;
+ $645 = ($644 | 0) == 0;
+ if ($645) {
+ label = 162;
+ break;
+ } else {
+ label = 149;
+ break;
+ }
+ case 149:
+ $647 = HEAP32[138672 >> 2] | 0;
+ $648 = $644;
+ $649 = HEAP32[$648 >> 2] | 0;
+ $650 = $649;
+ $651 = $647 + 8 | 0;
+ $652 = $651;
+ $653 = HEAP32[$652 >> 2] | 0;
+ $654 = ($649 | 0) == 82712;
+ if ($654) {
+ label = 150;
+ break;
+ } else {
+ $tib1_0_ph_i437 = $650;
+ label = 151;
+ break;
+ }
+ case 150:
+ $656 = $644 + 8 | 0;
+ $657 = $656;
+ $658 = HEAP32[$657 >> 2] | 0;
+ $659 = $658 + 8 | 0;
+ $660 = $659;
+ $661 = HEAP32[$660 >> 2] | 0;
+ $662 = $661;
+ $tib1_0_ph_i437 = $662;
+ label = 151;
+ break;
+ case 151:
+ $663 = $tib1_0_ph_i437 + 56 | 0;
+ $664 = HEAP32[$663 >> 2] | 0;
+ $665 = ($664 | 0) == 0;
+ if ($665) {
+ var $dimension_tib1_0_lcssa_i441 = 0;
+ var $tib1_0_lcssa_i440 = $tib1_0_ph_i437;
+ label = 153;
+ break;
+ } else {
+ var $dimension_tib1_029_i443 = 0;
+ var $671 = $664;
+ label = 154;
+ break;
+ }
+ case 152:
+ $666 = $674;
+ var $dimension_tib1_0_lcssa_i441 = $675;
+ var $tib1_0_lcssa_i440 = $666;
+ label = 153;
+ break;
+ case 153:
+ $667 = $653 + 56 | 0;
+ $668 = $667;
+ $669 = HEAP32[$668 >> 2] | 0;
+ $670 = ($669 | 0) == 0;
+ if ($670) {
+ var $dimension_tib2_0_lcssa_i448 = 0;
+ var $tib2_0_lcssa_in_i447 = $653;
+ label = 156;
+ break;
+ } else {
+ var $dimension_tib2_024_i445 = 0;
+ var $680 = $669;
+ label = 155;
+ break;
+ }
+ case 154:
+ $672 = $671 + 8 | 0;
+ $673 = $672;
+ $674 = HEAP32[$673 >> 2] | 0;
+ $675 = $dimension_tib1_029_i443 + 1 | 0;
+ $676 = $674 + 56 | 0;
+ $677 = $676;
+ $678 = HEAP32[$677 >> 2] | 0;
+ $679 = ($678 | 0) == 0;
+ if ($679) {
+ label = 152;
+ break;
+ } else {
+ var $dimension_tib1_029_i443 = $675;
+ var $671 = $678;
+ label = 154;
+ break;
+ }
+ case 155:
+ $681 = $680 + 8 | 0;
+ $682 = $681;
+ $683 = HEAP32[$682 >> 2] | 0;
+ $684 = $dimension_tib2_024_i445 + 1 | 0;
+ $685 = $683 + 56 | 0;
+ $686 = $685;
+ $687 = HEAP32[$686 >> 2] | 0;
+ $688 = ($687 | 0) == 0;
+ if ($688) {
+ var $dimension_tib2_0_lcssa_i448 = $684;
+ var $tib2_0_lcssa_in_i447 = $683;
+ label = 156;
+ break;
+ } else {
+ var $dimension_tib2_024_i445 = $684;
+ var $680 = $687;
+ label = 155;
+ break;
+ }
+ case 156:
+ $tib2_0_lcssa_i449 = $tib2_0_lcssa_in_i447;
+ $689 = ($dimension_tib1_0_lcssa_i441 | 0) < ($dimension_tib2_0_lcssa_i448 | 0);
+ $690 = ($tib1_0_lcssa_i440 | 0) == 0;
+ $or_cond_i450 = $689 | $690;
+ if ($or_cond_i450) {
+ label = 162;
+ break;
+ } else {
+ $tib1_121_i452 = $tib1_0_lcssa_i440;
+ label = 157;
+ break;
+ }
+ case 157:
+ $691 = ($tib1_121_i452 | 0) == ($tib2_0_lcssa_i449 | 0);
+ if ($691) {
+ label = 361;
+ break;
+ } else {
+ label = 158;
+ break;
+ }
+ case 158:
+ $692 = $tib1_121_i452 + 108 | 0;
+ $693 = HEAP32[$692 >> 2] | 0;
+ $694 = $tib1_121_i452 + 112 | 0;
+ $i_0_i455 = 0;
+ label = 159;
+ break;
+ case 159:
+ $696 = ($i_0_i455 | 0) < ($693 | 0);
+ if ($696) {
+ label = 160;
+ break;
+ } else {
+ label = 161;
+ break;
+ }
+ case 160:
+ $698 = HEAP32[$694 >> 2] | 0;
+ $699 = $698 + ($i_0_i455 << 2) | 0;
+ $700 = HEAP32[$699 >> 2] | 0;
+ $701 = ($700 | 0) == ($tib2_0_lcssa_i449 | 0);
+ $702 = $i_0_i455 + 1 | 0;
+ if ($701) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i455 = $702;
+ label = 159;
+ break;
+ }
+ case 161:
+ $704 = $tib1_121_i452 + 40 | 0;
+ $705 = HEAP32[$704 >> 2] | 0;
+ $706 = ($705 | 0) == 0;
+ if ($706) {
+ label = 162;
+ break;
+ } else {
+ $tib1_121_i452 = $705;
+ label = 157;
+ break;
+ }
+ case 162:
+ $707 = HEAP32[(107740 | 0) >> 2] | 0;
+ $708 = ($707 | 0) == 0;
+ if ($708) {
+ label = 163;
+ break;
+ } else {
+ label = 164;
+ break;
+ }
+ case 163:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 164;
+ break;
+ case 164:
+ $711 = HEAP32[$643 >> 2] | 0;
+ $712 = ($711 | 0) == 0;
+ if ($712) {
+ label = 178;
+ break;
+ } else {
+ label = 165;
+ break;
+ }
+ case 165:
+ $714 = HEAP32[137616 >> 2] | 0;
+ $715 = $711;
+ $716 = HEAP32[$715 >> 2] | 0;
+ $717 = $716;
+ $718 = $714 + 8 | 0;
+ $719 = $718;
+ $720 = HEAP32[$719 >> 2] | 0;
+ $721 = ($716 | 0) == 82712;
+ if ($721) {
+ label = 166;
+ break;
+ } else {
+ $tib1_0_ph_i416 = $717;
+ label = 167;
+ break;
+ }
+ case 166:
+ $723 = $711 + 8 | 0;
+ $724 = $723;
+ $725 = HEAP32[$724 >> 2] | 0;
+ $726 = $725 + 8 | 0;
+ $727 = $726;
+ $728 = HEAP32[$727 >> 2] | 0;
+ $729 = $728;
+ $tib1_0_ph_i416 = $729;
+ label = 167;
+ break;
+ case 167:
+ $730 = $tib1_0_ph_i416 + 56 | 0;
+ $731 = HEAP32[$730 >> 2] | 0;
+ $732 = ($731 | 0) == 0;
+ if ($732) {
+ var $dimension_tib1_0_lcssa_i420 = 0;
+ var $tib1_0_lcssa_i419 = $tib1_0_ph_i416;
+ label = 169;
+ break;
+ } else {
+ var $dimension_tib1_029_i422 = 0;
+ var $738 = $731;
+ label = 170;
+ break;
+ }
+ case 168:
+ $733 = $741;
+ var $dimension_tib1_0_lcssa_i420 = $742;
+ var $tib1_0_lcssa_i419 = $733;
+ label = 169;
+ break;
+ case 169:
+ $734 = $720 + 56 | 0;
+ $735 = $734;
+ $736 = HEAP32[$735 >> 2] | 0;
+ $737 = ($736 | 0) == 0;
+ if ($737) {
+ var $dimension_tib2_0_lcssa_i427 = 0;
+ var $tib2_0_lcssa_in_i426 = $720;
+ label = 172;
+ break;
+ } else {
+ var $dimension_tib2_024_i424 = 0;
+ var $747 = $736;
+ label = 171;
+ break;
+ }
+ case 170:
+ $739 = $738 + 8 | 0;
+ $740 = $739;
+ $741 = HEAP32[$740 >> 2] | 0;
+ $742 = $dimension_tib1_029_i422 + 1 | 0;
+ $743 = $741 + 56 | 0;
+ $744 = $743;
+ $745 = HEAP32[$744 >> 2] | 0;
+ $746 = ($745 | 0) == 0;
+ if ($746) {
+ label = 168;
+ break;
+ } else {
+ var $dimension_tib1_029_i422 = $742;
+ var $738 = $745;
+ label = 170;
+ break;
+ }
+ case 171:
+ $748 = $747 + 8 | 0;
+ $749 = $748;
+ $750 = HEAP32[$749 >> 2] | 0;
+ $751 = $dimension_tib2_024_i424 + 1 | 0;
+ $752 = $750 + 56 | 0;
+ $753 = $752;
+ $754 = HEAP32[$753 >> 2] | 0;
+ $755 = ($754 | 0) == 0;
+ if ($755) {
+ var $dimension_tib2_0_lcssa_i427 = $751;
+ var $tib2_0_lcssa_in_i426 = $750;
+ label = 172;
+ break;
+ } else {
+ var $dimension_tib2_024_i424 = $751;
+ var $747 = $754;
+ label = 171;
+ break;
+ }
+ case 172:
+ $tib2_0_lcssa_i428 = $tib2_0_lcssa_in_i426;
+ $756 = ($dimension_tib1_0_lcssa_i420 | 0) < ($dimension_tib2_0_lcssa_i427 | 0);
+ $757 = ($tib1_0_lcssa_i419 | 0) == 0;
+ $or_cond_i429 = $756 | $757;
+ if ($or_cond_i429) {
+ label = 178;
+ break;
+ } else {
+ $tib1_121_i431 = $tib1_0_lcssa_i419;
+ label = 173;
+ break;
+ }
+ case 173:
+ $758 = ($tib1_121_i431 | 0) == ($tib2_0_lcssa_i428 | 0);
+ if ($758) {
+ label = 386;
+ break;
+ } else {
+ label = 174;
+ break;
+ }
+ case 174:
+ $759 = $tib1_121_i431 + 108 | 0;
+ $760 = HEAP32[$759 >> 2] | 0;
+ $761 = $tib1_121_i431 + 112 | 0;
+ $i_0_i434 = 0;
+ label = 175;
+ break;
+ case 175:
+ $763 = ($i_0_i434 | 0) < ($760 | 0);
+ if ($763) {
+ label = 176;
+ break;
+ } else {
+ label = 177;
+ break;
+ }
+ case 176:
+ $765 = HEAP32[$761 >> 2] | 0;
+ $766 = $765 + ($i_0_i434 << 2) | 0;
+ $767 = HEAP32[$766 >> 2] | 0;
+ $768 = ($767 | 0) == ($tib2_0_lcssa_i428 | 0);
+ $769 = $i_0_i434 + 1 | 0;
+ if ($768) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i434 = $769;
+ label = 175;
+ break;
+ }
+ case 177:
+ $771 = $tib1_121_i431 + 40 | 0;
+ $772 = HEAP32[$771 >> 2] | 0;
+ $773 = ($772 | 0) == 0;
+ if ($773) {
+ label = 178;
+ break;
+ } else {
+ $tib1_121_i431 = $772;
+ label = 173;
+ break;
+ }
+ case 178:
+ $774 = HEAP32[$625 >> 2] | 0;
+ $775 = $774;
+ invoke_vii(48, $775 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 179:
+ $777 = HEAP32[(105500 | 0) >> 2] | 0;
+ $778 = ($777 | 0) == 0;
+ if ($778) {
+ label = 180;
+ break;
+ } else {
+ label = 181;
+ break;
+ }
+ case 180:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 181;
+ break;
+ case 181:
+ $780 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $781$0 = $780;
+ $781$1 = 0;
+ $782 = invoke_iii(364, $781$0 | 0, $781$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $783 = $local_env_w4567aaac23b1c31;
+ $784 = $782 + 16 | 0;
+ $785 = $784;
+ $786 = HEAP32[$785 >> 2] | 0;
+ _memcpy($783 | 0, $786 | 0, 40);
+ $787 = HEAP32[$785 >> 2] | 0;
+ $788 = $787;
+ $789 = _saveSetjmp($788 | 0, label, setjmpTable) | 0;
+ label = 419;
+ break;
+ case 419:
+ $790 = ($789 | 0) == 0;
+ if ($790) {
+ label = 182;
+ break;
+ } else {
+ label = 183;
+ break;
+ }
+ case 182:
+ $_r3_sroa_0_0_load596 = $_r3_sroa_0;
+ $792 = $_r3_sroa_0_0_load596;
+ $793 = HEAP32[$792 >> 2] | 0;
+ $794 = $793 + 116 | 0;
+ $795 = HEAP32[$794 >> 2] | 0;
+ $796 = HEAP32[$795 >> 2] | 0;
+ $797 = $796;
+ $_r3_sroa_0_0_load595 = $_r3_sroa_0;
+ $798 = invoke_ii($797 | 0, $_r3_sroa_0_0_load595 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0 = $798;
+ $799 = HEAP32[$785 >> 2] | 0;
+ _memcpy($799 | 0, $783 | 0, 40);
+ $_r0_sroa_0_0_load608 = $_r0_sroa_0;
+ $800 = ($_r0_sroa_0_0_load608 | 0) == 0;
+ if ($800) {
+ label = 216;
+ break;
+ } else {
+ label = 322;
+ break;
+ }
+ case 183:
+ $802 = HEAP32[$785 >> 2] | 0;
+ _memcpy($802 | 0, $783 | 0, 40);
+ $803 = HEAP32[(113236 | 0) >> 2] | 0;
+ $804 = ($803 | 0) == 0;
+ if ($804) {
+ label = 184;
+ break;
+ } else {
+ label = 185;
+ break;
+ }
+ case 184:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 185;
+ break;
+ case 185:
+ $807 = $782 + 20 | 0;
+ $808 = $807;
+ $809 = HEAP32[$808 >> 2] | 0;
+ $810 = ($809 | 0) == 0;
+ if ($810) {
+ label = 199;
+ break;
+ } else {
+ label = 186;
+ break;
+ }
+ case 186:
+ $812 = HEAP32[138672 >> 2] | 0;
+ $813 = $809;
+ $814 = HEAP32[$813 >> 2] | 0;
+ $815 = $814;
+ $816 = $812 + 8 | 0;
+ $817 = $816;
+ $818 = HEAP32[$817 >> 2] | 0;
+ $819 = ($814 | 0) == 82712;
+ if ($819) {
+ label = 187;
+ break;
+ } else {
+ $tib1_0_ph_i395 = $815;
+ label = 188;
+ break;
+ }
+ case 187:
+ $821 = $809 + 8 | 0;
+ $822 = $821;
+ $823 = HEAP32[$822 >> 2] | 0;
+ $824 = $823 + 8 | 0;
+ $825 = $824;
+ $826 = HEAP32[$825 >> 2] | 0;
+ $827 = $826;
+ $tib1_0_ph_i395 = $827;
+ label = 188;
+ break;
+ case 188:
+ $828 = $tib1_0_ph_i395 + 56 | 0;
+ $829 = HEAP32[$828 >> 2] | 0;
+ $830 = ($829 | 0) == 0;
+ if ($830) {
+ var $dimension_tib1_0_lcssa_i399 = 0;
+ var $tib1_0_lcssa_i398 = $tib1_0_ph_i395;
+ label = 190;
+ break;
+ } else {
+ var $dimension_tib1_029_i401 = 0;
+ var $836 = $829;
+ label = 191;
+ break;
+ }
+ case 189:
+ $831 = $839;
+ var $dimension_tib1_0_lcssa_i399 = $840;
+ var $tib1_0_lcssa_i398 = $831;
+ label = 190;
+ break;
+ case 190:
+ $832 = $818 + 56 | 0;
+ $833 = $832;
+ $834 = HEAP32[$833 >> 2] | 0;
+ $835 = ($834 | 0) == 0;
+ if ($835) {
+ var $dimension_tib2_0_lcssa_i406 = 0;
+ var $tib2_0_lcssa_in_i405 = $818;
+ label = 193;
+ break;
+ } else {
+ var $dimension_tib2_024_i403 = 0;
+ var $845 = $834;
+ label = 192;
+ break;
+ }
+ case 191:
+ $837 = $836 + 8 | 0;
+ $838 = $837;
+ $839 = HEAP32[$838 >> 2] | 0;
+ $840 = $dimension_tib1_029_i401 + 1 | 0;
+ $841 = $839 + 56 | 0;
+ $842 = $841;
+ $843 = HEAP32[$842 >> 2] | 0;
+ $844 = ($843 | 0) == 0;
+ if ($844) {
+ label = 189;
+ break;
+ } else {
+ var $dimension_tib1_029_i401 = $840;
+ var $836 = $843;
+ label = 191;
+ break;
+ }
+ case 192:
+ $846 = $845 + 8 | 0;
+ $847 = $846;
+ $848 = HEAP32[$847 >> 2] | 0;
+ $849 = $dimension_tib2_024_i403 + 1 | 0;
+ $850 = $848 + 56 | 0;
+ $851 = $850;
+ $852 = HEAP32[$851 >> 2] | 0;
+ $853 = ($852 | 0) == 0;
+ if ($853) {
+ var $dimension_tib2_0_lcssa_i406 = $849;
+ var $tib2_0_lcssa_in_i405 = $848;
+ label = 193;
+ break;
+ } else {
+ var $dimension_tib2_024_i403 = $849;
+ var $845 = $852;
+ label = 192;
+ break;
+ }
+ case 193:
+ $tib2_0_lcssa_i407 = $tib2_0_lcssa_in_i405;
+ $854 = ($dimension_tib1_0_lcssa_i399 | 0) < ($dimension_tib2_0_lcssa_i406 | 0);
+ $855 = ($tib1_0_lcssa_i398 | 0) == 0;
+ $or_cond_i408 = $854 | $855;
+ if ($or_cond_i408) {
+ label = 199;
+ break;
+ } else {
+ $tib1_121_i410 = $tib1_0_lcssa_i398;
+ label = 194;
+ break;
+ }
+ case 194:
+ $856 = ($tib1_121_i410 | 0) == ($tib2_0_lcssa_i407 | 0);
+ if ($856) {
+ label = 361;
+ break;
+ } else {
+ label = 195;
+ break;
+ }
+ case 195:
+ $857 = $tib1_121_i410 + 108 | 0;
+ $858 = HEAP32[$857 >> 2] | 0;
+ $859 = $tib1_121_i410 + 112 | 0;
+ $i_0_i413 = 0;
+ label = 196;
+ break;
+ case 196:
+ $861 = ($i_0_i413 | 0) < ($858 | 0);
+ if ($861) {
+ label = 197;
+ break;
+ } else {
+ label = 198;
+ break;
+ }
+ case 197:
+ $863 = HEAP32[$859 >> 2] | 0;
+ $864 = $863 + ($i_0_i413 << 2) | 0;
+ $865 = HEAP32[$864 >> 2] | 0;
+ $866 = ($865 | 0) == ($tib2_0_lcssa_i407 | 0);
+ $867 = $i_0_i413 + 1 | 0;
+ if ($866) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i413 = $867;
+ label = 196;
+ break;
+ }
+ case 198:
+ $869 = $tib1_121_i410 + 40 | 0;
+ $870 = HEAP32[$869 >> 2] | 0;
+ $871 = ($870 | 0) == 0;
+ if ($871) {
+ label = 199;
+ break;
+ } else {
+ $tib1_121_i410 = $870;
+ label = 194;
+ break;
+ }
+ case 199:
+ $872 = HEAP32[(107740 | 0) >> 2] | 0;
+ $873 = ($872 | 0) == 0;
+ if ($873) {
+ label = 200;
+ break;
+ } else {
+ label = 201;
+ break;
+ }
+ case 200:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 201;
+ break;
+ case 201:
+ $876 = HEAP32[$808 >> 2] | 0;
+ $877 = ($876 | 0) == 0;
+ if ($877) {
+ label = 215;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 202:
+ $879 = HEAP32[137616 >> 2] | 0;
+ $880 = $876;
+ $881 = HEAP32[$880 >> 2] | 0;
+ $882 = $881;
+ $883 = $879 + 8 | 0;
+ $884 = $883;
+ $885 = HEAP32[$884 >> 2] | 0;
+ $886 = ($881 | 0) == 82712;
+ if ($886) {
+ label = 203;
+ break;
+ } else {
+ $tib1_0_ph_i374 = $882;
+ label = 204;
+ break;
+ }
+ case 203:
+ $888 = $876 + 8 | 0;
+ $889 = $888;
+ $890 = HEAP32[$889 >> 2] | 0;
+ $891 = $890 + 8 | 0;
+ $892 = $891;
+ $893 = HEAP32[$892 >> 2] | 0;
+ $894 = $893;
+ $tib1_0_ph_i374 = $894;
+ label = 204;
+ break;
+ case 204:
+ $895 = $tib1_0_ph_i374 + 56 | 0;
+ $896 = HEAP32[$895 >> 2] | 0;
+ $897 = ($896 | 0) == 0;
+ if ($897) {
+ var $dimension_tib1_0_lcssa_i378 = 0;
+ var $tib1_0_lcssa_i377 = $tib1_0_ph_i374;
+ label = 206;
+ break;
+ } else {
+ var $dimension_tib1_029_i380 = 0;
+ var $903 = $896;
+ label = 207;
+ break;
+ }
+ case 205:
+ $898 = $906;
+ var $dimension_tib1_0_lcssa_i378 = $907;
+ var $tib1_0_lcssa_i377 = $898;
+ label = 206;
+ break;
+ case 206:
+ $899 = $885 + 56 | 0;
+ $900 = $899;
+ $901 = HEAP32[$900 >> 2] | 0;
+ $902 = ($901 | 0) == 0;
+ if ($902) {
+ var $dimension_tib2_0_lcssa_i385 = 0;
+ var $tib2_0_lcssa_in_i384 = $885;
+ label = 209;
+ break;
+ } else {
+ var $dimension_tib2_024_i382 = 0;
+ var $912 = $901;
+ label = 208;
+ break;
+ }
+ case 207:
+ $904 = $903 + 8 | 0;
+ $905 = $904;
+ $906 = HEAP32[$905 >> 2] | 0;
+ $907 = $dimension_tib1_029_i380 + 1 | 0;
+ $908 = $906 + 56 | 0;
+ $909 = $908;
+ $910 = HEAP32[$909 >> 2] | 0;
+ $911 = ($910 | 0) == 0;
+ if ($911) {
+ label = 205;
+ break;
+ } else {
+ var $dimension_tib1_029_i380 = $907;
+ var $903 = $910;
+ label = 207;
+ break;
+ }
+ case 208:
+ $913 = $912 + 8 | 0;
+ $914 = $913;
+ $915 = HEAP32[$914 >> 2] | 0;
+ $916 = $dimension_tib2_024_i382 + 1 | 0;
+ $917 = $915 + 56 | 0;
+ $918 = $917;
+ $919 = HEAP32[$918 >> 2] | 0;
+ $920 = ($919 | 0) == 0;
+ if ($920) {
+ var $dimension_tib2_0_lcssa_i385 = $916;
+ var $tib2_0_lcssa_in_i384 = $915;
+ label = 209;
+ break;
+ } else {
+ var $dimension_tib2_024_i382 = $916;
+ var $912 = $919;
+ label = 208;
+ break;
+ }
+ case 209:
+ $tib2_0_lcssa_i386 = $tib2_0_lcssa_in_i384;
+ $921 = ($dimension_tib1_0_lcssa_i378 | 0) < ($dimension_tib2_0_lcssa_i385 | 0);
+ $922 = ($tib1_0_lcssa_i377 | 0) == 0;
+ $or_cond_i387 = $921 | $922;
+ if ($or_cond_i387) {
+ label = 215;
+ break;
+ } else {
+ $tib1_121_i389 = $tib1_0_lcssa_i377;
+ label = 210;
+ break;
+ }
+ case 210:
+ $923 = ($tib1_121_i389 | 0) == ($tib2_0_lcssa_i386 | 0);
+ if ($923) {
+ label = 386;
+ break;
+ } else {
+ label = 211;
+ break;
+ }
+ case 211:
+ $924 = $tib1_121_i389 + 108 | 0;
+ $925 = HEAP32[$924 >> 2] | 0;
+ $926 = $tib1_121_i389 + 112 | 0;
+ $i_0_i392 = 0;
+ label = 212;
+ break;
+ case 212:
+ $928 = ($i_0_i392 | 0) < ($925 | 0);
+ if ($928) {
+ label = 213;
+ break;
+ } else {
+ label = 214;
+ break;
+ }
+ case 213:
+ $930 = HEAP32[$926 >> 2] | 0;
+ $931 = $930 + ($i_0_i392 << 2) | 0;
+ $932 = HEAP32[$931 >> 2] | 0;
+ $933 = ($932 | 0) == ($tib2_0_lcssa_i386 | 0);
+ $934 = $i_0_i392 + 1 | 0;
+ if ($933) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i392 = $934;
+ label = 212;
+ break;
+ }
+ case 214:
+ $936 = $tib1_121_i389 + 40 | 0;
+ $937 = HEAP32[$936 >> 2] | 0;
+ $938 = ($937 | 0) == 0;
+ if ($938) {
+ label = 215;
+ break;
+ } else {
+ $tib1_121_i389 = $937;
+ label = 210;
+ break;
+ }
+ case 215:
+ $939 = HEAP32[$785 >> 2] | 0;
+ $940 = $939;
+ invoke_vii(48, $940 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 216:
+ $_r0_sroa_0 = 0;
+ $942 = HEAP32[(105500 | 0) >> 2] | 0;
+ $943 = ($942 | 0) == 0;
+ if ($943) {
+ label = 217;
+ break;
+ } else {
+ label = 218;
+ break;
+ }
+ case 217:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 218;
+ break;
+ case 218:
+ $945 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $946$0 = $945;
+ $946$1 = 0;
+ $947 = invoke_iii(364, $946$0 | 0, $946$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $948 = $local_env_w4567aaac23b1c35;
+ $949 = $947 + 16 | 0;
+ $950 = $949;
+ $951 = HEAP32[$950 >> 2] | 0;
+ _memcpy($948 | 0, $951 | 0, 40);
+ $952 = HEAP32[$950 >> 2] | 0;
+ $953 = $952;
+ $954 = _saveSetjmp($953 | 0, label, setjmpTable) | 0;
+ label = 420;
+ break;
+ case 420:
+ $955 = ($954 | 0) == 0;
+ if ($955) {
+ label = 219;
+ break;
+ } else {
+ label = 222;
+ break;
+ }
+ case 219:
+ $_r0_sroa_0_0_load607 = $_r0_sroa_0;
+ $957 = HEAP32[(98772 | 0) >> 2] | 0;
+ $958 = ($957 | 0) == 0;
+ if ($958) {
+ label = 220;
+ break;
+ } else {
+ label = 221;
+ break;
+ }
+ case 220:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 221;
+ break;
+ case 221:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load607;
+ $960 = HEAP32[$950 >> 2] | 0;
+ _memcpy($960 | 0, $948 | 0, 40);
+ label = 239;
+ break;
+ case 222:
+ $962 = HEAP32[$950 >> 2] | 0;
+ _memcpy($962 | 0, $948 | 0, 40);
+ $963 = HEAP32[(107740 | 0) >> 2] | 0;
+ $964 = ($963 | 0) == 0;
+ if ($964) {
+ label = 223;
+ break;
+ } else {
+ label = 224;
+ break;
+ }
+ case 223:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 224;
+ break;
+ case 224:
+ $967 = $947 + 20 | 0;
+ $968 = $967;
+ $969 = HEAP32[$968 >> 2] | 0;
+ $970 = ($969 | 0) == 0;
+ if ($970) {
+ label = 238;
+ break;
+ } else {
+ label = 225;
+ break;
+ }
+ case 225:
+ $972 = HEAP32[137616 >> 2] | 0;
+ $973 = $969;
+ $974 = HEAP32[$973 >> 2] | 0;
+ $975 = $974;
+ $976 = $972 + 8 | 0;
+ $977 = $976;
+ $978 = HEAP32[$977 >> 2] | 0;
+ $979 = ($974 | 0) == 82712;
+ if ($979) {
+ label = 226;
+ break;
+ } else {
+ $tib1_0_ph_i353 = $975;
+ label = 227;
+ break;
+ }
+ case 226:
+ $981 = $969 + 8 | 0;
+ $982 = $981;
+ $983 = HEAP32[$982 >> 2] | 0;
+ $984 = $983 + 8 | 0;
+ $985 = $984;
+ $986 = HEAP32[$985 >> 2] | 0;
+ $987 = $986;
+ $tib1_0_ph_i353 = $987;
+ label = 227;
+ break;
+ case 227:
+ $988 = $tib1_0_ph_i353 + 56 | 0;
+ $989 = HEAP32[$988 >> 2] | 0;
+ $990 = ($989 | 0) == 0;
+ if ($990) {
+ var $dimension_tib1_0_lcssa_i357 = 0;
+ var $tib1_0_lcssa_i356 = $tib1_0_ph_i353;
+ label = 229;
+ break;
+ } else {
+ var $dimension_tib1_029_i359 = 0;
+ var $996 = $989;
+ label = 230;
+ break;
+ }
+ case 228:
+ $991 = $999;
+ var $dimension_tib1_0_lcssa_i357 = $1000;
+ var $tib1_0_lcssa_i356 = $991;
+ label = 229;
+ break;
+ case 229:
+ $992 = $978 + 56 | 0;
+ $993 = $992;
+ $994 = HEAP32[$993 >> 2] | 0;
+ $995 = ($994 | 0) == 0;
+ if ($995) {
+ var $dimension_tib2_0_lcssa_i364 = 0;
+ var $tib2_0_lcssa_in_i363 = $978;
+ label = 232;
+ break;
+ } else {
+ var $dimension_tib2_024_i361 = 0;
+ var $1005 = $994;
+ label = 231;
+ break;
+ }
+ case 230:
+ $997 = $996 + 8 | 0;
+ $998 = $997;
+ $999 = HEAP32[$998 >> 2] | 0;
+ $1000 = $dimension_tib1_029_i359 + 1 | 0;
+ $1001 = $999 + 56 | 0;
+ $1002 = $1001;
+ $1003 = HEAP32[$1002 >> 2] | 0;
+ $1004 = ($1003 | 0) == 0;
+ if ($1004) {
+ label = 228;
+ break;
+ } else {
+ var $dimension_tib1_029_i359 = $1000;
+ var $996 = $1003;
+ label = 230;
+ break;
+ }
+ case 231:
+ $1006 = $1005 + 8 | 0;
+ $1007 = $1006;
+ $1008 = HEAP32[$1007 >> 2] | 0;
+ $1009 = $dimension_tib2_024_i361 + 1 | 0;
+ $1010 = $1008 + 56 | 0;
+ $1011 = $1010;
+ $1012 = HEAP32[$1011 >> 2] | 0;
+ $1013 = ($1012 | 0) == 0;
+ if ($1013) {
+ var $dimension_tib2_0_lcssa_i364 = $1009;
+ var $tib2_0_lcssa_in_i363 = $1008;
+ label = 232;
+ break;
+ } else {
+ var $dimension_tib2_024_i361 = $1009;
+ var $1005 = $1012;
+ label = 231;
+ break;
+ }
+ case 232:
+ $tib2_0_lcssa_i365 = $tib2_0_lcssa_in_i363;
+ $1014 = ($dimension_tib1_0_lcssa_i357 | 0) < ($dimension_tib2_0_lcssa_i364 | 0);
+ $1015 = ($tib1_0_lcssa_i356 | 0) == 0;
+ $or_cond_i366 = $1014 | $1015;
+ if ($or_cond_i366) {
+ label = 238;
+ break;
+ } else {
+ $tib1_121_i368 = $tib1_0_lcssa_i356;
+ label = 233;
+ break;
+ }
+ case 233:
+ $1016 = ($tib1_121_i368 | 0) == ($tib2_0_lcssa_i365 | 0);
+ if ($1016) {
+ label = 54;
+ break;
+ } else {
+ label = 234;
+ break;
+ }
+ case 234:
+ $1017 = $tib1_121_i368 + 108 | 0;
+ $1018 = HEAP32[$1017 >> 2] | 0;
+ $1019 = $tib1_121_i368 + 112 | 0;
+ $i_0_i371 = 0;
+ label = 235;
+ break;
+ case 235:
+ $1021 = ($i_0_i371 | 0) < ($1018 | 0);
+ if ($1021) {
+ label = 236;
+ break;
+ } else {
+ label = 237;
+ break;
+ }
+ case 236:
+ $1023 = HEAP32[$1019 >> 2] | 0;
+ $1024 = $1023 + ($i_0_i371 << 2) | 0;
+ $1025 = HEAP32[$1024 >> 2] | 0;
+ $1026 = ($1025 | 0) == ($tib2_0_lcssa_i365 | 0);
+ $1027 = $i_0_i371 + 1 | 0;
+ if ($1026) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i371 = $1027;
+ label = 235;
+ break;
+ }
+ case 237:
+ $1029 = $tib1_121_i368 + 40 | 0;
+ $1030 = HEAP32[$1029 >> 2] | 0;
+ $1031 = ($1030 | 0) == 0;
+ if ($1031) {
+ label = 238;
+ break;
+ } else {
+ $tib1_121_i368 = $1030;
+ label = 233;
+ break;
+ }
+ case 238:
+ $1032 = HEAP32[$950 >> 2] | 0;
+ $1033 = $1032;
+ invoke_vii(48, $1033 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 239:
+ $_r0_sroa_0 = 0;
+ label = 28;
+ break;
+ case 240:
+ $1036 = $local_env_w4567aaac23b1c40;
+ $1037 = $548 + 16 | 0;
+ $1038 = $1037;
+ $1039 = HEAP32[$1038 >> 2] | 0;
+ _memcpy($1036 | 0, $1039 | 0, 40);
+ $1040 = HEAP32[$1038 >> 2] | 0;
+ $1041 = $1040;
+ $1042 = _saveSetjmp($1041 | 0, label, setjmpTable) | 0;
+ label = 421;
+ break;
+ case 421:
+ $1043 = ($1042 | 0) == 0;
+ if ($1043) {
+ label = 241;
+ break;
+ } else {
+ label = 253;
+ break;
+ }
+ case 241:
+ $1045 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1046 = ($1045 | 0) == 0;
+ if ($1046) {
+ label = 242;
+ break;
+ } else {
+ label = 244;
+ break;
+ }
+ case 242:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_pr = HEAP32[(98772 | 0) >> 2] | 0;
+ $1048 = ($_pr | 0) == 0;
+ if ($1048) {
+ label = 243;
+ break;
+ } else {
+ label = 244;
+ break;
+ }
+ case 243:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 244;
+ break;
+ case 244:
+ $1050 = HEAP32[140040 >> 2] | 0;
+ $1051 = ($1050 | 0) == 0;
+ if ($1051) {
+ label = 245;
+ break;
+ } else {
+ label = 246;
+ break;
+ }
+ case 245:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126768 | 0 | 0, 573 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 246:
+ $1053 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1054 = ($1053 | 0) == 0;
+ if ($1054) {
+ label = 247;
+ break;
+ } else {
+ $1056 = $1050;
+ label = 248;
+ break;
+ }
+ case 247:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_pre855 = HEAP32[140040 >> 2] | 0;
+ $1056 = $_pre855;
+ label = 248;
+ break;
+ case 248:
+ $1057 = $1056;
+ $_r0_sroa_0 = $1057;
+ $_r0_sroa_0_0_load606 = $_r0_sroa_0;
+ $1058 = ($_r0_sroa_0_0_load606 | 0) == 0;
+ if ($1058) {
+ label = 252;
+ break;
+ } else {
+ label = 249;
+ break;
+ }
+ case 249:
+ $1060 = HEAP32[$1038 >> 2] | 0;
+ _memcpy($1060 | 0, $1036 | 0, 40);
+ $1061 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1062 = ($1061 | 0) == 0;
+ if ($1062) {
+ label = 250;
+ break;
+ } else {
+ label = 251;
+ break;
+ }
+ case 250:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 251;
+ break;
+ case 251:
+ $1064 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1065$0 = $1064;
+ $1065$1 = 0;
+ $1066 = invoke_iii(364, $1065$0 | 0, $1065$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1067 = $local_env_w4567aaac23b1c42;
+ $1068 = $1066 + 16 | 0;
+ $1069 = $1068;
+ $1070 = HEAP32[$1069 >> 2] | 0;
+ _memcpy($1067 | 0, $1070 | 0, 40);
+ $1071 = HEAP32[$1069 >> 2] | 0;
+ $1072 = $1071;
+ $1073 = _saveSetjmp($1072 | 0, label, setjmpTable) | 0;
+ label = 422;
+ break;
+ case 422:
+ $1074 = ($1073 | 0) == 0;
+ if ($1074) {
+ label = 286;
+ break;
+ } else {
+ label = 289;
+ break;
+ }
+ case 252:
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1581 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 253:
+ $1077 = HEAP32[$1038 >> 2] | 0;
+ _memcpy($1077 | 0, $1036 | 0, 40);
+ $1078 = HEAP32[(113236 | 0) >> 2] | 0;
+ $1079 = ($1078 | 0) == 0;
+ if ($1079) {
+ label = 254;
+ break;
+ } else {
+ label = 255;
+ break;
+ }
+ case 254:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 255;
+ break;
+ case 255:
+ $1082 = $548 + 20 | 0;
+ $1083 = $1082;
+ $1084 = HEAP32[$1083 >> 2] | 0;
+ $1085 = ($1084 | 0) == 0;
+ if ($1085) {
+ label = 269;
+ break;
+ } else {
+ label = 256;
+ break;
+ }
+ case 256:
+ $1087 = HEAP32[138672 >> 2] | 0;
+ $1088 = $1084;
+ $1089 = HEAP32[$1088 >> 2] | 0;
+ $1090 = $1089;
+ $1091 = $1087 + 8 | 0;
+ $1092 = $1091;
+ $1093 = HEAP32[$1092 >> 2] | 0;
+ $1094 = ($1089 | 0) == 82712;
+ if ($1094) {
+ label = 257;
+ break;
+ } else {
+ $tib1_0_ph_i332 = $1090;
+ label = 258;
+ break;
+ }
+ case 257:
+ $1096 = $1084 + 8 | 0;
+ $1097 = $1096;
+ $1098 = HEAP32[$1097 >> 2] | 0;
+ $1099 = $1098 + 8 | 0;
+ $1100 = $1099;
+ $1101 = HEAP32[$1100 >> 2] | 0;
+ $1102 = $1101;
+ $tib1_0_ph_i332 = $1102;
+ label = 258;
+ break;
+ case 258:
+ $1103 = $tib1_0_ph_i332 + 56 | 0;
+ $1104 = HEAP32[$1103 >> 2] | 0;
+ $1105 = ($1104 | 0) == 0;
+ if ($1105) {
+ var $dimension_tib1_0_lcssa_i336 = 0;
+ var $tib1_0_lcssa_i335 = $tib1_0_ph_i332;
+ label = 260;
+ break;
+ } else {
+ var $dimension_tib1_029_i338 = 0;
+ var $1111 = $1104;
+ label = 261;
+ break;
+ }
+ case 259:
+ $1106 = $1114;
+ var $dimension_tib1_0_lcssa_i336 = $1115;
+ var $tib1_0_lcssa_i335 = $1106;
+ label = 260;
+ break;
+ case 260:
+ $1107 = $1093 + 56 | 0;
+ $1108 = $1107;
+ $1109 = HEAP32[$1108 >> 2] | 0;
+ $1110 = ($1109 | 0) == 0;
+ if ($1110) {
+ var $dimension_tib2_0_lcssa_i343 = 0;
+ var $tib2_0_lcssa_in_i342 = $1093;
+ label = 263;
+ break;
+ } else {
+ var $dimension_tib2_024_i340 = 0;
+ var $1120 = $1109;
+ label = 262;
+ break;
+ }
+ case 261:
+ $1112 = $1111 + 8 | 0;
+ $1113 = $1112;
+ $1114 = HEAP32[$1113 >> 2] | 0;
+ $1115 = $dimension_tib1_029_i338 + 1 | 0;
+ $1116 = $1114 + 56 | 0;
+ $1117 = $1116;
+ $1118 = HEAP32[$1117 >> 2] | 0;
+ $1119 = ($1118 | 0) == 0;
+ if ($1119) {
+ label = 259;
+ break;
+ } else {
+ var $dimension_tib1_029_i338 = $1115;
+ var $1111 = $1118;
+ label = 261;
+ break;
+ }
+ case 262:
+ $1121 = $1120 + 8 | 0;
+ $1122 = $1121;
+ $1123 = HEAP32[$1122 >> 2] | 0;
+ $1124 = $dimension_tib2_024_i340 + 1 | 0;
+ $1125 = $1123 + 56 | 0;
+ $1126 = $1125;
+ $1127 = HEAP32[$1126 >> 2] | 0;
+ $1128 = ($1127 | 0) == 0;
+ if ($1128) {
+ var $dimension_tib2_0_lcssa_i343 = $1124;
+ var $tib2_0_lcssa_in_i342 = $1123;
+ label = 263;
+ break;
+ } else {
+ var $dimension_tib2_024_i340 = $1124;
+ var $1120 = $1127;
+ label = 262;
+ break;
+ }
+ case 263:
+ $tib2_0_lcssa_i344 = $tib2_0_lcssa_in_i342;
+ $1129 = ($dimension_tib1_0_lcssa_i336 | 0) < ($dimension_tib2_0_lcssa_i343 | 0);
+ $1130 = ($tib1_0_lcssa_i335 | 0) == 0;
+ $or_cond_i345 = $1129 | $1130;
+ if ($or_cond_i345) {
+ label = 269;
+ break;
+ } else {
+ $tib1_121_i347 = $tib1_0_lcssa_i335;
+ label = 264;
+ break;
+ }
+ case 264:
+ $1131 = ($tib1_121_i347 | 0) == ($tib2_0_lcssa_i344 | 0);
+ if ($1131) {
+ label = 361;
+ break;
+ } else {
+ label = 265;
+ break;
+ }
+ case 265:
+ $1132 = $tib1_121_i347 + 108 | 0;
+ $1133 = HEAP32[$1132 >> 2] | 0;
+ $1134 = $tib1_121_i347 + 112 | 0;
+ $i_0_i350 = 0;
+ label = 266;
+ break;
+ case 266:
+ $1136 = ($i_0_i350 | 0) < ($1133 | 0);
+ if ($1136) {
+ label = 267;
+ break;
+ } else {
+ label = 268;
+ break;
+ }
+ case 267:
+ $1138 = HEAP32[$1134 >> 2] | 0;
+ $1139 = $1138 + ($i_0_i350 << 2) | 0;
+ $1140 = HEAP32[$1139 >> 2] | 0;
+ $1141 = ($1140 | 0) == ($tib2_0_lcssa_i344 | 0);
+ $1142 = $i_0_i350 + 1 | 0;
+ if ($1141) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i350 = $1142;
+ label = 266;
+ break;
+ }
+ case 268:
+ $1144 = $tib1_121_i347 + 40 | 0;
+ $1145 = HEAP32[$1144 >> 2] | 0;
+ $1146 = ($1145 | 0) == 0;
+ if ($1146) {
+ label = 269;
+ break;
+ } else {
+ $tib1_121_i347 = $1145;
+ label = 264;
+ break;
+ }
+ case 269:
+ $1147 = HEAP32[(107740 | 0) >> 2] | 0;
+ $1148 = ($1147 | 0) == 0;
+ if ($1148) {
+ label = 270;
+ break;
+ } else {
+ label = 271;
+ break;
+ }
+ case 270:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 271;
+ break;
+ case 271:
+ $1151 = HEAP32[$1083 >> 2] | 0;
+ $1152 = ($1151 | 0) == 0;
+ if ($1152) {
+ label = 285;
+ break;
+ } else {
+ label = 272;
+ break;
+ }
+ case 272:
+ $1154 = HEAP32[137616 >> 2] | 0;
+ $1155 = $1151;
+ $1156 = HEAP32[$1155 >> 2] | 0;
+ $1157 = $1156;
+ $1158 = $1154 + 8 | 0;
+ $1159 = $1158;
+ $1160 = HEAP32[$1159 >> 2] | 0;
+ $1161 = ($1156 | 0) == 82712;
+ if ($1161) {
+ label = 273;
+ break;
+ } else {
+ $tib1_0_ph_i311 = $1157;
+ label = 274;
+ break;
+ }
+ case 273:
+ $1163 = $1151 + 8 | 0;
+ $1164 = $1163;
+ $1165 = HEAP32[$1164 >> 2] | 0;
+ $1166 = $1165 + 8 | 0;
+ $1167 = $1166;
+ $1168 = HEAP32[$1167 >> 2] | 0;
+ $1169 = $1168;
+ $tib1_0_ph_i311 = $1169;
+ label = 274;
+ break;
+ case 274:
+ $1170 = $tib1_0_ph_i311 + 56 | 0;
+ $1171 = HEAP32[$1170 >> 2] | 0;
+ $1172 = ($1171 | 0) == 0;
+ if ($1172) {
+ var $dimension_tib1_0_lcssa_i315 = 0;
+ var $tib1_0_lcssa_i314 = $tib1_0_ph_i311;
+ label = 276;
+ break;
+ } else {
+ var $dimension_tib1_029_i317 = 0;
+ var $1178 = $1171;
+ label = 277;
+ break;
+ }
+ case 275:
+ $1173 = $1181;
+ var $dimension_tib1_0_lcssa_i315 = $1182;
+ var $tib1_0_lcssa_i314 = $1173;
+ label = 276;
+ break;
+ case 276:
+ $1174 = $1160 + 56 | 0;
+ $1175 = $1174;
+ $1176 = HEAP32[$1175 >> 2] | 0;
+ $1177 = ($1176 | 0) == 0;
+ if ($1177) {
+ var $dimension_tib2_0_lcssa_i322 = 0;
+ var $tib2_0_lcssa_in_i321 = $1160;
+ label = 279;
+ break;
+ } else {
+ var $dimension_tib2_024_i319 = 0;
+ var $1187 = $1176;
+ label = 278;
+ break;
+ }
+ case 277:
+ $1179 = $1178 + 8 | 0;
+ $1180 = $1179;
+ $1181 = HEAP32[$1180 >> 2] | 0;
+ $1182 = $dimension_tib1_029_i317 + 1 | 0;
+ $1183 = $1181 + 56 | 0;
+ $1184 = $1183;
+ $1185 = HEAP32[$1184 >> 2] | 0;
+ $1186 = ($1185 | 0) == 0;
+ if ($1186) {
+ label = 275;
+ break;
+ } else {
+ var $dimension_tib1_029_i317 = $1182;
+ var $1178 = $1185;
+ label = 277;
+ break;
+ }
+ case 278:
+ $1188 = $1187 + 8 | 0;
+ $1189 = $1188;
+ $1190 = HEAP32[$1189 >> 2] | 0;
+ $1191 = $dimension_tib2_024_i319 + 1 | 0;
+ $1192 = $1190 + 56 | 0;
+ $1193 = $1192;
+ $1194 = HEAP32[$1193 >> 2] | 0;
+ $1195 = ($1194 | 0) == 0;
+ if ($1195) {
+ var $dimension_tib2_0_lcssa_i322 = $1191;
+ var $tib2_0_lcssa_in_i321 = $1190;
+ label = 279;
+ break;
+ } else {
+ var $dimension_tib2_024_i319 = $1191;
+ var $1187 = $1194;
+ label = 278;
+ break;
+ }
+ case 279:
+ $tib2_0_lcssa_i323 = $tib2_0_lcssa_in_i321;
+ $1196 = ($dimension_tib1_0_lcssa_i315 | 0) < ($dimension_tib2_0_lcssa_i322 | 0);
+ $1197 = ($tib1_0_lcssa_i314 | 0) == 0;
+ $or_cond_i324 = $1196 | $1197;
+ if ($or_cond_i324) {
+ label = 285;
+ break;
+ } else {
+ $tib1_121_i326 = $tib1_0_lcssa_i314;
+ label = 280;
+ break;
+ }
+ case 280:
+ $1198 = ($tib1_121_i326 | 0) == ($tib2_0_lcssa_i323 | 0);
+ if ($1198) {
+ label = 386;
+ break;
+ } else {
+ label = 281;
+ break;
+ }
+ case 281:
+ $1199 = $tib1_121_i326 + 108 | 0;
+ $1200 = HEAP32[$1199 >> 2] | 0;
+ $1201 = $tib1_121_i326 + 112 | 0;
+ $i_0_i329 = 0;
+ label = 282;
+ break;
+ case 282:
+ $1203 = ($i_0_i329 | 0) < ($1200 | 0);
+ if ($1203) {
+ label = 283;
+ break;
+ } else {
+ label = 284;
+ break;
+ }
+ case 283:
+ $1205 = HEAP32[$1201 >> 2] | 0;
+ $1206 = $1205 + ($i_0_i329 << 2) | 0;
+ $1207 = HEAP32[$1206 >> 2] | 0;
+ $1208 = ($1207 | 0) == ($tib2_0_lcssa_i323 | 0);
+ $1209 = $i_0_i329 + 1 | 0;
+ if ($1208) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i329 = $1209;
+ label = 282;
+ break;
+ }
+ case 284:
+ $1211 = $tib1_121_i326 + 40 | 0;
+ $1212 = HEAP32[$1211 >> 2] | 0;
+ $1213 = ($1212 | 0) == 0;
+ if ($1213) {
+ label = 285;
+ break;
+ } else {
+ $tib1_121_i326 = $1212;
+ label = 280;
+ break;
+ }
+ case 285:
+ $1214 = HEAP32[$1038 >> 2] | 0;
+ $1215 = $1214;
+ invoke_vii(48, $1215 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 286:
+ $1217 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1218 = ($1217 | 0) == 0;
+ if ($1218) {
+ label = 287;
+ break;
+ } else {
+ label = 288;
+ break;
+ }
+ case 287:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 288;
+ break;
+ case 288:
+ $1220 = HEAP32[140040 >> 2] | 0;
+ $1221 = $1220;
+ $_r0_sroa_0 = $1221;
+ $1222 = invoke_ii(556, 709 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r3_sroa_0 = $1222;
+ $_r0_sroa_0_0_load605 = $_r0_sroa_0;
+ $_r3_sroa_0_0_load594 = $_r3_sroa_0;
+ $_r0_sroa_0 = 0;
+ $_r0_sroa_0_0_load623 = $_r0_sroa_0;
+ $1223 = $_r0_sroa_0_0_load623;
+ $_r3_sroa_0 = $1223;
+ $_r0_sroa_1_4__r3_sroa_1_4_idx_idx = $_r3_sroa_1 | 0;
+ $_r0_sroa_1_4_idx156 = $_r0_sroa_1 | 0;
+ HEAP32[$_r0_sroa_1_4__r3_sroa_1_4_idx_idx >> 2] = HEAP32[$_r0_sroa_1_4_idx156 >> 2] | 0;
+ $1224 = HEAP32[$1069 >> 2] | 0;
+ _memcpy($1224 | 0, $1067 | 0, 40);
+ label = 179;
+ break;
+ case 289:
+ $1226 = HEAP32[$1069 >> 2] | 0;
+ _memcpy($1226 | 0, $1067 | 0, 40);
+ $1227 = HEAP32[(113236 | 0) >> 2] | 0;
+ $1228 = ($1227 | 0) == 0;
+ if ($1228) {
+ label = 290;
+ break;
+ } else {
+ label = 291;
+ break;
+ }
+ case 290:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 291;
+ break;
+ case 291:
+ $1231 = $1066 + 20 | 0;
+ $1232 = $1231;
+ $1233 = HEAP32[$1232 >> 2] | 0;
+ $1234 = ($1233 | 0) == 0;
+ if ($1234) {
+ label = 305;
+ break;
+ } else {
+ label = 292;
+ break;
+ }
+ case 292:
+ $1236 = HEAP32[138672 >> 2] | 0;
+ $1237 = $1233;
+ $1238 = HEAP32[$1237 >> 2] | 0;
+ $1239 = $1238;
+ $1240 = $1236 + 8 | 0;
+ $1241 = $1240;
+ $1242 = HEAP32[$1241 >> 2] | 0;
+ $1243 = ($1238 | 0) == 82712;
+ if ($1243) {
+ label = 293;
+ break;
+ } else {
+ $tib1_0_ph_i290 = $1239;
+ label = 294;
+ break;
+ }
+ case 293:
+ $1245 = $1233 + 8 | 0;
+ $1246 = $1245;
+ $1247 = HEAP32[$1246 >> 2] | 0;
+ $1248 = $1247 + 8 | 0;
+ $1249 = $1248;
+ $1250 = HEAP32[$1249 >> 2] | 0;
+ $1251 = $1250;
+ $tib1_0_ph_i290 = $1251;
+ label = 294;
+ break;
+ case 294:
+ $1252 = $tib1_0_ph_i290 + 56 | 0;
+ $1253 = HEAP32[$1252 >> 2] | 0;
+ $1254 = ($1253 | 0) == 0;
+ if ($1254) {
+ var $dimension_tib1_0_lcssa_i294 = 0;
+ var $tib1_0_lcssa_i293 = $tib1_0_ph_i290;
+ label = 296;
+ break;
+ } else {
+ var $dimension_tib1_029_i296 = 0;
+ var $1260 = $1253;
+ label = 297;
+ break;
+ }
+ case 295:
+ $1255 = $1263;
+ var $dimension_tib1_0_lcssa_i294 = $1264;
+ var $tib1_0_lcssa_i293 = $1255;
+ label = 296;
+ break;
+ case 296:
+ $1256 = $1242 + 56 | 0;
+ $1257 = $1256;
+ $1258 = HEAP32[$1257 >> 2] | 0;
+ $1259 = ($1258 | 0) == 0;
+ if ($1259) {
+ var $dimension_tib2_0_lcssa_i301 = 0;
+ var $tib2_0_lcssa_in_i300 = $1242;
+ label = 299;
+ break;
+ } else {
+ var $dimension_tib2_024_i298 = 0;
+ var $1269 = $1258;
+ label = 298;
+ break;
+ }
+ case 297:
+ $1261 = $1260 + 8 | 0;
+ $1262 = $1261;
+ $1263 = HEAP32[$1262 >> 2] | 0;
+ $1264 = $dimension_tib1_029_i296 + 1 | 0;
+ $1265 = $1263 + 56 | 0;
+ $1266 = $1265;
+ $1267 = HEAP32[$1266 >> 2] | 0;
+ $1268 = ($1267 | 0) == 0;
+ if ($1268) {
+ label = 295;
+ break;
+ } else {
+ var $dimension_tib1_029_i296 = $1264;
+ var $1260 = $1267;
+ label = 297;
+ break;
+ }
+ case 298:
+ $1270 = $1269 + 8 | 0;
+ $1271 = $1270;
+ $1272 = HEAP32[$1271 >> 2] | 0;
+ $1273 = $dimension_tib2_024_i298 + 1 | 0;
+ $1274 = $1272 + 56 | 0;
+ $1275 = $1274;
+ $1276 = HEAP32[$1275 >> 2] | 0;
+ $1277 = ($1276 | 0) == 0;
+ if ($1277) {
+ var $dimension_tib2_0_lcssa_i301 = $1273;
+ var $tib2_0_lcssa_in_i300 = $1272;
+ label = 299;
+ break;
+ } else {
+ var $dimension_tib2_024_i298 = $1273;
+ var $1269 = $1276;
+ label = 298;
+ break;
+ }
+ case 299:
+ $tib2_0_lcssa_i302 = $tib2_0_lcssa_in_i300;
+ $1278 = ($dimension_tib1_0_lcssa_i294 | 0) < ($dimension_tib2_0_lcssa_i301 | 0);
+ $1279 = ($tib1_0_lcssa_i293 | 0) == 0;
+ $or_cond_i303 = $1278 | $1279;
+ if ($or_cond_i303) {
+ label = 305;
+ break;
+ } else {
+ $tib1_121_i305 = $tib1_0_lcssa_i293;
+ label = 300;
+ break;
+ }
+ case 300:
+ $1280 = ($tib1_121_i305 | 0) == ($tib2_0_lcssa_i302 | 0);
+ if ($1280) {
+ label = 361;
+ break;
+ } else {
+ label = 301;
+ break;
+ }
+ case 301:
+ $1281 = $tib1_121_i305 + 108 | 0;
+ $1282 = HEAP32[$1281 >> 2] | 0;
+ $1283 = $tib1_121_i305 + 112 | 0;
+ $i_0_i308 = 0;
+ label = 302;
+ break;
+ case 302:
+ $1285 = ($i_0_i308 | 0) < ($1282 | 0);
+ if ($1285) {
+ label = 303;
+ break;
+ } else {
+ label = 304;
+ break;
+ }
+ case 303:
+ $1287 = HEAP32[$1283 >> 2] | 0;
+ $1288 = $1287 + ($i_0_i308 << 2) | 0;
+ $1289 = HEAP32[$1288 >> 2] | 0;
+ $1290 = ($1289 | 0) == ($tib2_0_lcssa_i302 | 0);
+ $1291 = $i_0_i308 + 1 | 0;
+ if ($1290) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i308 = $1291;
+ label = 302;
+ break;
+ }
+ case 304:
+ $1293 = $tib1_121_i305 + 40 | 0;
+ $1294 = HEAP32[$1293 >> 2] | 0;
+ $1295 = ($1294 | 0) == 0;
+ if ($1295) {
+ label = 305;
+ break;
+ } else {
+ $tib1_121_i305 = $1294;
+ label = 300;
+ break;
+ }
+ case 305:
+ $1296 = HEAP32[(107740 | 0) >> 2] | 0;
+ $1297 = ($1296 | 0) == 0;
+ if ($1297) {
+ label = 306;
+ break;
+ } else {
+ label = 307;
+ break;
+ }
+ case 306:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 307;
+ break;
+ case 307:
+ $1300 = HEAP32[$1232 >> 2] | 0;
+ $1301 = ($1300 | 0) == 0;
+ if ($1301) {
+ label = 321;
+ break;
+ } else {
+ label = 308;
+ break;
+ }
+ case 308:
+ $1303 = HEAP32[137616 >> 2] | 0;
+ $1304 = $1300;
+ $1305 = HEAP32[$1304 >> 2] | 0;
+ $1306 = $1305;
+ $1307 = $1303 + 8 | 0;
+ $1308 = $1307;
+ $1309 = HEAP32[$1308 >> 2] | 0;
+ $1310 = ($1305 | 0) == 82712;
+ if ($1310) {
+ label = 309;
+ break;
+ } else {
+ $tib1_0_ph_i269 = $1306;
+ label = 310;
+ break;
+ }
+ case 309:
+ $1312 = $1300 + 8 | 0;
+ $1313 = $1312;
+ $1314 = HEAP32[$1313 >> 2] | 0;
+ $1315 = $1314 + 8 | 0;
+ $1316 = $1315;
+ $1317 = HEAP32[$1316 >> 2] | 0;
+ $1318 = $1317;
+ $tib1_0_ph_i269 = $1318;
+ label = 310;
+ break;
+ case 310:
+ $1319 = $tib1_0_ph_i269 + 56 | 0;
+ $1320 = HEAP32[$1319 >> 2] | 0;
+ $1321 = ($1320 | 0) == 0;
+ if ($1321) {
+ var $dimension_tib1_0_lcssa_i273 = 0;
+ var $tib1_0_lcssa_i272 = $tib1_0_ph_i269;
+ label = 312;
+ break;
+ } else {
+ var $dimension_tib1_029_i275 = 0;
+ var $1327 = $1320;
+ label = 313;
+ break;
+ }
+ case 311:
+ $1322 = $1330;
+ var $dimension_tib1_0_lcssa_i273 = $1331;
+ var $tib1_0_lcssa_i272 = $1322;
+ label = 312;
+ break;
+ case 312:
+ $1323 = $1309 + 56 | 0;
+ $1324 = $1323;
+ $1325 = HEAP32[$1324 >> 2] | 0;
+ $1326 = ($1325 | 0) == 0;
+ if ($1326) {
+ var $dimension_tib2_0_lcssa_i280 = 0;
+ var $tib2_0_lcssa_in_i279 = $1309;
+ label = 315;
+ break;
+ } else {
+ var $dimension_tib2_024_i277 = 0;
+ var $1336 = $1325;
+ label = 314;
+ break;
+ }
+ case 313:
+ $1328 = $1327 + 8 | 0;
+ $1329 = $1328;
+ $1330 = HEAP32[$1329 >> 2] | 0;
+ $1331 = $dimension_tib1_029_i275 + 1 | 0;
+ $1332 = $1330 + 56 | 0;
+ $1333 = $1332;
+ $1334 = HEAP32[$1333 >> 2] | 0;
+ $1335 = ($1334 | 0) == 0;
+ if ($1335) {
+ label = 311;
+ break;
+ } else {
+ var $dimension_tib1_029_i275 = $1331;
+ var $1327 = $1334;
+ label = 313;
+ break;
+ }
+ case 314:
+ $1337 = $1336 + 8 | 0;
+ $1338 = $1337;
+ $1339 = HEAP32[$1338 >> 2] | 0;
+ $1340 = $dimension_tib2_024_i277 + 1 | 0;
+ $1341 = $1339 + 56 | 0;
+ $1342 = $1341;
+ $1343 = HEAP32[$1342 >> 2] | 0;
+ $1344 = ($1343 | 0) == 0;
+ if ($1344) {
+ var $dimension_tib2_0_lcssa_i280 = $1340;
+ var $tib2_0_lcssa_in_i279 = $1339;
+ label = 315;
+ break;
+ } else {
+ var $dimension_tib2_024_i277 = $1340;
+ var $1336 = $1343;
+ label = 314;
+ break;
+ }
+ case 315:
+ $tib2_0_lcssa_i281 = $tib2_0_lcssa_in_i279;
+ $1345 = ($dimension_tib1_0_lcssa_i273 | 0) < ($dimension_tib2_0_lcssa_i280 | 0);
+ $1346 = ($tib1_0_lcssa_i272 | 0) == 0;
+ $or_cond_i282 = $1345 | $1346;
+ if ($or_cond_i282) {
+ label = 321;
+ break;
+ } else {
+ $tib1_121_i284 = $tib1_0_lcssa_i272;
+ label = 316;
+ break;
+ }
+ case 316:
+ $1347 = ($tib1_121_i284 | 0) == ($tib2_0_lcssa_i281 | 0);
+ if ($1347) {
+ label = 386;
+ break;
+ } else {
+ label = 317;
+ break;
+ }
+ case 317:
+ $1348 = $tib1_121_i284 + 108 | 0;
+ $1349 = HEAP32[$1348 >> 2] | 0;
+ $1350 = $tib1_121_i284 + 112 | 0;
+ $i_0_i287 = 0;
+ label = 318;
+ break;
+ case 318:
+ $1352 = ($i_0_i287 | 0) < ($1349 | 0);
+ if ($1352) {
+ label = 319;
+ break;
+ } else {
+ label = 320;
+ break;
+ }
+ case 319:
+ $1354 = HEAP32[$1350 >> 2] | 0;
+ $1355 = $1354 + ($i_0_i287 << 2) | 0;
+ $1356 = HEAP32[$1355 >> 2] | 0;
+ $1357 = ($1356 | 0) == ($tib2_0_lcssa_i281 | 0);
+ $1358 = $i_0_i287 + 1 | 0;
+ if ($1357) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i287 = $1358;
+ label = 318;
+ break;
+ }
+ case 320:
+ $1360 = $tib1_121_i284 + 40 | 0;
+ $1361 = HEAP32[$1360 >> 2] | 0;
+ $1362 = ($1361 | 0) == 0;
+ if ($1362) {
+ label = 321;
+ break;
+ } else {
+ $tib1_121_i284 = $1361;
+ label = 316;
+ break;
+ }
+ case 321:
+ $1363 = HEAP32[$1069 >> 2] | 0;
+ $1364 = $1363;
+ invoke_vii(48, $1364 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 322:
+ $1366 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1367 = ($1366 | 0) == 0;
+ if ($1367) {
+ label = 323;
+ break;
+ } else {
+ label = 324;
+ break;
+ }
+ case 323:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 324;
+ break;
+ case 324:
+ $1369 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1370$0 = $1369;
+ $1370$1 = 0;
+ $1371 = invoke_iii(364, $1370$0 | 0, $1370$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1372 = $local_env_w4567aaac23b1c44;
+ $1373 = $1371 + 16 | 0;
+ $1374 = $1373;
+ $1375 = HEAP32[$1374 >> 2] | 0;
+ _memcpy($1372 | 0, $1375 | 0, 40);
+ $1376 = HEAP32[$1374 >> 2] | 0;
+ $1377 = $1376;
+ $1378 = _saveSetjmp($1377 | 0, label, setjmpTable) | 0;
+ label = 423;
+ break;
+ case 423:
+ $1379 = ($1378 | 0) == 0;
+ if ($1379) {
+ label = 325;
+ break;
+ } else {
+ label = 328;
+ break;
+ }
+ case 325:
+ $_r0_sroa_0 = 1;
+ $_r0_sroa_0_0_load604 = $_r0_sroa_0;
+ $1381 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1382 = ($1381 | 0) == 0;
+ if ($1382) {
+ label = 326;
+ break;
+ } else {
+ label = 327;
+ break;
+ }
+ case 326:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 327;
+ break;
+ case 327:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load604;
+ $_r3_sroa_0_0_load593 = $_r3_sroa_0;
+ $1384 = $_r3_sroa_0_0_load593;
+ $1385 = HEAP32[$1384 >> 2] | 0;
+ $1386 = $1385 + 116 | 0;
+ $1387 = HEAP32[$1386 >> 2] | 0;
+ $1388 = $1387 + 4 | 0;
+ $1389 = HEAP32[$1388 >> 2] | 0;
+ $1390 = $1389;
+ $_r3_sroa_0_0_load = $_r3_sroa_0;
+ $1391 = invoke_ii($1390 | 0, $_r3_sroa_0_0_load | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1392 = $1391;
+ $_r0_sroa_0 = $1392;
+ invoke_viiii(14, 16136 | 0 | 0, 11648 | 0 | 0, 126872 | 0 | 0, 1630 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 328:
+ $1394 = HEAP32[$1374 >> 2] | 0;
+ _memcpy($1394 | 0, $1372 | 0, 40);
+ $1395 = HEAP32[(113236 | 0) >> 2] | 0;
+ $1396 = ($1395 | 0) == 0;
+ if ($1396) {
+ label = 329;
+ break;
+ } else {
+ label = 330;
+ break;
+ }
+ case 329:
+ invoke_v(538);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 330;
+ break;
+ case 330:
+ $1399 = $1371 + 20 | 0;
+ $1400 = $1399;
+ $1401 = HEAP32[$1400 >> 2] | 0;
+ $1402 = ($1401 | 0) == 0;
+ if ($1402) {
+ label = 344;
+ break;
+ } else {
+ label = 331;
+ break;
+ }
+ case 331:
+ $1404 = HEAP32[138672 >> 2] | 0;
+ $1405 = $1401;
+ $1406 = HEAP32[$1405 >> 2] | 0;
+ $1407 = $1406;
+ $1408 = $1404 + 8 | 0;
+ $1409 = $1408;
+ $1410 = HEAP32[$1409 >> 2] | 0;
+ $1411 = ($1406 | 0) == 82712;
+ if ($1411) {
+ label = 332;
+ break;
+ } else {
+ $tib1_0_ph_i248 = $1407;
+ label = 333;
+ break;
+ }
+ case 332:
+ $1413 = $1401 + 8 | 0;
+ $1414 = $1413;
+ $1415 = HEAP32[$1414 >> 2] | 0;
+ $1416 = $1415 + 8 | 0;
+ $1417 = $1416;
+ $1418 = HEAP32[$1417 >> 2] | 0;
+ $1419 = $1418;
+ $tib1_0_ph_i248 = $1419;
+ label = 333;
+ break;
+ case 333:
+ $1420 = $tib1_0_ph_i248 + 56 | 0;
+ $1421 = HEAP32[$1420 >> 2] | 0;
+ $1422 = ($1421 | 0) == 0;
+ if ($1422) {
+ var $dimension_tib1_0_lcssa_i252 = 0;
+ var $tib1_0_lcssa_i251 = $tib1_0_ph_i248;
+ label = 335;
+ break;
+ } else {
+ var $dimension_tib1_029_i254 = 0;
+ var $1428 = $1421;
+ label = 336;
+ break;
+ }
+ case 334:
+ $1423 = $1431;
+ var $dimension_tib1_0_lcssa_i252 = $1432;
+ var $tib1_0_lcssa_i251 = $1423;
+ label = 335;
+ break;
+ case 335:
+ $1424 = $1410 + 56 | 0;
+ $1425 = $1424;
+ $1426 = HEAP32[$1425 >> 2] | 0;
+ $1427 = ($1426 | 0) == 0;
+ if ($1427) {
+ var $dimension_tib2_0_lcssa_i259 = 0;
+ var $tib2_0_lcssa_in_i258 = $1410;
+ label = 338;
+ break;
+ } else {
+ var $dimension_tib2_024_i256 = 0;
+ var $1437 = $1426;
+ label = 337;
+ break;
+ }
+ case 336:
+ $1429 = $1428 + 8 | 0;
+ $1430 = $1429;
+ $1431 = HEAP32[$1430 >> 2] | 0;
+ $1432 = $dimension_tib1_029_i254 + 1 | 0;
+ $1433 = $1431 + 56 | 0;
+ $1434 = $1433;
+ $1435 = HEAP32[$1434 >> 2] | 0;
+ $1436 = ($1435 | 0) == 0;
+ if ($1436) {
+ label = 334;
+ break;
+ } else {
+ var $dimension_tib1_029_i254 = $1432;
+ var $1428 = $1435;
+ label = 336;
+ break;
+ }
+ case 337:
+ $1438 = $1437 + 8 | 0;
+ $1439 = $1438;
+ $1440 = HEAP32[$1439 >> 2] | 0;
+ $1441 = $dimension_tib2_024_i256 + 1 | 0;
+ $1442 = $1440 + 56 | 0;
+ $1443 = $1442;
+ $1444 = HEAP32[$1443 >> 2] | 0;
+ $1445 = ($1444 | 0) == 0;
+ if ($1445) {
+ var $dimension_tib2_0_lcssa_i259 = $1441;
+ var $tib2_0_lcssa_in_i258 = $1440;
+ label = 338;
+ break;
+ } else {
+ var $dimension_tib2_024_i256 = $1441;
+ var $1437 = $1444;
+ label = 337;
+ break;
+ }
+ case 338:
+ $tib2_0_lcssa_i260 = $tib2_0_lcssa_in_i258;
+ $1446 = ($dimension_tib1_0_lcssa_i252 | 0) < ($dimension_tib2_0_lcssa_i259 | 0);
+ $1447 = ($tib1_0_lcssa_i251 | 0) == 0;
+ $or_cond_i261 = $1446 | $1447;
+ if ($or_cond_i261) {
+ label = 344;
+ break;
+ } else {
+ $tib1_121_i263 = $tib1_0_lcssa_i251;
+ label = 339;
+ break;
+ }
+ case 339:
+ $1448 = ($tib1_121_i263 | 0) == ($tib2_0_lcssa_i260 | 0);
+ if ($1448) {
+ label = 361;
+ break;
+ } else {
+ label = 340;
+ break;
+ }
+ case 340:
+ $1449 = $tib1_121_i263 + 108 | 0;
+ $1450 = HEAP32[$1449 >> 2] | 0;
+ $1451 = $tib1_121_i263 + 112 | 0;
+ $i_0_i266 = 0;
+ label = 341;
+ break;
+ case 341:
+ $1453 = ($i_0_i266 | 0) < ($1450 | 0);
+ if ($1453) {
+ label = 342;
+ break;
+ } else {
+ label = 343;
+ break;
+ }
+ case 342:
+ $1455 = HEAP32[$1451 >> 2] | 0;
+ $1456 = $1455 + ($i_0_i266 << 2) | 0;
+ $1457 = HEAP32[$1456 >> 2] | 0;
+ $1458 = ($1457 | 0) == ($tib2_0_lcssa_i260 | 0);
+ $1459 = $i_0_i266 + 1 | 0;
+ if ($1458) {
+ label = 361;
+ break;
+ } else {
+ $i_0_i266 = $1459;
+ label = 341;
+ break;
+ }
+ case 343:
+ $1461 = $tib1_121_i263 + 40 | 0;
+ $1462 = HEAP32[$1461 >> 2] | 0;
+ $1463 = ($1462 | 0) == 0;
+ if ($1463) {
+ label = 344;
+ break;
+ } else {
+ $tib1_121_i263 = $1462;
+ label = 339;
+ break;
+ }
+ case 344:
+ $1464 = HEAP32[(107740 | 0) >> 2] | 0;
+ $1465 = ($1464 | 0) == 0;
+ if ($1465) {
+ label = 345;
+ break;
+ } else {
+ label = 346;
+ break;
+ }
+ case 345:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 346;
+ break;
+ case 346:
+ $1468 = HEAP32[$1400 >> 2] | 0;
+ $1469 = ($1468 | 0) == 0;
+ if ($1469) {
+ label = 360;
+ break;
+ } else {
+ label = 347;
+ break;
+ }
+ case 347:
+ $1471 = HEAP32[137616 >> 2] | 0;
+ $1472 = $1468;
+ $1473 = HEAP32[$1472 >> 2] | 0;
+ $1474 = $1473;
+ $1475 = $1471 + 8 | 0;
+ $1476 = $1475;
+ $1477 = HEAP32[$1476 >> 2] | 0;
+ $1478 = ($1473 | 0) == 82712;
+ if ($1478) {
+ label = 348;
+ break;
+ } else {
+ $tib1_0_ph_i227 = $1474;
+ label = 349;
+ break;
+ }
+ case 348:
+ $1480 = $1468 + 8 | 0;
+ $1481 = $1480;
+ $1482 = HEAP32[$1481 >> 2] | 0;
+ $1483 = $1482 + 8 | 0;
+ $1484 = $1483;
+ $1485 = HEAP32[$1484 >> 2] | 0;
+ $1486 = $1485;
+ $tib1_0_ph_i227 = $1486;
+ label = 349;
+ break;
+ case 349:
+ $1487 = $tib1_0_ph_i227 + 56 | 0;
+ $1488 = HEAP32[$1487 >> 2] | 0;
+ $1489 = ($1488 | 0) == 0;
+ if ($1489) {
+ var $dimension_tib1_0_lcssa_i231 = 0;
+ var $tib1_0_lcssa_i230 = $tib1_0_ph_i227;
+ label = 351;
+ break;
+ } else {
+ var $dimension_tib1_029_i233 = 0;
+ var $1495 = $1488;
+ label = 352;
+ break;
+ }
+ case 350:
+ $1490 = $1498;
+ var $dimension_tib1_0_lcssa_i231 = $1499;
+ var $tib1_0_lcssa_i230 = $1490;
+ label = 351;
+ break;
+ case 351:
+ $1491 = $1477 + 56 | 0;
+ $1492 = $1491;
+ $1493 = HEAP32[$1492 >> 2] | 0;
+ $1494 = ($1493 | 0) == 0;
+ if ($1494) {
+ var $dimension_tib2_0_lcssa_i238 = 0;
+ var $tib2_0_lcssa_in_i237 = $1477;
+ label = 354;
+ break;
+ } else {
+ var $dimension_tib2_024_i235 = 0;
+ var $1504 = $1493;
+ label = 353;
+ break;
+ }
+ case 352:
+ $1496 = $1495 + 8 | 0;
+ $1497 = $1496;
+ $1498 = HEAP32[$1497 >> 2] | 0;
+ $1499 = $dimension_tib1_029_i233 + 1 | 0;
+ $1500 = $1498 + 56 | 0;
+ $1501 = $1500;
+ $1502 = HEAP32[$1501 >> 2] | 0;
+ $1503 = ($1502 | 0) == 0;
+ if ($1503) {
+ label = 350;
+ break;
+ } else {
+ var $dimension_tib1_029_i233 = $1499;
+ var $1495 = $1502;
+ label = 352;
+ break;
+ }
+ case 353:
+ $1505 = $1504 + 8 | 0;
+ $1506 = $1505;
+ $1507 = HEAP32[$1506 >> 2] | 0;
+ $1508 = $dimension_tib2_024_i235 + 1 | 0;
+ $1509 = $1507 + 56 | 0;
+ $1510 = $1509;
+ $1511 = HEAP32[$1510 >> 2] | 0;
+ $1512 = ($1511 | 0) == 0;
+ if ($1512) {
+ var $dimension_tib2_0_lcssa_i238 = $1508;
+ var $tib2_0_lcssa_in_i237 = $1507;
+ label = 354;
+ break;
+ } else {
+ var $dimension_tib2_024_i235 = $1508;
+ var $1504 = $1511;
+ label = 353;
+ break;
+ }
+ case 354:
+ $tib2_0_lcssa_i239 = $tib2_0_lcssa_in_i237;
+ $1513 = ($dimension_tib1_0_lcssa_i231 | 0) < ($dimension_tib2_0_lcssa_i238 | 0);
+ $1514 = ($tib1_0_lcssa_i230 | 0) == 0;
+ $or_cond_i240 = $1513 | $1514;
+ if ($or_cond_i240) {
+ label = 360;
+ break;
+ } else {
+ $tib1_121_i242 = $tib1_0_lcssa_i230;
+ label = 355;
+ break;
+ }
+ case 355:
+ $1515 = ($tib1_121_i242 | 0) == ($tib2_0_lcssa_i239 | 0);
+ if ($1515) {
+ label = 386;
+ break;
+ } else {
+ label = 356;
+ break;
+ }
+ case 356:
+ $1516 = $tib1_121_i242 + 108 | 0;
+ $1517 = HEAP32[$1516 >> 2] | 0;
+ $1518 = $tib1_121_i242 + 112 | 0;
+ $i_0_i245 = 0;
+ label = 357;
+ break;
+ case 357:
+ $1520 = ($i_0_i245 | 0) < ($1517 | 0);
+ if ($1520) {
+ label = 358;
+ break;
+ } else {
+ label = 359;
+ break;
+ }
+ case 358:
+ $1522 = HEAP32[$1518 >> 2] | 0;
+ $1523 = $1522 + ($i_0_i245 << 2) | 0;
+ $1524 = HEAP32[$1523 >> 2] | 0;
+ $1525 = ($1524 | 0) == ($tib2_0_lcssa_i239 | 0);
+ $1526 = $i_0_i245 + 1 | 0;
+ if ($1525) {
+ label = 386;
+ break;
+ } else {
+ $i_0_i245 = $1526;
+ label = 357;
+ break;
+ }
+ case 359:
+ $1528 = $tib1_121_i242 + 40 | 0;
+ $1529 = HEAP32[$1528 >> 2] | 0;
+ $1530 = ($1529 | 0) == 0;
+ if ($1530) {
+ label = 360;
+ break;
+ } else {
+ $tib1_121_i242 = $1529;
+ label = 355;
+ break;
+ }
+ case 360:
+ $1531 = HEAP32[$1374 >> 2] | 0;
+ $1532 = $1531;
+ invoke_vii(48, $1532 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 361:
+ $1533 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1534 = ($1533 | 0) == 0;
+ if ($1534) {
+ label = 362;
+ break;
+ } else {
+ label = 363;
+ break;
+ }
+ case 362:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 363;
+ break;
+ case 363:
+ $1536 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1537$0 = $1536;
+ $1537$1 = 0;
+ $1538 = invoke_iii(364, $1537$0 | 0, $1537$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1539 = $local_env_w4567aaac23b1c48;
+ $1540 = $1538 + 16 | 0;
+ $1541 = $1540;
+ $1542 = HEAP32[$1541 >> 2] | 0;
+ _memcpy($1539 | 0, $1542 | 0, 40);
+ $1543 = HEAP32[$1541 >> 2] | 0;
+ $1544 = $1543;
+ $1545 = _saveSetjmp($1544 | 0, label, setjmpTable) | 0;
+ label = 424;
+ break;
+ case 424:
+ $1546 = ($1545 | 0) == 0;
+ if ($1546) {
+ label = 364;
+ break;
+ } else {
+ label = 369;
+ break;
+ }
+ case 364:
+ $1548 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1549 = ($1548 | 0) == 0;
+ if ($1549) {
+ label = 365;
+ break;
+ } else {
+ label = 366;
+ break;
+ }
+ case 365:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 366;
+ break;
+ case 366:
+ $1551 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1552$0 = $1551;
+ $1552$1 = 0;
+ $1553 = invoke_iii(364, $1552$0 | 0, $1552$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1554 = $1553 + 20 | 0;
+ $1555 = $1554;
+ $1556 = HEAP32[$1555 >> 2] | 0;
+ $1557 = $1556;
+ $_r0_sroa_0 = $1557;
+ $_r0_sroa_0 = 0;
+ $_r0_sroa_0_0_load602 = $_r0_sroa_0;
+ $1558 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1559 = ($1558 | 0) == 0;
+ if ($1559) {
+ label = 367;
+ break;
+ } else {
+ label = 368;
+ break;
+ }
+ case 367:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 368;
+ break;
+ case 368:
+ HEAP32[140048 >> 2] = $_r0_sroa_0_0_load602;
+ $1561 = HEAP32[$1541 >> 2] | 0;
+ _memcpy($1561 | 0, $1539 | 0, 40);
+ label = 239;
+ break;
+ case 369:
+ $1563 = HEAP32[$1541 >> 2] | 0;
+ _memcpy($1563 | 0, $1539 | 0, 40);
+ $1564 = HEAP32[(107740 | 0) >> 2] | 0;
+ $1565 = ($1564 | 0) == 0;
+ if ($1565) {
+ label = 370;
+ break;
+ } else {
+ label = 371;
+ break;
+ }
+ case 370:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 371;
+ break;
+ case 371:
+ $1568 = $1538 + 20 | 0;
+ $1569 = $1568;
+ $1570 = HEAP32[$1569 >> 2] | 0;
+ $1571 = ($1570 | 0) == 0;
+ if ($1571) {
+ label = 385;
+ break;
+ } else {
+ label = 372;
+ break;
+ }
+ case 372:
+ $1573 = HEAP32[137616 >> 2] | 0;
+ $1574 = $1570;
+ $1575 = HEAP32[$1574 >> 2] | 0;
+ $1576 = $1575;
+ $1577 = $1573 + 8 | 0;
+ $1578 = $1577;
+ $1579 = HEAP32[$1578 >> 2] | 0;
+ $1580 = ($1575 | 0) == 82712;
+ if ($1580) {
+ label = 373;
+ break;
+ } else {
+ $tib1_0_ph_i185 = $1576;
+ label = 374;
+ break;
+ }
+ case 373:
+ $1582 = $1570 + 8 | 0;
+ $1583 = $1582;
+ $1584 = HEAP32[$1583 >> 2] | 0;
+ $1585 = $1584 + 8 | 0;
+ $1586 = $1585;
+ $1587 = HEAP32[$1586 >> 2] | 0;
+ $1588 = $1587;
+ $tib1_0_ph_i185 = $1588;
+ label = 374;
+ break;
+ case 374:
+ $1589 = $tib1_0_ph_i185 + 56 | 0;
+ $1590 = HEAP32[$1589 >> 2] | 0;
+ $1591 = ($1590 | 0) == 0;
+ if ($1591) {
+ var $dimension_tib1_0_lcssa_i189 = 0;
+ var $tib1_0_lcssa_i188 = $tib1_0_ph_i185;
+ label = 376;
+ break;
+ } else {
+ var $dimension_tib1_029_i191 = 0;
+ var $1597 = $1590;
+ label = 377;
+ break;
+ }
+ case 375:
+ $1592 = $1600;
+ var $dimension_tib1_0_lcssa_i189 = $1601;
+ var $tib1_0_lcssa_i188 = $1592;
+ label = 376;
+ break;
+ case 376:
+ $1593 = $1579 + 56 | 0;
+ $1594 = $1593;
+ $1595 = HEAP32[$1594 >> 2] | 0;
+ $1596 = ($1595 | 0) == 0;
+ if ($1596) {
+ var $dimension_tib2_0_lcssa_i196 = 0;
+ var $tib2_0_lcssa_in_i195 = $1579;
+ label = 379;
+ break;
+ } else {
+ var $dimension_tib2_024_i193 = 0;
+ var $1606 = $1595;
+ label = 378;
+ break;
+ }
+ case 377:
+ $1598 = $1597 + 8 | 0;
+ $1599 = $1598;
+ $1600 = HEAP32[$1599 >> 2] | 0;
+ $1601 = $dimension_tib1_029_i191 + 1 | 0;
+ $1602 = $1600 + 56 | 0;
+ $1603 = $1602;
+ $1604 = HEAP32[$1603 >> 2] | 0;
+ $1605 = ($1604 | 0) == 0;
+ if ($1605) {
+ label = 375;
+ break;
+ } else {
+ var $dimension_tib1_029_i191 = $1601;
+ var $1597 = $1604;
+ label = 377;
+ break;
+ }
+ case 378:
+ $1607 = $1606 + 8 | 0;
+ $1608 = $1607;
+ $1609 = HEAP32[$1608 >> 2] | 0;
+ $1610 = $dimension_tib2_024_i193 + 1 | 0;
+ $1611 = $1609 + 56 | 0;
+ $1612 = $1611;
+ $1613 = HEAP32[$1612 >> 2] | 0;
+ $1614 = ($1613 | 0) == 0;
+ if ($1614) {
+ var $dimension_tib2_0_lcssa_i196 = $1610;
+ var $tib2_0_lcssa_in_i195 = $1609;
+ label = 379;
+ break;
+ } else {
+ var $dimension_tib2_024_i193 = $1610;
+ var $1606 = $1613;
+ label = 378;
+ break;
+ }
+ case 379:
+ $tib2_0_lcssa_i197 = $tib2_0_lcssa_in_i195;
+ $1615 = ($dimension_tib1_0_lcssa_i189 | 0) < ($dimension_tib2_0_lcssa_i196 | 0);
+ $1616 = ($tib1_0_lcssa_i188 | 0) == 0;
+ $or_cond_i198 = $1615 | $1616;
+ if ($or_cond_i198) {
+ label = 385;
+ break;
+ } else {
+ $tib1_121_i200 = $tib1_0_lcssa_i188;
+ label = 380;
+ break;
+ }
+ case 380:
+ $1617 = ($tib1_121_i200 | 0) == ($tib2_0_lcssa_i197 | 0);
+ if ($1617) {
+ label = 54;
+ break;
+ } else {
+ label = 381;
+ break;
+ }
+ case 381:
+ $1618 = $tib1_121_i200 + 108 | 0;
+ $1619 = HEAP32[$1618 >> 2] | 0;
+ $1620 = $tib1_121_i200 + 112 | 0;
+ $i_0_i203 = 0;
+ label = 382;
+ break;
+ case 382:
+ $1622 = ($i_0_i203 | 0) < ($1619 | 0);
+ if ($1622) {
+ label = 383;
+ break;
+ } else {
+ label = 384;
+ break;
+ }
+ case 383:
+ $1624 = HEAP32[$1620 >> 2] | 0;
+ $1625 = $1624 + ($i_0_i203 << 2) | 0;
+ $1626 = HEAP32[$1625 >> 2] | 0;
+ $1627 = ($1626 | 0) == ($tib2_0_lcssa_i197 | 0);
+ $1628 = $i_0_i203 + 1 | 0;
+ if ($1627) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i203 = $1628;
+ label = 382;
+ break;
+ }
+ case 384:
+ $1630 = $tib1_121_i200 + 40 | 0;
+ $1631 = HEAP32[$1630 >> 2] | 0;
+ $1632 = ($1631 | 0) == 0;
+ if ($1632) {
+ label = 385;
+ break;
+ } else {
+ $tib1_121_i200 = $1631;
+ label = 380;
+ break;
+ }
+ case 385:
+ $1633 = HEAP32[$1541 >> 2] | 0;
+ $1634 = $1633;
+ invoke_vii(48, $1634 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 386:
+ $1635 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1636 = ($1635 | 0) == 0;
+ if ($1636) {
+ label = 387;
+ break;
+ } else {
+ label = 388;
+ break;
+ }
+ case 387:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 388;
+ break;
+ case 388:
+ $1638 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1639$0 = $1638;
+ $1639$1 = 0;
+ $1640 = invoke_iii(364, $1639$0 | 0, $1639$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1641 = $local_env_w4567aaac23b1c50;
+ $1642 = $1640 + 16 | 0;
+ $1643 = $1642;
+ $1644 = HEAP32[$1643 >> 2] | 0;
+ _memcpy($1641 | 0, $1644 | 0, 40);
+ $1645 = HEAP32[$1643 >> 2] | 0;
+ $1646 = $1645;
+ $1647 = _saveSetjmp($1646 | 0, label, setjmpTable) | 0;
+ label = 425;
+ break;
+ case 425:
+ $1648 = ($1647 | 0) == 0;
+ if ($1648) {
+ label = 389;
+ break;
+ } else {
+ label = 396;
+ break;
+ }
+ case 389:
+ $1650 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1651 = ($1650 | 0) == 0;
+ if ($1651) {
+ label = 390;
+ break;
+ } else {
+ label = 391;
+ break;
+ }
+ case 390:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 391;
+ break;
+ case 391:
+ $1653 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1654$0 = $1653;
+ $1654$1 = 0;
+ $1655 = invoke_iii(364, $1654$0 | 0, $1654$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1656 = $1655 + 20 | 0;
+ $1657 = $1656;
+ $1658 = HEAP32[$1657 >> 2] | 0;
+ $1659 = $1658;
+ $_r0_sroa_0 = $1659;
+ $_r2_sroa_0 = 0;
+ $_r2_sroa_0_0_load = $_r2_sroa_0;
+ $1660 = HEAP32[(98772 | 0) >> 2] | 0;
+ $1661 = ($1660 | 0) == 0;
+ if ($1661) {
+ label = 392;
+ break;
+ } else {
+ label = 393;
+ break;
+ }
+ case 392:
+ invoke_v(702);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 393;
+ break;
+ case 393:
+ HEAP32[140048 >> 2] = $_r2_sroa_0_0_load;
+ $1663 = HEAP32[(105500 | 0) >> 2] | 0;
+ $1664 = ($1663 | 0) == 0;
+ if ($1664) {
+ label = 394;
+ break;
+ } else {
+ label = 395;
+ break;
+ }
+ case 394:
+ invoke_v(30);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 395;
+ break;
+ case 395:
+ $1666 = invoke_i(70) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $1667$0 = $1666;
+ $1667$1 = 0;
+ $1668 = invoke_iii(364, $1667$0 | 0, $1667$1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $_r0_sroa_0_0_load = $_r0_sroa_0;
+ $1669 = $_r0_sroa_0_0_load;
+ $1670 = $1668 + 16 | 0;
+ $1671 = $1668 + 20 | 0;
+ $1672 = $1671;
+ HEAP32[$1672 >> 2] = $1669;
+ $1673 = $1670;
+ $1674 = HEAP32[$1673 >> 2] | 0;
+ $1675 = $1674;
+ invoke_vii(48, $1675 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case 396:
+ $1677 = HEAP32[$1643 >> 2] | 0;
+ _memcpy($1677 | 0, $1641 | 0, 40);
+ $1678 = HEAP32[(107740 | 0) >> 2] | 0;
+ $1679 = ($1678 | 0) == 0;
+ if ($1679) {
+ label = 397;
+ break;
+ } else {
+ label = 398;
+ break;
+ }
+ case 397:
+ invoke_v(374);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 398;
+ break;
+ case 398:
+ $1682 = $1640 + 20 | 0;
+ $1683 = $1682;
+ $1684 = HEAP32[$1683 >> 2] | 0;
+ $1685 = ($1684 | 0) == 0;
+ if ($1685) {
+ label = 412;
+ break;
+ } else {
+ label = 399;
+ break;
+ }
+ case 399:
+ $1687 = HEAP32[137616 >> 2] | 0;
+ $1688 = $1684;
+ $1689 = HEAP32[$1688 >> 2] | 0;
+ $1690 = $1689;
+ $1691 = $1687 + 8 | 0;
+ $1692 = $1691;
+ $1693 = HEAP32[$1692 >> 2] | 0;
+ $1694 = ($1689 | 0) == 82712;
+ if ($1694) {
+ label = 400;
+ break;
+ } else {
+ $tib1_0_ph_i = $1690;
+ label = 401;
+ break;
+ }
+ case 400:
+ $1696 = $1684 + 8 | 0;
+ $1697 = $1696;
+ $1698 = HEAP32[$1697 >> 2] | 0;
+ $1699 = $1698 + 8 | 0;
+ $1700 = $1699;
+ $1701 = HEAP32[$1700 >> 2] | 0;
+ $1702 = $1701;
+ $tib1_0_ph_i = $1702;
+ label = 401;
+ break;
+ case 401:
+ $1703 = $tib1_0_ph_i + 56 | 0;
+ $1704 = HEAP32[$1703 >> 2] | 0;
+ $1705 = ($1704 | 0) == 0;
+ if ($1705) {
+ var $dimension_tib1_0_lcssa_i = 0;
+ var $tib1_0_lcssa_i = $tib1_0_ph_i;
+ label = 403;
+ break;
+ } else {
+ var $dimension_tib1_029_i = 0;
+ var $1711 = $1704;
+ label = 404;
+ break;
+ }
+ case 402:
+ $1706 = $1714;
+ var $dimension_tib1_0_lcssa_i = $1715;
+ var $tib1_0_lcssa_i = $1706;
+ label = 403;
+ break;
+ case 403:
+ $1707 = $1693 + 56 | 0;
+ $1708 = $1707;
+ $1709 = HEAP32[$1708 >> 2] | 0;
+ $1710 = ($1709 | 0) == 0;
+ if ($1710) {
+ var $dimension_tib2_0_lcssa_i = 0;
+ var $tib2_0_lcssa_in_i = $1693;
+ label = 406;
+ break;
+ } else {
+ var $dimension_tib2_024_i = 0;
+ var $1720 = $1709;
+ label = 405;
+ break;
+ }
+ case 404:
+ $1712 = $1711 + 8 | 0;
+ $1713 = $1712;
+ $1714 = HEAP32[$1713 >> 2] | 0;
+ $1715 = $dimension_tib1_029_i + 1 | 0;
+ $1716 = $1714 + 56 | 0;
+ $1717 = $1716;
+ $1718 = HEAP32[$1717 >> 2] | 0;
+ $1719 = ($1718 | 0) == 0;
+ if ($1719) {
+ label = 402;
+ break;
+ } else {
+ var $dimension_tib1_029_i = $1715;
+ var $1711 = $1718;
+ label = 404;
+ break;
+ }
+ case 405:
+ $1721 = $1720 + 8 | 0;
+ $1722 = $1721;
+ $1723 = HEAP32[$1722 >> 2] | 0;
+ $1724 = $dimension_tib2_024_i + 1 | 0;
+ $1725 = $1723 + 56 | 0;
+ $1726 = $1725;
+ $1727 = HEAP32[$1726 >> 2] | 0;
+ $1728 = ($1727 | 0) == 0;
+ if ($1728) {
+ var $dimension_tib2_0_lcssa_i = $1724;
+ var $tib2_0_lcssa_in_i = $1723;
+ label = 406;
+ break;
+ } else {
+ var $dimension_tib2_024_i = $1724;
+ var $1720 = $1727;
+ label = 405;
+ break;
+ }
+ case 406:
+ $tib2_0_lcssa_i = $tib2_0_lcssa_in_i;
+ $1729 = ($dimension_tib1_0_lcssa_i | 0) < ($dimension_tib2_0_lcssa_i | 0);
+ $1730 = ($tib1_0_lcssa_i | 0) == 0;
+ $or_cond_i = $1729 | $1730;
+ if ($or_cond_i) {
+ label = 412;
+ break;
+ } else {
+ $tib1_121_i = $tib1_0_lcssa_i;
+ label = 407;
+ break;
+ }
+ case 407:
+ $1731 = ($tib1_121_i | 0) == ($tib2_0_lcssa_i | 0);
+ if ($1731) {
+ label = 54;
+ break;
+ } else {
+ label = 408;
+ break;
+ }
+ case 408:
+ $1732 = $tib1_121_i + 108 | 0;
+ $1733 = HEAP32[$1732 >> 2] | 0;
+ $1734 = $tib1_121_i + 112 | 0;
+ $i_0_i = 0;
+ label = 409;
+ break;
+ case 409:
+ $1736 = ($i_0_i | 0) < ($1733 | 0);
+ if ($1736) {
+ label = 410;
+ break;
+ } else {
+ label = 411;
+ break;
+ }
+ case 410:
+ $1738 = HEAP32[$1734 >> 2] | 0;
+ $1739 = $1738 + ($i_0_i << 2) | 0;
+ $1740 = HEAP32[$1739 >> 2] | 0;
+ $1741 = ($1740 | 0) == ($tib2_0_lcssa_i | 0);
+ $1742 = $i_0_i + 1 | 0;
+ if ($1741) {
+ label = 54;
+ break;
+ } else {
+ $i_0_i = $1742;
+ label = 409;
+ break;
+ }
+ case 411:
+ $1744 = $tib1_121_i + 40 | 0;
+ $1745 = HEAP32[$1744 >> 2] | 0;
+ $1746 = ($1745 | 0) == 0;
+ if ($1746) {
+ label = 412;
+ break;
+ } else {
+ $tib1_121_i = $1745;
+ label = 407;
+ break;
+ }
+ case 412:
+ $1747 = HEAP32[$1643 >> 2] | 0;
+ $1748 = $1747;
+ invoke_vii(48, $1748 | 0, 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1111;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ return 0 | 0;
+ case -1111:
+ if ((setjmpLabel | 0) == 7) {
+ $25 = threwValue;
+ label = 413;
+ } else if ((setjmpLabel | 0) == 35) {
+ $159 = threwValue;
+ label = 414;
+ } else if ((setjmpLabel | 0) == 62) {
+ $290 = threwValue;
+ label = 415;
+ } else if ((setjmpLabel | 0) == 91) {
+ $401 = threwValue;
+ label = 416;
+ } else if ((setjmpLabel | 0) == 97) {
+ $433 = threwValue;
+ label = 417;
+ } else if ((setjmpLabel | 0) == 144) {
+ $629 = threwValue;
+ label = 418;
+ } else if ((setjmpLabel | 0) == 181) {
+ $789 = threwValue;
+ label = 419;
+ } else if ((setjmpLabel | 0) == 218) {
+ $954 = threwValue;
+ label = 420;
+ } else if ((setjmpLabel | 0) == 240) {
+ $1042 = threwValue;
+ label = 421;
+ } else if ((setjmpLabel | 0) == 251) {
+ $1073 = threwValue;
+ label = 422;
+ } else if ((setjmpLabel | 0) == 324) {
+ $1378 = threwValue;
+ label = 423;
+ } else if ((setjmpLabel | 0) == 363) {
+ $1545 = threwValue;
+ label = 424;
+ } else if ((setjmpLabel | 0) == 388) {
+ $1647 = threwValue;
+ label = 425;
+ }
+ __THREW__ = threwValue = 0;
+ break;
+ }
+}// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String"]
diff --git a/tools/file_packager.py b/tools/file_packager.py
index ef113cb5..6a8390ad 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -112,16 +112,20 @@ for arg in sys.argv[1:]:
in_preload = False
in_embed = False
in_compress = 0
- elif in_preload:
- if os.path.isfile(arg) or os.path.isdir(arg):
- data_files.append({ 'name': arg, 'mode': 'preload' })
+ elif in_preload or in_embed:
+ mode = 'preload'
+ if in_embed:
+ mode = 'embed'
+ if '@' in arg:
+ srcpath, dstpath = arg.split('@') # User is specifying destination filename explicitly.
else:
- print >> sys.stderr, 'Warning: ' + arg + ' does not exist, ignoring.'
- elif in_embed:
- if os.path.isfile(arg) or os.path.isdir(arg):
- data_files.append({ 'name': arg, 'mode': 'embed' })
+ srcpath = dstpath = arg # Use source path as destination path.
+ if os.path.isabs(dstpath):
+ print >> sys.stderr, 'Warning: Embedding an absolute file/directory name "' + dstpath + '" to the virtual filesystem. The file will be made available in the path "' + dstpath + '", and not in the root of the generated file system. Use the explicit syntax --preload-file srcpath@dstpath to specify the target location the absolute source path should be directed to.'
+ if os.path.isfile(srcpath) or os.path.isdir(srcpath):
+ data_files.append({ 'srcpath': srcpath, 'dstpath': dstpath, 'mode': mode })
else:
- print >> sys.stderr, 'Warning:' + arg + ' does not exist, ignoring.'
+ print >> sys.stderr, 'Warning: ' + arg + ' does not exist, ignoring.'
elif in_compress:
if in_compress == 1:
Compression.encoder = arg
@@ -147,20 +151,26 @@ function assert(check, msg) {
'''
# Expand directories into individual files
-def add(mode, dirname, names):
+def add(arg, dirname, names):
+ # rootpathsrc: The path name of the root directory on the local FS we are adding to emscripten virtual FS.
+ # rootpathdst: The name we want to make the source path available on the emscripten virtual FS.
+ mode, rootpathsrc, rootpathdst = arg
for name in names:
fullname = os.path.join(dirname, name)
if not os.path.isdir(fullname):
- data_files.append({ 'name': fullname, 'mode': mode })
+ dstpath = os.path.join(rootpathdst, os.path.relpath(fullname, rootpathsrc)) # Convert source filename relative to root directory of target FS.
+ data_files.append({ 'srcpath': fullname, 'dstpath': dstpath, 'mode': mode })
for file_ in data_files:
- if os.path.isdir(file_['name']):
- os.path.walk(file_['name'], add, file_['mode'])
-data_files = filter(lambda file_: not os.path.isdir(file_['name']), data_files)
+ if os.path.isdir(file_['srcpath']):
+ os.path.walk(file_['srcpath'], add, [file_['mode'], file_['srcpath'], file_['dstpath']])
+data_files = filter(lambda file_: not os.path.isdir(file_['srcpath']), data_files)
for file_ in data_files:
- file_['name'] = file_['name'].replace(os.path.sep, '/') # name in the filesystem, native and emulated
- file_['localname'] = file_['name'] # name to actually load from local filesystem, after transformations
+ file_['dstpath'] = file_['dstpath'].replace(os.path.sep, '/') # name in the filesystem, native and emulated
+ if file_['dstpath'].endswith('/'): # If user has submitted a directory name as the destination but omitted the destination filename, use the filename from source file
+ file_['dstpath'] = file_['dstpath'] + os.path.basename(file_['srcpath'])
+ if file_['dstpath'].startswith('./'): file_['dstpath'] = file_['dstpath'][2:] # remove redundant ./ prefix
# Remove duplicates (can occur naively, for example preload dir/, preload dir/subdir/)
seen = {}
@@ -168,7 +178,7 @@ def was_seen(name):
if seen.get(name): return True
seen[name] = 1
return False
-data_files = filter(lambda file_: not was_seen(file_['name']), data_files)
+data_files = filter(lambda file_: not was_seen(file_['dstpath']), data_files)
if AV_WORKAROUND:
random.shuffle(data_files)
@@ -200,20 +210,24 @@ if crunch:
'''
for file_ in data_files:
- if file_['name'].endswith(CRUNCH_INPUT_SUFFIX):
- # Do not crunch if crunched version exists and is more recent than dds source
- crunch_name = unsuffixed(file_['name']) + CRUNCH_OUTPUT_SUFFIX
- file_['localname'] = crunch_name
+ if file_['dstpath'].endswith(CRUNCH_INPUT_SUFFIX):
+ src_dds_name = file_['srcpath']
+ src_crunch_name = unsuffixed(src_dds_name) + CRUNCH_OUTPUT_SUFFIX
+
+ # Preload/embed the .crn version instead of the .dds version, but use the .dds suffix for the target file in the virtual FS.
+ file_['srcpath'] = src_crunch_name
+
try:
- crunch_time = os.stat(crunch_name).st_mtime
- dds_time = os.stat(file_['name']).st_mtime
+ # Do not crunch if crunched version exists and is more recent than dds source
+ crunch_time = os.stat(src_crunch_name).st_mtime
+ dds_time = os.stat(src_dds_name).st_mtime
if dds_time < crunch_time: continue
except:
pass # if one of them does not exist, continue on
# guess at format. this lets us tell crunch to not try to be clever and use odd formats like DXT5_AGBR
try:
- format = Popen(['file', file_['name']], stdout=PIPE).communicate()[0]
+ format = Popen(['file', file_['srcpath']], stdout=PIPE).communicate()[0]
if 'DXT5' in format:
format = ['-dxt5']
elif 'DXT1' in format:
@@ -222,23 +236,22 @@ if crunch:
raise Exception('unknown format')
except:
format = []
- Popen([CRUNCH, '-file', file_['name'], '-quality', crunch] + format, stdout=sys.stderr).communicate()
+ Popen([CRUNCH, '-outsamedir', '-file', src_dds_name, '-quality', crunch] + format, stdout=sys.stderr).communicate()
#if not os.path.exists(os.path.basename(crunch_name)):
# print >> sys.stderr, 'Failed to crunch, perhaps a weird dxt format? Looking for a source PNG for the DDS'
- # Popen([CRUNCH, '-file', unsuffixed(file_['name']) + '.png', '-quality', crunch] + format, stdout=sys.stderr).communicate()
- assert os.path.exists(os.path.basename(crunch_name)), 'crunch failed to generate output'
- shutil.move(os.path.basename(crunch_name), crunch_name) # crunch places files in the current dir
+ # Popen([CRUNCH, '-file', unsuffixed(file_['srcpath']) + '.png', '-quality', crunch] + format, stdout=sys.stderr).communicate()
+ assert os.path.exists(os.path.basename(src_crunch_name)), 'crunch failed to generate output'
# prepend the dds header
- crunched = open(crunch_name, 'rb').read()
- c = open(crunch_name, 'wb')
- c.write(open(file_['name'], 'rb').read()[:DDS_HEADER_SIZE])
+ crunched = open(src_crunch_name, 'rb').read()
+ c = open(src_crunch_name, 'wb')
+ c.write(open(src_dds_name, 'rb').read()[:DDS_HEADER_SIZE])
c.write(crunched)
c.close()
# Set up folders
partial_dirs = []
for file_ in data_files:
- dirname = os.path.dirname(file_['name'])
+ dirname = os.path.dirname(file_['dstpath'])
dirname = dirname.lstrip('/') # absolute paths start with '/', remove that
if dirname != '':
parts = dirname.split('/')
@@ -254,10 +267,10 @@ if has_preloaded:
start = 0
for file_ in data_files:
file_['data_start'] = start
- curr = open(file_['localname'], 'rb').read()
+ curr = open(file_['srcpath'], 'rb').read()
file_['data_end'] = start + len(curr)
if AV_WORKAROUND: curr += '\x00'
- #print >> sys.stderr, 'bundling', file_['name'], file_['localname'], file_['data_start'], file_['data_end']
+ #print >> sys.stderr, 'bundling', file_['srcpath'], file_['dstpath'], file_['data_start'], file_['data_end']
start += len(curr)
data.write(curr)
data.close()
@@ -279,10 +292,10 @@ if has_preloaded:
counter = 0
for file_ in data_files:
- filename = file_['name']
+ filename = file_['dstpath']
if file_['mode'] == 'embed':
# Embed
- data = map(ord, open(file_['localname'], 'rb').read())
+ data = map(ord, open(file_['srcpath'], 'rb').read())
str_data = ''
chunk_size = 10240
while len(data) > 0:
@@ -351,9 +364,12 @@ if has_preloaded:
if file_['mode'] == 'preload':
use_data += '''
curr = DataRequest.prototype.requests['%s'];
- curr.response = byteArray.subarray(%d,%d);
+ var data = byteArray.subarray(%d, %d);
+ var ptr = Module['_malloc'](%d);
+ Module['HEAPU8'].set(data, ptr);
+ curr.response = Module['HEAPU8'].subarray(ptr, ptr + %d);
curr.onload();
- ''' % (file_['name'], file_['data_start'], file_['data_end'])
+ ''' % (file_['dstpath'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start'])
use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target
if Compression.on:
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 32ed1cce..09791150 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -403,6 +403,23 @@ function removeUnneededLabelSettings(ast) {
// Various expression simplifications. Pre run before closure (where we still have metadata), Post run after.
function simplifyExpressionsPre(ast) {
+ // Look for (x&A)<<B>>B and replace it with X&A if possible.
+ function simplifySignExtends(ast) {
+ traverseGenerated(ast, function(node, type) {
+ if (type == 'binary' && node[1] == '>>' && node[3][0] == 'num' &&
+ node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' && node[3][1] == node[2][3][1]) {
+ var innerNode = node[2][2];
+ var shifts = node[3][1];
+ if (innerNode[0] == 'binary' && innerNode[1] == '&' && innerNode[3][0] == 'num') {
+ var mask = innerNode[3][1];
+ if (mask << shifts >> shifts == mask) {
+ return innerNode;
+ }
+ }
+ }
+ });
+ }
+
// When there is a bunch of math like (((8+5)|0)+12)|0, only the external |0 is needed, one correction is enough.
// At each node, ((X|0)+Y)|0 can be transformed into (X+Y): The inner corrections are not needed
// TODO: Is the same is true for 0xff, 0xffff?
@@ -592,6 +609,7 @@ function simplifyExpressionsPre(ast) {
});
}
+ simplifySignExtends(ast);
simplifyBitops(ast);
joinAdditions(ast);
// simplifyZeroComp(ast); TODO: investigate performance
@@ -1487,7 +1505,7 @@ function registerize(ast) {
// Replace all var definitions with assignments; we will add var definitions at the top after we registerize
// We also mark local variables - i.e., having a var definition
var localVars = {};
- var hasSwitch = false; // we cannot optimize variables if there is a switch
+ var hasSwitch = false; // we cannot optimize variables if there is a switch, unless in asm mode
traverse(fun, function(node, type) {
if (type == 'var') {
node[1].forEach(function(defined) { localVars[defined[0]] = 1 });
@@ -1578,7 +1596,15 @@ function registerize(ast) {
var varLevels = {};
var possibles = {};
var unoptimizables = {};
- traverse(fun, function(node, type) {
+ function purgeLevel() {
+ // Invalidate all dominating on this level, further users make it unoptimizable
+ for (var name in levelDominations[level]) {
+ varLevels[name] = 0;
+ }
+ levelDominations[level] = null;
+ level--;
+ }
+ traverse(fun, function possibilifier(node, type) {
if (type == 'name') {
var name = node[1];
if (localVars[name]) {
@@ -1599,24 +1625,61 @@ function registerize(ast) {
}
}
} else if (type in CONTROL_FLOW) {
- level++;
- }
- }, function(node, type) {
- if (type in CONTROL_FLOW) {
- // Invalidate all dominating on this level, further users make it unoptimizable
- for (var name in levelDominations[level]) {
- varLevels[name] = 0;
+ // recurse children, in the context of a loop
+ switch(type) {
+ case 'while': case 'do': {
+ traverse(node[1], possibilifier);
+ level++;
+ traverse(node[2], possibilifier);
+ purgeLevel();
+ break;
+ }
+ case 'for': {
+ traverse(node[1], possibilifier);
+ for (var i = 2; i <= 4; i++) {
+ level++;
+ traverse(node[i], possibilifier);
+ purgeLevel();
+ }
+ break;
+ }
+ case 'if': {
+ traverse(node[1], possibilifier);
+ level++;
+ traverse(node[2], possibilifier);
+ purgeLevel();
+ if (node[3]) {
+ level++;
+ traverse(node[3], possibilifier);
+ purgeLevel();
+ }
+ break;
+ }
+ case 'switch': {
+ traverse(node[1], possibilifier);
+ var cases = node[2];
+ for (var i = 0; i < cases.length; i++) {
+ level++;
+ traverse(cases[i][1], possibilifier);
+ purgeLevel();
+ }
+ break;
+ }
+ default: throw dumpAst(node);
}
- levelDominations[level] = null;
- level--;
+ return null; // prevent recursion into children, which we already did
}
});
var optimizables = {};
- if (!hasSwitch) {
+ if (!hasSwitch || asm) {
for (var possible in possibles) {
if (!unoptimizables[possible]) optimizables[possible] = 1;
}
}
+
+ //printErr('optimizables: ' + JSON.stringify(optimizables));
+ //printErr('unoptimizables: ' + JSON.stringify(unoptimizables));
+
// Go through the function's code, assigning 'registers'.
// The only tricky bit is to keep variables locked on a register through loops,
// since they can potentially be returned to. Optimizable variables lock onto
@@ -1776,10 +1839,10 @@ function registerize(ast) {
// In memSafe mode, we are more careful and assume functions can replace HEAP and FUNCTION_TABLE, which
// can happen in ALLOW_MEMORY_GROWTH mode
-var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label'); // do is checked carefully, however
+var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label', 'switch'); // do is checked carefully, however
var NODES_WITHOUT_ELIMINATION_SIDE_EFFECTS = set('name', 'num', 'string', 'binary', 'sub', 'unary-prefix');
var IGNORABLE_ELIMINATOR_SCAN_NODES = set('num', 'toplevel', 'string', 'break', 'continue', 'dot'); // dot can only be STRING_TABLE.*
-var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', 'switch', 'for', 'while', 'array', 'throw'); // we could handle some of these, TODO, but nontrivial (e.g. for while, the condition is hit multiple times after the body)
+var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', 'for', 'while', 'array', 'throw'); // we could handle some of these, TODO, but nontrivial (e.g. for while, the condition is hit multiple times after the body)
function eliminate(ast, memSafe) {
// Find variables that have a single use, and if they can be eliminated, do so
@@ -1787,7 +1850,6 @@ function eliminate(ast, memSafe) {
if (asm) var asmData = normalizeAsm(func);
//printErr('eliminate in ' + func[1]);
-
// First, find the potentially eliminatable functions: that have one definition and one use
var definitions = {};
var uses = {};
@@ -1841,12 +1903,7 @@ function eliminate(ast, memSafe) {
});
// we cannot eliminate variables if there is a switch
- if (traverse(func, function(node, type) {
- if (type == 'switch') return true;
- })) {
- if (asm) denormalizeAsm(func, asmData);
- return;
- }
+ if (hasSwitch && !asm) return;
var potentials = {}; // local variables with 1 definition and 1 use
var sideEffectFree = {}; // whether a local variable has no side effects in its definition
@@ -2153,13 +2210,14 @@ function eliminate(ast, memSafe) {
invalidateCalls();
callsInvalidated = true;
}
+
allowTracking = false;
traverseInOrder(node[2]); // 2 and 3 could be 'parallel', really..
if (node[3]) traverseInOrder(node[3]);
allowTracking = true;
+
} else {
tracked = {};
- abort = true;
}
} else if (type == 'block') {
var stats = node[1];
@@ -2180,7 +2238,6 @@ function eliminate(ast, memSafe) {
traverseInOrder(node[2]);
} else {
tracked = {};
- abort = true;
}
} else if (type == 'return') {
if (node[1]) traverseInOrder(node[1]);
@@ -2188,6 +2245,17 @@ function eliminate(ast, memSafe) {
traverseInOrder(node[1]);
traverseInOrder(node[2]);
traverseInOrder(node[3]);
+ } else if (type == 'switch') {
+ traverseInOrder(node[1]);
+ var cases = node[2];
+ for (var i = 0; i < cases.length; i++) {
+ var c = cases[i];
+ assert(c[0] === null || c[0][0] == 'num' || (c[0][0] == 'unary-prefix' && c[0][2][0] == 'num'));
+ var stats = c[1];
+ for (var j = 0; j < stats.length; j++) {
+ traverseInOrder(stats[j]);
+ }
+ }
} else {
if (!(type in ABORTING_ELIMINATOR_SCAN_NODES)) {
printErr('unfamiliar eliminator scan node: ' + JSON.stringify(node));
@@ -2234,13 +2302,15 @@ function eliminate(ast, memSafe) {
}
}
traverse(func, function(block) {
- var stats = getStatements(block);
+ // Look for statements, including while-switch pattern
+ var stats = getStatements(block) || (block[0] == 'while' && block[2][0] == 'switch' ? [block[2]] : stats);
if (!stats) return;
+ //printErr('Stats: ' + JSON.stringify(stats).substr(0,100));
tracked = {};
//printErr('new StatBlock');
for (var i = 0; i < stats.length; i++) {
var node = stats[i];
- //printErr('StatBlock[' + i + '] => ' + JSON.stringify(node));
+ //printErr('StatBlock[' + i + '] => ' + JSON.stringify(node).substr(0,100));
var type = node[0];
if (type == 'stat') {
node = node[1];
diff --git a/tools/shared.py b/tools/shared.py
index 321fa073..799a5bbe 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -295,7 +295,7 @@ def check_node_version():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.4.3'
+EMSCRIPTEN_VERSION = '1.4.7'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target()
@@ -631,6 +631,11 @@ def unique_ordered(values): # return a list of unique values in an input list, w
return True
return filter(check, values)
+def expand_response(data):
+ if type(data) == str and data[0] == '@':
+ return json.loads(open(data[1:]).read())
+ return data
+
# Settings. A global singleton. Not pretty, but nicer than passing |, settings| everywhere
class Settings:
@@ -722,6 +727,7 @@ class Building:
env['HOST_CXXFLAGS'] = "-W" #if set to nothing, CXXFLAGS is used, which we don't want
env['PKG_CONFIG_LIBDIR'] = path_from_root('system', 'local', 'lib', 'pkgconfig') + os.path.pathsep + path_from_root('system', 'lib', 'pkgconfig')
env['PKG_CONFIG_PATH'] = os.environ.get ('EM_PKG_CONFIG_PATH') or ''
+ env['EMSCRIPTEN'] = '1'
return env
@staticmethod
@@ -1097,7 +1103,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
@staticmethod
def get_safe_internalize():
- exports = ','.join(map(lambda exp: exp[1:], Settings.EXPORTED_FUNCTIONS))
+ exports = ','.join(map(lambda exp: exp[1:], expand_response(Settings.EXPORTED_FUNCTIONS)))
# internalize carefully, llvm 3.2 will remove even main if not told not to
return ['-internalize', '-internalize-public-api-list=' + exports]
diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js
index 72608aa8..ab953e5d 100644
--- a/tools/test-js-optimizer-asm-pre-output.js
+++ b/tools/test-js-optimizer-asm-pre-output.js
@@ -18,7 +18,7 @@ function b($this, $__n) {
}
$4 = $this;
$5 = HEAP8[$4 & 16777215] | 0;
- if (($5 & 1) << 24 >> 24 == 0) {
+ if (($5 & 1) == 0) {
$14 = 10;
$13 = $5;
} else {
@@ -38,14 +38,14 @@ function b($this, $__n) {
} else {
$30 = $13;
}
- if (($30 & 1) << 24 >> 24 == 0) {
+ if (($30 & 1) == 0) {
$38 = $this + 1 | 0;
} else {
$38 = HEAP32[($this + 8 & 16777215) >> 2] | 0;
}
_memset($38 + $23 | 0, 0, $__n | 0, 1, 1213141516);
$40 = $23 + $__n | 0;
- if ((HEAP8[$4 & 16777215] & 1) << 24 >> 24 == 0) {
+ if ((HEAP8[$4 & 16777215] & 1) == 0) {
HEAP8[$4 & 16777215] = $40 << 1 & 255;
} else {
HEAP32[($this + 4 & 16777215) >> 2] = $40;
@@ -93,4 +93,18 @@ function i32_8() {
print(5);
}
}
+function sign_extension_simplification() {
+ if ((HEAP8[$4 & 16777215] & 127) == 0) {
+ print(5);
+ }
+ if ((HEAP8[$4 & 16777215] & 128) << 24 >> 24 == 0) {
+ print(5);
+ }
+ if ((HEAP32[$5 & 16777215] & 32767) == 0) {
+ print(5);
+ }
+ if ((HEAP32[$5 & 16777215] & 32768) << 16 >> 16 == 0) {
+ print(5);
+ }
+}
diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js
index f2ffaef4..264587d2 100644
--- a/tools/test-js-optimizer-asm-pre.js
+++ b/tools/test-js-optimizer-asm-pre.js
@@ -95,4 +95,18 @@ function i32_8() {
print(5);
}
}
+function sign_extension_simplification() {
+ if ((HEAP8[$4 & 16777215] & 127) << 24 >> 24 == 0) {
+ print(5);
+ }
+ if ((HEAP8[$4 & 16777215] & 128) << 24 >> 24 == 0) {
+ print(5);
+ }
+ if ((HEAP32[$5 & 16777215] & 32767) << 16 >> 16 == 0) {
+ print(5);
+ }
+ if ((HEAP32[$5 & 16777215] & 32768) << 16 >> 16 == 0) {
+ print(5);
+ }
+}
// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8"]
diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js
index bb6a502b..c2efa506 100644
--- a/tools/test-js-optimizer-asm-regs-output.js
+++ b/tools/test-js-optimizer-asm-regs-output.js
@@ -22,4 +22,85 @@ function stackRestore(i1) {
i1 = i1 | 0;
STACKTOP = i1;
}
+function switchey(d1, i2) {
+ d1 = +d1;
+ i2 = i2 | 0;
+ var i3 = 0, d4 = +0;
+ switch (d1 | 0) {
+ case 0:
+ i2 = d1 + d1 | 0;
+ d1 = d(Math_max(10, Math_min(5, f())));
+ i3 = i2 + 2 | 0;
+ print(i3);
+ d4 = d1 * 5;
+ return d4;
+ case 1:
+ return 20;
+ }
+}
+function switchey2() {
+ var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0, i8 = 0, i9 = 0;
+ i1 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ i2 = 1;
+ while (1) switch (i2 | 0) {
+ case 1:
+ i3 = i1 | 0;
+ __ZN6RandomC1Ev(i3);
+ i4 = 0;
+ i5 = 0;
+ i2 = 2;
+ break;
+ case 2:
+ d6 = +__ZN6Random3getEf(8, +1);
+ d7 = +__ZN6Random3getEf(i3, +1);
+ _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d6, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0);
+ i8 = (d6 != d7 & 1) + i5 | 0;
+ i9 = i4 + 1 | 0;
+ if ((i9 | 0) < 100) {
+ i4 = i9;
+ i5 = i8;
+ i2 = 2;
+ break;
+ } else {
+ i2 = 3;
+ break;
+ }
+ case 3:
+ _printf(16, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[CHECK_ALIGN_4(tempInt | 0) >> 2] = i8, tempInt) | 0);
+ STACKTOP = i1;
+ return 0;
+ }
+ return 0;
+}
+function iffey() {
+ var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0, i8 = 0, i9 = 0;
+ i1 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ i2 = 1;
+ while (1) {
+ if (i2 | 0) {
+ i3 = i1 | 0;
+ __ZN6RandomC1Ev(i3);
+ i4 = 0;
+ i5 = 0;
+ i2 = 2;
+ } else {
+ d6 = +__ZN6Random3getEf(8, +1);
+ d7 = +__ZN6Random3getEf(i3, +1);
+ _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d6, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0);
+ i8 = (d6 != d7 & 1) + i5 | 0;
+ i9 = i4 + 1 | 0;
+ if ((i9 | 0) < 100) {
+ i4 = i9;
+ i5 = i8;
+ i2 = 2;
+ } else {
+ i2 = 3;
+ return 10;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js
index 4f7e04d4..8c3a1c98 100644
--- a/tools/test-js-optimizer-asm-regs.js
+++ b/tools/test-js-optimizer-asm-regs.js
@@ -24,5 +24,87 @@ function stackRestore(top) {
top = top|0;
STACKTOP = top;
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore"]
+function switchey(x, y) {
+ x = +x;
+ y = y | 0;
+ var int1 = 0, int2 = 0; // do not mix the types!
+ var double1 = +0, double2 = +0;
+ switch(x|0) {
+ case 0:
+ int1 = (x+x)|0;
+ double1 = d(Math.max(10, Math_min(5, f())));
+ int2 = (int1+2)|0;
+ print(int2);
+ double2 = double1*5;
+ return double2;
+ case 1:
+ return 20;
+ }
+}
+function switchey2() {
+ var $rng2 = 0, $count_06 = 0, $i_05 = 0, $2 = +0, $3 = +0, $count_1 = 0, $9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 1;
+ while (1) switch (label | 0) {
+ case 1:
+ $rng2 = __stackBase__ | 0;
+ __ZN6RandomC1Ev($rng2);
+ $i_05 = 0;
+ $count_06 = 0;
+ label = 2;
+ break;
+ case 2:
+ $2 = +__ZN6Random3getEf(8, +1);
+ $3 = +__ZN6Random3getEf($rng2, +1);
+ _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = $2, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = $3, tempInt) | 0);
+ $count_1 = ($2 != $3 & 1) + $count_06 | 0;
+ $9 = $i_05 + 1 | 0;
+ if (($9 | 0) < 100) {
+ $i_05 = $9;
+ $count_06 = $count_1;
+ label = 2;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _printf(16, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[CHECK_ALIGN_4(tempInt | 0) >> 2] = $count_1, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return 0;
+ }
+ return 0;
+}
+function iffey() {
+ var $rng2 = 0, $count_06 = 0, $i_05 = 0, $2 = +0, $3 = +0, $count_1 = 0, $9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 1;
+ while (1) {
+ if (label | 0) {
+ $rng2 = __stackBase__ | 0;
+ __ZN6RandomC1Ev($rng2);
+ $i_05 = 0;
+ $count_06 = 0;
+ label = 2;
+ } else {
+ $2 = +__ZN6Random3getEf(8, +1);
+ $3 = +__ZN6Random3getEf($rng2, +1);
+ _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = $2, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = $3, tempInt) | 0);
+ $count_1 = ($2 != $3 & 1) + $count_06 | 0;
+ $9 = $i_05 + 1 | 0;
+ if (($9 | 0) < 100) {
+ $i_05 = $9;
+ $count_06 = $count_1;
+ label = 2;
+ } else {
+ label = 3;
+ return 10;
+ }
+ }
+ }
+ return 0;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore", "switchey", "switchey2", "iffey"]